[mips] Improve encapsulation of the .MIPS.abiflags implementation and limit scope...
authorDaniel Sanders <daniel.sanders@imgtec.com>
Tue, 8 Jul 2014 10:11:38 +0000 (10:11 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Tue, 8 Jul 2014 10:11:38 +0000 (10:11 +0000)
Summary:
Follow on to r212519 to improve the encapsulation and limit the scope of the enums.

Also merged two very similar parser functions, fixed a bug where ASE's
were not being reported, and marked CPR1's as being 128-bit when MSA is
enabled.

Differential Revision: http://reviews.llvm.org/D4384

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MCTargetDesc/CMakeLists.txt
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp [new file with mode: 0644]
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h [new file with mode: 0644]
lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsTargetStreamer.h
test/MC/Mips/msa/abiflags.s [new file with mode: 0644]

index 4a0059d..92deb3b 100644 (file)
@@ -38,7 +38,7 @@ class MCInstrInfo;
 namespace {
 class MipsAssemblerOptions {
 public:
-  MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true), fpAbiMode(0) {}
+  MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
 
   unsigned getATRegNum() { return aTReg; }
   bool setATReg(unsigned Reg);
@@ -46,18 +46,15 @@ public:
   bool isReorder() { return reorder; }
   void setReorder() { reorder = true; }
   void setNoreorder() { reorder = false; }
-  void setFpAbiMode(int Mode) { fpAbiMode = Mode; }
 
   bool isMacro() { return macro; }
   void setMacro() { macro = true; }
   void setNomacro() { macro = false; }
-  int getFpAbiMode() { return fpAbiMode; }
 
 private:
   unsigned aTReg;
   bool reorder;
   bool macro;
-  int fpAbiMode;
 };
 }
 
@@ -136,8 +133,8 @@ class MipsAsmParser : public MCTargetAsmParser {
   void expandMemInst(MCInst &Inst, SMLoc IDLoc,
                      SmallVectorImpl<MCInst> &Instructions, bool isLoad,
                      bool isImmOpnd);
-  bool reportParseError(StringRef ErrorMsg);
-  bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
+  bool reportParseError(Twine ErrorMsg);
+  bool reportParseError(SMLoc Loc, Twine ErrorMsg);
 
   bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
   bool parseRelocOperand(const MCExpr *&Res);
@@ -167,6 +164,8 @@ class MipsAsmParser : public MCTargetAsmParser {
   bool parseDirectiveGpWord();
   bool parseDirectiveGpDWord();
   bool parseDirectiveModule();
+  bool parseDirectiveModuleFP();
+  bool parseFpABIValue(Val_GNU_MIPS_ABI &FpABI, StringRef Directive);
 
   MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
 
@@ -2304,13 +2303,13 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
   return false;
 }
 
-bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
+bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
   SMLoc Loc = getLexer().getLoc();
   Parser.eatToEndOfStatement();
   return Error(Loc, ErrorMsg);
 }
 
-bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
+bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
   return Error(Loc, ErrorMsg);
 }
 
@@ -2445,7 +2444,7 @@ bool MipsAsmParser::parseSetNoMips16Directive() {
 }
 
 bool MipsAsmParser::parseSetFpDirective() {
-  int FpAbiMode;
+  Val_GNU_MIPS_ABI FpAbiVal;
   // Line can be: .set fp=32
   //              .set fp=xx
   //              .set fp=64
@@ -2457,43 +2456,15 @@ bool MipsAsmParser::parseSetFpDirective() {
   }
   Parser.Lex(); // Eat '=' token.
   Tok = Parser.getTok();
-  if (Tok.is(AsmToken::Identifier)) {
-    StringRef XX = Tok.getString();
-    if (XX != "xx") {
-      reportParseError("unsupported option");
-      return false;
-    }
-    if (!isABI_O32()) {
-      reportParseError("'set fp=xx'option requires O32 ABI");
-      return false;
-    }
-    FpAbiMode = Val_GNU_MIPS_ABI_FP_XX;
-  } else if (Tok.is(AsmToken::Integer)) {
-    unsigned Value = Tok.getIntVal();
-    if (Value != 32 && Value != 64) {
-      reportParseError("unsupported option");
-      return false;
-    }
-    if (Value == 32) {
-      if (!isABI_O32()) {
-        reportParseError("'set fp=32'option requires O32 ABI");
-        return false;
-      }
-      FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
-    } else {
-      if (isABI_N32() || isABI_N64())
-        FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
-      else if (isABI_O32())
-        FpAbiMode = Val_GNU_MIPS_ABI_FP_64;
-    }
-  }
-  Parser.Lex(); // Eat option token.
+
+  if (!parseFpABIValue(FpAbiVal, ".set"))
+    return false;
+
   if (getLexer().isNot(AsmToken::EndOfStatement)) {
     reportParseError("unexpected token in statement");
     return false;
   }
-  Options.setFpAbiMode(FpAbiMode);
-  getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32());
+  getTargetStreamer().emitDirectiveSetFp(FpAbiVal, isABI_O32());
   Parser.Lex(); // Consume the EndOfStatement.
   return false;
 }
