ARM IAS: support .object_arch

The .object_arch directive indicates an alternative architecture to be specified
in the object file.  The directive does *not* effect the enabled feature bits
for the object file generation.  This is particularly useful when the code
performs runtime detection and would like to indicate a lower architecture as
the requirements than the actual instructions used.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200451 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Saleem Abdulrasool 2014-01-30 04:46:41 +00:00
parent 459c949777
commit 09f38a0ef1
7 changed files with 138 additions and 3 deletions

View File

@ -107,6 +107,7 @@ public:
StringRef StringValue = "") = 0; StringRef StringValue = "") = 0;
virtual void emitFPU(unsigned FPU) = 0; virtual void emitFPU(unsigned FPU) = 0;
virtual void emitArch(unsigned Arch) = 0; virtual void emitArch(unsigned Arch) = 0;
virtual void emitObjectArch(unsigned Arch) = 0;
virtual void finishAttributeSection() = 0; virtual void finishAttributeSection() = 0;
virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0; virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0;

View File

@ -298,6 +298,7 @@ class ARMAsmParser : public MCTargetAsmParser {
bool parseDirectiveUnwindRaw(SMLoc L); bool parseDirectiveUnwindRaw(SMLoc L);
bool parseDirectiveTLSDescSeq(SMLoc L); bool parseDirectiveTLSDescSeq(SMLoc L);
bool parseDirectiveMovSP(SMLoc L); bool parseDirectiveMovSP(SMLoc L);
bool parseDirectiveObjectArch(SMLoc L);
StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
bool &CarrySetting, unsigned &ProcessorIMod, bool &CarrySetting, unsigned &ProcessorIMod,
@ -8090,6 +8091,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
return parseDirectiveTLSDescSeq(DirectiveID.getLoc()); return parseDirectiveTLSDescSeq(DirectiveID.getLoc());
else if (IDVal == ".movsp") else if (IDVal == ".movsp")
return parseDirectiveMovSP(DirectiveID.getLoc()); return parseDirectiveMovSP(DirectiveID.getLoc());
else if (IDVal == ".object_arch")
return parseDirectiveObjectArch(DirectiveID.getLoc());
return true; return true;
} }
@ -9094,6 +9097,45 @@ bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
return false; return false;
} }
/// parseDirectiveObjectArch
/// ::= .object_arch name
bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) {
if (getLexer().isNot(AsmToken::Identifier)) {
Error(getLexer().getLoc(), "unexpected token");
Parser.eatToEndOfStatement();
return false;
}
StringRef Arch = Parser.getTok().getString();
SMLoc ArchLoc = Parser.getTok().getLoc();
getLexer().Lex();
unsigned ID = StringSwitch<unsigned>(Arch)
#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
.Case(NAME, ARM::ID)
#define ARM_ARCH_ALIAS(NAME, ID) \
.Case(NAME, ARM::ID)
#include "MCTargetDesc/ARMArchName.def"
#undef ARM_ARCH_NAME
#undef ARM_ARCH_ALIAS
.Default(ARM::INVALID_ARCH);
if (ID == ARM::INVALID_ARCH) {
Error(ArchLoc, "unknown architecture '" + Arch + "'");
Parser.eatToEndOfStatement();
return false;
}
getTargetStreamer().emitObjectArch(ID);
if (getLexer().isNot(AsmToken::EndOfStatement)) {
Error(getLexer().getLoc(), "unexpected token");
Parser.eatToEndOfStatement();
}
return false;
}
/// Force static initialization. /// Force static initialization.
extern "C" void LLVMInitializeARMAsmParser() { extern "C" void LLVMInitializeARMAsmParser() {
RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget); RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);

View File

