diff options
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp | 21 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 15 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/instructions.ll | 9 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types-function.ll | 21 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types.ll | 8 |
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 |