ARM IAS: improve .eabi_attribute handling
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 7 Jan 2014 02:28:42 +0000 (02:28 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 7 Jan 2014 02:28:42 +0000 (02:28 +0000)
Parse tag names as well as expressions.  The former is part of the
specification, the latter is for improved compatibility with the GNU assembler.
Fix attribute value handling to be comformant to the specification.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198662 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCStreamer.h
lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMBuildAttrs.h [deleted file]
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.cpp [new file with mode: 0644]
lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.h [new file with mode: 0644]
lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
lib/Target/ARM/MCTargetDesc/CMakeLists.txt
test/CodeGen/ARM/build-attributes-encoding.s
test/MC/ARM/directive-eabi_attribute-2.s [new file with mode: 0644]
test/MC/ARM/directive-eabi_attribute-diagnostics.s [new file with mode: 0644]

index e26b4116bbf1dab5adcd857150b6ed6ef97c248f..5579186ec9abdd1bd12593813323c054bfe2c1ba 100644 (file)
@@ -92,6 +92,8 @@ public:
   virtual void switchVendor(StringRef Vendor) = 0;
   virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0;
   virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0;
+  virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+                                   StringRef StringValue = "") = 0;
   virtual void emitFPU(unsigned FPU) = 0;
   virtual void emitArch(unsigned Arch) = 0;
   virtual void finishAttributeSection() = 0;
index 296bb0dcee8faf856e8f9f729d1207bd69403eb0..a0d2b75c03fae178c1623cb9a7f3cab1c1f93b00 100644 (file)
@@ -15,7 +15,6 @@
 #define DEBUG_TYPE "asm-printer"
 #include "ARMAsmPrinter.h"
 #include "ARM.h"
-#include "ARMBuildAttrs.h"
 #include "ARMConstantPoolValue.h"
 #include "ARMFPUName.h"
 #include "ARMMachineFunctionInfo.h"
@@ -23,6 +22,7 @@
 #include "ARMTargetObjectFile.h"
 #include "InstPrinter/ARMInstPrinter.h"
 #include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMBuildAttrs.h"
 #include "MCTargetDesc/ARMMCExpr.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