@@ -2817,7 +2788,6 @@ bool MipsAsmParser::parseDirectiveModule() {
   // Line can be: .module fp=32
   //              .module fp=xx
   //              .module fp=64
-  unsigned FpAbiVal = 0;
   if (!getTargetStreamer().getCanHaveModuleDir()) {
     // TODO : get a better message.
     reportParseError(".module directive must appear before any code");
@@ -2835,39 +2805,76 @@ bool MipsAsmParser::parseDirectiveModule() {
     return false;
   }
   Parser.Lex(); // Eat '=' token.
-  Tok = Parser.getTok();
-  if (Tok.is(AsmToken::Identifier)) {
-    StringRef XX = Tok.getString();
-    if (XX != "xx") {
-      reportParseError("unsupported option");
+
+  Val_GNU_MIPS_ABI FpABI;
+  if (!parseFpABIValue(FpABI, ".module"))
+    return false;
+
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("unexpected token in statement");
+    return false;
+  }
+
+  return false;
+}
+
+bool MipsAsmParser::parseFpABIValue(Val_GNU_MIPS_ABI &FpABI,
+                                    StringRef Directive) {
+  MCAsmLexer &Lexer = getLexer();
+
+  if (Lexer.is(AsmToken::Identifier)) {
+    StringRef Value = Parser.getTok().getString();
+    Parser.Lex();
+
+    if (Value != "xx") {
+      reportParseError("unsupported value, expected 'xx', '32' or '64'");
+      return false;
+    }
+
+    if (!isABI_O32()) {
+      reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
       return false;
     }
-    FpAbiVal = Val_GNU_MIPS_ABI_FP_XX;
-  } else if (Tok.is(AsmToken::Integer)) {
-    unsigned Value = Tok.getIntVal();
+
+    FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_XX;
+    return true;
+  }
+
+  if (Lexer.is(AsmToken::Integer)) {
+    unsigned Value = Parser.getTok().getIntVal();
+    Parser.Lex();
+
     if (Value != 32 && Value != 64) {
-      reportParseError("unsupported value, expected 32 or 64");
+      reportParseError("unsupported value, expected 'xx', '32' or '64'");
       return false;
     }
-    if (Value == 64) {
-      if (isABI_N32() || isABI_N64())
-        FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
-      else if (isABI_O32())
-        FpAbiVal = Val_GNU_MIPS_ABI_FP_64;
-    } else if (isABI_O32())
-      FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
-  }
-  Parser.Lex(); // Eat option token.
-  if (getLexer().isNot(AsmToken::EndOfStatement)) {
-    reportParseError("unexpected token in statement");
-    return false;
+
+    if (Value == 32) {
+      if (!isABI_O32()) {
+        reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
+        return false;
+      }
+
+      FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE;
+      return true;
+    } else {
+      if (isABI_N32() || isABI_N64()) {
+        FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE;
+        return true;
+      }
+
+      if (isABI_O32()) {
+        FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64;
+        return true;
+      }
+
+      llvm_unreachable("Unknown ABI");
+    }
   }
-  // Emit appropriate flags.
-  getTargetStreamer().emitDirectiveModule(FpAbiVal, isABI_O32());
-  getTargetStreamer().setFpABI(FpAbiVal);
-  Parser.Lex(); // Consume the EndOfStatement.
+
   return false;
 }
+
 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getString();
 
index d3e2fd7..c14ee35 100644 (file)
@@ -1,4 +1,5 @@
 add_llvm_library(LLVMMipsDesc
+  MipsABIFlagsSection.cpp
   MipsAsmBackend.cpp
   MipsELFObjectWriter.cpp
   MipsELFStreamer.cpp
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
new file mode 100644 (file)
index 0000000..a901af2
--- /dev/null
@@ -0,0 +1,46 @@
+//===-- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsABIFlagsSection.h"
+
+using namespace llvm;
+
+StringRef MipsABIFlagsSection::getFpABIString(Val_GNU_MIPS_ABI Value,
+                                              bool Is32BitAbi) {
+  switch (Value) {
+  case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_XX:
+    return "xx";
+  case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64:
+    return "64";
+  case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE:
+    if (Is32BitAbi)
+      return "32";
+    return "64";
+  default:
+    llvm_unreachable("unsupported fp abi value");
+  }
+}
+
+namespace llvm {
+MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) {
+  // Write out a Elf_Internal_ABIFlags_v0 struct
+  OS.EmitIntValue(ABIFlagsSection.getVersion(), 2);         // version
+  OS.EmitIntValue(ABIFlagsSection.getISALevel(), 1);        // isa_level
+  OS.EmitIntValue(ABIFlagsSection.getISARevision(), 1);     // isa_rev
+  OS.EmitIntValue(ABIFlagsSection.getGPRSize(), 1);         // gpr_size
+  OS.EmitIntValue(ABIFlagsSection.getCPR1Size(), 1);        // cpr1_size
+  OS.EmitIntValue(ABIFlagsSection.getCPR2Size(), 1);        // cpr2_size
+  OS.EmitIntValue(ABIFlagsSection.getFpABI(), 1);           // fp_abi
+  OS.EmitIntValue(ABIFlagsSection.getISAExtensionSet(), 4); // isa_ext
+  OS.EmitIntValue(ABIFlagsSection.getASESet(), 4);          // ases
+  OS.EmitIntValue(ABIFlagsSection.getFlags1(), 4);          // flags1
+  OS.EmitIntValue(ABIFlagsSection.getFlags2(), 4);          // flags2
+  return OS;
+}
+}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
new file mode 100644 (file)
index 0000000..ed6df5a
--- /dev/null
@@ -0,0 +1,206 @@
+//===-- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -----*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSABIFLAGSSECTION_H
+#define MIPSABIFLAGSSECTION_H
+
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+
+class MCStreamer;
+
+struct MipsABIFlagsSection {
+  // Values for the xxx_size bytes of an ABI flags structure.
+  enum AFL_REG {
+    AFL_REG_NONE = 0x00, // No registers.
+    AFL_REG_32 = 0x01,   // 32-bit registers.
+    AFL_REG_64 = 0x02,   // 64-bit registers.
+    AFL_REG_128 = 0x03   // 128-bit registers.
+  };
+
+  // Masks for the ases word of an ABI flags structure.
+  enum AFL_ASE {
+    AFL_ASE_DSP = 0x00000001,       // DSP ASE.
+    AFL_ASE_DSPR2 = 0x00000002,     // DSP R2 ASE.
+    AFL_ASE_EVA = 0x00000004,       // Enhanced VA Scheme.
+    AFL_ASE_MCU = 0x00000008,       // MCU (MicroController) ASE.
+    AFL_ASE_MDMX = 0x00000010,      // MDMX ASE.
+    AFL_ASE_MIPS3D = 0x00000020,    // MIPS-3D ASE.
+    AFL_ASE_MT = 0x00000040,        // MT ASE.
+    AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE.
+    AFL_ASE_VIRT = 0x00000100,      // VZ ASE.
+    AFL_ASE_MSA = 0x00000200,       // MSA ASE.
+    AFL_ASE_MIPS16 = 0x00000400,    // MIPS16 ASE.
+    AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE.
+    AFL_ASE_XPA = 0x00001000        // XPA ASE.
+  };
+
+  // Values for the isa_ext word of an ABI flags structure.
+  enum AFL_EXT {
+    AFL_EXT_XLR = 1,          // RMI Xlr instruction.
+    AFL_EXT_OCTEON2 = 2,      // Cavium Networks Octeon2.
+    AFL_EXT_OCTEONP = 3,      // Cavium Networks OcteonP.
+    AFL_EXT_LOONGSON_3A = 4,  // Loongson 3A.
+    AFL_EXT_OCTEON = 5,       // Cavium Networks Octeon.
+    AFL_EXT_5900 = 6,         // MIPS R5900 instruction.
+    AFL_EXT_4650 = 7,         // MIPS R4650 instruction.
+    AFL_EXT_4010 = 8,         // LSI R4010 instruction.
+    AFL_EXT_4100 = 9,         // NEC VR4100 instruction.
+    AFL_EXT_3900 = 10,        // Toshiba R3900 instruction.
+    AFL_EXT_10000 = 11,       // MIPS R10000 instruction.
+    AFL_EXT_SB1 = 12,         // Broadcom SB-1 instruction.
+    AFL_EXT_4111 = 13,        // NEC VR4111/VR4181 instruction.
+    AFL_EXT_4120 = 14,        // NEC VR4120 instruction.
+    AFL_EXT_5400 = 15,        // NEC VR5400 instruction.
+    AFL_EXT_5500 = 16,        // NEC VR5500 instruction.
+    AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E.
+    AFL_EXT_LOONGSON_2F = 18  // ST Microelectronics Loongson 2F.
+  };
+
+  // Values for the fp_abi word of an ABI flags structure.
+  enum Val_GNU_MIPS_ABI {
+    Val_GNU_MIPS_ABI_FP_ANY = 0,
+    Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+    Val_GNU_MIPS_ABI_FP_XX = 5,
+    Val_GNU_MIPS_ABI_FP_64 = 6
+  };
+
+  // Version of flags structure.
+  uint16_t Version;
+  // The level of the ISA: 1-5, 32, 64.
+  uint8_t ISALevel;
+  // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
+  uint8_t ISARevision;
+  // The size of general purpose registers.
+  AFL_REG GPRSize;
+  // The size of co-processor 1 registers.
+  AFL_REG CPR1Size;
+  // The size of co-processor 2 registers.
+  AFL_REG CPR2Size;
+  // The floating-point ABI.
+  Val_GNU_MIPS_ABI FpABI;
+  // Processor-specific extension.
+  uint32_t ISAExtensionSet;
+  // Mask of ASEs used.
+  uint32_t ASESet;
+
+  MipsABIFlagsSection()
+      : Version(0), ISALevel(0), ISARevision(0), GPRSize(AFL_REG_NONE),
+        CPR1Size(AFL_REG_NONE), CPR2Size(AFL_REG_NONE),
+        FpABI(Val_GNU_MIPS_ABI_FP_ANY), ISAExtensionSet(0), ASESet(0) {}
+
+  uint16_t getVersion() { return (uint16_t)Version; }
+  uint8_t getISALevel() { return (uint8_t)ISALevel; }
+  uint8_t getISARevision() { return (uint8_t)ISARevision; }
+  uint8_t getGPRSize() { return (uint8_t)GPRSize; }
+  uint8_t getCPR1Size() { return (uint8_t)CPR1Size; }
+  uint8_t getCPR2Size() { return (uint8_t)CPR2Size; }
+  uint8_t getFpABI() { return (uint8_t)FpABI; }
+  uint32_t getISAExtensionSet() { return (uint32_t)ISAExtensionSet; }
+  uint32_t getASESet() { return (uint32_t)ASESet; }
+  uint32_t getFlags1() { return 0; }
+  uint32_t getFlags2() { return 0; }
+
+  StringRef getFpABIString(Val_GNU_MIPS_ABI Value, bool Is32BitAbi);
+
+  template <class PredicateLibrary>
+  void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) {
+    if (P.hasMips64()) {
+      ISALevel = 64;
+      if (P.hasMips64r6())
+        ISARevision = 6;
+      else if (P.hasMips64r2())
+        ISARevision = 2;
+      else
+        ISARevision = 1;
+    } else if (P.hasMips32()) {
+      ISALevel = 32;
+      if (P.hasMips32r6())
+        ISARevision = 6;
+      else if (P.hasMips32r2())
+        ISARevision = 2;
+      else
+        ISARevision = 1;
+    } else {
+      ISARevision = 0;
+      if (P.hasMips5())
+        ISALevel = 5;
+      else if (P.hasMips4())
+        ISALevel = 4;
+      else if (P.hasMips3())
+        ISALevel = 3;
+      else if (P.hasMips2())
+        ISALevel = 2;
+      else if (P.hasMips1())
+        ISALevel = 1;
+      else
+        llvm_unreachable("Unknown ISA level!");
+    }
+  }
+
+  template <class PredicateLibrary>
+  void setGPRSizeFromPredicates(const PredicateLibrary &P) {
+    GPRSize = P.isGP64bit() ? AFL_REG_64 : AFL_REG_32;
+  }
+
+  template <class PredicateLibrary>
+  void setCPR1SizeFromPredicates(const PredicateLibrary &P) {
+    if (P.mipsSEUsesSoftFloat())
+      CPR1Size = AFL_REG_NONE;
+    else if (P.hasMSA())
+      CPR1Size = AFL_REG_128;
+    else
+      CPR1Size = P.isFP64bit() ? AFL_REG_64 : AFL_REG_32;
+  }
+
+  template <class PredicateLibrary>
+  void setASESetFromPredicates(const PredicateLibrary &P) {
+    ASESet = 0;
+    if (P.hasDSP())
+      ASESet |= AFL_ASE_DSP;
+    if (P.hasDSPR2())
+      ASESet |= AFL_ASE_DSPR2;
+    if (P.hasMSA())
+      ASESet |= AFL_ASE_MSA;
+    if (P.inMicroMipsMode())
+      ASESet |= AFL_ASE_MICROMIPS;
+    if (P.inMips16Mode())
+      ASESet |= AFL_ASE_MIPS16;
+  }
+
+  template <class PredicateLibrary>
+  void setFpAbiFromPredicates(const PredicateLibrary &P) {
+    FpABI = Val_GNU_MIPS_ABI_FP_ANY;
+    if (P.isABI_N32() || P.isABI_N64())
+      FpABI = Val_GNU_MIPS_ABI_FP_DOUBLE;
+    else if (P.isABI_O32()) {
+      if (P.isFP64bit())
+        FpABI = Val_GNU_MIPS_ABI_FP_64;
+      else if (P.isABI_FPXX())
+        FpABI = Val_GNU_MIPS_ABI_FP_XX;
+      else
+        FpABI = Val_GNU_MIPS_ABI_FP_DOUBLE;
+    }
+  }
+
+  template <class PredicateLibrary>
+  void setAllFromPredicates(const PredicateLibrary &P) {
+    setISALevelAndRevisionFromPredicates(P);
+    setGPRSizeFromPredicates(P);
+    setCPR1SizeFromPredicates(P);
+    setASESetFromPredicates(P);
+    setFpAbiFromPredicates(P);
+  }
+};
+
+MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
+}
+
+#endif
index a81849e..5ebcbc8 100644 (file)
@@ -211,50 +211,20 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
   setCanHaveModuleDir(false);
 }
 
