From 09f38a0ef13bf542f7b3f1862d718e33e7de587b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 30 Jan 2014 04:46:41 +0000 Subject: [PATCH] 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 --- include/llvm/MC/MCStreamer.h | 1 + lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 42 +++++++++++++++++++ .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 20 +++++++-- test/MC/ARM/directive-object_arch-2.s | 22 ++++++++++ test/MC/ARM/directive-object_arch-3.s | 11 +++++ .../ARM/directive-object_arch-diagnostics.s | 23 ++++++++++ test/MC/ARM/directive-object_arch.s | 22 ++++++++++ 7 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 test/MC/ARM/directive-object_arch-2.s create mode 100644 test/MC/ARM/directive-object_arch-3.s create mode 100644 test/MC/ARM/directive-object_arch-diagnostics.s create mode 100644 test/MC/ARM/directive-object_arch.s diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index f272572bb62..49501978401 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -107,6 +107,7 @@ public: StringRef StringValue = "") = 0; virtual void emitFPU(unsigned FPU) = 0; virtual void emitArch(unsigned Arch) = 0; + virtual void emitObjectArch(unsigned Arch) = 0; virtual void finishAttributeSection() = 0; virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 531e2cc906a..74e4e66c6e7 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -298,6 +298,7 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveUnwindRaw(SMLoc L); bool parseDirectiveTLSDescSeq(SMLoc L); bool parseDirectiveMovSP(SMLoc L); + bool parseDirectiveObjectArch(SMLoc L); StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, bool &CarrySetting, unsigned &ProcessorIMod, @@ -8090,6 +8091,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveTLSDescSeq(DirectiveID.getLoc()); else if (IDVal == ".movsp") return parseDirectiveMovSP(DirectiveID.getLoc()); + else if (IDVal == ".object_arch") + return parseDirectiveObjectArch(DirectiveID.getLoc()); return true; } @@ -9094,6 +9097,45 @@ bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { 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(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. extern "C" void LLVMInitializeARMAsmParser() { RegisterMCAsmParser X(TheARMTarget); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 151d48df63e..44b56fbe199 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -136,6 +136,7 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer { 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(); @@ -249,6 +250,9 @@ void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, 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"; } @@ -300,6 +304,7 @@ private: StringRef CurrentVendor; unsigned FPU; unsigned Arch; + unsigned EmittedArch; SmallVector Contents; const MCSection *AttributeSection; @@ -411,6 +416,7 @@ private: 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(); @@ -421,8 +427,9 @@ private: public: ARMTargetELFStreamer(MCStreamer &S) - : ARMTargetStreamer(S), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU), - Arch(ARM::INVALID_ARCH), AttributeSection(0) {} + : 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 @@ -714,10 +721,17 @@ void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, 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: diff --git a/test/MC/ARM/directive-object_arch-2.s b/test/MC/ARM/directive-object_arch-2.s new file mode 100644 index 00000000000..3aca434a1e4 --- /dev/null +++ b/test/MC/ARM/directive-object_arch-2.s @@ -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: } + diff --git a/test/MC/ARM/directive-object_arch-3.s b/test/MC/ARM/directive-object_arch-3.s new file mode 100644 index 00000000000..5dd26197ab1 --- /dev/null +++ b/test/MC/ARM/directive-object_arch-3.s @@ -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 + diff --git a/test/MC/ARM/directive-object_arch-diagnostics.s b/test/MC/ARM/directive-object_arch-diagnostics.s new file mode 100644 index 00000000000..91b15c8d2d8 --- /dev/null +++ b/test/MC/ARM/directive-object_arch-diagnostics.s @@ -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: ^ + diff --git a/test/MC/ARM/directive-object_arch.s b/test/MC/ARM/directive-object_arch.s new file mode 100644 index 00000000000..0707077630e --- /dev/null +++ b/test/MC/ARM/directive-object_arch.s @@ -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: } +