[PowerPC] Support @tls in the asm parser
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 5 Jul 2013 12:22:36 +0000 (12:22 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 5 Jul 2013 12:22:36 +0000 (12:22 +0000)
This adds support for the last missing construct to parse TLS-related
assembler code:
   add 3, 4, symbol@tls

The ADD8TLS currently hard-codes the @tls into the assembler string.
This cannot be handled by the asm parser, since @tls is parsed as
a symbol variant.  This patch changes ADD8TLS to have the @tls suffix
printed as symbol variant on output too, which allows us to remove
the isCodeGenOnly marker from ADD8TLS.  This in turn means that we
can add a AsmOperand to accept @tls marked symbols on input.

As a side effect, this means that the fixup_ppc_tlsreg fixup type
is no longer necessary and can be merged into fixup_ppc_nofixup.

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

lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
lib/Target/PowerPC/PPC.h
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCInstr64Bit.td
lib/Target/PowerPC/PPCMCInstLower.cpp
test/MC/PowerPC/ppc64-errors.s
test/MC/PowerPC/ppc64-fixups.s

index e4fc3b9ded7a7be486262972efb867662fc2e29b..237ecdc60e428e2df53d9f4f70da2b301aa9d2fb 100644 (file)
@@ -237,7 +237,8 @@ struct PPCOperand : public MCParsedAsmOperand {
   enum KindTy {
     Token,
     Immediate,
-    Expression
+    Expression,
+    TLSRegister
   } Kind;
 
   SMLoc StartLoc, EndLoc;
@@ -257,10 +258,15 @@ struct PPCOperand : public MCParsedAsmOperand {
     int64_t CRVal;     // Cached result of EvaluateCRExpr(Val)
   };
 
+  struct TLSRegOp {
+    const MCSymbolRefExpr *Sym;
+  };
+
   union {
     struct TokOp Tok;
     struct ImmOp Imm;
     struct ExprOp Expr;
+    struct TLSRegOp TLSReg;
   };
 
   PPCOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -280,6 +286,9 @@ public:
     case Expression:
       Expr = o.Expr;
       break;
+    case TLSRegister:
+      TLSReg = o.TLSReg;
+      break;
     }
   }
 
@@ -307,6 +316,11 @@ public:
     return Expr.CRVal;
   }
 
+  const MCExpr *getTLSReg() const {
+    assert(Kind == TLSRegister && "Invalid access!");
+    return TLSReg.Sym;
+  }
+
   unsigned getReg() const {
     assert(isRegNumber() && "Invalid access!");
     return (unsigned) Imm.Val;
@@ -341,6 +355,7 @@ public:
                                     (getImm() & 3) == 0); }
   bool isS17Imm() const { return Kind == Expression ||
                                  (Kind == Immediate && isInt<17>(getImm())); }
+  bool isTLSReg() const { return Kind == TLSRegister; }
   bool isDirectBr() const { return Kind == Expression ||
                                    (Kind == Immediate && isInt<26>(getImm()) &&
                                     (getImm() & 3) == 0); }
@@ -445,6 +460,11 @@ public:
       Inst.addOperand(MCOperand::CreateExpr(getExpr()));
   }
 
+  void addTLSRegOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::CreateExpr(getTLSReg()));
+  }
+
   StringRef getToken() const {
     assert(Kind == Token && "Invalid access!");
     return StringRef(Tok.Data, Tok.Length);
@@ -481,6 +501,28 @@ public:
     Op->IsPPC64 = IsPPC64;
     return Op;
   }
+
+  static PPCOperand *CreateTLSReg(const MCSymbolRefExpr *Sym,
+                                  SMLoc S, SMLoc E, bool IsPPC64) {
+    PPCOperand *Op = new PPCOperand(TLSRegister);
+    Op->TLSReg.Sym = Sym;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    Op->IsPPC64 = IsPPC64;
+    return Op;
+  }
+
+  static PPCOperand *CreateFromMCExpr(const MCExpr *Val,
+                                      SMLoc S, SMLoc E, bool IsPPC64) {
+    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
+      return CreateImm(CE->getValue(), S, E, IsPPC64);
+
+    if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val))
+      if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS)
+        return CreateTLSReg(SRE, S, E, IsPPC64);
+
+    return CreateExpr(Val, S, E, IsPPC64);
+  }
 };
 
 } // end anonymous namespace.
@@ -496,6 +538,9 @@ void PPCOperand::print(raw_ostream &OS) const {
   case Expression:
     getExpr()->print(OS);
     break;
+  case TLSRegister:
+    getTLSReg()->print(OS);
+    break;
   }
 }
 
