xref: /aosp_15_r20/external/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file assembles .s files and emits ARM ELF .o object files. Different
11*9880d681SAndroid Build Coastguard Worker // from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to
12*9880d681SAndroid Build Coastguard Worker // delimit regions of data and code.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #include "ARMRegisterInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "ARMUnwindOpAsm.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmBackend.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCCodeEmitter.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFStreamer.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstPrinter.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectStreamer.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSection.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionELF.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbolELF.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ARMBuildAttributes.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ARMEHABI.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetParser.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FormattedStream.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LEB128.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
45*9880d681SAndroid Build Coastguard Worker #include <algorithm>
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker using namespace llvm;
48*9880d681SAndroid Build Coastguard Worker 
GetAEABIUnwindPersonalityName(unsigned Index)49*9880d681SAndroid Build Coastguard Worker static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
50*9880d681SAndroid Build Coastguard Worker   assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX &&
51*9880d681SAndroid Build Coastguard Worker          "Invalid personality index");
52*9880d681SAndroid Build Coastguard Worker   return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker namespace {
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker class ARMELFStreamer;
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker class ARMTargetAsmStreamer : public ARMTargetStreamer {
60*9880d681SAndroid Build Coastguard Worker   formatted_raw_ostream &OS;
61*9880d681SAndroid Build Coastguard Worker   MCInstPrinter &InstPrinter;
62*9880d681SAndroid Build Coastguard Worker   bool IsVerboseAsm;
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   void emitFnStart() override;
65*9880d681SAndroid Build Coastguard Worker   void emitFnEnd() override;
66*9880d681SAndroid Build Coastguard Worker   void emitCantUnwind() override;
67*9880d681SAndroid Build Coastguard Worker   void emitPersonality(const MCSymbol *Personality) override;
68*9880d681SAndroid Build Coastguard Worker   void emitPersonalityIndex(unsigned Index) override;
69*9880d681SAndroid Build Coastguard Worker   void emitHandlerData() override;
70*9880d681SAndroid Build Coastguard Worker   void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override;
71*9880d681SAndroid Build Coastguard Worker   void emitMovSP(unsigned Reg, int64_t Offset = 0) override;
72*9880d681SAndroid Build Coastguard Worker   void emitPad(int64_t Offset) override;
73*9880d681SAndroid Build Coastguard Worker   void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
74*9880d681SAndroid Build Coastguard Worker                    bool isVector) override;
75*9880d681SAndroid Build Coastguard Worker   void emitUnwindRaw(int64_t Offset,
76*9880d681SAndroid Build Coastguard Worker                      const SmallVectorImpl<uint8_t> &Opcodes) override;
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   void switchVendor(StringRef Vendor) override;
79*9880d681SAndroid Build Coastguard Worker   void emitAttribute(unsigned Attribute, unsigned Value) override;
80*9880d681SAndroid Build Coastguard Worker   void emitTextAttribute(unsigned Attribute, StringRef String) override;
81*9880d681SAndroid Build Coastguard Worker   void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
82*9880d681SAndroid Build Coastguard Worker                             StringRef StringValue) override;
83*9880d681SAndroid Build Coastguard Worker   void emitArch(unsigned Arch) override;
84*9880d681SAndroid Build Coastguard Worker   void emitArchExtension(unsigned ArchExt) override;
85*9880d681SAndroid Build Coastguard Worker   void emitObjectArch(unsigned Arch) override;
86*9880d681SAndroid Build Coastguard Worker   void emitFPU(unsigned FPU) override;
87*9880d681SAndroid Build Coastguard Worker   void emitInst(uint32_t Inst, char Suffix = '\0') override;
88*9880d681SAndroid Build Coastguard Worker   void finishAttributeSection() override;
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker   void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
91*9880d681SAndroid Build Coastguard Worker   void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker public:
94*9880d681SAndroid Build Coastguard Worker   ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,
95*9880d681SAndroid Build Coastguard Worker                        MCInstPrinter &InstPrinter, bool VerboseAsm);
96*9880d681SAndroid Build Coastguard Worker };
97*9880d681SAndroid Build Coastguard Worker 
ARMTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter & InstPrinter,bool VerboseAsm)98*9880d681SAndroid Build Coastguard Worker ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S,
99*9880d681SAndroid Build Coastguard Worker                                            formatted_raw_ostream &OS,
100*9880d681SAndroid Build Coastguard Worker                                            MCInstPrinter &InstPrinter,
101*9880d681SAndroid Build Coastguard Worker                                            bool VerboseAsm)
102*9880d681SAndroid Build Coastguard Worker     : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter),
103*9880d681SAndroid Build Coastguard Worker       IsVerboseAsm(VerboseAsm) {}
emitFnStart()104*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; }
emitFnEnd()105*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; }
emitCantUnwind()106*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
emitPersonality(const MCSymbol * Personality)107*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
108*9880d681SAndroid Build Coastguard Worker   OS << "\t.personality " << Personality->getName() << '\n';
109*9880d681SAndroid Build Coastguard Worker }
emitPersonalityIndex(unsigned Index)110*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) {
111*9880d681SAndroid Build Coastguard Worker   OS << "\t.personalityindex " << Index << '\n';
112*9880d681SAndroid Build Coastguard Worker }
emitHandlerData()113*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
emitSetFP(unsigned FpReg,unsigned SpReg,int64_t Offset)114*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
115*9880d681SAndroid Build Coastguard Worker                                      int64_t Offset) {
116*9880d681SAndroid Build Coastguard Worker   OS << "\t.setfp\t";
117*9880d681SAndroid Build Coastguard Worker   InstPrinter.printRegName(OS, FpReg);
118*9880d681SAndroid Build Coastguard Worker   OS << ", ";
119*9880d681SAndroid Build Coastguard Worker   InstPrinter.printRegName(OS, SpReg);
120*9880d681SAndroid Build Coastguard Worker   if (Offset)
121*9880d681SAndroid Build Coastguard Worker     OS << ", #" << Offset;
122*9880d681SAndroid Build Coastguard Worker   OS << '\n';
123*9880d681SAndroid Build Coastguard Worker }
emitMovSP(unsigned Reg,int64_t Offset)124*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
125*9880d681SAndroid Build Coastguard Worker   assert((Reg != ARM::SP && Reg != ARM::PC) &&
126*9880d681SAndroid Build Coastguard Worker          "the operand of .movsp cannot be either sp or pc");
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   OS << "\t.movsp\t";
129*9880d681SAndroid Build Coastguard Worker   InstPrinter.printRegName(OS, Reg);
130*9880d681SAndroid Build Coastguard Worker   if (Offset)
131*9880d681SAndroid Build Coastguard Worker     OS << ", #" << Offset;
132*9880d681SAndroid Build Coastguard Worker   OS << '\n';
133*9880d681SAndroid Build Coastguard Worker }
emitPad(int64_t Offset)134*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
135*9880d681SAndroid Build Coastguard Worker   OS << "\t.pad\t#" << Offset << '\n';
136*9880d681SAndroid Build Coastguard Worker }
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool isVector)137*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
138*9880d681SAndroid Build Coastguard Worker                                        bool isVector) {
139*9880d681SAndroid Build Coastguard Worker   assert(RegList.size() && "RegList should not be empty");
140*9880d681SAndroid Build Coastguard Worker   if (isVector)
141*9880d681SAndroid Build Coastguard Worker     OS << "\t.vsave\t{";
142*9880d681SAndroid Build Coastguard Worker   else
143*9880d681SAndroid Build Coastguard Worker     OS << "\t.save\t{";
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   InstPrinter.printRegName(OS, RegList[0]);
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1, e = RegList.size(); i != e; ++i) {
148*9880d681SAndroid Build Coastguard Worker     OS << ", ";
149*9880d681SAndroid Build Coastguard Worker     InstPrinter.printRegName(OS, RegList[i]);
150*9880d681SAndroid Build Coastguard Worker   }
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   OS << "}\n";
153*9880d681SAndroid Build Coastguard Worker }
switchVendor(StringRef Vendor)154*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {
155*9880d681SAndroid Build Coastguard Worker }
emitAttribute(unsigned Attribute,unsigned Value)156*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
157*9880d681SAndroid Build Coastguard Worker   OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value);
158*9880d681SAndroid Build Coastguard Worker   if (IsVerboseAsm) {
159*9880d681SAndroid Build Coastguard Worker     StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute);
160*9880d681SAndroid Build Coastguard Worker     if (!Name.empty())
161*9880d681SAndroid Build Coastguard Worker       OS << "\t@ " << Name;
162*9880d681SAndroid Build Coastguard Worker   }
163*9880d681SAndroid Build Coastguard Worker   OS << "\n";
164*9880d681SAndroid Build Coastguard Worker }
emitTextAttribute(unsigned Attribute,StringRef String)165*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
166*9880d681SAndroid Build Coastguard Worker                                              StringRef String) {
167*9880d681SAndroid Build Coastguard Worker   switch (Attribute) {
168*9880d681SAndroid Build Coastguard Worker   case ARMBuildAttrs::CPU_name:
169*9880d681SAndroid Build Coastguard Worker     OS << "\t.cpu\t" << String.lower();
170*9880d681SAndroid Build Coastguard Worker     break;
171*9880d681SAndroid Build Coastguard Worker   default:
172*9880d681SAndroid Build Coastguard Worker     OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\"";
173*9880d681SAndroid Build Coastguard Worker     if (IsVerboseAsm) {
174*9880d681SAndroid Build Coastguard Worker       StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute);
175*9880d681SAndroid Build Coastguard Worker       if (!Name.empty())
176*9880d681SAndroid Build Coastguard Worker         OS << "\t@ " << Name;
177*9880d681SAndroid Build Coastguard Worker     }
178*9880d681SAndroid Build Coastguard Worker     break;
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker   OS << "\n";
181*9880d681SAndroid Build Coastguard Worker }
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)182*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
183*9880d681SAndroid Build Coastguard Worker                                                 unsigned IntValue,
184*9880d681SAndroid Build Coastguard Worker                                                 StringRef StringValue) {
185*9880d681SAndroid Build Coastguard Worker   switch (Attribute) {
186*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("unsupported multi-value attribute in asm mode");
187*9880d681SAndroid Build Coastguard Worker   case ARMBuildAttrs::compatibility:
188*9880d681SAndroid Build Coastguard Worker     OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue;
189*9880d681SAndroid Build Coastguard Worker     if (!StringValue.empty())
190*9880d681SAndroid Build Coastguard Worker       OS << ", \"" << StringValue << "\"";
191*9880d681SAndroid Build Coastguard Worker     if (IsVerboseAsm)
192*9880d681SAndroid Build Coastguard Worker       OS << "\t@ " << ARMBuildAttrs::AttrTypeAsString(Attribute);
193*9880d681SAndroid Build Coastguard Worker     break;
194*9880d681SAndroid Build Coastguard Worker   }
195*9880d681SAndroid Build Coastguard Worker   OS << "\n";
196*9880d681SAndroid Build Coastguard Worker }
emitArch(unsigned Arch)197*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitArch(unsigned Arch) {
198*9880d681SAndroid Build Coastguard Worker   OS << "\t.arch\t" << ARM::getArchName(Arch) << "\n";
199*9880d681SAndroid Build Coastguard Worker }
emitArchExtension(unsigned ArchExt)200*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitArchExtension(unsigned ArchExt) {
201*9880d681SAndroid Build Coastguard Worker   OS << "\t.arch_extension\t" << ARM::getArchExtName(ArchExt) << "\n";
202*9880d681SAndroid Build Coastguard Worker }
emitObjectArch(unsigned Arch)203*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitObjectArch(unsigned Arch) {
204*9880d681SAndroid Build Coastguard Worker   OS << "\t.object_arch\t" << ARM::getArchName(Arch) << '\n';
205*9880d681SAndroid Build Coastguard Worker }
emitFPU(unsigned FPU)206*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
207*9880d681SAndroid Build Coastguard Worker   OS << "\t.fpu\t" << ARM::getFPUName(FPU) << "\n";
208*9880d681SAndroid Build Coastguard Worker }
finishAttributeSection()209*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::finishAttributeSection() {
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker void
AnnotateTLSDescriptorSequence(const MCSymbolRefExpr * S)212*9880d681SAndroid Build Coastguard Worker ARMTargetAsmStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
213*9880d681SAndroid Build Coastguard Worker   OS << "\t.tlsdescseq\t" << S->getSymbol().getName();
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker 
emitThumbSet(MCSymbol * Symbol,const MCExpr * Value)216*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {
217*9880d681SAndroid Build Coastguard Worker   const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   OS << "\t.thumb_set\t";
220*9880d681SAndroid Build Coastguard Worker   Symbol->print(OS, MAI);
221*9880d681SAndroid Build Coastguard Worker   OS << ", ";
222*9880d681SAndroid Build Coastguard Worker   Value->print(OS, MAI);
223*9880d681SAndroid Build Coastguard Worker   OS << '\n';
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker 
emitInst(uint32_t Inst,char Suffix)226*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) {
227*9880d681SAndroid Build Coastguard Worker   OS << "\t.inst";
228*9880d681SAndroid Build Coastguard Worker   if (Suffix)
229*9880d681SAndroid Build Coastguard Worker     OS << "." << Suffix;
230*9880d681SAndroid Build Coastguard Worker   OS << "\t0x" << Twine::utohexstr(Inst) << "\n";
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker 
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)233*9880d681SAndroid Build Coastguard Worker void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset,
234*9880d681SAndroid Build Coastguard Worker                                       const SmallVectorImpl<uint8_t> &Opcodes) {
235*9880d681SAndroid Build Coastguard Worker   OS << "\t.unwind_raw " << Offset;
236*9880d681SAndroid Build Coastguard Worker   for (SmallVectorImpl<uint8_t>::const_iterator OCI = Opcodes.begin(),
237*9880d681SAndroid Build Coastguard Worker                                                 OCE = Opcodes.end();
238*9880d681SAndroid Build Coastguard Worker        OCI != OCE; ++OCI)
239*9880d681SAndroid Build Coastguard Worker     OS << ", 0x" << Twine::utohexstr(*OCI);
240*9880d681SAndroid Build Coastguard Worker   OS << '\n';
241*9880d681SAndroid Build Coastguard Worker }
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker class ARMTargetELFStreamer : public ARMTargetStreamer {
244*9880d681SAndroid Build Coastguard Worker private:
245*9880d681SAndroid Build Coastguard Worker   // This structure holds all attributes, accounting for
246*9880d681SAndroid Build Coastguard Worker   // their string/numeric value, so we can later emit them
247*9880d681SAndroid Build Coastguard Worker   // in declaration order, keeping all in the same vector
248*9880d681SAndroid Build Coastguard Worker   struct AttributeItem {
249*9880d681SAndroid Build Coastguard Worker     enum {
250*9880d681SAndroid Build Coastguard Worker       HiddenAttribute = 0,
251*9880d681SAndroid Build Coastguard Worker       NumericAttribute,
252*9880d681SAndroid Build Coastguard Worker       TextAttribute,
253*9880d681SAndroid Build Coastguard Worker       NumericAndTextAttributes
254*9880d681SAndroid Build Coastguard Worker     } Type;
255*9880d681SAndroid Build Coastguard Worker     unsigned Tag;
256*9880d681SAndroid Build Coastguard Worker     unsigned IntValue;
257*9880d681SAndroid Build Coastguard Worker     std::string StringValue;
258*9880d681SAndroid Build Coastguard Worker 
LessTag__anon7ce36a2c0111::ARMTargetELFStreamer::AttributeItem259*9880d681SAndroid Build Coastguard Worker     static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) {
260*9880d681SAndroid Build Coastguard Worker       // The conformance tag must be emitted first when serialised
261*9880d681SAndroid Build Coastguard Worker       // into an object file. Specifically, the addenda to the ARM ABI
262*9880d681SAndroid Build Coastguard Worker       // states that (2.3.7.4):
263*9880d681SAndroid Build Coastguard Worker       //
264*9880d681SAndroid Build Coastguard Worker       // "To simplify recognition by consumers in the common case of
265*9880d681SAndroid Build Coastguard Worker       // claiming conformity for the whole file, this tag should be
266*9880d681SAndroid Build Coastguard Worker       // emitted first in a file-scope sub-subsection of the first
267*9880d681SAndroid Build Coastguard Worker       // public subsection of the attributes section."
268*9880d681SAndroid Build Coastguard Worker       //
269*9880d681SAndroid Build Coastguard Worker       // So it is special-cased in this comparison predicate when the
270*9880d681SAndroid Build Coastguard Worker       // attributes are sorted in finishAttributeSection().
271*9880d681SAndroid Build Coastguard Worker       return (RHS.Tag != ARMBuildAttrs::conformance) &&
272*9880d681SAndroid Build Coastguard Worker              ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
273*9880d681SAndroid Build Coastguard Worker     }
274*9880d681SAndroid Build Coastguard Worker   };
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker   StringRef CurrentVendor;
277*9880d681SAndroid Build Coastguard Worker   unsigned FPU;
278*9880d681SAndroid Build Coastguard Worker   unsigned Arch;
279*9880d681SAndroid Build Coastguard Worker   unsigned EmittedArch;
280*9880d681SAndroid Build Coastguard Worker   SmallVector<AttributeItem, 64> Contents;
281*9880d681SAndroid Build Coastguard Worker 
282*9880d681SAndroid Build Coastguard Worker   MCSection *AttributeSection;
283*9880d681SAndroid Build Coastguard Worker 
getAttributeItem(unsigned Attribute)284*9880d681SAndroid Build Coastguard Worker   AttributeItem *getAttributeItem(unsigned Attribute) {
285*9880d681SAndroid Build Coastguard Worker     for (size_t i = 0; i < Contents.size(); ++i)
286*9880d681SAndroid Build Coastguard Worker       if (Contents[i].Tag == Attribute)
287*9880d681SAndroid Build Coastguard Worker         return &Contents[i];
288*9880d681SAndroid Build Coastguard Worker     return nullptr;
289*9880d681SAndroid Build Coastguard Worker   }
290*9880d681SAndroid Build Coastguard Worker 
setAttributeItem(unsigned Attribute,unsigned Value,bool OverwriteExisting)291*9880d681SAndroid Build Coastguard Worker   void setAttributeItem(unsigned Attribute, unsigned Value,
292*9880d681SAndroid Build Coastguard Worker                         bool OverwriteExisting) {
293*9880d681SAndroid Build Coastguard Worker     // Look for existing attribute item
294*9880d681SAndroid Build Coastguard Worker     if (AttributeItem *Item = getAttributeItem(Attribute)) {
295*9880d681SAndroid Build Coastguard Worker       if (!OverwriteExisting)
296*9880d681SAndroid Build Coastguard Worker         return;
297*9880d681SAndroid Build Coastguard Worker       Item->Type = AttributeItem::NumericAttribute;
298*9880d681SAndroid Build Coastguard Worker       Item->IntValue = Value;
299*9880d681SAndroid Build Coastguard Worker       return;
300*9880d681SAndroid Build Coastguard Worker     }
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker     // Create new attribute item
303*9880d681SAndroid Build Coastguard Worker     AttributeItem Item = {
304*9880d681SAndroid Build Coastguard Worker       AttributeItem::NumericAttribute,
305*9880d681SAndroid Build Coastguard Worker       Attribute,
306*9880d681SAndroid Build Coastguard Worker       Value,
307*9880d681SAndroid Build Coastguard Worker       StringRef("")
308*9880d681SAndroid Build Coastguard Worker     };
309*9880d681SAndroid Build Coastguard Worker     Contents.push_back(Item);
310*9880d681SAndroid Build Coastguard Worker   }
311*9880d681SAndroid Build Coastguard Worker 
setAttributeItem(unsigned Attribute,StringRef Value,bool OverwriteExisting)312*9880d681SAndroid Build Coastguard Worker   void setAttributeItem(unsigned Attribute, StringRef Value,
313*9880d681SAndroid Build Coastguard Worker                         bool OverwriteExisting) {
314*9880d681SAndroid Build Coastguard Worker     // Look for existing attribute item
315*9880d681SAndroid Build Coastguard Worker     if (AttributeItem *Item = getAttributeItem(Attribute)) {
316*9880d681SAndroid Build Coastguard Worker       if (!OverwriteExisting)
317*9880d681SAndroid Build Coastguard Worker         return;
318*9880d681SAndroid Build Coastguard Worker       Item->Type = AttributeItem::TextAttribute;
319*9880d681SAndroid Build Coastguard Worker       Item->StringValue = Value;
320*9880d681SAndroid Build Coastguard Worker       return;
321*9880d681SAndroid Build Coastguard Worker     }
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker     // Create new attribute item
324*9880d681SAndroid Build Coastguard Worker     AttributeItem Item = {
325*9880d681SAndroid Build Coastguard Worker       AttributeItem::TextAttribute,
326*9880d681SAndroid Build Coastguard Worker       Attribute,
327*9880d681SAndroid Build Coastguard Worker       0,
328*9880d681SAndroid Build Coastguard Worker       Value
329*9880d681SAndroid Build Coastguard Worker     };
330*9880d681SAndroid Build Coastguard Worker     Contents.push_back(Item);
331*9880d681SAndroid Build Coastguard Worker   }
332*9880d681SAndroid Build Coastguard Worker 
setAttributeItems(unsigned Attribute,unsigned IntValue,StringRef StringValue,bool OverwriteExisting)333*9880d681SAndroid Build Coastguard Worker   void setAttributeItems(unsigned Attribute, unsigned IntValue,
334*9880d681SAndroid Build Coastguard Worker                          StringRef StringValue, bool OverwriteExisting) {
335*9880d681SAndroid Build Coastguard Worker     // Look for existing attribute item
336*9880d681SAndroid Build Coastguard Worker     if (AttributeItem *Item = getAttributeItem(Attribute)) {
337*9880d681SAndroid Build Coastguard Worker       if (!OverwriteExisting)
338*9880d681SAndroid Build Coastguard Worker         return;
339*9880d681SAndroid Build Coastguard Worker       Item->Type = AttributeItem::NumericAndTextAttributes;
340*9880d681SAndroid Build Coastguard Worker       Item->IntValue = IntValue;
341*9880d681SAndroid Build Coastguard Worker       Item->StringValue = StringValue;
342*9880d681SAndroid Build Coastguard Worker       return;
343*9880d681SAndroid Build Coastguard Worker     }
344*9880d681SAndroid Build Coastguard Worker 
345*9880d681SAndroid Build Coastguard Worker     // Create new attribute item
346*9880d681SAndroid Build Coastguard Worker     AttributeItem Item = {
347*9880d681SAndroid Build Coastguard Worker       AttributeItem::NumericAndTextAttributes,
348*9880d681SAndroid Build Coastguard Worker       Attribute,
349*9880d681SAndroid Build Coastguard Worker       IntValue,
350*9880d681SAndroid Build Coastguard Worker       StringValue
351*9880d681SAndroid Build Coastguard Worker     };
352*9880d681SAndroid Build Coastguard Worker     Contents.push_back(Item);
353*9880d681SAndroid Build Coastguard Worker   }
354*9880d681SAndroid Build Coastguard Worker 
355*9880d681SAndroid Build Coastguard Worker   void emitArchDefaultAttributes();
356*9880d681SAndroid Build Coastguard Worker   void emitFPUDefaultAttributes();
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker   ARMELFStreamer &getStreamer();
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker   void emitFnStart() override;
361*9880d681SAndroid Build Coastguard Worker   void emitFnEnd() override;
362*9880d681SAndroid Build Coastguard Worker   void emitCantUnwind() override;
363*9880d681SAndroid Build Coastguard Worker   void emitPersonality(const MCSymbol *Personality) override;
364*9880d681SAndroid Build Coastguard Worker   void emitPersonalityIndex(unsigned Index) override;
365*9880d681SAndroid Build Coastguard Worker   void emitHandlerData() override;
366*9880d681SAndroid Build Coastguard Worker   void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override;
367*9880d681SAndroid Build Coastguard Worker   void emitMovSP(unsigned Reg, int64_t Offset = 0) override;
368*9880d681SAndroid Build Coastguard Worker   void emitPad(int64_t Offset) override;
369*9880d681SAndroid Build Coastguard Worker   void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
370*9880d681SAndroid Build Coastguard Worker                    bool isVector) override;
371*9880d681SAndroid Build Coastguard Worker   void emitUnwindRaw(int64_t Offset,
372*9880d681SAndroid Build Coastguard Worker                      const SmallVectorImpl<uint8_t> &Opcodes) override;
373*9880d681SAndroid Build Coastguard Worker 
374*9880d681SAndroid Build Coastguard Worker   void switchVendor(StringRef Vendor) override;
375*9880d681SAndroid Build Coastguard Worker   void emitAttribute(unsigned Attribute, unsigned Value) override;
376*9880d681SAndroid Build Coastguard Worker   void emitTextAttribute(unsigned Attribute, StringRef String) override;
377*9880d681SAndroid Build Coastguard Worker   void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
378*9880d681SAndroid Build Coastguard Worker                             StringRef StringValue) override;
379*9880d681SAndroid Build Coastguard Worker   void emitArch(unsigned Arch) override;
380*9880d681SAndroid Build Coastguard Worker   void emitObjectArch(unsigned Arch) override;
381*9880d681SAndroid Build Coastguard Worker   void emitFPU(unsigned FPU) override;
382*9880d681SAndroid Build Coastguard Worker   void emitInst(uint32_t Inst, char Suffix = '\0') override;
383*9880d681SAndroid Build Coastguard Worker   void finishAttributeSection() override;
384*9880d681SAndroid Build Coastguard Worker   void emitLabel(MCSymbol *Symbol) override;
385*9880d681SAndroid Build Coastguard Worker 
386*9880d681SAndroid Build Coastguard Worker   void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
387*9880d681SAndroid Build Coastguard Worker   void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker   size_t calculateContentSize() const;
390*9880d681SAndroid Build Coastguard Worker 
391*9880d681SAndroid Build Coastguard Worker   // Reset state between object emissions
392*9880d681SAndroid Build Coastguard Worker   void reset() override;
393*9880d681SAndroid Build Coastguard Worker 
394*9880d681SAndroid Build Coastguard Worker public:
ARMTargetELFStreamer(MCStreamer & S)395*9880d681SAndroid Build Coastguard Worker   ARMTargetELFStreamer(MCStreamer &S)
396*9880d681SAndroid Build Coastguard Worker     : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::FK_INVALID),
397*9880d681SAndroid Build Coastguard Worker       Arch(ARM::AK_INVALID), EmittedArch(ARM::AK_INVALID),
398*9880d681SAndroid Build Coastguard Worker       AttributeSection(nullptr) {}
399*9880d681SAndroid Build Coastguard Worker };
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker /// Extend the generic ELFStreamer class so that it can emit mapping symbols at
402*9880d681SAndroid Build Coastguard Worker /// the appropriate points in the object files. These symbols are defined in the
403*9880d681SAndroid Build Coastguard Worker /// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
404*9880d681SAndroid Build Coastguard Worker ///
405*9880d681SAndroid Build Coastguard Worker /// In brief: $a, $t or $d should be emitted at the start of each contiguous
406*9880d681SAndroid Build Coastguard Worker /// region of ARM code, Thumb code or data in a section. In practice, this
407*9880d681SAndroid Build Coastguard Worker /// emission does not rely on explicit assembler directives but on inherent
408*9880d681SAndroid Build Coastguard Worker /// properties of the directives doing the emission (e.g. ".byte" is data, "add
409*9880d681SAndroid Build Coastguard Worker /// r0, r0, r0" an instruction).
410*9880d681SAndroid Build Coastguard Worker ///
411*9880d681SAndroid Build Coastguard Worker /// As a result this system is orthogonal to the DataRegion infrastructure used
412*9880d681SAndroid Build Coastguard Worker /// by MachO. Beware!
413*9880d681SAndroid Build Coastguard Worker class ARMELFStreamer : public MCELFStreamer {
414*9880d681SAndroid Build Coastguard Worker public:
415*9880d681SAndroid Build Coastguard Worker   friend class ARMTargetELFStreamer;
416*9880d681SAndroid Build Coastguard Worker 
ARMELFStreamer(MCContext & Context,MCAsmBackend & TAB,raw_pwrite_stream & OS,MCCodeEmitter * Emitter,bool IsThumb)417*9880d681SAndroid Build Coastguard Worker   ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
418*9880d681SAndroid Build Coastguard Worker                  MCCodeEmitter *Emitter, bool IsThumb)
419*9880d681SAndroid Build Coastguard Worker       : MCELFStreamer(Context, TAB, OS, Emitter), IsThumb(IsThumb),
420*9880d681SAndroid Build Coastguard Worker         MappingSymbolCounter(0), LastEMS(EMS_None) {
421*9880d681SAndroid Build Coastguard Worker     EHReset();
422*9880d681SAndroid Build Coastguard Worker   }
423*9880d681SAndroid Build Coastguard Worker 
~ARMELFStreamer()424*9880d681SAndroid Build Coastguard Worker   ~ARMELFStreamer() {}
425*9880d681SAndroid Build Coastguard Worker 
426*9880d681SAndroid Build Coastguard Worker   void FinishImpl() override;
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker   // ARM exception handling directives
429*9880d681SAndroid Build Coastguard Worker   void emitFnStart();
430*9880d681SAndroid Build Coastguard Worker   void emitFnEnd();
431*9880d681SAndroid Build Coastguard Worker   void emitCantUnwind();
432*9880d681SAndroid Build Coastguard Worker   void emitPersonality(const MCSymbol *Per);
433*9880d681SAndroid Build Coastguard Worker   void emitPersonalityIndex(unsigned index);
434*9880d681SAndroid Build Coastguard Worker   void emitHandlerData();
435*9880d681SAndroid Build Coastguard Worker   void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
436*9880d681SAndroid Build Coastguard Worker   void emitMovSP(unsigned Reg, int64_t Offset = 0);
437*9880d681SAndroid Build Coastguard Worker   void emitPad(int64_t Offset);
438*9880d681SAndroid Build Coastguard Worker   void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
439*9880d681SAndroid Build Coastguard Worker   void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
440*9880d681SAndroid Build Coastguard Worker 
ChangeSection(MCSection * Section,const MCExpr * Subsection)441*9880d681SAndroid Build Coastguard Worker   void ChangeSection(MCSection *Section, const MCExpr *Subsection) override {
442*9880d681SAndroid Build Coastguard Worker     // We have to keep track of the mapping symbol state of any sections we
443*9880d681SAndroid Build Coastguard Worker     // use. Each one should start off as EMS_None, which is provided as the
444*9880d681SAndroid Build Coastguard Worker     // default constructor by DenseMap::lookup.
445*9880d681SAndroid Build Coastguard Worker     LastMappingSymbols[getPreviousSection().first] = LastEMS;
446*9880d681SAndroid Build Coastguard Worker     LastEMS = LastMappingSymbols.lookup(Section);
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::ChangeSection(Section, Subsection);
449*9880d681SAndroid Build Coastguard Worker   }
450*9880d681SAndroid Build Coastguard Worker 
451*9880d681SAndroid Build Coastguard Worker   /// This function is the one used to emit instruction data into the ELF
452*9880d681SAndroid Build Coastguard Worker   /// streamer. We override it to add the appropriate mapping symbol if
453*9880d681SAndroid Build Coastguard Worker   /// necessary.
EmitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)454*9880d681SAndroid Build Coastguard Worker   void EmitInstruction(const MCInst& Inst,
455*9880d681SAndroid Build Coastguard Worker                        const MCSubtargetInfo &STI) override {
456*9880d681SAndroid Build Coastguard Worker     if (IsThumb)
457*9880d681SAndroid Build Coastguard Worker       EmitThumbMappingSymbol();
458*9880d681SAndroid Build Coastguard Worker     else
459*9880d681SAndroid Build Coastguard Worker       EmitARMMappingSymbol();
460*9880d681SAndroid Build Coastguard Worker 
461*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::EmitInstruction(Inst, STI);
462*9880d681SAndroid Build Coastguard Worker   }
463*9880d681SAndroid Build Coastguard Worker 
emitInst(uint32_t Inst,char Suffix)464*9880d681SAndroid Build Coastguard Worker   void emitInst(uint32_t Inst, char Suffix) {
465*9880d681SAndroid Build Coastguard Worker     unsigned Size;
466*9880d681SAndroid Build Coastguard Worker     char Buffer[4];
467*9880d681SAndroid Build Coastguard Worker     const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();
468*9880d681SAndroid Build Coastguard Worker 
469*9880d681SAndroid Build Coastguard Worker     switch (Suffix) {
470*9880d681SAndroid Build Coastguard Worker     case '\0':
471*9880d681SAndroid Build Coastguard Worker       Size = 4;
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker       assert(!IsThumb);
474*9880d681SAndroid Build Coastguard Worker       EmitARMMappingSymbol();
475*9880d681SAndroid Build Coastguard Worker       for (unsigned II = 0, IE = Size; II != IE; II++) {
476*9880d681SAndroid Build Coastguard Worker         const unsigned I = LittleEndian ? (Size - II - 1) : II;
477*9880d681SAndroid Build Coastguard Worker         Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
478*9880d681SAndroid Build Coastguard Worker       }
479*9880d681SAndroid Build Coastguard Worker 
480*9880d681SAndroid Build Coastguard Worker       break;
481*9880d681SAndroid Build Coastguard Worker     case 'n':
482*9880d681SAndroid Build Coastguard Worker     case 'w':
483*9880d681SAndroid Build Coastguard Worker       Size = (Suffix == 'n' ? 2 : 4);
484*9880d681SAndroid Build Coastguard Worker 
485*9880d681SAndroid Build Coastguard Worker       assert(IsThumb);
486*9880d681SAndroid Build Coastguard Worker       EmitThumbMappingSymbol();
487*9880d681SAndroid Build Coastguard Worker       for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
488*9880d681SAndroid Build Coastguard Worker         const unsigned I0 = LittleEndian ? II + 0 : (Size - II - 1);
489*9880d681SAndroid Build Coastguard Worker         const unsigned I1 = LittleEndian ? II + 1 : (Size - II - 2);
490*9880d681SAndroid Build Coastguard Worker         Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
491*9880d681SAndroid Build Coastguard Worker         Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
492*9880d681SAndroid Build Coastguard Worker       }
493*9880d681SAndroid Build Coastguard Worker 
494*9880d681SAndroid Build Coastguard Worker       break;
495*9880d681SAndroid Build Coastguard Worker     default:
496*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid Suffix");
497*9880d681SAndroid Build Coastguard Worker     }
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::EmitBytes(StringRef(Buffer, Size));
500*9880d681SAndroid Build Coastguard Worker   }
501*9880d681SAndroid Build Coastguard Worker 
502*9880d681SAndroid Build Coastguard Worker   /// This is one of the functions used to emit data into an ELF section, so the
503*9880d681SAndroid Build Coastguard Worker   /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
504*9880d681SAndroid Build Coastguard Worker   /// necessary.
EmitBytes(StringRef Data)505*9880d681SAndroid Build Coastguard Worker   void EmitBytes(StringRef Data) override {
506*9880d681SAndroid Build Coastguard Worker     EmitDataMappingSymbol();
507*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::EmitBytes(Data);
508*9880d681SAndroid Build Coastguard Worker   }
509*9880d681SAndroid Build Coastguard Worker 
510*9880d681SAndroid Build Coastguard Worker   /// This is one of the functions used to emit data into an ELF section, so the
511*9880d681SAndroid Build Coastguard Worker   /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
512*9880d681SAndroid Build Coastguard Worker   /// necessary.
EmitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)513*9880d681SAndroid Build Coastguard Worker   void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
514*9880d681SAndroid Build Coastguard Worker     if (const MCSymbolRefExpr *SRE = dyn_cast_or_null<MCSymbolRefExpr>(Value))
515*9880d681SAndroid Build Coastguard Worker       if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_SBREL && !(Size == 4)) {
516*9880d681SAndroid Build Coastguard Worker         getContext().reportError(Loc, "relocated expression must be 32-bit");
517*9880d681SAndroid Build Coastguard Worker         return;
518*9880d681SAndroid Build Coastguard Worker       }
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker     EmitDataMappingSymbol();
521*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::EmitValueImpl(Value, Size, Loc);
522*9880d681SAndroid Build Coastguard Worker   }
523*9880d681SAndroid Build Coastguard Worker 
EmitAssemblerFlag(MCAssemblerFlag Flag)524*9880d681SAndroid Build Coastguard Worker   void EmitAssemblerFlag(MCAssemblerFlag Flag) override {
525*9880d681SAndroid Build Coastguard Worker     MCELFStreamer::EmitAssemblerFlag(Flag);
526*9880d681SAndroid Build Coastguard Worker 
527*9880d681SAndroid Build Coastguard Worker     switch (Flag) {
528*9880d681SAndroid Build Coastguard Worker     case MCAF_SyntaxUnified:
529*9880d681SAndroid Build Coastguard Worker       return; // no-op here.
530*9880d681SAndroid Build Coastguard Worker     case MCAF_Code16:
531*9880d681SAndroid Build Coastguard Worker       IsThumb = true;
532*9880d681SAndroid Build Coastguard Worker       return; // Change to Thumb mode
533*9880d681SAndroid Build Coastguard Worker     case MCAF_Code32:
534*9880d681SAndroid Build Coastguard Worker       IsThumb = false;
535*9880d681SAndroid Build Coastguard Worker       return; // Change to ARM mode
536*9880d681SAndroid Build Coastguard Worker     case MCAF_Code64:
537*9880d681SAndroid Build Coastguard Worker       return;
538*9880d681SAndroid Build Coastguard Worker     case MCAF_SubsectionsViaSymbols:
539*9880d681SAndroid Build Coastguard Worker       return;
540*9880d681SAndroid Build Coastguard Worker     }
541*9880d681SAndroid Build Coastguard Worker   }
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker private:
544*9880d681SAndroid Build Coastguard Worker   enum ElfMappingSymbol {
545*9880d681SAndroid Build Coastguard Worker     EMS_None,
546*9880d681SAndroid Build Coastguard Worker     EMS_ARM,
547*9880d681SAndroid Build Coastguard Worker     EMS_Thumb,
548*9880d681SAndroid Build Coastguard Worker     EMS_Data
549*9880d681SAndroid Build Coastguard Worker   };
550*9880d681SAndroid Build Coastguard Worker 
EmitDataMappingSymbol()551*9880d681SAndroid Build Coastguard Worker   void EmitDataMappingSymbol() {
552*9880d681SAndroid Build Coastguard Worker     if (LastEMS == EMS_Data) return;
553*9880d681SAndroid Build Coastguard Worker     EmitMappingSymbol("$d");
554*9880d681SAndroid Build Coastguard Worker     LastEMS = EMS_Data;
555*9880d681SAndroid Build Coastguard Worker   }
556*9880d681SAndroid Build Coastguard Worker 
EmitThumbMappingSymbol()557*9880d681SAndroid Build Coastguard Worker   void EmitThumbMappingSymbol() {
558*9880d681SAndroid Build Coastguard Worker     if (LastEMS == EMS_Thumb) return;
559*9880d681SAndroid Build Coastguard Worker     EmitMappingSymbol("$t");
560*9880d681SAndroid Build Coastguard Worker     LastEMS = EMS_Thumb;
561*9880d681SAndroid Build Coastguard Worker   }
562*9880d681SAndroid Build Coastguard Worker 
EmitARMMappingSymbol()563*9880d681SAndroid Build Coastguard Worker   void EmitARMMappingSymbol() {
564*9880d681SAndroid Build Coastguard Worker     if (LastEMS == EMS_ARM) return;
565*9880d681SAndroid Build Coastguard Worker     EmitMappingSymbol("$a");
566*9880d681SAndroid Build Coastguard Worker     LastEMS = EMS_ARM;
567*9880d681SAndroid Build Coastguard Worker   }
568*9880d681SAndroid Build Coastguard Worker 
EmitMappingSymbol(StringRef Name)569*9880d681SAndroid Build Coastguard Worker   void EmitMappingSymbol(StringRef Name) {
570*9880d681SAndroid Build Coastguard Worker     auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
571*9880d681SAndroid Build Coastguard Worker         Name + "." + Twine(MappingSymbolCounter++)));
572*9880d681SAndroid Build Coastguard Worker     EmitLabel(Symbol);
573*9880d681SAndroid Build Coastguard Worker 
574*9880d681SAndroid Build Coastguard Worker     Symbol->setType(ELF::STT_NOTYPE);
575*9880d681SAndroid Build Coastguard Worker     Symbol->setBinding(ELF::STB_LOCAL);
576*9880d681SAndroid Build Coastguard Worker     Symbol->setExternal(false);
577*9880d681SAndroid Build Coastguard Worker   }
578*9880d681SAndroid Build Coastguard Worker 
EmitThumbFunc(MCSymbol * Func)579*9880d681SAndroid Build Coastguard Worker   void EmitThumbFunc(MCSymbol *Func) override {
580*9880d681SAndroid Build Coastguard Worker     getAssembler().setIsThumbFunc(Func);
581*9880d681SAndroid Build Coastguard Worker     EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction);
582*9880d681SAndroid Build Coastguard Worker   }
583*9880d681SAndroid Build Coastguard Worker 
584*9880d681SAndroid Build Coastguard Worker   // Helper functions for ARM exception handling directives
585*9880d681SAndroid Build Coastguard Worker   void EHReset();
586*9880d681SAndroid Build Coastguard Worker 
587*9880d681SAndroid Build Coastguard Worker   // Reset state between object emissions
588*9880d681SAndroid Build Coastguard Worker   void reset() override;
589*9880d681SAndroid Build Coastguard Worker 
590*9880d681SAndroid Build Coastguard Worker   void EmitPersonalityFixup(StringRef Name);
591*9880d681SAndroid Build Coastguard Worker   void FlushPendingOffset();
592*9880d681SAndroid Build Coastguard Worker   void FlushUnwindOpcodes(bool NoHandlerData);
593*9880d681SAndroid Build Coastguard Worker 
594*9880d681SAndroid Build Coastguard Worker   void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
595*9880d681SAndroid Build Coastguard Worker                          SectionKind Kind, const MCSymbol &Fn);
596*9880d681SAndroid Build Coastguard Worker   void SwitchToExTabSection(const MCSymbol &FnStart);
597*9880d681SAndroid Build Coastguard Worker   void SwitchToExIdxSection(const MCSymbol &FnStart);
598*9880d681SAndroid Build Coastguard Worker 
599*9880d681SAndroid Build Coastguard Worker   void EmitFixup(const MCExpr *Expr, MCFixupKind Kind);
600*9880d681SAndroid Build Coastguard Worker 
601*9880d681SAndroid Build Coastguard Worker   bool IsThumb;
602*9880d681SAndroid Build Coastguard Worker   int64_t MappingSymbolCounter;
603*9880d681SAndroid Build Coastguard Worker 
604*9880d681SAndroid Build Coastguard Worker   DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
605*9880d681SAndroid Build Coastguard Worker   ElfMappingSymbol LastEMS;
606*9880d681SAndroid Build Coastguard Worker 
607*9880d681SAndroid Build Coastguard Worker   // ARM Exception Handling Frame Information
608*9880d681SAndroid Build Coastguard Worker   MCSymbol *ExTab;
609*9880d681SAndroid Build Coastguard Worker   MCSymbol *FnStart;
610*9880d681SAndroid Build Coastguard Worker   const MCSymbol *Personality;
611*9880d681SAndroid Build Coastguard Worker   unsigned PersonalityIndex;
612*9880d681SAndroid Build Coastguard Worker   unsigned FPReg; // Frame pointer register
613*9880d681SAndroid Build Coastguard Worker   int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp)
614*9880d681SAndroid Build Coastguard Worker   int64_t SPOffset; // Offset: (final $sp) - (initial $sp)
615*9880d681SAndroid Build Coastguard Worker   int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp)
616*9880d681SAndroid Build Coastguard Worker   bool UsedFP;
617*9880d681SAndroid Build Coastguard Worker   bool CantUnwind;
618*9880d681SAndroid Build Coastguard Worker   SmallVector<uint8_t, 64> Opcodes;
619*9880d681SAndroid Build Coastguard Worker   UnwindOpcodeAssembler UnwindOpAsm;
620*9880d681SAndroid Build Coastguard Worker };
621*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
622*9880d681SAndroid Build Coastguard Worker 
getStreamer()623*9880d681SAndroid Build Coastguard Worker ARMELFStreamer &ARMTargetELFStreamer::getStreamer() {
624*9880d681SAndroid Build Coastguard Worker   return static_cast<ARMELFStreamer &>(Streamer);
625*9880d681SAndroid Build Coastguard Worker }
626*9880d681SAndroid Build Coastguard Worker 
emitFnStart()627*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); }
emitFnEnd()628*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); }
emitCantUnwind()629*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); }
emitPersonality(const MCSymbol * Personality)630*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
631*9880d681SAndroid Build Coastguard Worker   getStreamer().emitPersonality(Personality);
632*9880d681SAndroid Build Coastguard Worker }
emitPersonalityIndex(unsigned Index)633*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) {
634*9880d681SAndroid Build Coastguard Worker   getStreamer().emitPersonalityIndex(Index);
635*9880d681SAndroid Build Coastguard Worker }
emitHandlerData()636*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitHandlerData() {
637*9880d681SAndroid Build Coastguard Worker   getStreamer().emitHandlerData();
638*9880d681SAndroid Build Coastguard Worker }
emitSetFP(unsigned FpReg,unsigned SpReg,int64_t Offset)639*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
640*9880d681SAndroid Build Coastguard Worker                                      int64_t Offset) {
641*9880d681SAndroid Build Coastguard Worker   getStreamer().emitSetFP(FpReg, SpReg, Offset);
642*9880d681SAndroid Build Coastguard Worker }
emitMovSP(unsigned Reg,int64_t Offset)643*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
644*9880d681SAndroid Build Coastguard Worker   getStreamer().emitMovSP(Reg, Offset);
645*9880d681SAndroid Build Coastguard Worker }
emitPad(int64_t Offset)646*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitPad(int64_t Offset) {
647*9880d681SAndroid Build Coastguard Worker   getStreamer().emitPad(Offset);
648*9880d681SAndroid Build Coastguard Worker }
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool isVector)649*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
650*9880d681SAndroid Build Coastguard Worker                                        bool isVector) {
651*9880d681SAndroid Build Coastguard Worker   getStreamer().emitRegSave(RegList, isVector);
652*9880d681SAndroid Build Coastguard Worker }
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)653*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
654*9880d681SAndroid Build Coastguard Worker                                       const SmallVectorImpl<uint8_t> &Opcodes) {
655*9880d681SAndroid Build Coastguard Worker   getStreamer().emitUnwindRaw(Offset, Opcodes);
656*9880d681SAndroid Build Coastguard Worker }
switchVendor(StringRef Vendor)657*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
658*9880d681SAndroid Build Coastguard Worker   assert(!Vendor.empty() && "Vendor cannot be empty.");
659*9880d681SAndroid Build Coastguard Worker 
660*9880d681SAndroid Build Coastguard Worker   if (CurrentVendor == Vendor)
661*9880d681SAndroid Build Coastguard Worker     return;
662*9880d681SAndroid Build Coastguard Worker 
663*9880d681SAndroid Build Coastguard Worker   if (!CurrentVendor.empty())
664*9880d681SAndroid Build Coastguard Worker     finishAttributeSection();
665*9880d681SAndroid Build Coastguard Worker 
666*9880d681SAndroid Build Coastguard Worker   assert(Contents.empty() &&
667*9880d681SAndroid Build Coastguard Worker          ".ARM.attributes should be flushed before changing vendor");
668*9880d681SAndroid Build Coastguard Worker   CurrentVendor = Vendor;
669*9880d681SAndroid Build Coastguard Worker 
670*9880d681SAndroid Build Coastguard Worker }
emitAttribute(unsigned Attribute,unsigned Value)671*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
672*9880d681SAndroid Build Coastguard Worker   setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
673*9880d681SAndroid Build Coastguard Worker }
emitTextAttribute(unsigned Attribute,StringRef Value)674*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
675*9880d681SAndroid Build Coastguard Worker                                              StringRef Value) {
676*9880d681SAndroid Build Coastguard Worker   setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
677*9880d681SAndroid Build Coastguard Worker }
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)678*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
679*9880d681SAndroid Build Coastguard Worker                                                 unsigned IntValue,
680*9880d681SAndroid Build Coastguard Worker                                                 StringRef StringValue) {
681*9880d681SAndroid Build Coastguard Worker   setAttributeItems(Attribute, IntValue, StringValue,
682*9880d681SAndroid Build Coastguard Worker                     /* OverwriteExisting= */ true);
683*9880d681SAndroid Build Coastguard Worker }
emitArch(unsigned Value)684*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitArch(unsigned Value) {
685*9880d681SAndroid Build Coastguard Worker   Arch = Value;
686*9880d681SAndroid Build Coastguard Worker }
emitObjectArch(unsigned Value)687*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitObjectArch(unsigned Value) {
688*9880d681SAndroid Build Coastguard Worker   EmittedArch = Value;
689*9880d681SAndroid Build Coastguard Worker }
emitArchDefaultAttributes()690*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitArchDefaultAttributes() {
691*9880d681SAndroid Build Coastguard Worker   using namespace ARMBuildAttrs;
692*9880d681SAndroid Build Coastguard Worker 
693*9880d681SAndroid Build Coastguard Worker   setAttributeItem(CPU_name,
694*9880d681SAndroid Build Coastguard Worker                    ARM::getCPUAttr(Arch),
695*9880d681SAndroid Build Coastguard Worker                    false);
696*9880d681SAndroid Build Coastguard Worker 
697*9880d681SAndroid Build Coastguard Worker   if (EmittedArch == ARM::AK_INVALID)
698*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch,
699*9880d681SAndroid Build Coastguard Worker                      ARM::getArchAttr(Arch),
700*9880d681SAndroid Build Coastguard Worker                      false);
701*9880d681SAndroid Build Coastguard Worker   else
702*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch,
703*9880d681SAndroid Build Coastguard Worker                      ARM::getArchAttr(EmittedArch),
704*9880d681SAndroid Build Coastguard Worker                      false);
705*9880d681SAndroid Build Coastguard Worker 
706*9880d681SAndroid Build Coastguard Worker   switch (Arch) {
707*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV2:
708*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV2A:
709*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV3:
710*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV3M:
711*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV4:
712*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
713*9880d681SAndroid Build Coastguard Worker     break;
714*9880d681SAndroid Build Coastguard Worker 
715*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV4T:
716*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV5T:
717*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV5TE:
718*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV6:
719*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
720*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, Allowed, false);
721*9880d681SAndroid Build Coastguard Worker     break;
722*9880d681SAndroid Build Coastguard Worker 
723*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV6T2:
724*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
725*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
726*9880d681SAndroid Build Coastguard Worker     break;
727*9880d681SAndroid Build Coastguard Worker 
728*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV6K:
729*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV6KZ:
730*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
731*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, Allowed, false);
732*9880d681SAndroid Build Coastguard Worker     setAttributeItem(Virtualization_use, AllowTZ, false);
733*9880d681SAndroid Build Coastguard Worker     break;
734*9880d681SAndroid Build Coastguard Worker 
735*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV6M:
736*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, Allowed, false);
737*9880d681SAndroid Build Coastguard Worker     break;
738*9880d681SAndroid Build Coastguard Worker 
739*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV7A:
740*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
741*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
742*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
743*9880d681SAndroid Build Coastguard Worker     break;
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV7R:
746*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
747*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
748*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
749*9880d681SAndroid Build Coastguard Worker     break;
750*9880d681SAndroid Build Coastguard Worker 
751*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV7M:
752*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
753*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
754*9880d681SAndroid Build Coastguard Worker     break;
755*9880d681SAndroid Build Coastguard Worker 
756*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV8A:
757*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV8_1A:
758*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV8_2A:
759*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
760*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
761*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
762*9880d681SAndroid Build Coastguard Worker     setAttributeItem(MPextension_use, Allowed, false);
763*9880d681SAndroid Build Coastguard Worker     setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
764*9880d681SAndroid Build Coastguard Worker     break;
765*9880d681SAndroid Build Coastguard Worker 
766*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV8MBaseline:
767*9880d681SAndroid Build Coastguard Worker   case ARM::AK_ARMV8MMainline:
768*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
769*9880d681SAndroid Build Coastguard Worker     setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
770*9880d681SAndroid Build Coastguard Worker     break;
771*9880d681SAndroid Build Coastguard Worker 
772*9880d681SAndroid Build Coastguard Worker   case ARM::AK_IWMMXT:
773*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
774*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, Allowed, false);
775*9880d681SAndroid Build Coastguard Worker     setAttributeItem(WMMX_arch, AllowWMMXv1, false);
776*9880d681SAndroid Build Coastguard Worker     break;
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker   case ARM::AK_IWMMXT2:
779*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARM_ISA_use, Allowed, false);
780*9880d681SAndroid Build Coastguard Worker     setAttributeItem(THUMB_ISA_use, Allowed, false);
781*9880d681SAndroid Build Coastguard Worker     setAttributeItem(WMMX_arch, AllowWMMXv2, false);
782*9880d681SAndroid Build Coastguard Worker     break;
783*9880d681SAndroid Build Coastguard Worker 
784*9880d681SAndroid Build Coastguard Worker   default:
785*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Unknown Arch: " + Twine(Arch));
786*9880d681SAndroid Build Coastguard Worker     break;
787*9880d681SAndroid Build Coastguard Worker   }
788*9880d681SAndroid Build Coastguard Worker }
emitFPU(unsigned Value)789*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitFPU(unsigned Value) {
790*9880d681SAndroid Build Coastguard Worker   FPU = Value;
791*9880d681SAndroid Build Coastguard Worker }
emitFPUDefaultAttributes()792*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
793*9880d681SAndroid Build Coastguard Worker   switch (FPU) {
794*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFP:
795*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV2:
796*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
797*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv2,
798*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
799*9880d681SAndroid Build Coastguard Worker     break;
800*9880d681SAndroid Build Coastguard Worker 
801*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3:
802*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
803*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3A,
804*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
805*9880d681SAndroid Build Coastguard Worker     break;
806*9880d681SAndroid Build Coastguard Worker 
807*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3_FP16:
808*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
809*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3A,
810*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
811*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_HP_extension,
812*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowHPFP,
813*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
814*9880d681SAndroid Build Coastguard Worker     break;
815*9880d681SAndroid Build Coastguard Worker 
816*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3_D16:
817*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
818*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3B,
819*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
820*9880d681SAndroid Build Coastguard Worker     break;
821*9880d681SAndroid Build Coastguard Worker 
822*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3_D16_FP16:
823*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
824*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3B,
825*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
826*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_HP_extension,
827*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowHPFP,
828*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
829*9880d681SAndroid Build Coastguard Worker     break;
830*9880d681SAndroid Build Coastguard Worker 
831*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3XD:
832*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
833*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3B,
834*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
835*9880d681SAndroid Build Coastguard Worker     break;
836*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV3XD_FP16:
837*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
838*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3B,
839*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
840*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_HP_extension,
841*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowHPFP,
842*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
843*9880d681SAndroid Build Coastguard Worker     break;
844*9880d681SAndroid Build Coastguard Worker 
845*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV4:
846*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
847*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv4A,
848*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
849*9880d681SAndroid Build Coastguard Worker     break;
850*9880d681SAndroid Build Coastguard Worker 
851*9880d681SAndroid Build Coastguard Worker   // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same
852*9880d681SAndroid Build Coastguard Worker   // as _D16 here.
853*9880d681SAndroid Build Coastguard Worker   case ARM::FK_FPV4_SP_D16:
854*9880d681SAndroid Build Coastguard Worker   case ARM::FK_VFPV4_D16:
855*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
856*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv4B,
857*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
858*9880d681SAndroid Build Coastguard Worker     break;
859*9880d681SAndroid Build Coastguard Worker 
860*9880d681SAndroid Build Coastguard Worker   case ARM::FK_FP_ARMV8:
861*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
862*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPARMv8A,
863*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
864*9880d681SAndroid Build Coastguard Worker     break;
865*9880d681SAndroid Build Coastguard Worker 
866*9880d681SAndroid Build Coastguard Worker   // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so
867*9880d681SAndroid Build Coastguard Worker   // uses the FP_ARMV8_D16 build attribute.
868*9880d681SAndroid Build Coastguard Worker   case ARM::FK_FPV5_SP_D16:
869*9880d681SAndroid Build Coastguard Worker   case ARM::FK_FPV5_D16:
870*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
871*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPARMv8B,
872*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
873*9880d681SAndroid Build Coastguard Worker     break;
874*9880d681SAndroid Build Coastguard Worker 
875*9880d681SAndroid Build Coastguard Worker   case ARM::FK_NEON:
876*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
877*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3A,
878*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
879*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
880*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowNeon,
881*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
882*9880d681SAndroid Build Coastguard Worker     break;
883*9880d681SAndroid Build Coastguard Worker 
884*9880d681SAndroid Build Coastguard Worker   case ARM::FK_NEON_FP16:
885*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
886*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv3A,
887*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
888*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
889*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowNeon,
890*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
891*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_HP_extension,
892*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowHPFP,
893*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
894*9880d681SAndroid Build Coastguard Worker     break;
895*9880d681SAndroid Build Coastguard Worker 
896*9880d681SAndroid Build Coastguard Worker   case ARM::FK_NEON_VFPV4:
897*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
898*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPv4A,
899*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
900*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
901*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowNeon2,
902*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
903*9880d681SAndroid Build Coastguard Worker     break;
904*9880d681SAndroid Build Coastguard Worker 
905*9880d681SAndroid Build Coastguard Worker   case ARM::FK_NEON_FP_ARMV8:
906*9880d681SAndroid Build Coastguard Worker   case ARM::FK_CRYPTO_NEON_FP_ARMV8:
907*9880d681SAndroid Build Coastguard Worker     setAttributeItem(ARMBuildAttrs::FP_arch,
908*9880d681SAndroid Build Coastguard Worker                      ARMBuildAttrs::AllowFPARMv8A,
909*9880d681SAndroid Build Coastguard Worker                      /* OverwriteExisting= */ false);
910*9880d681SAndroid Build Coastguard Worker     // 'Advanced_SIMD_arch' must be emitted not here, but within
911*9880d681SAndroid Build Coastguard Worker     // ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a()
912*9880d681SAndroid Build Coastguard Worker     break;
913*9880d681SAndroid Build Coastguard Worker 
914*9880d681SAndroid Build Coastguard Worker   case ARM::FK_SOFTVFP:
915*9880d681SAndroid Build Coastguard Worker   case ARM::FK_NONE:
916*9880d681SAndroid Build Coastguard Worker     break;
917*9880d681SAndroid Build Coastguard Worker 
918*9880d681SAndroid Build Coastguard Worker   default:
919*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Unknown FPU: " + Twine(FPU));
920*9880d681SAndroid Build Coastguard Worker     break;
921*9880d681SAndroid Build Coastguard Worker   }
922*9880d681SAndroid Build Coastguard Worker }
calculateContentSize() const923*9880d681SAndroid Build Coastguard Worker size_t ARMTargetELFStreamer::calculateContentSize() const {
924*9880d681SAndroid Build Coastguard Worker   size_t Result = 0;
925*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < Contents.size(); ++i) {
926*9880d681SAndroid Build Coastguard Worker     AttributeItem item = Contents[i];
927*9880d681SAndroid Build Coastguard Worker     switch (item.Type) {
928*9880d681SAndroid Build Coastguard Worker     case AttributeItem::HiddenAttribute:
929*9880d681SAndroid Build Coastguard Worker       break;
930*9880d681SAndroid Build Coastguard Worker     case AttributeItem::NumericAttribute:
931*9880d681SAndroid Build Coastguard Worker       Result += getULEB128Size(item.Tag);
932*9880d681SAndroid Build Coastguard Worker       Result += getULEB128Size(item.IntValue);
933*9880d681SAndroid Build Coastguard Worker       break;
934*9880d681SAndroid Build Coastguard Worker     case AttributeItem::TextAttribute:
935*9880d681SAndroid Build Coastguard Worker       Result += getULEB128Size(item.Tag);
936*9880d681SAndroid Build Coastguard Worker       Result += item.StringValue.size() + 1; // string + '\0'
937*9880d681SAndroid Build Coastguard Worker       break;
938*9880d681SAndroid Build Coastguard Worker     case AttributeItem::NumericAndTextAttributes:
939*9880d681SAndroid Build Coastguard Worker       Result += getULEB128Size(item.Tag);
940*9880d681SAndroid Build Coastguard Worker       Result += getULEB128Size(item.IntValue);
941*9880d681SAndroid Build Coastguard Worker       Result += item.StringValue.size() + 1; // string + '\0';
942*9880d681SAndroid Build Coastguard Worker       break;
943*9880d681SAndroid Build Coastguard Worker     }
944*9880d681SAndroid Build Coastguard Worker   }
945*9880d681SAndroid Build Coastguard Worker   return Result;
946*9880d681SAndroid Build Coastguard Worker }
finishAttributeSection()947*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::finishAttributeSection() {
948*9880d681SAndroid Build Coastguard Worker   // <format-version>
949*9880d681SAndroid Build Coastguard Worker   // [ <section-length> "vendor-name"
950*9880d681SAndroid Build Coastguard Worker   // [ <file-tag> <size> <attribute>*
951*9880d681SAndroid Build Coastguard Worker   //   | <section-tag> <size> <section-number>* 0 <attribute>*
952*9880d681SAndroid Build Coastguard Worker   //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
953*9880d681SAndroid Build Coastguard Worker   //   ]+
954*9880d681SAndroid Build Coastguard Worker   // ]*
955*9880d681SAndroid Build Coastguard Worker 
956*9880d681SAndroid Build Coastguard Worker   if (FPU != ARM::FK_INVALID)
957*9880d681SAndroid Build Coastguard Worker     emitFPUDefaultAttributes();
958*9880d681SAndroid Build Coastguard Worker 
959*9880d681SAndroid Build Coastguard Worker   if (Arch != ARM::AK_INVALID)
960*9880d681SAndroid Build Coastguard Worker     emitArchDefaultAttributes();
961*9880d681SAndroid Build Coastguard Worker 
962*9880d681SAndroid Build Coastguard Worker   if (Contents.empty())
963*9880d681SAndroid Build Coastguard Worker     return;
964*9880d681SAndroid Build Coastguard Worker 
965*9880d681SAndroid Build Coastguard Worker   std::sort(Contents.begin(), Contents.end(), AttributeItem::LessTag);
966*9880d681SAndroid Build Coastguard Worker 
967*9880d681SAndroid Build Coastguard Worker   ARMELFStreamer &Streamer = getStreamer();
968*9880d681SAndroid Build Coastguard Worker 
969*9880d681SAndroid Build Coastguard Worker   // Switch to .ARM.attributes section
970*9880d681SAndroid Build Coastguard Worker   if (AttributeSection) {
971*9880d681SAndroid Build Coastguard Worker     Streamer.SwitchSection(AttributeSection);
972*9880d681SAndroid Build Coastguard Worker   } else {
973*9880d681SAndroid Build Coastguard Worker     AttributeSection = Streamer.getContext().getELFSection(
974*9880d681SAndroid Build Coastguard Worker         ".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, 0);
975*9880d681SAndroid Build Coastguard Worker     Streamer.SwitchSection(AttributeSection);
976*9880d681SAndroid Build Coastguard Worker 
977*9880d681SAndroid Build Coastguard Worker     // Format version
978*9880d681SAndroid Build Coastguard Worker     Streamer.EmitIntValue(0x41, 1);
979*9880d681SAndroid Build Coastguard Worker   }
980*9880d681SAndroid Build Coastguard Worker 
981*9880d681SAndroid Build Coastguard Worker   // Vendor size + Vendor name + '\0'
982*9880d681SAndroid Build Coastguard Worker   const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
983*9880d681SAndroid Build Coastguard Worker 
984*9880d681SAndroid Build Coastguard Worker   // Tag + Tag Size
985*9880d681SAndroid Build Coastguard Worker   const size_t TagHeaderSize = 1 + 4;
986*9880d681SAndroid Build Coastguard Worker 
987*9880d681SAndroid Build Coastguard Worker   const size_t ContentsSize = calculateContentSize();
988*9880d681SAndroid Build Coastguard Worker 
989*9880d681SAndroid Build Coastguard Worker   Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
990*9880d681SAndroid Build Coastguard Worker   Streamer.EmitBytes(CurrentVendor);
991*9880d681SAndroid Build Coastguard Worker   Streamer.EmitIntValue(0, 1); // '\0'
992*9880d681SAndroid Build Coastguard Worker 
993*9880d681SAndroid Build Coastguard Worker   Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
994*9880d681SAndroid Build Coastguard Worker   Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
995*9880d681SAndroid Build Coastguard Worker 
996*9880d681SAndroid Build Coastguard Worker   // Size should have been accounted for already, now
997*9880d681SAndroid Build Coastguard Worker   // emit each field as its type (ULEB or String)
998*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < Contents.size(); ++i) {
999*9880d681SAndroid Build Coastguard Worker     AttributeItem item = Contents[i];
1000*9880d681SAndroid Build Coastguard Worker     Streamer.EmitULEB128IntValue(item.Tag);
1001*9880d681SAndroid Build Coastguard Worker     switch (item.Type) {
1002*9880d681SAndroid Build Coastguard Worker     default: llvm_unreachable("Invalid attribute type");
1003*9880d681SAndroid Build Coastguard Worker     case AttributeItem::NumericAttribute:
1004*9880d681SAndroid Build Coastguard Worker       Streamer.EmitULEB128IntValue(item.IntValue);
1005*9880d681SAndroid Build Coastguard Worker       break;
1006*9880d681SAndroid Build Coastguard Worker     case AttributeItem::TextAttribute:
1007*9880d681SAndroid Build Coastguard Worker       Streamer.EmitBytes(item.StringValue);
1008*9880d681SAndroid Build Coastguard Worker       Streamer.EmitIntValue(0, 1); // '\0'
1009*9880d681SAndroid Build Coastguard Worker       break;
1010*9880d681SAndroid Build Coastguard Worker     case AttributeItem::NumericAndTextAttributes:
1011*9880d681SAndroid Build Coastguard Worker       Streamer.EmitULEB128IntValue(item.IntValue);
1012*9880d681SAndroid Build Coastguard Worker       Streamer.EmitBytes(item.StringValue);
1013*9880d681SAndroid Build Coastguard Worker       Streamer.EmitIntValue(0, 1); // '\0'
1014*9880d681SAndroid Build Coastguard Worker       break;
1015*9880d681SAndroid Build Coastguard Worker     }
1016*9880d681SAndroid Build Coastguard Worker   }
1017*9880d681SAndroid Build Coastguard Worker 
1018*9880d681SAndroid Build Coastguard Worker   Contents.clear();
1019*9880d681SAndroid Build Coastguard Worker   FPU = ARM::FK_INVALID;
1020*9880d681SAndroid Build Coastguard Worker }
1021*9880d681SAndroid Build Coastguard Worker 
emitLabel(MCSymbol * Symbol)1022*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) {
1023*9880d681SAndroid Build Coastguard Worker   ARMELFStreamer &Streamer = getStreamer();
1024*9880d681SAndroid Build Coastguard Worker   if (!Streamer.IsThumb)
1025*9880d681SAndroid Build Coastguard Worker     return;
1026*9880d681SAndroid Build Coastguard Worker 
1027*9880d681SAndroid Build Coastguard Worker   Streamer.getAssembler().registerSymbol(*Symbol);
1028*9880d681SAndroid Build Coastguard Worker   unsigned Type = cast<MCSymbolELF>(Symbol)->getType();
1029*9880d681SAndroid Build Coastguard Worker   if (Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC)
1030*9880d681SAndroid Build Coastguard Worker     Streamer.EmitThumbFunc(Symbol);
1031*9880d681SAndroid Build Coastguard Worker }
1032*9880d681SAndroid Build Coastguard Worker 
1033*9880d681SAndroid Build Coastguard Worker void
AnnotateTLSDescriptorSequence(const MCSymbolRefExpr * S)1034*9880d681SAndroid Build Coastguard Worker ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
1035*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitFixup(S, FK_Data_4);
1036*9880d681SAndroid Build Coastguard Worker }
1037*9880d681SAndroid Build Coastguard Worker 
emitThumbSet(MCSymbol * Symbol,const MCExpr * Value)1038*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {
1039*9880d681SAndroid Build Coastguard Worker   if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Value)) {
1040*9880d681SAndroid Build Coastguard Worker     const MCSymbol &Sym = SRE->getSymbol();
1041*9880d681SAndroid Build Coastguard Worker     if (!Sym.isDefined()) {
1042*9880d681SAndroid Build Coastguard Worker       getStreamer().EmitAssignment(Symbol, Value);
1043*9880d681SAndroid Build Coastguard Worker       return;
1044*9880d681SAndroid Build Coastguard Worker     }
1045*9880d681SAndroid Build Coastguard Worker   }
1046*9880d681SAndroid Build Coastguard Worker 
1047*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitThumbFunc(Symbol);
1048*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitAssignment(Symbol, Value);
1049*9880d681SAndroid Build Coastguard Worker }
1050*9880d681SAndroid Build Coastguard Worker 
emitInst(uint32_t Inst,char Suffix)1051*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
1052*9880d681SAndroid Build Coastguard Worker   getStreamer().emitInst(Inst, Suffix);
1053*9880d681SAndroid Build Coastguard Worker }
1054*9880d681SAndroid Build Coastguard Worker 
reset()1055*9880d681SAndroid Build Coastguard Worker void ARMTargetELFStreamer::reset() { AttributeSection = nullptr; }
1056*9880d681SAndroid Build Coastguard Worker 
FinishImpl()1057*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::FinishImpl() {
1058*9880d681SAndroid Build Coastguard Worker   MCTargetStreamer &TS = *getTargetStreamer();
1059*9880d681SAndroid Build Coastguard Worker   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1060*9880d681SAndroid Build Coastguard Worker   ATS.finishAttributeSection();
1061*9880d681SAndroid Build Coastguard Worker 
1062*9880d681SAndroid Build Coastguard Worker   MCELFStreamer::FinishImpl();
1063*9880d681SAndroid Build Coastguard Worker }
1064*9880d681SAndroid Build Coastguard Worker 
reset()1065*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::reset() {
1066*9880d681SAndroid Build Coastguard Worker   MCTargetStreamer &TS = *getTargetStreamer();
1067*9880d681SAndroid Build Coastguard Worker   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1068*9880d681SAndroid Build Coastguard Worker   ATS.reset();
1069*9880d681SAndroid Build Coastguard Worker   MappingSymbolCounter = 0;
1070*9880d681SAndroid Build Coastguard Worker   MCELFStreamer::reset();
1071*9880d681SAndroid Build Coastguard Worker   // MCELFStreamer clear's the assembler's e_flags. However, for
1072*9880d681SAndroid Build Coastguard Worker   // arm we manually set the ABI version on streamer creation, so
1073*9880d681SAndroid Build Coastguard Worker   // do the same here
1074*9880d681SAndroid Build Coastguard Worker   getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5);
1075*9880d681SAndroid Build Coastguard Worker }
1076*9880d681SAndroid Build Coastguard Worker 
SwitchToEHSection(const char * Prefix,unsigned Type,unsigned Flags,SectionKind Kind,const MCSymbol & Fn)1077*9880d681SAndroid Build Coastguard Worker inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
1078*9880d681SAndroid Build Coastguard Worker                                               unsigned Type,
1079*9880d681SAndroid Build Coastguard Worker                                               unsigned Flags,
1080*9880d681SAndroid Build Coastguard Worker                                               SectionKind Kind,
1081*9880d681SAndroid Build Coastguard Worker                                               const MCSymbol &Fn) {
1082*9880d681SAndroid Build Coastguard Worker   const MCSectionELF &FnSection =
1083*9880d681SAndroid Build Coastguard Worker     static_cast<const MCSectionELF &>(Fn.getSection());
1084*9880d681SAndroid Build Coastguard Worker 
1085*9880d681SAndroid Build Coastguard Worker   // Create the name for new section
1086*9880d681SAndroid Build Coastguard Worker   StringRef FnSecName(FnSection.getSectionName());
1087*9880d681SAndroid Build Coastguard Worker   SmallString<128> EHSecName(Prefix);
1088*9880d681SAndroid Build Coastguard Worker   if (FnSecName != ".text") {
1089*9880d681SAndroid Build Coastguard Worker     EHSecName += FnSecName;
1090*9880d681SAndroid Build Coastguard Worker   }
1091*9880d681SAndroid Build Coastguard Worker 
1092*9880d681SAndroid Build Coastguard Worker   // Get .ARM.extab or .ARM.exidx section
1093*9880d681SAndroid Build Coastguard Worker   const MCSymbolELF *Group = FnSection.getGroup();
1094*9880d681SAndroid Build Coastguard Worker   if (Group)
1095*9880d681SAndroid Build Coastguard Worker     Flags |= ELF::SHF_GROUP;
1096*9880d681SAndroid Build Coastguard Worker   MCSectionELF *EHSection =
1097*9880d681SAndroid Build Coastguard Worker       getContext().getELFSection(EHSecName, Type, Flags, 0, Group,
1098*9880d681SAndroid Build Coastguard Worker                                  FnSection.getUniqueID(), nullptr, &FnSection);
1099*9880d681SAndroid Build Coastguard Worker 
1100*9880d681SAndroid Build Coastguard Worker   assert(EHSection && "Failed to get the required EH section");
1101*9880d681SAndroid Build Coastguard Worker 
1102*9880d681SAndroid Build Coastguard Worker   // Switch to .ARM.extab or .ARM.exidx section
1103*9880d681SAndroid Build Coastguard Worker   SwitchSection(EHSection);
1104*9880d681SAndroid Build Coastguard Worker   EmitCodeAlignment(4);
1105*9880d681SAndroid Build Coastguard Worker }
1106*9880d681SAndroid Build Coastguard Worker 
SwitchToExTabSection(const MCSymbol & FnStart)1107*9880d681SAndroid Build Coastguard Worker inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
1108*9880d681SAndroid Build Coastguard Worker   SwitchToEHSection(".ARM.extab", ELF::SHT_PROGBITS, ELF::SHF_ALLOC,
1109*9880d681SAndroid Build Coastguard Worker                     SectionKind::getData(), FnStart);
1110*9880d681SAndroid Build Coastguard Worker }
1111*9880d681SAndroid Build Coastguard Worker 
SwitchToExIdxSection(const MCSymbol & FnStart)1112*9880d681SAndroid Build Coastguard Worker inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
1113*9880d681SAndroid Build Coastguard Worker   SwitchToEHSection(".ARM.exidx", ELF::SHT_ARM_EXIDX,
1114*9880d681SAndroid Build Coastguard Worker                     ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
1115*9880d681SAndroid Build Coastguard Worker                     SectionKind::getData(), FnStart);
1116*9880d681SAndroid Build Coastguard Worker }
EmitFixup(const MCExpr * Expr,MCFixupKind Kind)1117*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) {
1118*9880d681SAndroid Build Coastguard Worker   MCDataFragment *Frag = getOrCreateDataFragment();
1119*9880d681SAndroid Build Coastguard Worker   Frag->getFixups().push_back(MCFixup::create(Frag->getContents().size(), Expr,
1120*9880d681SAndroid Build Coastguard Worker                                               Kind));
1121*9880d681SAndroid Build Coastguard Worker }
1122*9880d681SAndroid Build Coastguard Worker 
EHReset()1123*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::EHReset() {
1124*9880d681SAndroid Build Coastguard Worker   ExTab = nullptr;
1125*9880d681SAndroid Build Coastguard Worker   FnStart = nullptr;
1126*9880d681SAndroid Build Coastguard Worker   Personality = nullptr;
1127*9880d681SAndroid Build Coastguard Worker   PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX;
1128*9880d681SAndroid Build Coastguard Worker   FPReg = ARM::SP;
1129*9880d681SAndroid Build Coastguard Worker   FPOffset = 0;
1130*9880d681SAndroid Build Coastguard Worker   SPOffset = 0;
1131*9880d681SAndroid Build Coastguard Worker   PendingOffset = 0;
1132*9880d681SAndroid Build Coastguard Worker   UsedFP = false;
1133*9880d681SAndroid Build Coastguard Worker   CantUnwind = false;
1134*9880d681SAndroid Build Coastguard Worker 
1135*9880d681SAndroid Build Coastguard Worker   Opcodes.clear();
1136*9880d681SAndroid Build Coastguard Worker   UnwindOpAsm.Reset();
1137*9880d681SAndroid Build Coastguard Worker }
1138*9880d681SAndroid Build Coastguard Worker 
emitFnStart()1139*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitFnStart() {
1140*9880d681SAndroid Build Coastguard Worker   assert(FnStart == nullptr);
1141*9880d681SAndroid Build Coastguard Worker   FnStart = getContext().createTempSymbol();
1142*9880d681SAndroid Build Coastguard Worker   EmitLabel(FnStart);
1143*9880d681SAndroid Build Coastguard Worker }
1144*9880d681SAndroid Build Coastguard Worker 
emitFnEnd()1145*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitFnEnd() {
1146*9880d681SAndroid Build Coastguard Worker   assert(FnStart && ".fnstart must precedes .fnend");
1147*9880d681SAndroid Build Coastguard Worker 
1148*9880d681SAndroid Build Coastguard Worker   // Emit unwind opcodes if there is no .handlerdata directive
1149*9880d681SAndroid Build Coastguard Worker   if (!ExTab && !CantUnwind)
1150*9880d681SAndroid Build Coastguard Worker     FlushUnwindOpcodes(true);
1151*9880d681SAndroid Build Coastguard Worker 
1152*9880d681SAndroid Build Coastguard Worker   // Emit the exception index table entry
1153*9880d681SAndroid Build Coastguard Worker   SwitchToExIdxSection(*FnStart);
1154*9880d681SAndroid Build Coastguard Worker 
1155*9880d681SAndroid Build Coastguard Worker   if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX)
1156*9880d681SAndroid Build Coastguard Worker     EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
1157*9880d681SAndroid Build Coastguard Worker 
1158*9880d681SAndroid Build Coastguard Worker   const MCSymbolRefExpr *FnStartRef =
1159*9880d681SAndroid Build Coastguard Worker     MCSymbolRefExpr::create(FnStart,
1160*9880d681SAndroid Build Coastguard Worker                             MCSymbolRefExpr::VK_ARM_PREL31,
1161*9880d681SAndroid Build Coastguard Worker                             getContext());
1162*9880d681SAndroid Build Coastguard Worker 
1163*9880d681SAndroid Build Coastguard Worker   EmitValue(FnStartRef, 4);
1164*9880d681SAndroid Build Coastguard Worker 
1165*9880d681SAndroid Build Coastguard Worker   if (CantUnwind) {
1166*9880d681SAndroid Build Coastguard Worker     EmitIntValue(ARM::EHABI::EXIDX_CANTUNWIND, 4);
1167*9880d681SAndroid Build Coastguard Worker   } else if (ExTab) {
1168*9880d681SAndroid Build Coastguard Worker     // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
1169*9880d681SAndroid Build Coastguard Worker     const MCSymbolRefExpr *ExTabEntryRef =
1170*9880d681SAndroid Build Coastguard Worker       MCSymbolRefExpr::create(ExTab,
1171*9880d681SAndroid Build Coastguard Worker                               MCSymbolRefExpr::VK_ARM_PREL31,
1172*9880d681SAndroid Build Coastguard Worker                               getContext());
1173*9880d681SAndroid Build Coastguard Worker     EmitValue(ExTabEntryRef, 4);
1174*9880d681SAndroid Build Coastguard Worker   } else {
1175*9880d681SAndroid Build Coastguard Worker     // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
1176*9880d681SAndroid Build Coastguard Worker     // the second word of exception index table entry.  The size of the unwind
1177*9880d681SAndroid Build Coastguard Worker     // opcodes should always be 4 bytes.
1178*9880d681SAndroid Build Coastguard Worker     assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 &&
1179*9880d681SAndroid Build Coastguard Worker            "Compact model must use __aeabi_unwind_cpp_pr0 as personality");
1180*9880d681SAndroid Build Coastguard Worker     assert(Opcodes.size() == 4u &&
1181*9880d681SAndroid Build Coastguard Worker            "Unwind opcode size for __aeabi_unwind_cpp_pr0 must be equal to 4");
1182*9880d681SAndroid Build Coastguard Worker     uint64_t Intval = Opcodes[0] |
1183*9880d681SAndroid Build Coastguard Worker                       Opcodes[1] << 8 |
1184*9880d681SAndroid Build Coastguard Worker                       Opcodes[2] << 16 |
1185*9880d681SAndroid Build Coastguard Worker                       Opcodes[3] << 24;
1186*9880d681SAndroid Build Coastguard Worker     EmitIntValue(Intval, Opcodes.size());
1187*9880d681SAndroid Build Coastguard Worker   }
1188*9880d681SAndroid Build Coastguard Worker 
1189*9880d681SAndroid Build Coastguard Worker   // Switch to the section containing FnStart
1190*9880d681SAndroid Build Coastguard Worker   SwitchSection(&FnStart->getSection());
1191*9880d681SAndroid Build Coastguard Worker 
1192*9880d681SAndroid Build Coastguard Worker   // Clean exception handling frame information
1193*9880d681SAndroid Build Coastguard Worker   EHReset();
1194*9880d681SAndroid Build Coastguard Worker }
1195*9880d681SAndroid Build Coastguard Worker 
emitCantUnwind()1196*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; }
1197*9880d681SAndroid Build Coastguard Worker 
1198*9880d681SAndroid Build Coastguard Worker // Add the R_ARM_NONE fixup at the same position
EmitPersonalityFixup(StringRef Name)1199*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
1200*9880d681SAndroid Build Coastguard Worker   const MCSymbol *PersonalitySym = getContext().getOrCreateSymbol(Name);
1201*9880d681SAndroid Build Coastguard Worker 
1202*9880d681SAndroid Build Coastguard Worker   const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::create(
1203*9880d681SAndroid Build Coastguard Worker       PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext());
1204*9880d681SAndroid Build Coastguard Worker 
1205*9880d681SAndroid Build Coastguard Worker   visitUsedExpr(*PersonalityRef);
1206*9880d681SAndroid Build Coastguard Worker   MCDataFragment *DF = getOrCreateDataFragment();
1207*9880d681SAndroid Build Coastguard Worker   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
1208*9880d681SAndroid Build Coastguard Worker                                             PersonalityRef,
1209*9880d681SAndroid Build Coastguard Worker                                             MCFixup::getKindForSize(4, false)));
1210*9880d681SAndroid Build Coastguard Worker }
1211*9880d681SAndroid Build Coastguard Worker 
FlushPendingOffset()1212*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::FlushPendingOffset() {
1213*9880d681SAndroid Build Coastguard Worker   if (PendingOffset != 0) {
1214*9880d681SAndroid Build Coastguard Worker     UnwindOpAsm.EmitSPOffset(-PendingOffset);
1215*9880d681SAndroid Build Coastguard Worker     PendingOffset = 0;
1216*9880d681SAndroid Build Coastguard Worker   }
1217*9880d681SAndroid Build Coastguard Worker }
1218*9880d681SAndroid Build Coastguard Worker 
FlushUnwindOpcodes(bool NoHandlerData)1219*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
1220*9880d681SAndroid Build Coastguard Worker   // Emit the unwind opcode to restore $sp.
1221*9880d681SAndroid Build Coastguard Worker   if (UsedFP) {
1222*9880d681SAndroid Build Coastguard Worker     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1223*9880d681SAndroid Build Coastguard Worker     int64_t LastRegSaveSPOffset = SPOffset - PendingOffset;
1224*9880d681SAndroid Build Coastguard Worker     UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset);
1225*9880d681SAndroid Build Coastguard Worker     UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
1226*9880d681SAndroid Build Coastguard Worker   } else {
1227*9880d681SAndroid Build Coastguard Worker     FlushPendingOffset();
1228*9880d681SAndroid Build Coastguard Worker   }
1229*9880d681SAndroid Build Coastguard Worker 
1230*9880d681SAndroid Build Coastguard Worker   // Finalize the unwind opcode sequence
1231*9880d681SAndroid Build Coastguard Worker   UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
1232*9880d681SAndroid Build Coastguard Worker 
1233*9880d681SAndroid Build Coastguard Worker   // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
1234*9880d681SAndroid Build Coastguard Worker   // section.  Thus, we don't have to create an entry in the .ARM.extab
1235*9880d681SAndroid Build Coastguard Worker   // section.
1236*9880d681SAndroid Build Coastguard Worker   if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0)
1237*9880d681SAndroid Build Coastguard Worker     return;
1238*9880d681SAndroid Build Coastguard Worker 
1239*9880d681SAndroid Build Coastguard Worker   // Switch to .ARM.extab section.
1240*9880d681SAndroid Build Coastguard Worker   SwitchToExTabSection(*FnStart);
1241*9880d681SAndroid Build Coastguard Worker 
1242*9880d681SAndroid Build Coastguard Worker   // Create .ARM.extab label for offset in .ARM.exidx
1243*9880d681SAndroid Build Coastguard Worker   assert(!ExTab);
1244*9880d681SAndroid Build Coastguard Worker   ExTab = getContext().createTempSymbol();
1245*9880d681SAndroid Build Coastguard Worker   EmitLabel(ExTab);
1246*9880d681SAndroid Build Coastguard Worker 
1247*9880d681SAndroid Build Coastguard Worker   // Emit personality
1248*9880d681SAndroid Build Coastguard Worker   if (Personality) {
1249*9880d681SAndroid Build Coastguard Worker     const MCSymbolRefExpr *PersonalityRef =
1250*9880d681SAndroid Build Coastguard Worker       MCSymbolRefExpr::create(Personality,
1251*9880d681SAndroid Build Coastguard Worker                               MCSymbolRefExpr::VK_ARM_PREL31,
1252*9880d681SAndroid Build Coastguard Worker                               getContext());
1253*9880d681SAndroid Build Coastguard Worker 
1254*9880d681SAndroid Build Coastguard Worker     EmitValue(PersonalityRef, 4);
1255*9880d681SAndroid Build Coastguard Worker   }
1256*9880d681SAndroid Build Coastguard Worker 
1257*9880d681SAndroid Build Coastguard Worker   // Emit unwind opcodes
1258*9880d681SAndroid Build Coastguard Worker   assert((Opcodes.size() % 4) == 0 &&
1259*9880d681SAndroid Build Coastguard Worker          "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be multiple of 4");
1260*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I != Opcodes.size(); I += 4) {
1261*9880d681SAndroid Build Coastguard Worker     uint64_t Intval = Opcodes[I] |
1262*9880d681SAndroid Build Coastguard Worker                       Opcodes[I + 1] << 8 |
1263*9880d681SAndroid Build Coastguard Worker                       Opcodes[I + 2] << 16 |
1264*9880d681SAndroid Build Coastguard Worker                       Opcodes[I + 3] << 24;
1265*9880d681SAndroid Build Coastguard Worker     EmitIntValue(Intval, 4);
1266*9880d681SAndroid Build Coastguard Worker   }
1267*9880d681SAndroid Build Coastguard Worker 
1268*9880d681SAndroid Build Coastguard Worker   // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or
1269*9880d681SAndroid Build Coastguard Worker   // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted
1270*9880d681SAndroid Build Coastguard Worker   // after the unwind opcodes.  The handler data consists of several 32-bit
1271*9880d681SAndroid Build Coastguard Worker   // words, and should be terminated by zero.
1272*9880d681SAndroid Build Coastguard Worker   //
1273*9880d681SAndroid Build Coastguard Worker   // In case that the .handlerdata directive is not specified by the
1274*9880d681SAndroid Build Coastguard Worker   // programmer, we should emit zero to terminate the handler data.
1275*9880d681SAndroid Build Coastguard Worker   if (NoHandlerData && !Personality)
1276*9880d681SAndroid Build Coastguard Worker     EmitIntValue(0, 4);
1277*9880d681SAndroid Build Coastguard Worker }
1278*9880d681SAndroid Build Coastguard Worker 
emitHandlerData()1279*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); }
1280*9880d681SAndroid Build Coastguard Worker 
emitPersonality(const MCSymbol * Per)1281*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitPersonality(const MCSymbol *Per) {
1282*9880d681SAndroid Build Coastguard Worker   Personality = Per;
1283*9880d681SAndroid Build Coastguard Worker   UnwindOpAsm.setPersonality(Per);
1284*9880d681SAndroid Build Coastguard Worker }
1285*9880d681SAndroid Build Coastguard Worker 
emitPersonalityIndex(unsigned Index)1286*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitPersonalityIndex(unsigned Index) {
1287*9880d681SAndroid Build Coastguard Worker   assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index");
1288*9880d681SAndroid Build Coastguard Worker   PersonalityIndex = Index;
1289*9880d681SAndroid Build Coastguard Worker }
1290*9880d681SAndroid Build Coastguard Worker 
emitSetFP(unsigned NewFPReg,unsigned NewSPReg,int64_t Offset)1291*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg,
1292*9880d681SAndroid Build Coastguard Worker                                int64_t Offset) {
1293*9880d681SAndroid Build Coastguard Worker   assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
1294*9880d681SAndroid Build Coastguard Worker          "the operand of .setfp directive should be either $sp or $fp");
1295*9880d681SAndroid Build Coastguard Worker 
1296*9880d681SAndroid Build Coastguard Worker   UsedFP = true;
1297*9880d681SAndroid Build Coastguard Worker   FPReg = NewFPReg;
1298*9880d681SAndroid Build Coastguard Worker 
1299*9880d681SAndroid Build Coastguard Worker   if (NewSPReg == ARM::SP)
1300*9880d681SAndroid Build Coastguard Worker     FPOffset = SPOffset + Offset;
1301*9880d681SAndroid Build Coastguard Worker   else
1302*9880d681SAndroid Build Coastguard Worker     FPOffset += Offset;
1303*9880d681SAndroid Build Coastguard Worker }
1304*9880d681SAndroid Build Coastguard Worker 
emitMovSP(unsigned Reg,int64_t Offset)1305*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
1306*9880d681SAndroid Build Coastguard Worker   assert((Reg != ARM::SP && Reg != ARM::PC) &&
1307*9880d681SAndroid Build Coastguard Worker          "the operand of .movsp cannot be either sp or pc");
1308*9880d681SAndroid Build Coastguard Worker   assert(FPReg == ARM::SP && "current FP must be SP");
1309*9880d681SAndroid Build Coastguard Worker 
1310*9880d681SAndroid Build Coastguard Worker   FlushPendingOffset();
1311*9880d681SAndroid Build Coastguard Worker 
1312*9880d681SAndroid Build Coastguard Worker   FPReg = Reg;
1313*9880d681SAndroid Build Coastguard Worker   FPOffset = SPOffset + Offset;
1314*9880d681SAndroid Build Coastguard Worker 
1315*9880d681SAndroid Build Coastguard Worker   const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1316*9880d681SAndroid Build Coastguard Worker   UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
1317*9880d681SAndroid Build Coastguard Worker }
1318*9880d681SAndroid Build Coastguard Worker 
emitPad(int64_t Offset)1319*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitPad(int64_t Offset) {
1320*9880d681SAndroid Build Coastguard Worker   // Track the change of the $sp offset
1321*9880d681SAndroid Build Coastguard Worker   SPOffset -= Offset;
1322*9880d681SAndroid Build Coastguard Worker 
1323*9880d681SAndroid Build Coastguard Worker   // To squash multiple .pad directives, we should delay the unwind opcode
1324*9880d681SAndroid Build Coastguard Worker   // until the .save, .vsave, .handlerdata, or .fnend directives.
1325*9880d681SAndroid Build Coastguard Worker   PendingOffset -= Offset;
1326*9880d681SAndroid Build Coastguard Worker }
1327*9880d681SAndroid Build Coastguard Worker 
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool IsVector)1328*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
1329*9880d681SAndroid Build Coastguard Worker                                  bool IsVector) {
1330*9880d681SAndroid Build Coastguard Worker   // Collect the registers in the register list
1331*9880d681SAndroid Build Coastguard Worker   unsigned Count = 0;
1332*9880d681SAndroid Build Coastguard Worker   uint32_t Mask = 0;
1333*9880d681SAndroid Build Coastguard Worker   const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1334*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < RegList.size(); ++i) {
1335*9880d681SAndroid Build Coastguard Worker     unsigned Reg = MRI->getEncodingValue(RegList[i]);
1336*9880d681SAndroid Build Coastguard Worker     assert(Reg < (IsVector ? 32U : 16U) && "Register out of range");
1337*9880d681SAndroid Build Coastguard Worker     unsigned Bit = (1u << Reg);
1338*9880d681SAndroid Build Coastguard Worker     if ((Mask & Bit) == 0) {
1339*9880d681SAndroid Build Coastguard Worker       Mask |= Bit;
1340*9880d681SAndroid Build Coastguard Worker       ++Count;
1341*9880d681SAndroid Build Coastguard Worker     }
1342*9880d681SAndroid Build Coastguard Worker   }
1343*9880d681SAndroid Build Coastguard Worker 
1344*9880d681SAndroid Build Coastguard Worker   // Track the change the $sp offset: For the .save directive, the
1345*9880d681SAndroid Build Coastguard Worker   // corresponding push instruction will decrease the $sp by (4 * Count).
1346*9880d681SAndroid Build Coastguard Worker   // For the .vsave directive, the corresponding vpush instruction will
1347*9880d681SAndroid Build Coastguard Worker   // decrease $sp by (8 * Count).
1348*9880d681SAndroid Build Coastguard Worker   SPOffset -= Count * (IsVector ? 8 : 4);
1349*9880d681SAndroid Build Coastguard Worker 
1350*9880d681SAndroid Build Coastguard Worker   // Emit the opcode
1351*9880d681SAndroid Build Coastguard Worker   FlushPendingOffset();
1352*9880d681SAndroid Build Coastguard Worker   if (IsVector)
1353*9880d681SAndroid Build Coastguard Worker     UnwindOpAsm.EmitVFPRegSave(Mask);
1354*9880d681SAndroid Build Coastguard Worker   else
1355*9880d681SAndroid Build Coastguard Worker     UnwindOpAsm.EmitRegSave(Mask);
1356*9880d681SAndroid Build Coastguard Worker }
1357*9880d681SAndroid Build Coastguard Worker 
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)1358*9880d681SAndroid Build Coastguard Worker void ARMELFStreamer::emitUnwindRaw(int64_t Offset,
1359*9880d681SAndroid Build Coastguard Worker                                    const SmallVectorImpl<uint8_t> &Opcodes) {
1360*9880d681SAndroid Build Coastguard Worker   FlushPendingOffset();
1361*9880d681SAndroid Build Coastguard Worker   SPOffset = SPOffset - Offset;
1362*9880d681SAndroid Build Coastguard Worker   UnwindOpAsm.EmitRaw(Opcodes);
1363*9880d681SAndroid Build Coastguard Worker }
1364*9880d681SAndroid Build Coastguard Worker 
1365*9880d681SAndroid Build Coastguard Worker namespace llvm {
1366*9880d681SAndroid Build Coastguard Worker 
createARMTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter * InstPrint,bool isVerboseAsm)1367*9880d681SAndroid Build Coastguard Worker MCTargetStreamer *createARMTargetAsmStreamer(MCStreamer &S,
1368*9880d681SAndroid Build Coastguard Worker                                              formatted_raw_ostream &OS,
1369*9880d681SAndroid Build Coastguard Worker                                              MCInstPrinter *InstPrint,
1370*9880d681SAndroid Build Coastguard Worker                                              bool isVerboseAsm) {
1371*9880d681SAndroid Build Coastguard Worker   return new ARMTargetAsmStreamer(S, OS, *InstPrint, isVerboseAsm);
1372*9880d681SAndroid Build Coastguard Worker }
1373*9880d681SAndroid Build Coastguard Worker 
createARMNullTargetStreamer(MCStreamer & S)1374*9880d681SAndroid Build Coastguard Worker MCTargetStreamer *createARMNullTargetStreamer(MCStreamer &S) {
1375*9880d681SAndroid Build Coastguard Worker   return new ARMTargetStreamer(S);
1376*9880d681SAndroid Build Coastguard Worker }
1377*9880d681SAndroid Build Coastguard Worker 
createARMObjectTargetStreamer(MCStreamer & S,const MCSubtargetInfo & STI)1378*9880d681SAndroid Build Coastguard Worker MCTargetStreamer *createARMObjectTargetStreamer(MCStreamer &S,
1379*9880d681SAndroid Build Coastguard Worker                                                 const MCSubtargetInfo &STI) {
1380*9880d681SAndroid Build Coastguard Worker   const Triple &TT = STI.getTargetTriple();
1381*9880d681SAndroid Build Coastguard Worker   if (TT.isOSBinFormatELF())
1382*9880d681SAndroid Build Coastguard Worker     return new ARMTargetELFStreamer(S);
1383*9880d681SAndroid Build Coastguard Worker   return new ARMTargetStreamer(S);
1384*9880d681SAndroid Build Coastguard Worker }
1385*9880d681SAndroid Build Coastguard Worker 
createARMELFStreamer(MCContext & Context,MCAsmBackend & TAB,raw_pwrite_stream & OS,MCCodeEmitter * Emitter,bool RelaxAll,bool IsThumb)1386*9880d681SAndroid Build Coastguard Worker MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
1387*9880d681SAndroid Build Coastguard Worker                                     raw_pwrite_stream &OS,
1388*9880d681SAndroid Build Coastguard Worker                                     MCCodeEmitter *Emitter, bool RelaxAll,
1389*9880d681SAndroid Build Coastguard Worker                                     bool IsThumb) {
1390*9880d681SAndroid Build Coastguard Worker     ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
1391*9880d681SAndroid Build Coastguard Worker     // FIXME: This should eventually end up somewhere else where more
1392*9880d681SAndroid Build Coastguard Worker     // intelligent flag decisions can be made. For now we are just maintaining
1393*9880d681SAndroid Build Coastguard Worker     // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default.
1394*9880d681SAndroid Build Coastguard Worker     S->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5);
1395*9880d681SAndroid Build Coastguard Worker 
1396*9880d681SAndroid Build Coastguard Worker     if (RelaxAll)
1397*9880d681SAndroid Build Coastguard Worker       S->getAssembler().setRelaxAll(true);
1398*9880d681SAndroid Build Coastguard Worker     return S;
1399*9880d681SAndroid Build Coastguard Worker   }
1400*9880d681SAndroid Build Coastguard Worker 
1401*9880d681SAndroid Build Coastguard Worker }
1402*9880d681SAndroid Build Coastguard Worker 
1403*9880d681SAndroid Build Coastguard Worker 
1404