xref: /llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp (revision 3fa5b52714b3dadbc5fddfc4ae1e7c423a652962)
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 XCOFFObjectWriter &MCXCOFFStreamer::getWriter() {
36   return static_cast<XCOFFObjectWriter &>(getAssembler().getWriter());
37 }
38 
39 bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
40                                           MCSymbolAttr Attribute) {
41   auto *Symbol = cast<MCSymbolXCOFF>(Sym);
42   getAssembler().registerSymbol(*Symbol);
43 
44   switch (Attribute) {
45   // XCOFF doesn't support the cold feature.
46   case MCSA_Cold:
47     return false;
48 
49   case MCSA_Global:
50   case MCSA_Extern:
51     Symbol->setStorageClass(XCOFF::C_EXT);
52     Symbol->setExternal(true);
53     break;
54   case MCSA_LGlobal:
55     Symbol->setStorageClass(XCOFF::C_HIDEXT);
56     Symbol->setExternal(true);
57     break;
58   case llvm::MCSA_Weak:
59     Symbol->setStorageClass(XCOFF::C_WEAKEXT);
60     Symbol->setExternal(true);
61     break;
62   case llvm::MCSA_Hidden:
63     Symbol->setVisibilityType(XCOFF::SYM_V_HIDDEN);
64     break;
65   case llvm::MCSA_Protected:
66     Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);
67     break;
68   case llvm::MCSA_Exported:
69     Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED);
70     break;
71   default:
72     report_fatal_error("Not implemented yet.");
73   }
74   return true;
75 }
76 
77 void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
78     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
79 
80   emitSymbolAttribute(Symbol, Linkage);
81 
82   // When the caller passes `MCSA_Invalid` for the visibility, do not emit one.
83   if (Visibility == MCSA_Invalid)
84     return;
85 
86   emitSymbolAttribute(Symbol, Visibility);
87 }
88 
89 void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
90   // Add a Fixup here to later record a relocation of type R_REF to prevent the
91   // ref symbol from being garbage collected (by the binder).
92   MCDataFragment *DF = getOrCreateDataFragment();
93   const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
94   std::optional<MCFixupKind> MaybeKind =
95       getAssembler().getBackend().getFixupKind("R_REF");
96   if (!MaybeKind)
97     report_fatal_error("failed to get fixup kind for R_REF relocation");
98 
99   MCFixupKind Kind = *MaybeKind;
100   MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, Kind);
101   DF->getFixups().push_back(Fixup);
102 }
103 
104 void MCXCOFFStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
105                                                StringRef Rename) {
106   const MCSymbolXCOFF *Symbol = cast<const MCSymbolXCOFF>(Name);
107   if (!Symbol->hasRename())
108     report_fatal_error("Only explicit .rename is supported for XCOFF.");
109 }
110 
111 void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
112                                                const MCSymbol *Trap,
113                                                unsigned Lang, unsigned Reason,
114                                                unsigned FunctionSize,
115                                                bool hasDebug) {
116   getWriter().addExceptionEntry(Symbol, Trap, Lang, Reason, FunctionSize,
117                                 hasDebug);
118 }
119 
120 void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
121   getWriter().addCInfoSymEntry(Name, Metadata);
122 }
123 
124 void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
125                                        Align ByteAlignment) {
126   getAssembler().registerSymbol(*Symbol);
127   Symbol->setExternal(cast<MCSymbolXCOFF>(Symbol)->getStorageClass() !=
128                       XCOFF::C_HIDEXT);
129   Symbol->setCommon(Size, ByteAlignment);
130 
131   // Default csect align is 4, but common symbols have explicit alignment values
132   // and we should honor it.
133   cast<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment(
134       ByteAlignment);
135 
136   // Emit the alignment and storage for the variable to the section.
137   emitValueToAlignment(ByteAlignment);
138   emitZeros(Size);
139 }
140 
141 void MCXCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
142                                    uint64_t Size, Align ByteAlignment,
143                                    SMLoc Loc) {
144   report_fatal_error("Zero fill not implemented for XCOFF.");
145 }
146 
147 void MCXCOFFStreamer::emitInstToData(const MCInst &Inst,
148                                      const MCSubtargetInfo &STI) {
149   MCAssembler &Assembler = getAssembler();
150   SmallVector<MCFixup, 4> Fixups;
151   SmallString<256> Code;
152   Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
153 
154   // Add the fixups and data.
155   MCDataFragment *DF = getOrCreateDataFragment(&STI);
156   const size_t ContentsSize = DF->getContents().size();
157   auto &DataFragmentFixups = DF->getFixups();
158   for (auto &Fixup : Fixups) {
159     Fixup.setOffset(Fixup.getOffset() + ContentsSize);
160     DataFragmentFixups.push_back(Fixup);
161   }
162 
163   DF->setHasInstructions(STI);
164   DF->appendContents(Code);
165 }
166 
167 void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
168                                                  uint64_t Size,
169                                                  MCSymbol *CsectSym,
170                                                  Align Alignment) {
171   emitCommonSymbol(CsectSym, Size, Alignment);
172 }
173