-void MipsTargetAsmStreamer::emitDirectiveModule(unsigned Value,
-                                                bool is32BitAbi) {
+void MipsTargetAsmStreamer::emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value,
+                                                  bool Is32BitAbi) {
+  MipsTargetStreamer::emitDirectiveModuleFP(Value, Is32BitAbi);
+
   StringRef ModuleValue;
   OS << "\t.module\tfp=";
-  switch (Value) {
-  case Val_GNU_MIPS_ABI_FP_XX:
-    ModuleValue = "xx";
-    break;
-  case Val_GNU_MIPS_ABI_FP_64:
-    ModuleValue = "64";
-    break;
-  case Val_GNU_MIPS_ABI_FP_DOUBLE:
-    if (is32BitAbi)
-      ModuleValue = "32";
-    else
-      ModuleValue = "64";
-    break;
-  default:
-    llvm_unreachable("unsupported .module value");
-  }
-  OS << ModuleValue << "\n";
+  OS << ABIFlagsSection.getFpABIString(Value, Is32BitAbi) << "\n";
 }
 
-void MipsTargetAsmStreamer::emitDirectiveSetFp(unsigned Value,
-                                               bool is32BitAbi) {
+void MipsTargetAsmStreamer::emitDirectiveSetFp(Val_GNU_MIPS_ABI Value,
+                                               bool Is32BitAbi) {
   StringRef ModuleValue;
   OS << "\t.set\tfp=";
-  switch (Value) {
-  case Val_GNU_MIPS_ABI_FP_XX:
-    ModuleValue = "xx";
-    break;
-  case Val_GNU_MIPS_ABI_FP_64:
-    ModuleValue = "64";
-    break;
-  case Val_GNU_MIPS_ABI_FP_DOUBLE:
-    if (is32BitAbi)
-      ModuleValue = "32";
-    else
-      ModuleValue = "64";
-    break;
-  default:
-    llvm_unreachable("unsupported .set fp value");
-  }
-  OS << ModuleValue << "\n";
+  OS << ABIFlagsSection.getFpABIString(Value, Is32BitAbi) << "\n";
 }
 
 void MipsTargetAsmStreamer::emitMipsAbiFlags() {
@@ -661,15 +631,5 @@ void MipsTargetELFStreamer::emitMipsAbiFlags() {
   ABIShndxSD.setAlignment(8);
   OS.SwitchSection(Sec);
 
-  OS.EmitIntValue(MipsABIFlags.version, 2);   // version
-  OS.EmitIntValue(MipsABIFlags.isa_level, 1); // isa_level
-  OS.EmitIntValue(MipsABIFlags.isa_rev, 1);   // isa_rev
-  OS.EmitIntValue(MipsABIFlags.gpr_size, 1);  // gpr_size
-  OS.EmitIntValue(MipsABIFlags.cpr1_size, 1); // cpr1_size
-  OS.EmitIntValue(MipsABIFlags.cpr2_size, 1); // cpr2_size
-  OS.EmitIntValue(MipsABIFlags.fp_abi, 1);    // fp_abi
-  OS.EmitIntValue(MipsABIFlags.isa_ext, 4);   // isa_ext
-  OS.EmitIntValue(MipsABIFlags.ases, 4);      // ases
-  OS.EmitIntValue(MipsABIFlags.flags1, 4);    // flags1
-  OS.EmitIntValue(MipsABIFlags.flags2, 4);    // flags2
+  OS << ABIFlagsSection;
 }
index 6070932..16db9ac 100644 (file)
@@ -94,6 +94,7 @@ bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) {
 void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   MipsTargetStreamer &TS = getTargetStreamer();
   TS.setCanHaveModuleDir(false);
+
   if (MI->isDebugValue()) {
     SmallString<128> Str;
     raw_svector_ostream OS(Str);
@@ -660,18 +661,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
                                    SectionKind::getDataRel()));
   }
   getTargetStreamer().updateABIInfo(*Subtarget);
