mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Add support for emitting ARM file attributes.
llvm-svn: 117275
This commit is contained in:
parent
3a5f798790
commit
5748458e7d
@ -299,6 +299,16 @@ enum {
|
||||
SHT_LOOS = 0x60000000, // Lowest operating system-specific type.
|
||||
SHT_HIOS = 0x6fffffff, // Highest operating system-specific type.
|
||||
SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type.
|
||||
// Fixme: All this is duplicated in MCSectionELF. Why??
|
||||
// Exception Index table
|
||||
SHT_ARM_EXIDX = 0x70000001U,
|
||||
// BPABI DLL dynamic linking pre-emption map
|
||||
SHT_ARM_PREEMPTMAP = 0x70000002U,
|
||||
// Object file compatibility attributes
|
||||
SHT_ARM_ATTRIBUTES = 0x70000003U,
|
||||
SHT_ARM_DEBUGOVERLAY = 0x70000004U,
|
||||
SHT_ARM_OVERLAYSECTION = 0x70000005U,
|
||||
|
||||
SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type.
|
||||
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
|
||||
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
|
||||
|
@ -1200,12 +1200,10 @@ void ELFObjectWriterImpl::WriteObject(MCAssembler &Asm,
|
||||
case ELF::SHT_STRTAB:
|
||||
case ELF::SHT_NOBITS:
|
||||
case ELF::SHT_NULL:
|
||||
case ELF::SHT_ARM_ATTRIBUTES:
|
||||
// Nothing to do.
|
||||
break;
|
||||
|
||||
case ELF::SHT_HASH:
|
||||
case ELF::SHT_GROUP:
|
||||
case ELF::SHT_SYMTAB_SHNDX:
|
||||
default:
|
||||
assert(0 && "FIXME: sh_type value not supported!");
|
||||
break;
|
||||
|
@ -55,12 +55,11 @@ void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
|
||||
}
|
||||
|
||||
bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
assert(0 && "ARMAsmBackend::WriteNopData() unimplemented");
|
||||
if ((Count % 4) != 0) {
|
||||
// Fixme: % 2 for Thumb?
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -32,10 +32,12 @@
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.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"
|
||||
@ -63,6 +65,91 @@ namespace llvm {
|
||||
}
|
||||
|
||||
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
|
||||
@ -110,8 +197,6 @@ namespace {
|
||||
private:
|
||||
// Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
|
||||
void emitAttributes();
|
||||
void emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, StringRef v);
|
||||
void emitAttribute(ARMBuildAttrs::AttrType attr, int v);
|
||||
|
||||
// Helper for ELF .o only
|
||||
void emitARMAttributeSection();
|
||||
@ -502,34 +587,58 @@ 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();
|
||||
emitTextAttribute(ARMBuildAttrs::SEL_CPU, CPUString);
|
||||
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())
|
||||
emitAttribute(ARMBuildAttrs::VFP_arch, 2);
|
||||
AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, 2);
|
||||
|
||||
// Signal various FP modes.
|
||||
if (!UnsafeFPMath) {
|
||||
emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
|
||||
emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
|
||||
AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, 1);
|
||||
AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 1);
|
||||
}
|
||||
|
||||
if (NoInfsFPMath && NoNaNsFPMath)
|
||||
emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
|
||||
AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 1);
|
||||
else
|
||||
emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
|
||||
AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, 3);
|
||||
|
||||
// 8-bytes alignment stuff.
|
||||
emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
|
||||
emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
|
||||
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) {
|
||||
emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
|
||||
emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
|
||||
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() {
|
||||
@ -549,32 +658,9 @@ void ARMAsmPrinter::emitARMAttributeSection() {
|
||||
(getObjFileLowering());
|
||||
|
||||
OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
|
||||
// Fixme: Still more to do here.
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::emitAttribute(ARMBuildAttrs::AttrType attr, int v) {
|
||||
if (OutStreamer.hasRawTextSupport()) {
|
||||
OutStreamer.EmitRawText("\t.eabi_attribute " +
|
||||
Twine(attr) + ", " + Twine(v));
|
||||
|
||||
} else {
|
||||
assert(0 && "ELF .ARM.attributes unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::emitTextAttribute(ARMBuildAttrs::SpecialAttr attr,
|
||||
StringRef val) {
|
||||
switch (attr) {
|
||||
default: assert(0 && "Unimplemented ARMBuildAttrs::SpecialAttr"); break;
|
||||
case ARMBuildAttrs::SEL_CPU:
|
||||
if (OutStreamer.hasRawTextSupport()) {
|
||||
if (val != "generic") {
|
||||
OutStreamer.EmitRawText("\t.cpu " + val);
|
||||
}
|
||||
} else {
|
||||
// FIXME: ELF
|
||||
}
|
||||
}
|
||||
// Format version
|
||||
OutStreamer.EmitIntValue(0x41, 1);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains enumerations and support routines for ARM build attributes
|
||||
// as defined in ARM ABI addenda document (ABI release 2.07).
|
||||
// as defined in ARM ABI addenda document (ABI release 2.08).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -59,18 +59,39 @@ namespace ARMBuildAttrs {
|
||||
CPU_unaligned_access = 34,
|
||||
VFP_HP_extension = 36,
|
||||
ABI_FP_16bit_format = 38,
|
||||
MPextension_use = 42, // was 70, 2.08 ABI
|
||||
DIV_use = 44,
|
||||
nodefaults = 64,
|
||||
also_compatible_with = 65,
|
||||
T2EE_use = 66,
|
||||
conformance = 67,
|
||||
Virtualization_use = 68,
|
||||
MPextension_use = 70
|
||||
MPextension_use_old = 70
|
||||
};
|
||||
|
||||
// Magic numbers for .ARM.attributes
|
||||
enum AttrMagic {
|
||||
Format_Version = 0x41
|
||||
};
|
||||
|
||||
// Legal Values for CPU_arch, (=6), uleb128
|
||||
enum CPUArch {
|
||||
Pre_v4 = 0,
|
||||
v4 = 1, // e.g. SA110
|
||||
v4T = 2, // e.g. ARM7TDMI
|
||||
v5T = 3, // e.g. ARM9TDMI
|
||||
v5TE = 4, // e.g. ARM946E_S
|
||||
v5TEJ = 5, // e.g. ARM926EJ_S
|
||||
v6 = 6, // e.g. ARM1136J_S
|
||||
v6KZ = 7, // e.g. ARM1176JZ_S
|
||||
v6T2 = 8, // e.g. ARM1156T2F_S
|
||||
v6K = 9, // e.g. ARM1136J_S
|
||||
v7 = 10, // e.g. Cortex A8, Cortex M3
|
||||
v6_M = 11, // e.g. Cortex M1
|
||||
v6S_M = 12, // v6_M with the System extensions
|
||||
v7E_M = 13 // v7_M with DSP extensions
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __TARGET_ARMBUILDATTRS_H__
|
||||
|
19
test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll
Normal file
19
test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llc %s -mtriple=arm-linux-gnueabi -filetype=obj -o - | \
|
||||
; RUN: elf-dump --dump-section-data | FileCheck %s
|
||||
; This tests that the extpected ARM attributes are emitted.
|
||||
;
|
||||
; CHECK: .ARM.attributes
|
||||
; CHECK-NEXT: 0x70000003
|
||||
; CHECK-NEXT: 0x00000000
|
||||
; CHECK-NEXT: 0x00000000
|
||||
; CHECK-NEXT: 0x0000003c
|
||||
; CHECK-NEXT: 0x00000022
|
||||
; CHECK-NEXT: 0x00000000
|
||||
; CHECK-NEXT: 0x00000000
|
||||
; CHECK-NEXT: 0x00000001
|
||||
; CHECK-NEXT: 0x00000000
|
||||
; CHECK-NEXT: '41210000 00616561 62690001 17000000 06020801 09011401 15011703 18011901 2c01'
|
||||
|
||||
define i32 @f(i64 %z) {
|
||||
ret i32 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user