xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
1 //===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file assembles .s files and emits XCOFF .o object files.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/MC/MCXCOFFStreamer.h"
14 #include "llvm/BinaryFormat/XCOFF.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCDirectives.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSectionXCOFF.h"
21 #include "llvm/MC/MCSymbolXCOFF.h"
22 #include "llvm/MC/MCXCOFFObjectWriter.h"
23 #include "llvm/MC/TargetRegistry.h"
24 #include "llvm/Support/Casting.h"
25 
26 using namespace llvm;
27 
28 MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context,
29                                  std::unique_ptr<MCAsmBackend> MAB,
30                                  std::unique_ptr<MCObjectWriter> OW,
31                                  std::unique_ptr<MCCodeEmitter> Emitter)
32     : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
33                        std::move(Emitter)) {}
34 
35 bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
36                                           MCSymbolAttr Attribute) {
37   auto *Symbol = cast<MCSymbolXCOFF>(Sym);
38   getAssembler().registerSymbol(*Symbol);
39 
40   switch (Attribute) {
41   // XCOFF doesn't support the cold feature.
42   case MCSA_Cold:
43     return false;
44 
45   case MCSA_Global:
46   case MCSA_Extern:
47     Symbol->setStorageClass(XCOFF::C_EXT);
48     Symbol->setExternal(true);
49     break;
50   case MCSA_LGlobal:
51     Symbol->setStorageClass(XCOFF::C_HIDEXT);
52     Symbol->setExternal(true);
53     break;
54   case llvm::MCSA_Weak:
55     Symbol->setStorageClass(XCOFF::C_WEAKEXT);
56     Symbol->setExternal(true);
57     break;
58   case llvm::MCSA_Hidden:
59     Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN);
60     break;
61   case llvm::MCSA_Protected:
62     Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);
63     break;
64   case llvm::MCSA_Exported:
65     Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED);
66     break;
67   default:
68     report_fatal_error("Not implemented yet.");
69   }
70   return true;
71 }
72 
73 void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
74     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
75 
76   emitSymbolAttribute(Symbol, Linkage);
77 
78   // When the caller passes `MCSA_Invalid` for the visibility, do not emit one.
79   if (Visibility == MCSA_Invalid)
80     return;
81 
82   emitSymbolAttribute(Symbol, Visibility);
83 }
84 
85 void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
86   // Add a Fixup here to later record a relocation of type R_REF to prevent the
87   // ref symbol from being garbage collected (by the binder).
88   MCDataFragment *DF = getOrCreateDataFragment();
89   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
90   std::optional<MCFixupKind> MaybeKind =
91       getAssembler().getBackend().getFixupKind("R_REF");
92   if (!MaybeKind)
93     report_fatal_error("failed to get fixup kind for R_REF relocation");
94 
95   MCFixupKind Kind = *MaybeKind;
96   MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, Kind);
97   DF->getFixups().push_back(Fixup);
98 }
99 
100 void MCXCOFFStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
101                                                StringRef Rename) {
102   const MCSymbolXCOFF *Symbol = cast<const MCSymbolXCOFF>(Name);
103   if (!Symbol->hasRename())
104     report_fatal_error("Only explicit .rename is supported for XCOFF.");
105 }
106 
107 void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
108                                                const MCSymbol *Trap,
109                                                unsigned Lang, unsigned Reason,
110                                                unsigned FunctionSize,
111                                                bool hasDebug) {
112   // TODO: Export XCOFFObjectWriter to llvm/MC/MCXCOFFObjectWriter.h and access
113   // it from MCXCOFFStreamer.
114   XCOFF::addExceptionEntry(getAssembler().getWriter(), Symbol, Trap, Lang,
115                            Reason, FunctionSize, hasDebug);
116 }
117 
118 void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
119   XCOFF::addCInfoSymEntry(getAssembler().getWriter(), Name, Metadata);
120 }
121 
122 void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
123                                        Align ByteAlignment) {
124   getAssembler().registerSymbol(*Symbol);
125   Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() !=
126                       XCOFF::C_HIDEXT);
127   Symbol->setCommon(Size, ByteAlignment);
128 
129   // Default csect align is 4, but common symbols have explicit alignment values
130   // and we should honor it.
131   cast<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment(
132       ByteAlignment);
133 
134   // Emit the alignment and storage for the variable to the section.
135   emitValueToAlignment(ByteAlignment);
136   emitZeros(Size);
137 }
138 
139 void MCXCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
140                                    uint64_t Size, Align ByteAlignment,
141                                    SMLoc Loc) {
142   report_fatal_error("Zero fill not implemented for XCOFF.");
143 }
144 
145 void MCXCOFFStreamer::emitInstToData(const MCInst &Inst,
146                                      const MCSubtargetInfo &STI) {
147   MCAssembler &Assembler = getAssembler();
148   SmallVector<MCFixup, 4> Fixups;
149   SmallString<256> Code;
150   Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
151 
152   // Add the fixups and data.
153   MCDataFragment *DF = getOrCreateDataFragment(&STI);
154   const size_t ContentsSize = DF->getContents().size();
155   auto &DataFragmentFixups = DF->getFixups();
156   for (auto &Fixup : Fixups) {
157     Fixup.setOffset(Fixup.getOffset() + ContentsSize);
158     DataFragmentFixups.push_back(Fixup);
159   }
160 
161   DF->setHasInstructions(STI);
162   DF->getContents().append(Code.begin(), Code.end());
163 }
164 
165 void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
166                                                  uint64_t Size,
167                                                  MCSymbol *CsectSym,
168                                                  Align Alignment) {
169   emitCommonSymbol(CsectSym, Size, Alignment);
170 }
171