-  unsigned FpAbiVal;
-  if (Subtarget->isABI_N32() || Subtarget->isABI_N64())
-    FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
-  else if(Subtarget->isABI_O32()) {
-    if (Subtarget->isFP64bit())
-      FpAbiVal = Val_GNU_MIPS_ABI_FP_64;
-    else if(Subtarget->isABI_FPXX())
-      FpAbiVal = Val_GNU_MIPS_ABI_FP_XX;
-    else
-      FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
-  }
-  getTargetStreamer().emitDirectiveModule(FpAbiVal, Subtarget->isABI_O32());
+  getTargetStreamer().emitDirectiveModuleFP(
+      getTargetStreamer().getABIFlagsSection().FpABI, Subtarget->isABI_O32());
 }
 
 void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) {
index a0edc6f..1839082 100644 (file)
 
 #include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCStreamer.h"
+#include "MCTargetDesc/MipsABIFlagsSection.h"
 
 namespace llvm {
-struct Elf_Internal_ABIFlags_v0 {
-  // Version of flags structure.
-  uint16_t version;
-  // The level of the ISA: 1-5, 32, 64.
-  uint8_t isa_level;
-  // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
-  uint8_t isa_rev;
-  // The size of general purpose registers.
-  uint8_t gpr_size;
-  // The size of co-processor 1 registers.
-  uint8_t cpr1_size;
-  // The size of co-processor 2 registers.
-  uint8_t cpr2_size;
-  // The floating-point ABI.
-  uint8_t fp_abi;
-  // Processor-specific extension.
-  uint32_t isa_ext;
-  // Mask of ASEs used.
-  uint32_t ases;
-  // Mask of general flags.
-  uint32_t flags1;
-  uint32_t flags2;
 
-  Elf_Internal_ABIFlags_v0()
-      : version(0), isa_level(0), isa_rev(0), gpr_size(0), cpr1_size(0),
-        cpr2_size(0), fp_abi(0), isa_ext(0), ases(0), flags1(0), flags2(0) {}
-};
-
-// Values for the xxx_size bytes of an ABI flags structure.
-enum {
-  AFL_REG_NONE = 0x00, // No registers.
-  AFL_REG_32 = 0x01,   // 32-bit registers.
-  AFL_REG_64 = 0x02,   // 64-bit registers.
-  AFL_REG_128 = 0x03   // 128-bit registers.
-};
-
-// Masks for the ases word of an ABI flags structure.
-enum {
-  AFL_ASE_DSP = 0x00000001,       // DSP ASE.
-  AFL_ASE_DSPR2 = 0x00000002,     // DSP R2 ASE.
-  AFL_ASE_EVA = 0x00000004,       // Enhanced VA Scheme.
-  AFL_ASE_MCU = 0x00000008,       // MCU (MicroController) ASE.
-  AFL_ASE_MDMX = 0x00000010,      // MDMX ASE.
-  AFL_ASE_MIPS3D = 0x00000020,    // MIPS-3D ASE.
-  AFL_ASE_MT = 0x00000040,        // MT ASE.
-  AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE.
-  AFL_ASE_VIRT = 0x00000100,      // VZ ASE.
-  AFL_ASE_MSA = 0x00000200,       // MSA ASE.
-  AFL_ASE_MIPS16 = 0x00000400,    // MIPS16 ASE.
-  AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE.
-  AFL_ASE_XPA = 0x00001000        // XPA ASE.
-};
-
-// Values for the isa_ext word of an ABI flags structure.
-enum {
-  AFL_EXT_XLR = 1,          // RMI Xlr instruction.
-  AFL_EXT_OCTEON2 = 2,      // Cavium Networks Octeon2.
-  AFL_EXT_OCTEONP = 3,      // Cavium Networks OcteonP.
-  AFL_EXT_LOONGSON_3A = 4,  // Loongson 3A.
-  AFL_EXT_OCTEON = 5,       // Cavium Networks Octeon.
-  AFL_EXT_5900 = 6,         // MIPS R5900 instruction.
-  AFL_EXT_4650 = 7,         // MIPS R4650 instruction.
-  AFL_EXT_4010 = 8,         // LSI R4010 instruction.
-  AFL_EXT_4100 = 9,         // NEC VR4100 instruction.
-  AFL_EXT_3900 = 10,        // Toshiba R3900 instruction.
-  AFL_EXT_10000 = 11,       // MIPS R10000 instruction.
-  AFL_EXT_SB1 = 12,         // Broadcom SB-1 instruction.
-  AFL_EXT_4111 = 13,        // NEC VR4111/VR4181 instruction.
-  AFL_EXT_4120 = 14,        // NEC VR4120 instruction.
-  AFL_EXT_5400 = 15,        // NEC VR5400 instruction.
-  AFL_EXT_5500 = 16,        // NEC VR5500 instruction.
-  AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E.
-  AFL_EXT_LOONGSON_2F = 18  // ST Microelectronics Loongson 2F.
-};
+class MipsABIFlagsSection;
 
-// Values for the fp_abi word of an ABI flags structure.
-enum {
-  Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
-  Val_GNU_MIPS_ABI_FP_XX = 5,
-  Val_GNU_MIPS_ABI_FP_64 = 6
-};
+using Val_GNU_MIPS_ABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI;
 
 class MipsTargetStreamer : public MCTargetStreamer {
 public:
@@ -133,105 +57,25 @@ public:
   virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
                                     const MCSymbol &Sym, bool IsReg);
   // ABI Flags
-  virtual void emitDirectiveModule(unsigned Value, bool is32BitAbi){};
-  virtual void emitDirectiveSetFp(unsigned Value, bool is32BitAbi){};
+  virtual void emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) {
+    ABIFlagsSection.FpABI = Value;
+  }
+  virtual void emitDirectiveSetFp(Val_GNU_MIPS_ABI Value, bool Is32BitAbi){};
   virtual void emitMipsAbiFlags(){};
   void setCanHaveModuleDir(bool Can) { canHaveModuleDirective = Can; }
   bool getCanHaveModuleDir() { return canHaveModuleDirective; }
 
-  void setVersion(uint16_t Version) { MipsABIFlags.version = Version; }
-  void setISALevel(uint8_t Level) { MipsABIFlags.isa_level = Level; }
-  void setISARev(uint8_t Rev) { MipsABIFlags.isa_rev = Rev; }
-  void setGprSize(uint8_t Size) { MipsABIFlags.gpr_size = Size; }
-  void setCpr1Size(uint8_t Size) { MipsABIFlags.cpr1_size = Size; }
-  void setCpr2Size(uint8_t Size) { MipsABIFlags.cpr2_size = Size; }
-  void setFpABI(uint8_t Abi) { MipsABIFlags.fp_abi = Abi; }
-  void setIsaExt(uint32_t IsaExt) { MipsABIFlags.isa_ext = IsaExt; }
-  void setASEs(uint32_t Ases) { MipsABIFlags.ases = Ases; }
-  void setFlags1(uint32_t Flags) { MipsABIFlags.flags1 = Flags; }
-  void setFlags2(uint32_t Flags) { MipsABIFlags.flags2 = Flags; }
-
-  uint8_t getFPAbi() { return MipsABIFlags.fp_abi; }
   // This method enables template classes to set internal abi flags
   // structure values.
   template <class PredicateLibrary>
   void updateABIInfo(const PredicateLibrary &P) {
-    setVersion(0); // Version, default value is 0.
-
-    if (P.hasMips64()) { // isa_level
-      setISALevel(64);
-      if (P.hasMips64r6())
-        setISARev(6);
-      else if (P.hasMips64r2())
-        setISARev(2);
-      else
-        setISARev(1);
-    } else if (P.hasMips32()) {
-      setISALevel(32);
-      if (P.hasMips32r6())
-        setISARev(6);
-      else if (P.hasMips32r2())
-        setISARev(2);
-      else
-        setISARev(1);
-    } else {
-      setISARev(0);
-      if (P.hasMips5())
-        setISALevel(5);
-      else if (P.hasMips4())
-        setISALevel(4);
-      else if (P.hasMips3())
-        setISALevel(3);
-      else if (P.hasMips2())
-        setISALevel(2);
-      else if (P.hasMips1())
-        setISALevel(1);
-      else
-        llvm_unreachable("Unknown ISA level!");
-    }
-
-    if (P.isGP64bit()) // GPR size.
-      setGprSize(AFL_REG_64);
-    else
-      setGprSize(AFL_REG_32);
-
-    // TODO: check for MSA128 value.
-    if (P.mipsSEUsesSoftFloat())
-      setCpr1Size(AFL_REG_NONE);
-    else if (P.isFP64bit())
-      setCpr1Size(AFL_REG_64);
-    else
-      setCpr1Size(AFL_REG_32);
-    setCpr2Size(AFL_REG_NONE); // Default value.
-
-    // Set ASE.
-    unsigned AseFlags = 0;
-    if (P.hasDSP())
-      AseFlags |= AFL_ASE_DSP;
-    if (P.hasDSPR2())
-      AseFlags |= AFL_ASE_DSPR2;
-    if (P.hasMSA())
-      AseFlags |= AFL_ASE_MSA;
-    if (P.inMicroMipsMode())
-      AseFlags |= AFL_ASE_MICROMIPS;
-    if (P.inMips16Mode())
-      AseFlags |= AFL_ASE_MIPS16;
-
-    if (P.isABI_N32() || P.isABI_N64())
-      setFpABI(Val_GNU_MIPS_ABI_FP_DOUBLE);
-    else if (P.isABI_O32()) {
-      if (P.isFP64bit())
-        setFpABI(Val_GNU_MIPS_ABI_FP_64);
-      else if (P.isABI_FPXX())
-        setFpABI(Val_GNU_MIPS_ABI_FP_XX);
-      else
-        setFpABI(Val_GNU_MIPS_ABI_FP_DOUBLE);
-    } else
-      setFpABI(0); // Default value.
+    ABIFlagsSection.setAllFromPredicates(P);
   }
 
+  MipsABIFlagsSection &getABIFlagsSection() { return ABIFlagsSection; }
+
 protected:
-  Elf_Internal_ABIFlags_v0 MipsABIFlags;
+  MipsABIFlagsSection ABIFlagsSection;
 
 private:
   bool canHaveModuleDirective;
@@ -278,8 +122,8 @@ public:
                             const MCSymbol &Sym, bool IsReg) override;
 
   // ABI Flags