@@ -1011,12 +1056,8 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
     return Error(S, "unknown operand");
   }
 
-  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(EVal))
-    Op = PPCOperand::CreateImm(CE->getValue(), S, E, isPPC64());
-  else
-    Op = PPCOperand::CreateExpr(EVal, S, E, isPPC64());
-
   // Push the parsed operand into the list of operands
+  Op = PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64());
   Operands.push_back(Op);
 
   // Check whether this is a TLS call expression
@@ -1036,7 +1077,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
     E = Parser.getTok().getLoc();
     Parser.Lex(); // Eat the ')'.
 
-    Op = PPCOperand::CreateExpr(TLSSym, S, E, isPPC64());
+    Op = PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64());
     Operands.push_back(Op);
   }
 
index b37a17933c1399704c38b099eaaa5154e217bacc..4f999a15346d44f55a82b388ad957ca6dc29e372 100644 (file)
@@ -30,7 +30,6 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
   case FK_Data_2:
   case FK_Data_4:
   case FK_Data_8:
-  case PPC::fixup_ppc_tlsreg:
   case PPC::fixup_ppc_nofixup:
     return Value;
   case PPC::fixup_ppc_brcond14:
@@ -64,7 +63,6 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
     return 4;
   case FK_Data_8:
     return 8;
-  case PPC::fixup_ppc_tlsreg:
   case PPC::fixup_ppc_nofixup:
     return 0;
   }
@@ -101,7 +99,6 @@ public:
       { "fixup_ppc_brcond14abs", 16,     14,   0 },
       { "fixup_ppc_half16",       0,     16,   0 },
       { "fixup_ppc_half16ds",     0,     14,   0 },
-      { "fixup_ppc_tlsreg",       0,      0,   0 },
       { "fixup_ppc_nofixup",      0,      0,   0 }
     };
 
index 76cf43f6e583319ccdaa8f8c3b5099dcc1ea737d..ffc5002a96bccec931b7e8bcc3fa8a42bd359f7a 100644 (file)
@@ -289,9 +289,6 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
         break;
       }
       break;
-    case PPC::fixup_ppc_tlsreg:
-      Type = ELF::R_PPC64_TLS;
-      break;
     case PPC::fixup_ppc_nofixup:
       switch (Modifier) {
       default: llvm_unreachable("Unsupported Modifier");
@@ -301,6 +298,9 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
       case MCSymbolRefExpr::VK_TLSLD:
         Type = ELF::R_PPC64_TLSLD;
         break;
+      case MCSymbolRefExpr::VK_PPC_TLS:
+        Type = ELF::R_PPC64_TLS;
+        break;
       }
       break;
     case FK_Data_8:
index 0438c0e3abf19f032136dfb31eba72ffcc56068d..68de8c1f27a556036a67845539c0e544f98dedb1 100644 (file)
@@ -41,11 +41,9 @@ enum Fixups {
   /// implied 2 zero bits for instrs like 'std'.
   fixup_ppc_half16ds,
 
-  /// fixup_ppc_tlsreg - Insert thread-pointer register number.
-  fixup_ppc_tlsreg,
-
   /// fixup_ppc_nofixup - Not a true fixup, but ties a symbol to a call
-  /// to __tls_get_addr for the TLS general and local dynamic models.
+  /// to __tls_get_addr for the TLS general and local dynamic models,
+  /// or inserts the thread-pointer register number.
   fixup_ppc_nofixup,
   
   // Marker
index 27ad980703ac48c4e760fbbedd7dd3de0223dd52..59ba9c4af62e68aa4f00a55de1a4ce6cf04fdf87 100644 (file)
@@ -209,7 +209,7 @@ unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
   // hint to the linker that this statement is part of a relocation sequence.
   // Return the thread-pointer register's encoding.
   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
-                                   (MCFixupKind)PPC::fixup_ppc_tlsreg));
+                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
   return CTX.getRegisterInfo()->getEncodingValue(PPC::X13);
 }
 
index d5a08eed6dcdab10a2e46e1850323381293d6ae4..96b882aef1fa7b702b9e895083aa86075bb120e9 100644 (file)
@@ -85,7 +85,10 @@ namespace llvm {
     /// into memory operations.
     MO_DTPREL_LO = 5 << 4,
     MO_TLSLD_LO  = 6 << 4,
-    MO_TOC_LO    = 7 << 4
+    MO_TOC_LO    = 7 << 4,
+
+    // Symbol for VK_PPC_TLS fixup attached to an ADD instruction
+    MO_TLS       = 8 << 4
   };
   } // end namespace PPCII
   
