[llvm] r220906 - [dfsan] New calling convention for custom functions with variadic arguments.

Peter Collingbourne peter at pcc.me.uk
Thu Oct 30 06:22:57 PDT 2014


Author: pcc
Date: Thu Oct 30 08:22:57 2014
New Revision: 220906

URL: http://llvm.org/viewvc/llvm-project?rev=220906&view=rev
Log:
[dfsan] New calling convention for custom functions with variadic arguments.

Summary:
The previous calling convention prevented custom functions from being able
to access argument labels unless it knew how many variadic arguments there
were, and of which type. This restriction made it impossible to correctly
model functions in the printf family, as it is legal to pass more arguments
than required to those functions. We now pass arguments in the following order:

non-vararg arguments
labels for non-vararg arguments
[if vararg function, pointer to array of labels for vararg arguments]
[if non-void function, pointer to label for return value]
vararg arguments

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

Modified:
    llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
    llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll

Modified: llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp?rev=220906&r1=220905&r2=220906&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp Thu Oct 30 08:22:57 2014
@@ -389,12 +389,6 @@ FunctionType *DataFlowSanitizer::getTram
 }
 
 FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
-  if (T->isVarArg()) {
-    // The labels are passed after all the arguments so there is no need to
-    // adjust the function type.
-    return T;
-  }
-
   llvm::SmallVector<Type *, 4> ArgTypes;
   for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end();
        i != e; ++i) {
@@ -409,10 +403,12 @@ FunctionType *DataFlowSanitizer::getCust
   }
   for (unsigned i = 0, e = T->getNumParams(); i != e; ++i)
     ArgTypes.push_back(ShadowTy);
+  if (T->isVarArg())
+    ArgTypes.push_back(ShadowPtrTy);
   Type *RetType = T->getReturnType();
   if (!RetType->isVoidTy())
     ArgTypes.push_back(ShadowPtrTy);