diff --git a/lib/Target/ARM/ARMBuildAttrs.h b/lib/Target/ARM/ARMBuildAttrs.h
deleted file mode 100644 (file)
index c80659f..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-//===-- ARMBuildAttrs.h - ARM Build Attributes ------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains enumerations and support routines for ARM build attributes
-// as defined in ARM ABI addenda document (ABI release 2.08).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __TARGET_ARMBUILDATTRS_H__
-#define __TARGET_ARMBUILDATTRS_H__
-
-namespace llvm {
-namespace ARMBuildAttrs {
-
-  enum SpecialAttr {
-    // This is for the .cpu asm attr. It translates into one or more
-    // AttrType (below) entries in the .ARM.attributes section in the ELF.
-    SEL_CPU
-  };
-
-  enum AttrType {
-    // Rest correspond to ELF/.ARM.attributes
-    File                      = 1,
-    Section                   = 2,
-    Symbol                    = 3,
-    CPU_raw_name              = 4,
-    CPU_name                  = 5,
-    CPU_arch                  = 6,
-    CPU_arch_profile          = 7,
-    ARM_ISA_use               = 8,
-    THUMB_ISA_use             = 9,
-    FP_arch                   = 10,
-    WMMX_arch                 = 11,
-    Advanced_SIMD_arch        = 12,
-    PCS_config                = 13,
-    ABI_PCS_R9_use            = 14,
-    ABI_PCS_RW_data           = 15,
-    ABI_PCS_RO_data           = 16,
-    ABI_PCS_GOT_use           = 17,
-    ABI_PCS_wchar_t           = 18,
-    ABI_FP_rounding           = 19,
-    ABI_FP_denormal           = 20,
-    ABI_FP_exceptions         = 21,
-    ABI_FP_user_exceptions    = 22,
-    ABI_FP_number_model       = 23,
-    ABI_align8_needed         = 24,
-    ABI_align8_preserved      = 25,
-    ABI_enum_size             = 26,
-    ABI_HardFP_use            = 27,
-    ABI_VFP_args              = 28,
-    ABI_WMMX_args             = 29,
-    ABI_optimization_goals    = 30,
-    ABI_FP_optimization_goals = 31,
-    compatibility             = 32,
-    CPU_unaligned_access      = 34,
-    FP_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_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
-    v8       = 14   // v8, AArch32
-  };
-
-  enum CPUArchProfile { // (=7), uleb128
-    Not_Applicable = 0, // pre v7, or cross-profile code
-    ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8)
-    RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4)
-    MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3)
-    SystemProfile = (0x53) // 'S' Application or real-time profile
-  };
-
-  // The following have a lot of common use cases
-  enum {
-    Not_Allowed = 0,
-    Allowed = 1,
-
-    // Tag_ARM_ISA_use (=8), uleb128
-
-    // Tag_THUMB_ISA_use, (=9), uleb128
-    AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
-
-    // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
-    AllowFPv2  = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA)
-    AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA)
-    AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31
-    AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA)
-    AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31
-    AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted
-    AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only D0-D15, S0-S31
-
-    // Tag_WMMX_arch, (=11), uleb128
-    AllowWMMXv1 = 1,  // The user permitted this entity to use WMMX v1
-    AllowWMMXv2 = 2,  // The user permitted this entity to use WMMX v2
-
-    // Tag_Advanced_SIMD_arch, (=12), uleb128
-    AllowNeon = 1, // SIMDv1 was permitted
-    AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
-    AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
-
-    // Tag_ABI_FP_denormal, (=20), uleb128
-    PreserveFPSign = 2, // sign when flushed-to-zero is preserved
-
-    // Tag_ABI_FP_number_model, (=23), uleb128
-    AllowRTABI = 2,  // numbers, infinities, and one quiet NaN (see [RTABI])
-    AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
-
-    // Tag_ABI_HardFP_use, (=27), uleb128
-    HardFPImplied = 0, // FP use should be implied by Tag_FP_arch
-    HardFPSinglePrecision = 1, // Single-precision only
-
-    // Tag_ABI_VFP_args, (=28), uleb128
-    BaseAAPCS = 0,
-    HardFPAAPCS = 1,
-
-    // Tag_FP_HP_extension, (=36), uleb128
-    AllowHPFP = 1, // Allow use of Half Precision FP
-
-    // Tag_MPextension_use, (=42), uleb128
-    AllowMP = 1, // Allow use of MP extensions
-
-    // Tag_DIV_use, (=44), uleb128
-    AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no info exists.
-    DisallowDIV = 1, // Hardware divide explicitly disallowed
-    AllowDIVExt = 2, // Allow hardware divide as optional architecture extension above
-                     // the base arch specified by Tag_CPU_arch and Tag_CPU_arch_profile.
-
-    // Tag_Virtualization_use, (=68), uleb128
-    AllowTZ = 1,
-    AllowVirtualization = 2,
-    AllowTZVirtualization = 3
-  };
-
-} // namespace ARMBuildAttrs
-} // namespace llvm
-
-#endif // __TARGET_ARMBUILDATTRS_H__
index be148ca7d29ac02adfd58efcd6607f9de93558ec..81cad168ae919f146de8404113e4a0849d148d9c 100644 (file)
@@ -7,11 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ARMBuildAttrs.h"
 #include "ARMFPUName.h"
 #include "ARMFeatures.h"
 #include "llvm/MC/MCTargetAsmParser.h"
 #include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMBuildAttrs.h"
 #include "MCTargetDesc/ARMArchName.h"
 #include "MCTargetDesc/ARMBaseInfo.h"
 #include "MCTargetDesc/ARMMCExpr.h"
@@ -8189,30 +8189,109 @@ bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
 }
 
 /// parseDirectiveEabiAttr
-///  ::= .eabi_attribute int, int
+///  ::= .eabi_attribute int, int [, "str"]
+///  ::= .eabi_attribute Tag_name, int [, "str"]
 bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
