Include a source location when complaining about bad inline assembly.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 2 Jul 2011 03:53:34 +0000 (03:53 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 2 Jul 2011 03:53:34 +0000 (03:53 +0000)
Add a MI->emitError() method that the backend can use to report errors
related to inline assembly. Call it from X86FloatingPoint.cpp when the
constraints are wrong.

This enables proper clang diagnostics from the backend:

$ clang -c pr30848.c
pr30848.c:5:12: error: Inline asm output regs must be last on the x87 stack
  __asm__ ("" : "=u" (d));  /* { dg-error "output regs" } */
           ^
1 error generated.

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

include/llvm/CodeGen/MachineInstr.h
lib/CodeGen/MachineInstr.cpp
lib/Target/X86/X86FloatingPoint.cpp

index 788d149c868532229e0fbbd12f081ee1645964c3..5b3d3ea62a4527e13a1e76ca3d62ca8399184ef4 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/ilist_node.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/ilist_node.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/DebugLoc.h"
 #include <vector>
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/DebugLoc.h"
 #include <vector>
@@ -180,6 +181,15 @@ public:
   ///
   DebugLoc getDebugLoc() const { return debugLoc; }
 
   ///
   DebugLoc getDebugLoc() const { return debugLoc; }
 
+  /// emitError - Emit an error referring to the source location of this
+  /// instruction. This should only be used for inline assembly that is somehow
+  /// impossible to compile. Other errors should have been handled much
+  /// earlier.
+  ///
+  /// If this method returns, the caller should try to recover from the error.
+  ///
+  void emitError(StringRef Msg) const;
+
   /// getDesc - Returns the target instruction descriptor of this
   /// MachineInstr.
   const MCInstrDesc &getDesc() const { return *MCID; }
   /// getDesc - Returns the target instruction descriptor of this
   /// MachineInstr.
   const MCInstrDesc &getDesc() const { return *MCID; }
index 77828c929eb2d83a747f6014c5cb811e9fe6f2f0..f490713e7200c61d8c0e78e1c9148463487b27ee 100644 (file)
 #include "llvm/Constants.h"
 #include "llvm/Function.h"
 #include "llvm/InlineAsm.h"
 #include "llvm/Constants.h"
 #include "llvm/Function.h"
 #include "llvm/InlineAsm.h"
+#include "llvm/LLVMContext.h"
 #include "llvm/Metadata.h"
 #include "llvm/Metadata.h"
+#include "llvm/Module.h"
 #include "llvm/Type.h"
 #include "llvm/Value.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/Type.h"
 #include "llvm/Value.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/MC/MCInstrDesc.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/MC/MCInstrDesc.h"
@@ -1712,3 +1715,24 @@ MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) {
   }
   return Hash;
 }
   }
   return Hash;
 }
+
+void MachineInstr::emitError(StringRef Msg) const {
+  // Find the source location cookie.
+  unsigned LocCookie = 0;
+  const MDNode *LocMD = 0;
+  for (unsigned i = getNumOperands(); i != 0; --i) {
+    if (getOperand(i-1).isMetadata() &&
+        (LocMD = getOperand(i-1).getMetadata()) &&
+        LocMD->getNumOperands() != 0) {
+      if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) {
+        LocCookie = CI->getZExtValue();
+        break;
+      }
+    }
+  }
+
+  if (const MachineBasicBlock *MBB = getParent())
+    if (const MachineFunction *MF = MBB->getParent())
+      return MF->getMMI().getModule()->getContext().emitError(LocCookie, Msg);
+  report_fatal_error(Msg);
+}
index 463cde076a3b94570474e8ad4b31cc5925e36e9b..04e01ddf8f7e9f49a3299369e3d58b6a0d02d0eb 100644 (file)
@@ -884,7 +884,7 @@ void FPS::adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I) {
   // Kill registers by popping.
   if (Kills && I != MBB->begin()) {
     MachineBasicBlock::iterator I2 = llvm::prior(I);
   // Kill registers by popping.
   if (Kills && I != MBB->begin()) {
     MachineBasicBlock::iterator I2 = llvm::prior(I);
-    for (;;) {
+    while (StackTop) {
       unsigned KReg = getStackEntry(0);
       if (!(Kills & (1 << KReg)))
         break;
       unsigned KReg = getStackEntry(0);
       if (!(Kills & (1 << KReg)))
         break;
@@ -1467,25 +1467,27 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
     }
 
     if (STUses && !isMask_32(STUses))
     }
 
     if (STUses && !isMask_32(STUses))
-      report_fatal_error("Inline asm fixed input regs"
-                         " must be last on the x87 stack");
+      MI->emitError("Inline asm fixed input regs"
+                    " must be last on the x87 stack");
     unsigned NumSTUses = CountTrailingOnes_32(STUses);
 
     // Defs must be contiguous from the stack top. ST0-STn.
     unsigned NumSTUses = CountTrailingOnes_32(STUses);
 
     // Defs must be contiguous from the stack top. ST0-STn.
-    if (STDefs && !isMask_32(STDefs))
-      report_fatal_error("Inline asm output regs"
-                         " must be last on the x87 stack");
+    if (STDefs && !isMask_32(STDefs)) {
+      MI->emitError("Inline asm output regs"
+                    " must be last on the x87 stack");
+      STDefs = NextPowerOf2(STDefs) - 1;
+    }
     unsigned NumSTDefs = CountTrailingOnes_32(STDefs);
 
     // So must the clobbered stack slots. ST0-STm, m >= n.
     if (STClobbers && !isMask_32(STDefs | STClobbers))
     unsigned NumSTDefs = CountTrailingOnes_32(STDefs);
 
     // So must the clobbered stack slots. ST0-STm, m >= n.
     if (STClobbers && !isMask_32(STDefs | STClobbers))
-      report_fatal_error("Inline asm clobbers must be last on the x87 stack");
+      MI->emitError("Inline asm clobbers must be last on the x87 stack");
 
     // Popped inputs are the ones that are also clobbered or defined.
     unsigned STPopped = STUses & (STDefs | STClobbers);
     if (STPopped && !isMask_32(STPopped))
 
     // Popped inputs are the ones that are also clobbered or defined.
     unsigned STPopped = STUses & (STDefs | STClobbers);
     if (STPopped && !isMask_32(STPopped))
-      report_fatal_error("Inline asm implicitly popped regs"
-                         " must be last on the x87 stack");
+      MI->emitError("Inline asm implicitly popped regs"
+                    " must be last on the x87 stack");
     unsigned NumSTPopped = CountTrailingOnes_32(STPopped);
 
     DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops "
     unsigned NumSTPopped = CountTrailingOnes_32(STPopped);
 
     DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops "
@@ -1501,7 +1503,7 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
       if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
         continue;
       if (!Op.isUse())
       if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
         continue;
       if (!Op.isUse())
-        report_fatal_error("Illegal \"f\" output constraint in inline asm");
+        MI->emitError("Illegal \"f\" output constraint in inline asm");
       unsigned FPReg = getFPReg(Op);
       FPUsed |= 1U << FPReg;
 
       unsigned FPReg = getFPReg(Op);
       FPUsed |= 1U << FPReg;