-  void emitDirectiveModule(unsigned Value, bool is32BitAbi) override;
-  void emitDirectiveSetFp(unsigned Value, bool is32BitAbi) override;
+  void emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override;
+  void emitDirectiveSetFp(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override;
   void emitMipsAbiFlags() override;
 };
 
diff --git a/test/MC/Mips/msa/abiflags.s b/test/MC/Mips/msa/abiflags.s
new file mode 100644 (file)
index 0000000..83b83cc
--- /dev/null
@@ -0,0 +1,38 @@
+# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa | \
+# RUN:   FileCheck %s -check-prefix=CHECK-ASM
+#
+# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa -filetype=obj -o - | \
+# RUN:   llvm-readobj -sections -section-data -section-relocations - | \
+# RUN:     FileCheck %s -check-prefix=CHECK-OBJ
+
+# CHECK-ASM: .module fp=32
+# CHECK-ASM: .set fp=64
+
+# Checking if the Mips.abiflags were correctly emitted.
+# CHECK-OBJ:  Section {
+# CHECK-OBJ:    Index: 5
+# CHECK-OBJ:    Name: .MIPS.abiflags (12)
+# CHECK-OBJ:    Type:  (0x7000002A)
+# CHECK-OBJ:     Flags [ (0x2)
+# CHECK-OBJ:      SHF_ALLOC (0x2)
+# CHECK-OBJ:    ]
+# CHECK-OBJ:    Address: 0x0
+# CHECK-OBJ:    Offset: 0x50
+# CHECK-OBJ:    Size: 24
+# CHECK-OBJ:    Link: 0
+# CHECK-OBJ:    Info: 0
+# CHECK-OBJ:    AddressAlignment: 8
+# CHECK-OBJ:    EntrySize: 0
+# CHECK-OBJ:    Relocations [
+# CHECK-OBJ:    ]
+# CHECK-OBJ:    SectionData (
+# CHECK-OBJ:      0000: 00002002 01030001 00000000 00000200  |.. .............|
+# CHECK-OBJ:      0010: 00000000 00000000                    |........|
+# CHECK-OBJ:    )
+# CHECK-OBJ:  }
+
+        .module fp=32
+        .set fp=64
+# FIXME: Test should include gnu_attributes directive when implemented.
+#        An explicit .gnu_attribute must be checked against the effective
+#        command line options and any inconsistencies reported via a warning.