-  if (Parser.getTok().isNot(AsmToken::Integer)) {
-    Error(L, "integer expected");
-    return false;
+  int64_t Tag;
+  SMLoc TagLoc;
+
+  TagLoc = Parser.getTok().getLoc();
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    StringRef Name = Parser.getTok().getIdentifier();
+    Tag = ARMBuildAttrs::AttrTypeFromString(Name);
+    if (Tag == -1) {
+      Error(TagLoc, "attribute name not recognised: " + Name);
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+    Parser.Lex();
+  } else {
+    const MCExpr *AttrExpr;
+
+    TagLoc = Parser.getTok().getLoc();
+    if (Parser.parseExpression(AttrExpr)) {
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
+    if (!CE) {
+      Error(TagLoc, "expected numeric constant");
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+
+    Tag = CE->getValue();
   }
-  int64_t Tag = Parser.getTok().getIntVal();
-  Parser.Lex(); // eat tag integer
 
   if (Parser.getTok().isNot(AsmToken::Comma)) {
-    Error(L, "comma expected");
+    Error(Parser.getTok().getLoc(), "comma expected");
+    Parser.eatToEndOfStatement();
     return false;
   }
   Parser.Lex(); // skip comma
 
-  L = Parser.getTok().getLoc();
-  if (Parser.getTok().isNot(AsmToken::Integer)) {
-    Error(L, "integer expected");
-    return false;
+  StringRef StringValue = "";
+  bool IsStringValue = false;
+
+  int64_t IntegerValue = 0;
+  bool IsIntegerValue = false;
+
+  if (Tag == ARMBuildAttrs::CPU_raw_name || Tag == ARMBuildAttrs::CPU_name)
+    IsStringValue = true;
+  else if (Tag == ARMBuildAttrs::compatibility) {
+    IsStringValue = true;
+    IsIntegerValue = true;
+  } else if (Tag == ARMBuildAttrs::nodefaults || Tag < 32 || Tag % 2 == 0)
+    IsIntegerValue = true;
+  else if (Tag % 2 == 1)
+    IsStringValue = true;
+  else
+    llvm_unreachable("invalid tag type");
+
+  if (IsIntegerValue) {
+    const MCExpr *ValueExpr;
+    SMLoc ValueExprLoc = Parser.getTok().getLoc();
+    if (Parser.parseExpression(ValueExpr)) {
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
+    if (!CE) {
+      Error(ValueExprLoc, "expected numeric constant");
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+
+    IntegerValue = CE->getValue();
+  }
+
+  if (Tag == ARMBuildAttrs::compatibility) {
+    if (Parser.getTok().isNot(AsmToken::Comma))
+      IsStringValue = false;
+    else
+      Parser.Lex();
+  }
+
+  if (IsStringValue) {
+    if (Parser.getTok().isNot(AsmToken::String)) {
+      Error(Parser.getTok().getLoc(), "bad string constant");
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+
+    StringValue = Parser.getTok().getStringContents();
+    Parser.Lex();
   }
-  int64_t Value = Parser.getTok().getIntVal();
-  Parser.Lex(); // eat value integer
 
-  getTargetStreamer().emitAttribute(Tag, Value);
+  if (IsIntegerValue && IsStringValue) {
+    assert(Tag == ARMBuildAttrs::compatibility);
+    getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue);
+  } else if (IsIntegerValue)
+    getTargetStreamer().emitAttribute(Tag, IntegerValue);
+  else if (IsStringValue)
+    getTargetStreamer().emitTextAttribute(Tag, StringValue);
   return false;
 }
 
diff --git a/lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.cpp b/lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.cpp
new file mode 100644 (file)
index 0000000..9bb5072
--- /dev/null
@@ -0,0 +1,96 @@
+//===-- ARMBuildAttrs.cpp - ARM Build Attributes --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMBuildAttrs.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+namespace {
+const struct {
+  ARMBuildAttrs::AttrType Attr;
+  const char *TagName;
+} ARMAttributeTags[] = {
+  { ARMBuildAttrs::File, "Tag_File" },
+  { ARMBuildAttrs::Section, "Tag_Section" },
+  { ARMBuildAttrs::Symbol, "Tag_Symbol" },
+  { ARMBuildAttrs::CPU_raw_name, "Tag_CPU_raw_name" },
+  { ARMBuildAttrs::CPU_name, "Tag_CPU_name" },
+  { ARMBuildAttrs::CPU_arch, "Tag_CPU_arch" },
+  { ARMBuildAttrs::CPU_arch_profile, "Tag_CPU_arch_profile" },
+  { ARMBuildAttrs::ARM_ISA_use, "Tag_ARM_ISA_use" },
+  { ARMBuildAttrs::THUMB_ISA_use, "Tag_THUMB_ISA_use" },
+  { ARMBuildAttrs::FP_arch, "Tag_FP_arch" },
+  { ARMBuildAttrs::WMMX_arch, "Tag_WMMX_arch" },
+  { ARMBuildAttrs::Advanced_SIMD_arch, "Tag_Advanced_SIMD_arch" },
+  { ARMBuildAttrs::PCS_config, "Tag_PCS_config" },
+  { ARMBuildAttrs::ABI_PCS_R9_use, "Tag_ABI_PCS_R9_use" },
+  { ARMBuildAttrs::ABI_PCS_RW_data, "Tag_ABI_PCS_RW_data" },
+  { ARMBuildAttrs::ABI_PCS_RO_data, "Tag_ABI_PCS_RO_data" },
+  { ARMBuildAttrs::ABI_PCS_GOT_use, "Tag_ABI_PCS_GOT_use" },
+  { ARMBuildAttrs::ABI_PCS_wchar_t, "Tag_ABI_PCS_wchar_t" },
+  { ARMBuildAttrs::ABI_FP_rounding, "Tag_ABI_FP_rounding" },
+  { ARMBuildAttrs::ABI_FP_denormal, "Tag_ABI_FP_denormal" },
+  { ARMBuildAttrs::ABI_FP_exceptions, "Tag_ABI_FP_exceptions" },
+  { ARMBuildAttrs::ABI_FP_user_exceptions, "Tag_ABI_FP_user_exceptions" },
+  { ARMBuildAttrs::ABI_FP_number_model, "Tag_ABI_FP_number_model" },
+  { ARMBuildAttrs::ABI_align8_needed, "Tag_ABI_align8_needed" },
+  { ARMBuildAttrs::ABI_align8_preserved, "Tag_ABI_align8_preserved" },
+  { ARMBuildAttrs::ABI_enum_size, "Tag_ABI_enum_size" },
+  { ARMBuildAttrs::ABI_HardFP_use, "Tag_ABI_HardFP_use" },
+  { ARMBuildAttrs::ABI_VFP_args, "Tag_ABI_VFP_args" },
+  { ARMBuildAttrs::ABI_WMMX_args, "Tag_ABI_WMMX_args" },
+  { ARMBuildAttrs::ABI_optimization_goals, "Tag_ABI_optimization_goals" },
+  { ARMBuildAttrs::ABI_FP_optimization_goals, "Tag_ABI_FP_optimization_goals" },
+  { ARMBuildAttrs::compatibility, "Tag_compatibility" },
+  { ARMBuildAttrs::CPU_unaligned_access, "Tag_CPU_unaligned_access" },
+  { ARMBuildAttrs::FP_HP_extension, "Tag_FP_HP_extension" },
+  { ARMBuildAttrs::ABI_FP_16bit_format, "Tag_ABI_FP_16bit_format" },
+  { ARMBuildAttrs::MPextension_use, "Tag_MPextension_use" },
+  { ARMBuildAttrs::DIV_use, "Tag_DIV_use" },
+  { ARMBuildAttrs::nodefaults, "Tag_nodefaults" },
+  { ARMBuildAttrs::also_compatible_with, "Tag_also_compatible_with" },
+  { ARMBuildAttrs::T2EE_use, "Tag_T2EE_use" },
+  { ARMBuildAttrs::conformance, "Tag_conformance" },
+  { ARMBuildAttrs::Virtualization_use, "Tag_Virtualization_use" },
+
+  // Legacy Names
+  { ARMBuildAttrs::FP_arch, "Tag_VFP_arch" },
+  { ARMBuildAttrs::ABI_align8_needed, "Tag_ABI_align_needed" },
+  { ARMBuildAttrs::ABI_align8_preserved, "Tag_ABI_align_preserved" },
+  { ARMBuildAttrs::FP_HP_extension, "Tag_VFP_HP_extension" },
+};
+}
+
+namespace llvm {
+namespace ARMBuildAttrs {
+StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix) {
+  return AttrTypeAsString(static_cast<AttrType>(Attr), HasTagPrefix);
+}
+
+StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) {
+  for (unsigned TI = 0, TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags);
+       TI != TE; ++TI)
+    if (ARMAttributeTags[TI].Attr == Attr)
+      return ARMAttributeTags[TI].TagName + (HasTagPrefix ? 0 : 4);
+  return "";
+}
+
+int AttrTypeFromString(StringRef Tag) {
+  bool HasTagPrefix = Tag.startswith("Tag_");
+  for (unsigned TI = 0, TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags);
+       TI != TE; ++TI)
+    if (StringRef(ARMAttributeTags[TI].TagName + (HasTagPrefix ? 0 : 4)) == Tag)
+      return ARMAttributeTags[TI].Attr;
+  return -1;
+}
+}
+}
+
diff --git a/lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.h b/lib/Target/ARM/MCTargetDesc/ARMBuildAttrs.h
new file mode 100644 (file)
index 0000000..98cfecf
--- /dev/null
@@ -0,0 +1,177 @@
+//===-- ARMBuildAttrs.h - ARM Build Attributes ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for ARM build attributes
+// as defined in ARM ABI addenda document (ABI release 2.08).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __TARGET_ARMBUILDATTRS_H__
+#define __TARGET_ARMBUILDATTRS_H__
+
+namespace llvm {
+
+class StringRef;
+
+namespace ARMBuildAttrs {
+
+  enum SpecialAttr {
+    // This is for the .cpu asm attr. It translates into one or more
+    // AttrType (below) entries in the .ARM.attributes section in the ELF.
+    SEL_CPU
+  };
+
+  enum AttrType {
+    // Rest correspond to ELF/.ARM.attributes
+    File                      = 1,
+    Section                   = 2,
+    Symbol                    = 3,
+    CPU_raw_name              = 4,
+    CPU_name                  = 5,
+    CPU_arch                  = 6,
+    CPU_arch_profile          = 7,
+    ARM_ISA_use               = 8,
+    THUMB_ISA_use             = 9,
+    FP_arch                   = 10,
+    WMMX_arch                 = 11,
+    Advanced_SIMD_arch        = 12,
+    PCS_config                = 13,
+    ABI_PCS_R9_use            = 14,
+    ABI_PCS_RW_data           = 15,
+    ABI_PCS_RO_data           = 16,
+    ABI_PCS_GOT_use           = 17,
+    ABI_PCS_wchar_t           = 18,
+    ABI_FP_rounding           = 19,
+    ABI_FP_denormal           = 20,
+    ABI_FP_exceptions         = 21,
+    ABI_FP_user_exceptions    = 22,
+    ABI_FP_number_model       = 23,
+    ABI_align8_needed         = 24,
+    ABI_align8_preserved      = 25,
+    ABI_enum_size             = 26,
+    ABI_HardFP_use            = 27,
+    ABI_VFP_args              = 28,
+    ABI_WMMX_args             = 29,
+    ABI_optimization_goals    = 30,
+    ABI_FP_optimization_goals = 31,
+    compatibility             = 32,
+    CPU_unaligned_access      = 34,
+    FP_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_old       = 70
+  };
+
+  StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true);
+  StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
+  int AttrTypeFromString(StringRef Tag);
+
+  // 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
+    v8       = 14   // v8, AArch32
+  };
+
+  enum CPUArchProfile { // (=7), uleb128
+    Not_Applicable = 0, // pre v7, or cross-profile code
+    ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8)
+    RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4)
+    MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3)
+    SystemProfile = (0x53) // 'S' Application or real-time profile
+  };
+
+  // The following have a lot of common use cases
+  enum {
+    Not_Allowed = 0,
+    Allowed = 1,
+
+    // Tag_ARM_ISA_use (=8), uleb128
+
+    // Tag_THUMB_ISA_use, (=9), uleb128
+    AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
+
+    // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
+    AllowFPv2  = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA)
+    AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA)
+    AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31
+    AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA)
+    AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31
+    AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted
+    AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only D0-D15, S0-S31
+
+    // Tag_WMMX_arch, (=11), uleb128
+    AllowWMMXv1 = 1,  // The user permitted this entity to use WMMX v1
+    AllowWMMXv2 = 2,  // The user permitted this entity to use WMMX v2
+
+    // Tag_Advanced_SIMD_arch, (=12), uleb128
+    AllowNeon = 1, // SIMDv1 was permitted
+    AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
+    AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+
+    // Tag_ABI_FP_denormal, (=20), uleb128
+    PreserveFPSign = 2, // sign when flushed-to-zero is preserved
+
+    // Tag_ABI_FP_number_model, (=23), uleb128
+    AllowRTABI = 2,  // numbers, infinities, and one quiet NaN (see [RTABI])
+    AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
+
+    // Tag_ABI_HardFP_use, (=27), uleb128
+    HardFPImplied = 0, // FP use should be implied by Tag_FP_arch
+    HardFPSinglePrecision = 1, // Single-precision only
+
+    // Tag_ABI_VFP_args, (=28), uleb128
+    BaseAAPCS = 0,
+    HardFPAAPCS = 1,
+
+    // Tag_FP_HP_extension, (=36), uleb128
+    AllowHPFP = 1, // Allow use of Half Precision FP
+
+    // Tag_MPextension_use, (=42), uleb128
+    AllowMP = 1, // Allow use of MP extensions
+
+    // Tag_DIV_use, (=44), uleb128
+    AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no info exists.
+    DisallowDIV = 1, // Hardware divide explicitly disallowed
+    AllowDIVExt = 2, // Allow hardware divide as optional architecture extension above
+                     // the base arch specified by Tag_CPU_arch and Tag_CPU_arch_profile.
+
+    // Tag_Virtualization_use, (=68), uleb128
+    AllowTZ = 1,
+    AllowVirtualization = 2,
+    AllowTZVirtualization = 3
+  };
+
+} // namespace ARMBuildAttrs
+} // namespace llvm
+
+#endif // __TARGET_ARMBUILDATTRS_H__
index 3c0f82fd40f9cef3b6fd278ce7bb7b9127e314ea..1fb3beabd9ab849b3276cfccd8694d6fbc72901e 100644 (file)
@@ -125,6 +125,8 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer {
   virtual void switchVendor(StringRef Vendor);
   virtual void emitAttribute(unsigned Attribute, unsigned Value);
   virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+  virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+                                    StringRef StrinValue);
   virtual void emitArch(unsigned Arch);
   virtual void emitFPU(unsigned FPU);
   virtual void emitInst(uint32_t Inst, char Suffix = '\0');
