[SystemZ] Fix parsing of inline asm registers
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Fri, 12 Jul 2013 09:08:12 +0000 (09:08 +0000)
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Fri, 12 Jul 2013 09:08:12 +0000 (09:08 +0000)
GPR and FPR constraints like "{r2}" and "{f2}" weren't handled correctly
because the name-to-regno mapping depends on the value type and
(because of that) the internal names in RegStrings are not the
same as the AsmName.

CC constraints like "{cc}" didn't work either because there was no
associated register class.

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

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZMCInstLower.cpp
lib/Target/SystemZ/SystemZMCInstLower.h
lib/Target/SystemZ/SystemZRegisterInfo.td

index d344134b24f634313ea7afd7c60205a70b80e7f6..a317f0c3f6867adf8268eb42b5d1bc4bed985b40 100644 (file)
@@ -386,6 +386,22 @@ getSingleConstraintMatchWeight(AsmOperandInfo &info,
   return weight;
 }
 
+// Parse a "{tNNN}" register constraint for which the register type "t"
+// has already been verified.  MC is the class associated with "t" and
+// Map maps 0-based register numbers to LLVM register numbers.
+static std::pair<unsigned, const TargetRegisterClass *>
+parseRegisterNumber(const std::string &Constraint,
+                    const TargetRegisterClass *RC, const unsigned *Map) {
+  assert(*(Constraint.end()-1) == '}' && "Missing '}'");
+  if (isdigit(Constraint[2])) {
+    std::string Suffix(Constraint.data() + 2, Constraint.size() - 2);
+    unsigned Index = atoi(Suffix.c_str());
+    if (Index < 16 && Map[Index])
+      return std::make_pair(Map[Index], RC);
+  }
+  return std::make_pair(0u, static_cast<TargetRegisterClass*>(0));
+}
+
 std::pair<unsigned, const TargetRegisterClass *> SystemZTargetLowering::
 getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const {
   if (Constraint.size() == 1) {
@@ -415,6 +431,32 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const {
       return std::make_pair(0U, &SystemZ::FP32BitRegClass);
     }
   }
+  if (Constraint[0] == '{') {
+    // We need to override the default register parsing for GPRs and FPRs
+    // because the interpretation depends on VT.  The internal names of
+    // the registers are also different from the external names
+    // (F0D and F0S instead of F0, etc.).
+    if (Constraint[1] == 'r') {
+      if (VT == MVT::i32)
+        return parseRegisterNumber(Constraint, &SystemZ::GR32BitRegClass,
+                                   SystemZMC::GR32Regs);
+      if (VT == MVT::i128)
+        return parseRegisterNumber(Constraint, &SystemZ::GR128BitRegClass,
+                                   SystemZMC::GR128Regs);
+      return parseRegisterNumber(Constraint, &SystemZ::GR64BitRegClass,
+                                 SystemZMC::GR64Regs);
+    }
+    if (Constraint[1] == 'f') {
+      if (VT == MVT::f32)
+        return parseRegisterNumber(Constraint, &SystemZ::FP32BitRegClass,
+                                   SystemZMC::FP32Regs);
+      if (VT == MVT::f128)
+        return parseRegisterNumber(Constraint, &SystemZ::FP128BitRegClass,
+                                   SystemZMC::FP128Regs);
+      return parseRegisterNumber(Constraint, &SystemZ::FP64BitRegClass,
+                                 SystemZMC::FP64Regs);
+    }
+  }
   return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
 }
 
index fd3f867015c44e41c1b692a1a04e65d14f685a93..432a0d30b62719e1b178e2a5082b584e37255275 100644 (file)
@@ -57,9 +57,6 @@ MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
     llvm_unreachable("unknown operand type");
 
   case MachineOperand::MO_Register:
-    // Ignore all implicit register operands.
-    if (MO.isImplicit())
-      return MCOperand();
     return MCOperand::CreateReg(MO.getReg());
 
   case MachineOperand::MO_Immediate:
@@ -104,8 +101,8 @@ void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
   OutMI.setOpcode(Opcode);
   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
     const MachineOperand &MO = MI->getOperand(I);
-    MCOperand MCOp = lowerOperand(MO);
-    if (MCOp.isValid())
-      OutMI.addOperand(MCOp);
+    // Ignore all implicit register operands.
+    if (!MO.isReg() || !MO.isImplicit())
+      OutMI.addOperand(lowerOperand(MO));
   }
 }
index afa72f38add32a44e875be2fbbbc804471ad71f9..db5bdb05ab2de3341ad41ef04cedf6e1ebd39cc2 100644 (file)
@@ -35,7 +35,7 @@ public:
   // Lower MachineInstr MI to MCInst OutMI.
   void lower(const MachineInstr *MI, MCInst &OutMI) const;
 
-  // Return an MCOperand for MO.  Return an empty operand if MO is implicit.
+  // Return an MCOperand for MO.
   MCOperand lowerOperand(const MachineOperand& MO) const;
 
   // Return an MCOperand for MO, given that it equals Symbol + Offset.
index d65553e7500b7f376c3680df080b42429ef123fb..ffffe721cb7d477c70b21af67c5f08c973242d6f 100644 (file)
@@ -147,5 +147,7 @@ defm FP128 : SystemZRegClass<"FP128", f128, 128, (add F0Q, F1Q, F4Q, F5Q,
 // Other registers
 //===----------------------------------------------------------------------===//
 
-// The 2-bit condition code field of the PSW.
+// The 2-bit condition code field of the PSW.  Every register named in an
+// inline asm needs a class associated with it.
 def CC : SystemZReg<"cc">;
+def CCRegs : RegisterClass<"SystemZ", [i32], 32, (add CC)>;