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