@@ -182,11 +184,27 @@ void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
 void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
                                              StringRef String) {
   switch (Attribute) {
-  default: llvm_unreachable("Unsupported Text attribute in ASM Mode");
   case ARMBuildAttrs::CPU_name:
-    OS << "\t.cpu\t" << String.lower() << "\n";
+    OS << "\t.cpu\t" << String.lower();
+    break;
+  default:
+    OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\"";
     break;
   }
+  OS << "\n";
+}
+void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
+                                                unsigned IntValue,
+                                                StringRef StringValue) {
+  switch (Attribute) {
+  default: llvm_unreachable("unsupported multi-value attribute in asm mode");
+  case ARMBuildAttrs::compatibility:
+    OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue;
+    if (!StringValue.empty())
+      OS << ", \"" << StringValue << "\"";
+    break;
+  }
+  OS << "\n";
 }
 void ARMTargetAsmStreamer::emitArch(unsigned Arch) {
   OS << "\t.arch\t" << GetArchName(Arch) << "\n";
@@ -213,7 +231,8 @@ private:
     enum {
       HiddenAttribute = 0,
       NumericAttribute,
-      TextAttribute
+      TextAttribute,
+      NumericAndTextAttributes
     } Type;
     unsigned Tag;
     unsigned IntValue;
@@ -289,6 +308,27 @@ private:
     Contents.push_back(Item);
   }
 
