ARM IAS: support .object_arch
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 30 Jan 2014 04:46:41 +0000 (04:46 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 30 Jan 2014 04:46:41 +0000 (04:46 +0000)
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
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
test/MC/ARM/directive-object_arch-2.s [new file with mode: 0644]
test/MC/ARM/directive-object_arch-3.s [new file with mode: 0644]
test/MC/ARM/directive-object_arch-diagnostics.s [new file with mode: 0644]
test/MC/ARM/directive-object_arch.s [new file with mode: 0644]

index f272572bb62535386ae064b12a02d7c9b8309472..4950197840156584a4a34c6df1f4d2e96336b764 100644 (file)
@@ -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;
 
index 531e2cc906aa153c74611c1e81504a1d26361627..74e4e66c6e704ebdd64fccfb8bfbc44037d23155 100644 (file)
@@ -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<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.
 extern "C" void LLVMInitializeARMAsmParser() {
   RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
index 151d48df63e06d6ff37a224cc65d1830a25d3258..44b56fbe199f56ada28ae01e8051c09ce6d4d140 100644 (file)
@@ -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<AttributeItem, 64> 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 (file)
index 0000000..3aca434
--- /dev/null
@@ -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 (file)
index 0000000..5dd2619
--- /dev/null
@@ -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 (file)
index 0000000..91b15c8
--- /dev/null
@@ -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 (file)
index 0000000..0707077
--- /dev/null
@@ -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: }
+