aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp21
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyModule.cpp15
-rw-r--r--test/NaCl/PNaClABI/instructions.ll9
-rw-r--r--test/NaCl/PNaClABI/types-function.ll21
-rw-r--r--test/NaCl/PNaClABI/types.ll8
5 files changed, 68 insertions, 6 deletions
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
index 97278d95cc..ef1c26e175 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
@@ -15,7 +15,7 @@
#include "llvm/Pass.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Function.h"
-#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/NaCl.h"
@@ -44,6 +44,7 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
// For now just start with new errors on each function; this may change
// once we want to do something with them other than just calling print()
ErrorsString.clear();
+ // TODO: only report one error per instruction
for (Function::const_iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI) {
for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end();
@@ -128,6 +129,24 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
" has instruction with disallowed type: " +
PNaClABITypeChecker::getTypeName(BBI->getType()) + "\n";
}
+
+ // Check the instruction operands. Operands which are Instructions will
+ // be checked on their own here, and GlobalValues will be checked by the
+ // Module verifier. That leaves Constants.
+ // Switches are implemented in the in-memory IR with vectors, so don't
+ // check them.
+ if (!isa<SwitchInst>(*BBI))
+ for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end();
+ OI != OE; OI++) {
+ if (isa<Constant>(OI) && !isa<GlobalValue>(OI) &&
+ !isa<Instruction>(OI)) {
+ Type *T = TC.checkTypesInValue(*OI);
+ if (T)
+ Errors << "Function " + F.getName() +
+ " has instruction operand with disallowed type: " +
+ PNaClABITypeChecker::getTypeName(T) + "\n";
+ }
+ }
}
}
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
index 54666378b3..f2124e1d12 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
@@ -105,6 +105,21 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
E = M.alias_end(); MI != E; ++MI)
Errors << "Variable " + MI->getName() + " is an alias (disallowed)\n";
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
+ // Check types of functions and their arguments
+ FunctionType *FT = MI->getFunctionType();
+ if (!TC.isValidType(FT->getReturnType()))
+ Errors << "Function " + MI->getName() + " has disallowed return type: " +
+ PNaClABITypeChecker::getTypeName(FT->getReturnType()) + "\n";
+ for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) {
+ Type *PT = FT->getParamType(I);
+ if (!TC.isValidType(PT))
+ Errors << "Function " << MI->getName() << " argument " << I + 1 <<
+ " has disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(PT) + "\n";
+ }
+ }
+
Errors.flush();
return false;
}
diff --git a/test/NaCl/PNaClABI/instructions.ll b/test/NaCl/PNaClABI/instructions.ll
index c7615529c9..7461f7a361 100644
--- a/test/NaCl/PNaClABI/instructions.ll
+++ b/test/NaCl/PNaClABI/instructions.ll
@@ -15,9 +15,9 @@ next:
next2:
unreachable
resume i8 0
- indirectbr i8* undef, [label %next, label %next2]
; CHECK-NOT: disallowed
; CHECK: Function terminators has disallowed instruction: indirectbr
+ indirectbr i8* undef, [label %next, label %next2]
}
define void @binops() {
@@ -45,13 +45,14 @@ define void @binops() {
define void @vectors() {
; CHECK-NOT: disallowed
- %a1 = extractelement <2 x i32> <i32 0, i32 0>, i32 0
; CHECK: Function vectors has disallowed instruction: extractelement
- %a2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> undef
+ %a1 = extractelement <2 x i32> <i32 0, i32 0>, i32 0
; CHECK: Function vectors has disallowed instruction: shufflevector
- %a3 = insertelement <2 x i32> undef, i32 1, i32 0
+ %a2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> undef
; CHECK: Function vectors has disallowed instruction: insertelement
; CHECK: Function vectors has instruction with disallowed type
+; CHECK: Function vectors has instruction operand with disallowed type
+ %a3 = insertelement <2 x i32> undef, i32 1, i32 0
ret void
}
diff --git a/test/NaCl/PNaClABI/types-function.ll b/test/NaCl/PNaClABI/types-function.ll
index 0302d3715d..eb8aedcef5 100644
--- a/test/NaCl/PNaClABI/types-function.ll
+++ b/test/NaCl/PNaClABI/types-function.ll
@@ -3,8 +3,27 @@
; all the rules about the various types, but instead to make sure that types
; stashed in various places in function bodies are caught.
+@a2 = private global i17 zeroinitializer
+declare void @func(i15 %arg)
+
define void @types() {
; CHECK: Function types has instruction with disallowed type: half
%h1 = fptrunc double undef to half
+; CHECK: Function types has instruction operand with disallowed type: half
+ %h2 = bitcast half 0.0 to i16
+; see below...
+ %h3 = fadd double 0.0, fpext (half 0.0 to double)
+; CHECK: Function types has instruction operand with disallowed type: i17*
+ store i32 0, i32* bitcast (i17* @a2 to i32*), align 4
+; CHECK: Function types has instruction operand with disallowed type: i15
+ call void @func(i15 1)
ret void
-} \ No newline at end of file
+}
+; CHECK-NOT: disallowed
+
+
+; TODO:
+; the bitcode reader seems to expand some operations inline
+; (e.g. fpext, sext, uitofp) such that doing something like
+; %h3 = fadd double 0.0, fpext (half 0.0 to double)
+; means the verifier pass will never see the fpext or its operands
diff --git a/test/NaCl/PNaClABI/types.ll b/test/NaCl/PNaClABI/types.ll
index 0c68036a73..0447ea07ee 100644
--- a/test/NaCl/PNaClABI/types.ll
+++ b/test/NaCl/PNaClABI/types.ll
@@ -89,3 +89,11 @@
; CHECK: Variable alias1 is an alias (disallowed)
@alias1 = alias i32* @i32
+
+; CHECK: Function badReturn has disallowed return type
+declare half* @badReturn()
+
+; CHECK: Function badArgType1 argument 1 has disallowed type
+declare void @badArgType1(half %a, i32 %b)
+; CHECK: Function badArgType2 argument 2 has disallowed type
+declare void @badArgType2(i32 %a, half %b) \ No newline at end of file