+  void setAttributeItems(unsigned Attribute, unsigned IntValue,
+                         StringRef StringValue, bool OverwriteExisting) {
+    // Look for existing attribute item
+    if (AttributeItem *Item = getAttributeItem(Attribute)) {
+      if (!OverwriteExisting)
+        return;
+      Item->IntValue = IntValue;
+      Item->StringValue = StringValue;
+      return;
+    }
+
+    // Create new attribute item
+    AttributeItem Item = {
+      AttributeItem::NumericAndTextAttributes,
+      Attribute,
+      IntValue,
+      StringValue
+    };
+    Contents.push_back(Item);
+  }
+
   void emitArchDefaultAttributes();
   void emitFPUDefaultAttributes();
 
@@ -307,6 +347,8 @@ private:
   virtual void switchVendor(StringRef Vendor);
   virtual void emitAttribute(unsigned Attribute, unsigned Value);
   virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+  virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
+                                    StringRef StringValue);
   virtual void emitArch(unsigned Arch);
   virtual void emitFPU(unsigned FPU);
   virtual void emitInst(uint32_t Inst, char Suffix = '\0');
@@ -588,6 +630,12 @@ void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
                                              StringRef Value) {
   setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
 }
+void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
+                                                unsigned IntValue,
+                                                StringRef StringValue) {
+  setAttributeItems(Attribute, IntValue, StringValue,
+                    /* OverwriteExisting= */ true);
+}
 void ARMTargetELFStreamer::emitArch(unsigned Value) {
   Arch = Value;
 }
