//
//===----------------------------------------------------------------------===//
-#include "ARMBuildAttrs.h"
#include "ARMArchName.h"
#include "ARMFPUName.h"
#include "ARMRegisterInfo.h"
-#include "ARMUnwindOp.h"
#include "ARMUnwindOpAsm.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/Support/ARMEHABI.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
- assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");
+ assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX &&
+ "Invalid personality index");
return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
}
break;
#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
case ARM::ID: return NAME;
+#define ARM_ARCH_ALIAS(NAME, ID) /* empty */
#include "ARMArchName.def"
}
return NULL;
break;
#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
case ARM::ID: return DEFAULT_CPU_NAME;
+#define ARM_ARCH_ALIAS(NAME, ID) /* empty */
#include "ARMArchName.def"
}
return NULL;
break;
#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
case ARM::ID: return ARMBuildAttrs::DEFAULT_CPU_ARCH;
+#define ARM_ARCH_ALIAS(NAME, ID) /* empty */
#include "ARMArchName.def"
}
return 0;
class ARMTargetAsmStreamer : public ARMTargetStreamer {
formatted_raw_ostream &OS;
MCInstPrinter &InstPrinter;
+ bool IsVerboseAsm;
virtual void emitFnStart();
virtual void emitFnEnd();
virtual void emitCantUnwind();
virtual void emitPersonality(const MCSymbol *Personality);
+ virtual void emitPersonalityIndex(unsigned Index);
virtual void emitHandlerData();
virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
+ virtual void emitMovSP(unsigned Reg, int64_t Offset = 0);
virtual void emitPad(int64_t Offset);
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector);
+ virtual void emitUnwindRaw(int64_t Offset,
+ const SmallVectorImpl<uint8_t> &Opcodes);
virtual void switchVendor(StringRef Vendor);
virtual void emitAttribute(unsigned Attribute, unsigned Value);
virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+ virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+ StringRef StrinValue);
virtual void emitArch(unsigned Arch);
+ virtual void emitObjectArch(unsigned Arch);
virtual void emitFPU(unsigned FPU);
+ virtual void emitInst(uint32_t Inst, char Suffix = '\0');
virtual void finishAttributeSection();
+ virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);
+
public:
- ARMTargetAsmStreamer(formatted_raw_ostream &OS, MCInstPrinter &InstPrinter);
+ ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,
+ MCInstPrinter &InstPrinter, bool VerboseAsm);
};
-ARMTargetAsmStreamer::ARMTargetAsmStreamer(formatted_raw_ostream &OS,
- MCInstPrinter &InstPrinter)
- : OS(OS), InstPrinter(InstPrinter) {}
+ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter &InstPrinter,
+ bool VerboseAsm)
+ : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter),
+ IsVerboseAsm(VerboseAsm) {}
void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; }
void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; }
void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
OS << "\t.personality " << Personality->getName() << '\n';
}
+void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) {
+ OS << "\t.personalityindex " << Index << '\n';
+}
void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
int64_t Offset) {
OS << ", #" << Offset;
OS << '\n';
}
+void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+ assert((Reg != ARM::SP && Reg != ARM::PC) &&
+ "the operand of .movsp cannot be either sp or pc");
+
+ OS << "\t.movsp\t";
+ InstPrinter.printRegName(OS, Reg);
+ if (Offset)
+ OS << ", #" << Offset;
+ OS << '\n';
+}
void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
OS << "\t.pad\t#" << Offset << '\n';
}
void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {
}
void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
- OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value) << "\n";
+ OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value);
+ if (IsVerboseAsm) {
+ StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute);
+ if (!Name.empty())
+ OS << "\t@ " << Name;
+ }
+ OS << "\n";
}
void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
StringRef String) {
switch (Attribute) {
- default: llvm_unreachable("Unsupported Text attribute in ASM Mode");
case ARMBuildAttrs::CPU_name:
- OS << "\t.cpu\t" << String.lower() << "\n";
+ OS << "\t.cpu\t" << String.lower();
+ break;
+ default:
+ OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\"";
+ if (IsVerboseAsm) {
+ StringRef Name = ARMBuildAttrs::AttrTypeAsString(Attribute);
+ if (!Name.empty())
+ OS << "\t@ " << Name;
+ }
break;
}
+ OS << "\n";
+}
+void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
+ unsigned IntValue,
+ StringRef StringValue) {
+ switch (Attribute) {
+ default: llvm_unreachable("unsupported multi-value attribute in asm mode");
+ case ARMBuildAttrs::compatibility:
+ OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue;
+ if (!StringValue.empty())
+ OS << ", \"" << StringValue << "\"";
+ if (IsVerboseAsm)
+ OS << "\t@ " << ARMBuildAttrs::AttrTypeAsString(Attribute);
+ break;
+ }
+ OS << "\n";
}
void ARMTargetAsmStreamer::emitArch(unsigned Arch) {
OS << "\t.arch\t" << GetArchName(Arch) << "\n";
}
+void ARMTargetAsmStreamer::emitObjectArch(unsigned Arch) {
+ OS << "\t.object_arch\t" << GetArchName(Arch) << '\n';
+}
void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
OS << "\t.fpu\t" << GetFPUName(FPU) << "\n";
}
void ARMTargetAsmStreamer::finishAttributeSection() {
}
+void
+ARMTargetAsmStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
+ OS << "\t.tlsdescseq\t" << S->getSymbol().getName();
+}
+
+void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) {
+ OS << "\t.inst";
+ if (Suffix)
+ OS << "." << Suffix;
+ OS << "\t0x" << utohexstr(Inst) << "\n";
+}
+
+void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset,
+ const SmallVectorImpl<uint8_t> &Opcodes) {
+ OS << "\t.unwind_raw " << Offset;
+ for (SmallVectorImpl<uint8_t>::const_iterator OCI = Opcodes.begin(),
+ OCE = Opcodes.end();
+ OCI != OCE; ++OCI)
+ OS << ", 0x" << utohexstr(*OCI);
+ OS << '\n';
+}
class ARMTargetELFStreamer : public ARMTargetStreamer {
private:
enum {
HiddenAttribute = 0,
NumericAttribute,
- TextAttribute
+ TextAttribute,
+ NumericAndTextAttributes
} Type;
unsigned Tag;
unsigned IntValue;
StringRef CurrentVendor;
unsigned FPU;
unsigned Arch;
+ unsigned EmittedArch;
SmallVector<AttributeItem, 64> Contents;
const MCSection *AttributeSection;
- // FIXME: this should be in a more generic place, but
- // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf
- static size_t getULEBSize(int Value) {
- size_t Size = 0;
- do {
- Value >>= 7;
- Size += sizeof(int8_t); // Is this really necessary?
- } while (Value);
- return Size;
- }
-
AttributeItem *getAttributeItem(unsigned Attribute) {
for (size_t i = 0; i < Contents.size(); ++i)
if (Contents[i].Tag == Attribute)
if (AttributeItem *Item = getAttributeItem(Attribute)) {
if (!OverwriteExisting)
return;
+ Item->Type = AttributeItem::NumericAttribute;
Item->IntValue = Value;
return;
}
if (AttributeItem *Item = getAttributeItem(Attribute)) {
if (!OverwriteExisting)
return;
+ Item->Type = AttributeItem::TextAttribute;
Item->StringValue = Value;
return;
}
Contents.push_back(Item);
}
+ void setAttributeItems(unsigned Attribute, unsigned IntValue,
+ StringRef StringValue, bool OverwriteExisting) {
+ // Look for existing attribute item
+ if (AttributeItem *Item = getAttributeItem(Attribute)) {
+ if (!OverwriteExisting)
+ return;
+ Item->Type = AttributeItem::NumericAndTextAttributes;
+ Item->IntValue = IntValue;
+ Item->StringValue = StringValue;
+ return;
+ }
+
+ // Create new attribute item
+ AttributeItem Item = {
+ AttributeItem::NumericAndTextAttributes,
+ Attribute,
+ IntValue,
+ StringValue
+ };
+ Contents.push_back(Item);
+ }
+
void emitArchDefaultAttributes();
void emitFPUDefaultAttributes();
virtual void emitFnEnd();
virtual void emitCantUnwind();
virtual void emitPersonality(const MCSymbol *Personality);
+ virtual void emitPersonalityIndex(unsigned Index);
virtual void emitHandlerData();
virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
+ virtual void emitMovSP(unsigned Reg, int64_t Offset = 0);
virtual void emitPad(int64_t Offset);
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector);
+ virtual void emitUnwindRaw(int64_t Offset,
+ const SmallVectorImpl<uint8_t> &Opcodes);
virtual void switchVendor(StringRef Vendor);
virtual void emitAttribute(unsigned Attribute, unsigned Value);
virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+ virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+ StringRef StringValue);
virtual void emitArch(unsigned Arch);
+ virtual void emitObjectArch(unsigned Arch);
virtual void emitFPU(unsigned FPU);
+ virtual void emitInst(uint32_t Inst, char Suffix = '\0');
virtual void finishAttributeSection();
+ virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);
+
size_t calculateContentSize() const;
public:
- ARMTargetELFStreamer()
- : ARMTargetStreamer(), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU),
- Arch(ARM::INVALID_ARCH), AttributeSection(0) {
- }
+ ARMTargetELFStreamer(MCStreamer &S)
+ : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU),
+ Arch(ARM::INVALID_ARCH), EmittedArch(ARM::INVALID_ARCH),
+ AttributeSection(0) {}
};
/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
public:
friend class ARMTargetELFStreamer;
- ARMELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer,
- MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter,
- bool IsThumb)
- : MCELFStreamer(Context, TargetStreamer, TAB, OS, Emitter),
- IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {
+ ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
+ MCCodeEmitter *Emitter, bool IsThumb)
+ : MCELFStreamer(Context, TAB, OS, Emitter), IsThumb(IsThumb),
+ MappingSymbolCounter(0), LastEMS(EMS_None) {
Reset();
}
void emitFnEnd();
void emitCantUnwind();
void emitPersonality(const MCSymbol *Per);
+ void emitPersonalityIndex(unsigned index);
void emitHandlerData();
void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
+ void emitMovSP(unsigned Reg, int64_t Offset = 0);
void emitPad(int64_t Offset);
void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
+ void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
virtual void ChangeSection(const MCSection *Section,
const MCExpr *Subsection) {
/// This function is the one used to emit instruction data into the ELF
/// streamer. We override it to add the appropriate mapping symbol if
/// necessary.
- virtual void EmitInstruction(const MCInst& Inst) {
+ virtual void EmitInstruction(const MCInst& Inst, const MCSubtargetInfo &STI) {
if (IsThumb)
EmitThumbMappingSymbol();
else
EmitARMMappingSymbol();
- MCELFStreamer::EmitInstruction(Inst);
+ MCELFStreamer::EmitInstruction(Inst, STI);
+ }
+
+ virtual void emitInst(uint32_t Inst, char Suffix) {
+ unsigned Size;
+ char Buffer[4];
+ const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();
+
+ switch (Suffix) {
+ case '\0':
+ Size = 4;
+
+ assert(!IsThumb);
+ EmitARMMappingSymbol();
+ for (unsigned II = 0, IE = Size; II != IE; II++) {
+ const unsigned I = LittleEndian ? (Size - II - 1) : II;
+ Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
+ }
+
+ break;
+ case 'n':
+ case 'w':
+ Size = (Suffix == 'n' ? 2 : 4);
+
+ assert(IsThumb);
+ EmitThumbMappingSymbol();
+ for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
+ const unsigned I0 = LittleEndian ? II + 0 : (Size - II - 1);
+ const unsigned I1 = LittleEndian ? II + 1 : (Size - II - 2);
+ Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
+ Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
+ }
+
+ break;
+ default:
+ llvm_unreachable("Invalid Suffix");
+ }
+
+ MCELFStreamer::EmitBytes(StringRef(Buffer, Size));
}
/// This is one of the functions used to emit data into an ELF section, so the
void SwitchToExTabSection(const MCSymbol &FnStart);
void SwitchToExIdxSection(const MCSymbol &FnStart);
+ void EmitFixup(const MCExpr *Expr, MCFixupKind Kind);
+
bool IsThumb;
int64_t MappingSymbolCounter;
} // end anonymous namespace
ARMELFStreamer &ARMTargetELFStreamer::getStreamer() {
- ARMELFStreamer *S = static_cast<ARMELFStreamer *>(Streamer);
- return *S;
+ return static_cast<ARMELFStreamer &>(Streamer);
}
void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); }
void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
getStreamer().emitPersonality(Personality);
}
+void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) {
+ getStreamer().emitPersonalityIndex(Index);
+}
void ARMTargetELFStreamer::emitHandlerData() {
getStreamer().emitHandlerData();
}
int64_t Offset) {
getStreamer().emitSetFP(FpReg, SpReg, Offset);
}
+void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+ getStreamer().emitMovSP(Reg, Offset);
+}
void ARMTargetELFStreamer::emitPad(int64_t Offset) {
getStreamer().emitPad(Offset);
}
bool isVector) {
getStreamer().emitRegSave(RegList, isVector);
}
+void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
+ const SmallVectorImpl<uint8_t> &Opcodes) {
+ getStreamer().emitUnwindRaw(Offset, Opcodes);
+}
void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
assert(!Vendor.empty() && "Vendor cannot be empty.");
StringRef Value) {
setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
}
+void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
+ unsigned IntValue,
+ StringRef StringValue) {
+ setAttributeItems(Attribute, IntValue, StringValue,
+ /* OverwriteExisting= */ true);
+}
void ARMTargetELFStreamer::emitArch(unsigned Value) {
Arch = Value;
}
+void ARMTargetELFStreamer::emitObjectArch(unsigned Value) {
+ EmittedArch = Value;
+}
void ARMTargetELFStreamer::emitArchDefaultAttributes() {
using namespace ARMBuildAttrs;
+
setAttributeItem(CPU_name, GetArchDefaultCPUName(Arch), false);
- setAttributeItem(CPU_arch, GetArchDefaultCPUArch(Arch), false);
+ if (EmittedArch == ARM::INVALID_ARCH)
+ setAttributeItem(CPU_arch, GetArchDefaultCPUArch(Arch), false);
+ else
+ setAttributeItem(CPU_arch, GetArchDefaultCPUArch(EmittedArch), false);
switch (Arch) {
case ARM::ARMV2:
break;
case ARM::ARMV6M:
- setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
setAttributeItem(THUMB_ISA_use, Allowed, false);
break;
switch (FPU) {
case ARM::VFP:
case ARM::VFPV2:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv2,
/* OverwriteExisting= */ false);
break;
case ARM::VFPV3:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv3A,
/* OverwriteExisting= */ false);
break;
case ARM::VFPV3_D16:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv3B,
/* OverwriteExisting= */ false);
break;
case ARM::VFPV4:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv4A,
/* OverwriteExisting= */ false);
break;
case ARM::VFPV4_D16:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv4B,
/* OverwriteExisting= */ false);
break;
case ARM::FP_ARMV8:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPARMv8A,
/* OverwriteExisting= */ false);
break;
case ARM::NEON:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv3A,
/* OverwriteExisting= */ false);
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
break;
case ARM::NEON_VFPV4:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPv4A,
/* OverwriteExisting= */ false);
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
case ARM::NEON_FP_ARMV8:
case ARM::CRYPTO_NEON_FP_ARMV8:
- setAttributeItem(ARMBuildAttrs::VFP_arch,
+ setAttributeItem(ARMBuildAttrs::FP_arch,
ARMBuildAttrs::AllowFPARMv8A,
/* OverwriteExisting= */ false);
setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
/* OverwriteExisting= */ false);
break;
+ case ARM::SOFTVFP:
+ break;
+
default:
report_fatal_error("Unknown FPU: " + Twine(FPU));
break;
case AttributeItem::HiddenAttribute:
break;
case AttributeItem::NumericAttribute:
- Result += getULEBSize(item.Tag);
- Result += getULEBSize(item.IntValue);
+ Result += getULEB128Size(item.Tag);
+ Result += getULEB128Size(item.IntValue);
break;
case AttributeItem::TextAttribute:
- Result += getULEBSize(item.Tag);
+ Result += getULEB128Size(item.Tag);
Result += item.StringValue.size() + 1; // string + '\0'
break;
+ case AttributeItem::NumericAndTextAttributes:
+ Result += getULEB128Size(item.Tag);
+ Result += getULEB128Size(item.IntValue);
+ Result += item.StringValue.size() + 1; // string + '\0';
+ break;
}
}
return Result;
Streamer.EmitBytes(item.StringValue.upper());
Streamer.EmitIntValue(0, 1); // '\0'
break;
+ case AttributeItem::NumericAndTextAttributes:
+ Streamer.EmitULEB128IntValue(item.IntValue);
+ Streamer.EmitBytes(item.StringValue.upper());
+ Streamer.EmitIntValue(0, 1); // '\0'
+ break;
}
}
Contents.clear();
FPU = ARM::INVALID_FPU;
}
+void
+ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
+ getStreamer().EmitFixup(S, FK_Data_4);
+}
+void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
+ getStreamer().emitInst(Inst, Suffix);
+}
void ARMELFStreamer::FinishImpl() {
- MCTargetStreamer &TS = getTargetStreamer();
+ MCTargetStreamer &TS = *getTargetStreamer();
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
ATS.finishAttributeSection();
// Switch to .ARM.extab or .ARM.exidx section
SwitchSection(EHSection);
- EmitCodeAlignment(4, 0);
+ EmitCodeAlignment(4);
}
inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
SectionKind::getDataRel(),
FnStart);
}
+void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) {
+ MCDataFragment *Frag = getOrCreateDataFragment();
+ Frag->getFixups().push_back(MCFixup::Create(Frag->getContents().size(), Expr,
+ Kind));
+}
void ARMELFStreamer::Reset() {
ExTab = NULL;
FnStart = NULL;
Personality = NULL;
- PersonalityIndex = NUM_PERSONALITY_INDEX;
+ PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX;
FPReg = ARM::SP;
FPOffset = 0;
SPOffset = 0;
}
void ARMELFStreamer::emitFnEnd() {
- assert(FnStart && ".fnstart must preceeds .fnend");
+ assert(FnStart && ".fnstart must precedes .fnend");
// Emit unwind opcodes if there is no .handlerdata directive
if (!ExTab && !CantUnwind)
// Emit the exception index table entry
SwitchToExIdxSection(*FnStart);
- if (PersonalityIndex < NUM_PERSONALITY_INDEX)
+ if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX)
EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
const MCSymbolRefExpr *FnStartRef =
EmitValue(FnStartRef, 4);
if (CantUnwind) {
- EmitIntValue(EXIDX_CANTUNWIND, 4);
+ EmitIntValue(ARM::EHABI::EXIDX_CANTUNWIND, 4);
} else if (ExTab) {
// Emit a reference to the unwind opcodes in the ".ARM.extab" section.
const MCSymbolRefExpr *ExTabEntryRef =
// For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
// the second word of exception index table entry. The size of the unwind
// opcodes should always be 4 bytes.
- assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&
+ assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 &&
"Compact model must use __aeabi_cpp_unwind_pr0 as personality");
assert(Opcodes.size() == 4u &&
"Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4");
// For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
// section. Thus, we don't have to create an entry in the .ARM.extab
// section.
- if (NoHandlerData && PersonalityIndex == AEABI_UNWIND_CPP_PR0)
+ if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0)
return;
// Switch to .ARM.extab section.
UnwindOpAsm.setPersonality(Per);
}
+void ARMELFStreamer::emitPersonalityIndex(unsigned Index) {
+ assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index");
+ PersonalityIndex = Index;
+}
+
void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg,
int64_t Offset) {
assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
FPOffset += Offset;
}
+void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+ assert((Reg != ARM::SP && Reg != ARM::PC) &&
+ "the operand of .movsp cannot be either sp or pc");
+ assert(FPReg == ARM::SP && "current FP must be SP");
+
+ FlushPendingOffset();
+
+ FPReg = Reg;
+ FPOffset = SPOffset + Offset;
+
+ const MCRegisterInfo *MRI = getContext().getRegisterInfo();
+ UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
+}
+
void ARMELFStreamer::emitPad(int64_t Offset) {
// Track the change of the $sp offset
SPOffset -= Offset;
UnwindOpAsm.EmitRegSave(Mask);
}
+void ARMELFStreamer::emitUnwindRaw(int64_t Offset,
+ const SmallVectorImpl<uint8_t> &Opcodes) {
+ FlushPendingOffset();
+ SPOffset = SPOffset - Offset;
+ UnwindOpAsm.EmitRaw(Opcodes);
+}
+
namespace llvm {
MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
- bool isVerboseAsm, bool useLoc, bool useCFI,
+ bool isVerboseAsm, bool useCFI,
bool useDwarfDirectory,
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
MCAsmBackend *TAB, bool ShowInst) {
- ARMTargetAsmStreamer *S = new ARMTargetAsmStreamer(OS, *InstPrint);
-
- return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI,
- useDwarfDirectory, InstPrint, CE, TAB,
- ShowInst);
+ MCStreamer *S =
+ llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useCFI, useDwarfDirectory,
+ InstPrint, CE, TAB, ShowInst);
+ new ARMTargetAsmStreamer(*S, OS, *InstPrint, isVerboseAsm);
+ return S;
}
MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter,
bool RelaxAll, bool NoExecStack,
bool IsThumb) {
- ARMTargetELFStreamer *TS = new ARMTargetELFStreamer();
- ARMELFStreamer *S =
- new ARMELFStreamer(Context, TS, TAB, OS, Emitter, IsThumb);
+ ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
+ new ARMTargetELFStreamer(*S);
// FIXME: This should eventually end up somewhere else where more
// intelligent flag decisions can be made. For now we are just maintaining
// the status quo for ARM and setting EF_ARM_EABI_VER5 as the default.