-  return FunctionType::get(T->getReturnType(), ArgTypes, false);
+  return FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg());
 }
 
 bool DataFlowSanitizer::doInitialization(Module &M) {
@@ -1419,7 +1415,7 @@ void DFSanVisitor::visitCallSite(CallSit
         std::vector<Value *> Args;
 
         CallSite::arg_iterator i = CS.arg_begin();
-        for (unsigned n = CS.arg_size(); n != 0; ++i, --n) {
+        for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) {
           Type *T = (*i)->getType();
           FunctionType *ParamFT;
           if (isa<PointerType>(T) &&
@@ -1439,9 +1435,23 @@ void DFSanVisitor::visitCallSite(CallSit
         }
 
         i = CS.arg_begin();
-        for (unsigned n = CS.arg_size(); n != 0; ++i, --n)
+        for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
           Args.push_back(DFSF.getShadow(*i));
 
+        if (FT->isVarArg()) {
+          auto LabelVAAlloca =
+              new AllocaInst(ArrayType::get(DFSF.DFS.ShadowTy,
+                                            CS.arg_size() - FT->getNumParams()),
+                             "labelva", DFSF.F->getEntryBlock().begin());
+
+          for (unsigned n = 0; i != CS.arg_end(); ++i, ++n) {
+            auto LabelVAPtr = IRB.CreateStructGEP(LabelVAAlloca, n);
+            IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr);
+          }
+
+          Args.push_back(IRB.CreateStructGEP(LabelVAAlloca, 0));
+        }
+
         if (!FT->getReturnType()->isVoidTy()) {
           if (!DFSF.LabelReturnAlloca) {
             DFSF.LabelReturnAlloca =
@@ -1451,6 +1461,9 @@ void DFSanVisitor::visitCallSite(CallSit
           Args.push_back(DFSF.LabelReturnAlloca);
         }
 
+        for (i = CS.arg_begin() + FT->getNumParams(); i != CS.arg_end(); ++i)
+          Args.push_back(*i);
+
         CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
         CustomCI->setCallingConv(CI->getCallingConv());
         CustomCI->setAttributes(CI->getAttributes());

Modified: llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll?rev=220906&r1=220905&r2=220906&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll (original)
+++ llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll Thu Oct 30 08:22:57 2014
@@ -12,8 +12,21 @@ define i32 @functional(i32 %a, i32 %b) {
   ret i32 %c
 }
 
+; CHECK: define i32 (i32, i32)* @discardg(i32)
+; CHECK: %[[CALL:.*]] = call { i32 (i32, i32)*, i16 } @"dfs$g"(i32 %0, i16 0)
+; CHECK: %[[XVAL:.*]] = extractvalue { i32 (i32, i32)*, i16 } %[[CALL]], 0
+; CHECK: ret {{.*}} %[[XVAL]]
+ at discardg = alias i32 (i32, i32)* (i32)* @g
+
 declare void @custom1(i32 %a, i32 %b)
 
+; CHECK: define linkonce_odr { i32, i16 } @"dfsw$custom2"(i32, i32, i16, i16)
+; CHECK: %[[LABELRETURN2:.*]] = alloca i16
+; CHECK: %[[RV:.*]] = call i32 @__dfsw_custom2
+; CHECK: %[[RVSHADOW:.*]] = load i16* %[[LABELRETURN2]]
+; CHECK: insertvalue {{.*}}[[RV]], 0
+; CHECK: insertvalue {{.*}}[[RVSHADOW]], 1
+; CHECK: ret { i32, i16 }
 declare i32 @custom2(i32 %a, i32 %b)
 
 declare void @custom3(i32 %a, ...)
@@ -25,7 +38,9 @@ declare void @customcb(i32 (i32)* %cb)
 declare i32 @cb(i32)
 
 ; CHECK: @"dfs$f"
-define void @f() {
+define void @f(i32 %x) {
+  ; CHECK: %[[LABELVA2:.*]] = alloca [2 x i16]
+  ; CHECK: %[[LABELVA1:.*]] = alloca [2 x i16]
   ; CHECK: %[[LABELRETURN:.*]] = alloca i16
 
   ; CHECK: call void @__dfsw_custom1(i32 1, i32 2, i16 0, i16 0)
@@ -37,29 +52,22 @@ define void @f() {
   ; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @"dfs$cb" to i8*), i16 0)
   call void @customcb(i32 (i32)* @cb)
 
-  ; CHECK: call void (i32, ...)* @__dfsw_custom3(i32 1, i32 2, i32 3, i16 0, i16 0, i16 0)
-  call void (i32, ...)* @custom3(i32 1, i32 2, i32 3)
-
-  ; CHECK: call i32 (i32, ...)* @__dfsw_custom4(i32 1, i32 2, i32 3, i16 0, i16 0, i16 0, i16* %[[LABELRETURN]])
+  ; CHECK: %[[LABELVA1_0:.*]] = getelementptr inbounds [2 x i16]* %[[LABELVA1]], i32 0, i32 0
+  ; CHECK: store i16 0, i16* %[[LABELVA1_0]]
+  ; CHECK: %[[LABELVA1_1:.*]] = getelementptr inbounds [2 x i16]* %[[LABELVA1]], i32 0, i32 1
+  ; CHECK: store i16 %{{.*}}, i16* %[[LABELVA1_1]]
+  ; CHECK: %[[LABELVA1_0A:.*]] = getelementptr inbounds [2 x i16]* %[[LABELVA1]], i32 0, i32 0
+  ; CHECK: call void (i32, i16, i16*, ...)* @__dfsw_custom3(i32 1, i16 0, i16* %[[LABELVA1_0A]], i32 2, i32 %{{.*}})
+  call void (i32, ...)* @custom3(i32 1, i32 2, i32 %x)
+
+  ; CHECK: %[[LABELVA2_0:.*]] = getelementptr inbounds [2 x i16]* %[[LABELVA2]], i32 0, i32 0
+  ; CHECK: %[[LABELVA2_0A:.*]] = getelementptr inbounds [2 x i16]* %[[LABELVA2]], i32 0, i32 0
+  ; CHECK: call i32 (i32, i16, i16*, i16*, ...)* @__dfsw_custom4(i32 1, i16 0, i16* %[[LABELVA2_0A]], i16* %[[LABELRETURN]], i32 2, i32 3)
   call i32 (i32, ...)* @custom4(i32 1, i32 2, i32 3)
 
   ret void
 }
 
-; CHECK: define i32 (i32, i32)* @discardg(i32)
-; CHECK: %[[CALL:.*]] = call { i32 (i32, i32)*, i16 } @"dfs$g"(i32 %0, i16 0)
-; CHECK: %[[XVAL:.*]] = extractvalue { i32 (i32, i32)*, i16 } %[[CALL]], 0
-; CHECK: ret {{.*}} %[[XVAL]]
- at discardg = alias i32 (i32, i32)* (i32)* @g
-
-; CHECK: define linkonce_odr { i32, i16 } @"dfsw$custom2"(i32, i32, i16, i16)
-; CHECK: %[[LABELRETURN2:.*]] = alloca i16
-; CHECK: %[[RV:.*]] = call i32 @__dfsw_custom2
-; CHECK: %[[RVSHADOW:.*]] = load i16* %[[LABELRETURN2]]
-; CHECK: insertvalue {{.*}}[[RV]], 0
-; CHECK: insertvalue {{.*}}[[RVSHADOW]], 1
-; CHECK: ret { i32, i16 }
-
 ; CHECK: @"dfs$g"
 define i32 (i32, i32)* @g(i32) {
   ; CHECK: ret {{.*}} @"dfsw$custom2"
@@ -75,8 +83,8 @@ define i32 (i32, i32)* @g(i32) {
 
 ; CHECK: declare void @__dfsw_custom1(i32, i32, i16, i16)
 ; CHECK: declare i32 @__dfsw_custom2(i32, i32, i16, i16, i16*)
-; CHECK: declare void @__dfsw_custom3(i32, ...)
-; CHECK: declare i32 @__dfsw_custom4(i32, ...)
+; CHECK: declare void @__dfsw_custom3(i32, i16, i16*, ...)
+; CHECK: declare i32 @__dfsw_custom4(i32, i16, i16*, i16*, ...)
 
 ; CHECK-LABEL: define linkonce_odr i32 @"dfst0$customcb"(i32 (i32)*, i32, i16, i16*)
 ; CHECK: %[[BC:.*]] = bitcast i32 (i32)* %0 to { i32, i16 } (i32, i16)*
@@ -85,3 +93,4 @@ define i32 (i32, i32)* @g(i32) {
 ; CHECK: %[[XVAL1:.*]] = extractvalue { i32, i16 } %[[CALL]], 1
 ; CHECK: store i16 %[[XVAL1]], i16* %3
 ; CHECK: ret i32 %[[XVAL0]]
+





More information about the llvm-commits mailing list