@@ -771,6 +819,11 @@ size_t ARMTargetELFStreamer::calculateContentSize() const {
       Result += getULEBSize(item.Tag);
       Result += item.StringValue.size() + 1; // string + '\0'
       break;
+    case AttributeItem::NumericAndTextAttributes:
+      Result += getULEBSize(item.Tag);
+      Result += getULEBSize(item.IntValue);
+      Result += item.StringValue.size() + 1; // string + '\0';
+      break;
     }
   }
   return Result;
@@ -841,6 +894,11 @@ void ARMTargetELFStreamer::finishAttributeSection() {
       Streamer.EmitBytes(item.StringValue.upper());
       Streamer.EmitIntValue(0, 1); // '\0'
       break;
+    case AttributeItem::NumericAndTextAttributes:
+      Streamer.EmitULEB128IntValue(item.IntValue);
+      Streamer.EmitBytes(item.StringValue.upper());
+      Streamer.EmitIntValue(0, 1); // '\0'
+      break;
     }
   }
 
index 162de7d21e2137127371af02f31d39a692a74321..a65f6ab896e7f9e1ea108de44c5d2cb8f87a29b9 100644 (file)
@@ -1,5 +1,6 @@
 add_llvm_library(LLVMARMDesc
   ARMAsmBackend.cpp
+  ARMBuildAttrs.cpp
   ARMELFObjectWriter.cpp
   ARMELFStreamer.cpp
   ARMMCAsmInfo.cpp
index 5ad51b284113d1bd84881a1f132492b0db934169..34a1ad38fb179a4c10fe0ba5947d598dd91efdba 100644 (file)
@@ -4,7 +4,7 @@
 // RUN:   | llvm-readobj -s -sd | FileCheck %s
 
 // Tag_CPU_name (=5)
-.cpu Cortex-A8
+.cpu cortex-a8
 
 // Tag_CPU_arch (=6)
 .eabi_attribute 6, 10
@@ -61,7 +61,7 @@
 .eabi_attribute 110, 160
 
 // Check that tags > 128 are encoded properly
-.eabi_attribute 129, 1
+.eabi_attribute 129, "1"
 .eabi_attribute 250, 1
 
 // CHECK:        Section {
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
 // CHECK-NEXT:     Offset: 0x34
-// CHECK-NEXT:     Size: 70
+// CHECK-NEXT:     Size: 71
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
 // CHECK-NEXT:     AddressAlignment: 1
 // CHECK-NEXT:     EntrySize: 0
 // CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 41450000 00616561 62690001 3B000000
+// CHECK-NEXT:       0000: 41460000 00616561 62690001 3C000000
 // CHECK-NEXT:       0010: 05434F52 5445582D 41380006 0A074108
 // CHECK-NEXT:       0020: 0109020A 030C0214 01150117 01180119
 // CHECK-NEXT:       0030: 011B001C 0124012A 012C0244 036EA001
-// CHECK-NEXT:       0040: 810101FA 0101
+// CHECK-NEXT:       0040: 81013100 FA0101
 // CHECK-NEXT:     )
diff --git a/test/MC/ARM/directive-eabi_attribute-2.s b/test/MC/ARM/directive-eabi_attribute-2.s
new file mode 100644 (file)
index 0000000..fc8dc61
--- /dev/null
@@ -0,0 +1,91 @@
+@ RUN: llvm-mc -triple armv7-elf -filetype asm -o - %s | FileCheck %s
+
+       .syntax unified
+       .thumb
+
+       .eabi_attribute Tag_CPU_raw_name, "Cortex-A9"
+@ CHECK: .eabi_attribute 4, "Cortex-A9"
+       .eabi_attribute Tag_CPU_name, "cortex-a9"
+@ CHECK: .cpu cortex-a9
+       .eabi_attribute Tag_CPU_arch, 10
+@ CHECK: .eabi_attribute 6, 10
+       .eabi_attribute Tag_CPU_arch_profile, 'A'
+@ CHECK: .eabi_attribute 7, 65
+       .eabi_attribute Tag_ARM_ISA_use, 0
+@ CHECK: .eabi_attribute 8, 0
+       .eabi_attribute Tag_THUMB_ISA_use, 2
+@ CHECK: .eabi_attribute 9, 2
+       .eabi_attribute Tag_FP_arch, 3
+@ CHECK: .eabi_attribute 10, 3
+       .eabi_attribute Tag_WMMX_arch, 0
+@ CHECK: .eabi_attribute 11, 0
+       .eabi_attribute Tag_Advanced_SIMD_arch, 1
+@ CHECK: .eabi_attribute 12, 1
+       .eabi_attribute Tag_PCS_config, 2
+@ CHECK: .eabi_attribute 13, 2
+       .eabi_attribute Tag_ABI_PCS_R9_use, 0
+@ CHECK: .eabi_attribute 14, 0
+       .eabi_attribute Tag_ABI_PCS_RW_data, 0
+@ CHECK: .eabi_attribute 15, 0
+       .eabi_attribute Tag_ABI_PCS_RO_data, 0
+@ CHECK: .eabi_attribute 16, 0
+       .eabi_attribute Tag_ABI_PCS_GOT_use, 0
+@ CHECK: .eabi_attribute 17, 0
+       .eabi_attribute Tag_ABI_PCS_wchar_t, 4
+@ CHECK: .eabi_attribute 18, 4
+       .eabi_attribute Tag_ABI_FP_rounding, 1
+@ CHECK: .eabi_attribute 19, 1
+       .eabi_attribute Tag_ABI_FP_denormal, 2
+@ CHECK: .eabi_attribute 20, 2
+       .eabi_attribute Tag_ABI_FP_exceptions, 1
+@ CHECK: .eabi_attribute 21, 1
+       .eabi_attribute Tag_ABI_FP_user_exceptions, 1
+@ CHECK: .eabi_attribute 22, 1
+       .eabi_attribute Tag_ABI_FP_number_model, 3
+@ CHECK: .eabi_attribute 23, 3
+       .eabi_attribute Tag_ABI_align8_needed, 1
+@ CHECK: .eabi_attribute 24, 1
+       .eabi_attribute Tag_ABI_align8_preserved, 2
+@ CHECK: .eabi_attribute 25, 2
+       .eabi_attribute Tag_ABI_enum_size, 3
+@ CHECK: .eabi_attribute 26, 3
+       .eabi_attribute Tag_ABI_HardFP_use, 0
+@ CHECK: .eabi_attribute 27, 0
+       .eabi_attribute Tag_ABI_VFP_args, 1
+@ CHECK: .eabi_attribute 28, 1
+       .eabi_attribute Tag_ABI_WMMX_args, 0
+@ CHECK: .eabi_attribute 29, 0
+       .eabi_attribute Tag_ABI_FP_optimization_goals, 1
+@ CHECK: .eabi_attribute 31, 1
+       .eabi_attribute Tag_compatibility, 1
+@ CHECK: .eabi_attribute 32, 1
+       .eabi_attribute Tag_compatibility, 1, "aeabi"
+@ CHECK: .eabi_attribute 32, 1, "aeabi"
+       .eabi_attribute Tag_CPU_unaligned_access, 0
+@ CHECK: .eabi_attribute 34, 0
+       .eabi_attribute Tag_FP_HP_extension, 0
+@ CHECK: .eabi_attribute 36, 0
+       .eabi_attribute Tag_ABI_FP_16bit_format, 0
+@ CHECK: .eabi_attribute 38, 0
+       .eabi_attribute Tag_MPextension_use, 0
+@ CHECK: .eabi_attribute 42, 0
+       .eabi_attribute Tag_DIV_use, 0
+@ CHECK: .eabi_attribute 44, 0
+       .eabi_attribute Tag_nodefaults, 0
+@ CHECK: .eabi_attribute 64, 0
+       .eabi_attribute Tag_also_compatible_with, "gnu"
+@ CHECK: .eabi_attribute 65, "gnu"
+       .eabi_attribute Tag_T2EE_use, 0
+@ CHECK: .eabi_attribute 66, 0
+       .eabi_attribute Tag_conformance, "2.09"
+@ CHECK: .eabi_attribute 67, "2.09"
+       .eabi_attribute Tag_Virtualization_use, 0
+@ CHECK: .eabi_attribute 68, 0
+
+@ ===--- GNU AS Compatibility Checks ---===
+
+       .eabi_attribute 2 * 2 + 1, "cortex-a9"
+@ CHECK: .cpu cortex-a9
+       .eabi_attribute 2 * 2 + 2, 5 * 2
+@ CHECK: .eabi_attribute 6, 10
+
diff --git a/test/MC/ARM/directive-eabi_attribute-diagnostics.s b/test/MC/ARM/directive-eabi_attribute-diagnostics.s
new file mode 100644 (file)
index 0000000..d1ae352
--- /dev/null
@@ -0,0 +1,36 @@
+@ RUN: not llvm-mc -triple armv7-elf -filetype asm -o /dev/null %s 2>&1 \
+@ RUN:   | FileCheck %s
+
+       .syntax unified
+       .thumb
+
+       .eabi_attribute Tag_unknown_name, 0
+@ CHECK: error: attribute name not recognised: Tag_unknown_name
+@ CHECK:       .eabi_attribute Tag_unknown_name
+@ CHECK:                        ^
+
+       .eabi_attribute [non_constant_expression], 0
+@ CHECK: error: expected numeric constant
+@ CHECK:       .eabi_attribute [non_constant_expression], 0
+@ CHECK:                        ^
+
+       .eabi_attribute 42, "forty two"
+@ CHECK: error: expected numeric constant
+@ CHECK:       .eabi_attribute 42, "forty two"
+@ CHECK:                            ^
+
+       .eabi_attribute 43, 43
+@ CHECK: error: bad string constant
+@ CHECK:       .eabi_attribute 43, 43
+@ CHECK:                            ^
+
+       .eabi_attribute 0
+@ CHECK: error: comma expected
+@ CHECK:       .eabi_attribute 0
+@ CHECK:                         ^
+
+       .eabi_attribute Tag_MPextension_use_old, 0
+@ CHECK: error: attribute name not recognised: Tag_MPextension_use_old
+@ CHECK:       .eabi_attribute Tag_MPextension_use_old, 0
+@ CHECK:                        ^
+