Verify that calling conventions match function prototype.
authorTorok Edwin <edwintorok@gmail.com>
Fri, 22 May 2009 06:41:43 +0000 (06:41 +0000)
committerTorok Edwin <edwintorok@gmail.com>
Fri, 22 May 2009 06:41:43 +0000 (06:41 +0000)
This only rejects mismatches between target specific calling convention
and C/LLVM specific calling convention.
There are too many fastcc/C, coldcc/cc42 mismatches in the testsuite, these are
not reject by the verifier.

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

lib/VMCore/Verifier.cpp
test/Assembler/2009-05-22-CC.ll [new file with mode: 0644]
test/Verifier/2009-05-22-CC.ll [new file with mode: 0644]

index fc4cfcfe45db80ca6c2596da8a4a050c50b2501f..65d0a8236b91d00810102dc0f49c44ee2ee35f4f 100644 (file)
@@ -1024,6 +1024,31 @@ void Verifier::VerifyCallSite(CallSite CS) {
             "Call parameter type does not match function signature!",
             CS.getArgument(i), FTy->getParamType(i), I);
 
+  Assert2(CS.getType() == FTy->getReturnType(),
+          "Call return type does not match function signature!",
+          CS.getInstruction(), FTy->getReturnType());
+
+  // Verify calling convention for direct calls
+  Value *CalledF = CS.getCalledValue()->stripPointerCasts();
+  if (Function *F = dyn_cast<Function>(CalledF)) {
+    unsigned CC1 = CS.getCallingConv();
+    unsigned CC2 = F->getCallingConv();
+    if(CC1 != CC2) {
+      // tolerate some mismatch among C prototype and LLVM-specific calling conv
+      if (CC2 >= CallingConv::FirstTargetCC || 
+          CC1 >= CallingConv::FirstTargetCC) {
+        Instruction *I = CS.getInstruction()->clone();
+        if (CallInst *CI = dyn_cast<CallInst>(I)) {
+          CI->setCallingConv(F->getCallingConv());
+        } else
+          cast<InvokeInst>(I)->setCallingConv(F->getCallingConv());
+        Assert2(0,"Calling convention does not match function signature!",
+                CS.getInstruction(), I);
+        delete I;
+      }
+    }
+  }
+
   if (CS.getCalledValue()->getNameLen() < 5 ||
       strncmp(CS.getCalledValue()->getNameStart(), "llvm.", 5) != 0) {
     // Verify that none of the arguments are metadata...
diff --git a/test/Assembler/2009-05-22-CC.ll b/test/Assembler/2009-05-22-CC.ll
new file mode 100644 (file)
index 0000000..ba80d64
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s
+
+; Verify that calls with correct calling conv are accepted
+declare x86_stdcallcc i32 @re_string_construct(i8* inreg %pstr, i8* inreg %str, i32 inreg %len, i8* %trans, i32 %icase, i8* %dfa);
+define void @main() {
+entry:
+       %0 = call x86_stdcallcc i32 (...)* bitcast (i32 (i8*, i8*, i32, i8*, i32, i8*)* @re_string_construct to i32 (...)*)(i32 inreg 0, i32 inreg 0, i32 inreg 0, i32 0, i32 0, i8* inttoptr (i32 673194176 to i8*));
+        ret void
+}
diff --git a/test/Verifier/2009-05-22-CC.ll b/test/Verifier/2009-05-22-CC.ll
new file mode 100644 (file)
index 0000000..7775ded
--- /dev/null
@@ -0,0 +1,11 @@
+; RUN: not llvm-as < %s |& grep {Calling convention does not match function signature}
+; PR 4239
+
+; Verify that the calling convention on the call instruction matches the
+; declared calling convention
+declare x86_stdcallcc i32 @re_string_construct(i8* inreg %pstr, i8* inreg %str, i32 inreg %len, i8* %trans, i32 %icase, i8* %dfa);
+define void @main() {
+entry:
+       %0 = call i32 (...)* bitcast (i32 (i8*, i8*, i32, i8*, i32, i8*)* @re_string_construct to i32 (...)*)(i32 inreg 0, i32 inreg 0, i32 inreg 0, i32 0, i32 0, i8* inttoptr (i32 673194176 to i8*))
+        ret void
+}