xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
MCXCOFFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)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 
getWriter()35 XCOFFObjectWriter &MCXCOFFStreamer::getWriter() {
36   return static_cast<XCOFFObjectWriter &>(getAssembler().getWriter());
37 }
38 
emitSymbolAttribute(MCSymbol * Sym,MCSymbolAttr Attribute)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 
emitXCOFFSymbolLinkageWithVisibility(MCSymbol * Symbol,MCSymbolAttr Linkage,MCSymbolAttr Visibility)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 
emitXCOFFRefDirective(const MCSymbol * Symbol)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->addFixup(Fixup);
102 }
103 
emitXCOFFRenameDirective(const MCSymbol * Name,StringRef Rename)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 
emitXCOFFExceptDirective(const MCSymbol * Symbol,const MCSymbol * Trap,unsigned Lang,unsigned Reason,unsigned FunctionSize,bool hasDebug)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 
emitXCOFFCInfoSym(StringRef Name,StringRef Metadata)120 void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
121   getWriter().addCInfoSymEntry(Name, Metadata);
122 }
123 
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)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 
emitXCOFFLocalCommonSymbol(MCSymbol * LabelSym,uint64_t Size,MCSymbol * CsectSym,Align Alignment)141 void MCXCOFFStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
142                                                  uint64_t Size,
143                                                  MCSymbol *CsectSym,
144                                                  Align Alignment) {
145   emitCommonSymbol(CsectSym, Size, Alignment);
146 }
147