@ -136,6 +136,7 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer {
virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
StringRef StrinValue); StringRef StrinValue);
virtual void emitArch(unsigned Arch); virtual void emitArch(unsigned Arch);
virtual void emitObjectArch(unsigned Arch);
virtual void emitFPU(unsigned FPU); virtual void emitFPU(unsigned FPU);
virtual void emitInst(uint32_t Inst, char Suffix = '\0'); virtual void emitInst(uint32_t Inst, char Suffix = '\0');
virtual void finishAttributeSection(); virtual void finishAttributeSection();
@ -249,6 +250,9 @@ void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
void ARMTargetAsmStreamer::emitArch(unsigned Arch) { void ARMTargetAsmStreamer::emitArch(unsigned Arch) {
OS << "\t.arch\t" << GetArchName(Arch) << "\n"; 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) { void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
OS << "\t.fpu\t" << GetFPUName(FPU) << "\n"; OS << "\t.fpu\t" << GetFPUName(FPU) << "\n";
} }
@ -300,6 +304,7 @@ private:
StringRef CurrentVendor; StringRef CurrentVendor;
unsigned FPU; unsigned FPU;
unsigned Arch; unsigned Arch;
unsigned EmittedArch;
SmallVector<AttributeItem, 64> Contents; SmallVector<AttributeItem, 64> Contents;
const MCSection *AttributeSection; const MCSection *AttributeSection;
@ -411,6 +416,7 @@ private:
virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
StringRef StringValue); StringRef StringValue);
virtual void emitArch(unsigned Arch); virtual void emitArch(unsigned Arch);
virtual void emitObjectArch(unsigned Arch);
virtual void emitFPU(unsigned FPU); virtual void emitFPU(unsigned FPU);
virtual void emitInst(uint32_t Inst, char Suffix = '\0'); virtual void emitInst(uint32_t Inst, char Suffix = '\0');
virtual void finishAttributeSection(); virtual void finishAttributeSection();
@ -421,8 +427,9 @@ private:
public: public:
ARMTargetELFStreamer(MCStreamer &S) ARMTargetELFStreamer(MCStreamer &S)
: ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU), : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU),
Arch(ARM::INVALID_ARCH), AttributeSection(0) {} Arch(ARM::INVALID_ARCH), EmittedArch(ARM::INVALID_ARCH),
AttributeSection(0) {}
}; };
/// Extend the generic ELFStreamer class so that it can emit mapping symbols at /// Extend the generic ELFStreamer class so that it can emit mapping symbols at
@ -714,10 +721,17 @@ void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
void ARMTargetELFStreamer::emitArch(unsigned Value) { void ARMTargetELFStreamer::emitArch(unsigned Value) {
Arch = Value; Arch = Value;
} }
void ARMTargetELFStreamer::emitObjectArch(unsigned Value) {
EmittedArch = Value;
}
void ARMTargetELFStreamer::emitArchDefaultAttributes() { void ARMTargetELFStreamer::emitArchDefaultAttributes() {
using namespace ARMBuildAttrs; using namespace ARMBuildAttrs;
setAttributeItem(CPU_name, GetArchDefaultCPUName(Arch), false); 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) { switch (Arch) {
case ARM::ARMV2: case ARM::ARMV2:

View File

@ -0,0 +1,22 @@
@ RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s \
@ RUN: | llvm-readobj -arm-attributes | FileCheck %s
.syntax unified
.object_arch armv4
.arch armv7
@ CHECK: FileAttributes {
@ CHECK: Attribute {
@ CHECK: Tag: 5
@ CHECK: TagName: CPU_name
@ CHECK: Value: 7
@ CHECK: }
@ CHECK: Attribute {
@ CHECK: Tag: 6
@ CHEKC: Value: 1
@ CHECK: TagName: CPU_arch
@ CHECK: Description: ARM v4
@ CHECK: }
@ CHECK: }

View File

@ -0,0 +1,11 @@
@ RUN: llvm-mc -triple armv7-eabi -filetype asm -o - %s | FileCheck %s
.syntax unified
.arch armv7
.object_arch armv4
@ CHECK: .text
@ CHECK: .arch armv7
@ CHECK: .object_arch armv4

View File

@ -0,0 +1,23 @@
@ RUN: not llvm-mc -triple armv7-eabi -filetype asm -o /dev/null %s 2>&1 \
@ RUN: | FileCheck %s
.syntax unified
.object_arch i686
@ CHECK: error: unknown architecture 'i686'
@ CHECK: .object_arch i686
@ CHECK: ^
.object_arch armv4!
@ CHECK: error: unexpected token
@ CHECK: .object_arch armv4!
@ CHECK: ^
.object_arch, invalid
@ CHECK: error: unexpected token
@ CHECK: .object_arch, invalid
@ CHECK: ^

View File

@ -0,0 +1,22 @@
@ RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s \
@ RUN: | llvm-readobj -arm-attributes | FileCheck %s
.syntax unified
.arch armv7
.object_arch armv4
@ CHECK: FileAttributes {
@ CHECK: Attribute {
@ CHECK: Tag: 5
@ CHECK: TagName: CPU_name
@ CHECK: Value: 7
@ CHECK: }
@ CHECK: Attribute {
@ CHECK: Tag: 6
@ CHEKC: Value: 1
@ CHECK: TagName: CPU_arch
@ CHECK: Description: ARM v4
@ CHECK: }
@ CHECK: }