#include "ARMMachineFunctionInfo.h"
#include "ARMMCInstLower.h"
#include "ARMTargetMachine.h"
+#include "ARMTargetObjectFile.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
-#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
}
namespace {
+
+ // Per section and per symbol attributes are not supported.
+ // To implement them we would need the ability to delay this emission
+ // until the assembly file is fully parsed/generated as only then do we
+ // know the symbol and section numbers.
+ class AttributeEmitter {
+ public:
+ virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
+ virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
+ virtual void Finish() = 0;
+ };
+
+ class AsmAttributeEmitter : public AttributeEmitter {
+ MCStreamer &Streamer;
+
+ public:
+ AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
+ void MaybeSwitchVendor(StringRef Vendor) { }
+
+ void EmitAttribute(unsigned Attribute, unsigned Value) {
+ Streamer.EmitRawText("\t.eabi_attribute " +
+ Twine(Attribute) + ", " + Twine(Value));
+ }
+
+ void Finish() { }
+ };
+
+ class ObjectAttributeEmitter : public AttributeEmitter {
+ MCObjectStreamer &Streamer;
+ size_t SectionStart;
+ size_t TagStart;
+ StringRef CurrentVendor;
+ SmallString<64> Contents;
+
+ public:
+ ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
+ Streamer(Streamer_), CurrentVendor("") { }
+
+ void MaybeSwitchVendor(StringRef Vendor) {
+ assert(!Vendor.empty() && "Vendor cannot be empty.");
+
+ if (CurrentVendor.empty())
+ CurrentVendor = Vendor;
+ else if (CurrentVendor == Vendor)
+ return;
+ else
+ Finish();
+
+ CurrentVendor = Vendor;
+
+ SectionStart = Contents.size();
+
+ // Length of the data for this vendor.
+ Contents.append(4, (char)0);
+
+ Contents.append(Vendor.begin(), Vendor.end());
+ Contents += 0;
+
+ Contents += ARMBuildAttrs::File;
+
+ TagStart = Contents.size();
+
+ // Length of the data for this tag.
+ Contents.append(4, (char)0);
+ }
+
+ void EmitAttribute(unsigned Attribute, unsigned Value) {
+ // FIXME: should be ULEB
+ Contents += Attribute;
+ Contents += Value;
+ }
+
+ void Finish() {
+ size_t EndPos = Contents.size();
+
+ // FIXME: endian.
+ *((uint32_t*)&Contents[SectionStart]) = EndPos - SectionStart;
+
+ // +1 since it includes the tag that came before it.
+ *((uint32_t*)&Contents[TagStart]) = EndPos - TagStart + 1;
+
+ Streamer.EmitBytes(Contents, 0);
+ }
+ };
+
class ARMAsmPrinter : public AsmPrinter {
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
void EmitStartOfAsmFile(Module &M);
void EmitEndOfAsmFile(Module &M);
+ private:
+ // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
+ void emitAttributes();
+
+ // Helper for ELF .o only
+ void emitARMAttributeSection();
+
+ public:
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
O << *MO.getMBB()->getSymbol();
return;
case MachineOperand::MO_GlobalAddress: {
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
const GlobalValue *GV = MO.getGlobal();
-
if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
(TF & ARMII::MO_LO16))
O << ":lower16:";
O << *Mang->getSymbol(GV);
printOffset(MO.getOffset(), O);
-
- if (isCallOp && Subtarget->isTargetELF() &&
- TM.getRelocationModel() == Reloc::PIC_)
+ if (TF == ARMII::MO_PLT)
O << "(PLT)";
break;
}
case MachineOperand::MO_ExternalSymbol: {
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
O << *GetExternalSymbolSymbol(MO.getSymbolName());
-
- if (isCallOp && Subtarget->isTargetELF() &&
- TM.getRelocationModel() == Reloc::PIC_)
+ if (TF == ARMII::MO_PLT)
O << "(PLT)";
break;
}
// Emit ARM Build Attributes
if (Subtarget->isTargetELF()) {
- // CPU Type
- std::string CPUString = Subtarget->getCPUString();
- if (CPUString != "generic")
- OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString));
-
- // FIXME: Emit FPU type
- if (Subtarget->hasVFP2())
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::VFP_arch) + ", 2");
-
- // Signal various FP modes.
- if (!UnsafeFPMath) {
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1");
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1");
- }
- if (NoInfsFPMath && NoNaNsFPMath)
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1");
- else
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3");
-
- // 8-bytes alignment stuff.
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1");
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1");
-
- // Hard float. Use both S and D registers and conform to AAPCS-VFP.
- if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3");
- OutStreamer.EmitRawText("\t.eabi_attribute " +
- Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1");
- }
- // FIXME: Should we signal R9 usage?
+ emitAttributes();
}
}
}
}
+//===----------------------------------------------------------------------===//
+// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
+// FIXME:
+// The following seem like one-off assembler flags, but they actually need
+// to appear in the .ARM.attributes section in ELF.
+// Instead of subclassing the MCELFStreamer, we do the work here.
+
+void ARMAsmPrinter::emitAttributes() {
+
+ emitARMAttributeSection();
+
+ AttributeEmitter *AttrEmitter;
+ if (OutStreamer.hasRawTextSupport())
+ AttrEmitter = new AsmAttributeEmitter(OutStreamer);
+ else {
+ MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
+ AttrEmitter = new ObjectAttributeEmitter(O);
+ }
+
+ AttrEmitter->MaybeSwitchVendor("aeabi");
+
+ std::string CPUString = Subtarget->getCPUString();
+ if (OutStreamer.hasRawTextSupport()) {
+ if (CPUString != "generic")
+ OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString);
+ } else {
+ assert(CPUString == "generic" && "Unsupported .cpu attribute for ELF/.o");
+ // FIXME: Why these defaults?
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T);
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, 1);
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, 1);
+ }
+
+ // FIXME: Emit FPU type
+ if (Subtarget->hasVFP2())
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2);
+
+ // Signal various FP modes.
+ if (!UnsafeFPMath) {
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
+ }
+
+ if (NoInfsFPMath && NoNaNsFPMath)
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
+ else
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
+
+ // 8-bytes alignment stuff.
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
+
+ // Hard float. Use both S and D registers and conform to AAPCS-VFP.
+ if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
+ }
+ // FIXME: Should we signal R9 usage?
+
+ AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1);
+
+ AttrEmitter->Finish();
+ delete AttrEmitter;
+}
+
+void ARMAsmPrinter::emitARMAttributeSection() {
+ // <format-version>
+ // [ <section-length> "vendor-name"
+ // [ <file-tag> <size> <attribute>*
+ // | <section-tag> <size> <section-number>* 0 <attribute>*
+ // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
+ // ]+
+ // ]*
+
+ if (OutStreamer.hasRawTextSupport())
+ return;
+
+ const ARMElfTargetObjectFile &TLOFELF =
+ static_cast<const ARMElfTargetObjectFile &>
+ (getObjFileLowering());
+
+ OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
+
+ // Format version
+ OutStreamer.EmitIntValue(0x41, 1);
+}
+
//===----------------------------------------------------------------------===//
static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,