index c4f961cbd64e453b293fcb11de129f762719242e..0f790313638e4553a438dff3f395c90aeeac0fc8 100644 (file)
@@ -1359,12 +1359,14 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
 
   if (Model == TLSModel::InitialExec) {
     SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
+    SDValue TGATLS = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
+                                                PPCII::MO_TLS);
     SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
     SDValue TPOffsetHi = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl,
                                      PtrVT, GOTReg, TGA);
     SDValue TPOffset = DAG.getNode(PPCISD::LD_GOT_TPREL_L, dl,
                                    PtrVT, TGA, TPOffsetHi);
-    return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGA);
+    return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
   }
 
   if (Model == TLSModel::GeneralDynamic) {
index d19a7d439fd904805a71bfa60e37f93a54518bb8..e7bb25941d848e056b4d3d4173b5258abdec26d2 100644 (file)
@@ -36,8 +36,13 @@ def s17imm64 : Operand<i64> {
 def tocentry : Operand<iPTR> {
   let MIOperandInfo = (ops i64imm:$imm);
 }
+def PPCTLSRegOperand : AsmOperandClass {
+  let Name = "TLSReg"; let PredicateMethod = "isTLSReg";
+  let RenderMethod = "addTLSRegOperands";
+}
 def tlsreg : Operand<i64> {
   let EncoderMethod = "getTLSRegEncoding";
+  let ParserMatchClass = PPCTLSRegOperand;
 }
 def tlsgd : Operand<i64> {}
 def tlscall : Operand<i64> {
@@ -404,9 +409,8 @@ defm ADD8  : XOForm_1r<31, 266, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
                        [(set i64:$rT, (add i64:$rA, i64:$rB))]>;
 // ADD8 has a special form: reg = ADD8(reg, sym@tls) for use by the
 // initial-exec thread-local storage model.
-let isCodeGenOnly = 1 in
 def ADD8TLS  : XOForm_1<31, 266, 0, (outs g8rc:$rT), (ins g8rc:$rA, tlsreg:$rB),
-                        "add $rT, $rA, $rB@tls", IntSimple,
+                        "add $rT, $rA, $rB", IntSimple,
                         [(set i64:$rT, (add i64:$rA, tglobaltlsaddr:$rB))]>;
                      
 defm ADDC8 : XOForm_1rc<31, 10, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
index 1eefb7f08d23f95357c02c186dc97189e0c0793c..b7e88d452c49f90221d5051c1e70f61f4b483d5f 100644 (file)
@@ -127,6 +127,9 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
     case PPCII::MO_TOC_LO:
       RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
       break;
+    case PPCII::MO_TLS:
+      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
+      break;
   }
 
   const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
index 8b6dd5395ff569ef8eddf9c3bb7c9cb80b25680c..bc8c95c223748b5025a8c34aa70b15a05c393412 100644 (file)
 # CHECK-NEXT: add %r32, %r32, %r32
               add %r32, %r32, %r32
 
+# TLS register operands
+
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: add 3, symbol@tls, 4
+              add 3, symbol@tls, 4
+
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: subf 3, 4, symbol@tls
+              subf 3, 4, symbol@tls
+
 # Signed 16-bit immediate operands
 
 # CHECK: error: invalid operand for instruction
index 937e55758e84b3ea3561e9fe72c7f73339d10a83..9f23882e452519c791ae202c3b6c8851afea40ce 100644 (file)
@@ -206,8 +206,6 @@ base:
 # CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_LO_DS target 0x0
          ld 1, target@got@l(3)
 
-# FIXME: @tls
-
 
 # CHECK: addis 3, 2, target@tprel@ha     # encoding: [0x3c,0x62,A,A]
 # CHECK-NEXT:                            #   fixup A - offset: 2, value: target@tprel@ha, kind: fixup_ppc_half16
@@ -405,6 +403,11 @@ base:
 # CHECK-REL-NEXT:                        0x{{[0-9A-F]*[048C]}} R_PPC64_REL24 __tls_get_addr 0x0
          bl __tls_get_addr(target@tlsld)
 
+# CHECK: add 3, 4, target@tls            # encoding: [0x7c,0x64,0x6a,0x14]
+# CHECK-NEXT:                            #   fixup A - offset: 0, value: target@tls, kind: fixup_ppc_nofixup
+# CHECK-REL:                             0x{{[0-9A-F]*[048C]}} R_PPC64_TLS target 0x0
+         add 3, 4, target@tls
+
 
 # Data relocs
 # llvm-mc does not show any "encoding" string for data, so we just check the relocs