aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-09-21 00:27:27 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-09-21 00:27:27 +0000
commit662fd55f5efca9e34b7abdbfd76815c240aa22a5 (patch)
tree7fdd090438c0e64a603f824bdd742edc06c642bf /lib
parent4bc19308f533c03832125c121eabd53c6bcc1b23 (diff)
downloadklee-662fd55f5efca9e34b7abdbfd76815c240aa22a5.tar.gz
Improve skipping of debug intrinsics, we can't evaluate MDNode operands.
git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@82421 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Core/Executor.cpp155
1 files changed, 84 insertions, 71 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index d865bcb5..a2ad843c 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -957,6 +957,9 @@ const Cell& Executor::eval(KInstruction *ki, unsigned index,
assert(index < ki->inst->getNumOperands());
int vnumber = ki->operands[index];
+ assert(vnumber != -1 &&
+ "Invalid operand to eval(), not a value or constant!");
+
// Determine if this is a constant or not.
if (vnumber < 0) {
unsigned index = -vnumber - 2;
@@ -1093,83 +1096,72 @@ void Executor::executeCall(ExecutionState &state,
KInstruction *ki,
Function *f,
std::vector< ref<Expr> > &arguments) {
- if (WriteTraces) {
- // don't print out special debug stop point 'function' calls
- if (f->getIntrinsicID() != Intrinsic::dbg_stoppoint)
- state.exeTraceMgr.addEvent(new FunctionCallTraceEvent(state, ki,
- f->getName()));
- }
+ if (WriteTraces)
+ state.exeTraceMgr.addEvent(new FunctionCallTraceEvent(state, ki,
+ f->getName()));
Instruction *i = ki->inst;
if (f && f->isDeclaration()) {
- if (f!=kmodule->dbgStopPointFn) { // special case speed hack
- switch(f->getIntrinsicID()) {
- case Intrinsic::dbg_stoppoint:
- case Intrinsic::dbg_region_start:
- case Intrinsic::dbg_region_end:
- case Intrinsic::dbg_func_start:
- case Intrinsic::dbg_declare:
- case Intrinsic::not_intrinsic:
- // state may be destroyed by this call, cannot touch
- callExternalFunction(state, ki, f, arguments);
- break;
-
- // va_arg is handled by caller and intrinsic lowering, see comment for
- // ExecutionState::varargs
- case Intrinsic::vastart: {
- StackFrame &sf = state.stack.back();
- assert(sf.varargs &&
- "vastart called in function with no vararg object");
-
- // FIXME: This is really specific to the architecture, not the pointer
- // size. This happens to work fir x86-32 and x86-64, however.
- Expr::Width WordSize = Context::get().getPointerWidth();
- if (WordSize == Expr::Int32) {
- executeMemoryOperation(state, true, arguments[0],
- sf.varargs->getBaseExpr(), 0);
- } else {
- assert(WordSize == Expr::Int64 && "Unknown word size!");
-
- // X86-64 has quite complicated calling convention. However,
- // instead of implementing it, we can do a simple hack: just
- // make a function believe that all varargs are on stack.
- executeMemoryOperation(state, true, arguments[0],
- ConstantExpr::create(48, 32), 0); // gp_offset
- executeMemoryOperation(state, true,
- AddExpr::create(arguments[0],
- ConstantExpr::create(4, 64)),
- ConstantExpr::create(304, 32), 0); // fp_offset
- executeMemoryOperation(state, true,
- AddExpr::create(arguments[0],
- ConstantExpr::create(8, 64)),
- sf.varargs->getBaseExpr(), 0); // overflow_arg_area
- executeMemoryOperation(state, true,
- AddExpr::create(arguments[0],
- ConstantExpr::create(16, 64)),
- ConstantExpr::create(0, 64), 0); // reg_save_area
- }
- break;
- }
- case Intrinsic::vaend:
- // va_end is a noop for the interpreter.
- //
- // FIXME: We should validate that the target didn't do something bad
- // with vaeend, however (like call it twice).
- break;
-
- case Intrinsic::vacopy:
- // va_copy should have been lowered.
- //
- // FIXME: It would be nice to check for errors in the usage of this as
- // well.
- default:
- klee_error("unknown intrinsic: %s", f->getName().data());
+ switch(f->getIntrinsicID()) {
+ case Intrinsic::not_intrinsic:
+ // state may be destroyed by this call, cannot touch
+ callExternalFunction(state, ki, f, arguments);
+ break;
+
+ // va_arg is handled by caller and intrinsic lowering, see comment for
+ // ExecutionState::varargs
+ case Intrinsic::vastart: {
+ StackFrame &sf = state.stack.back();
+ assert(sf.varargs &&
+ "vastart called in function with no vararg object");
+
+ // FIXME: This is really specific to the architecture, not the pointer
+ // size. This happens to work fir x86-32 and x86-64, however.
+ Expr::Width WordSize = Context::get().getPointerWidth();
+ if (WordSize == Expr::Int32) {
+ executeMemoryOperation(state, true, arguments[0],
+ sf.varargs->getBaseExpr(), 0);
+ } else {
+ assert(WordSize == Expr::Int64 && "Unknown word size!");
+
+ // X86-64 has quite complicated calling convention. However,
+ // instead of implementing it, we can do a simple hack: just
+ // make a function believe that all varargs are on stack.
+ executeMemoryOperation(state, true, arguments[0],
+ ConstantExpr::create(48, 32), 0); // gp_offset
+ executeMemoryOperation(state, true,
+ AddExpr::create(arguments[0],
+ ConstantExpr::create(4, 64)),
+ ConstantExpr::create(304, 32), 0); // fp_offset
+ executeMemoryOperation(state, true,
+ AddExpr::create(arguments[0],
+ ConstantExpr::create(8, 64)),
+ sf.varargs->getBaseExpr(), 0); // overflow_arg_area
+ executeMemoryOperation(state, true,
+ AddExpr::create(arguments[0],
+ ConstantExpr::create(16, 64)),
+ ConstantExpr::create(0, 64), 0); // reg_save_area
}
+ break;
+ }
+ case Intrinsic::vaend:
+ // va_end is a noop for the interpreter.
+ //
+ // FIXME: We should validate that the target didn't do something bad
+ // with vaeend, however (like call it twice).
+ break;
+
+ case Intrinsic::vacopy:
+ // va_copy should have been lowered.
+ //
+ // FIXME: It would be nice to check for errors in the usage of this as
+ // well.
+ default:
+ klee_error("unknown intrinsic: %s", f->getName().data());
}
- if (InvokeInst *ii = dyn_cast<InvokeInst>(i)) {
+ if (InvokeInst *ii = dyn_cast<InvokeInst>(i))
transferToBasicBlock(ii->getNormalDest(), i->getParent(), state);
- }
} else {
// FIXME: I'm not really happy about this reliance on prevPC but it is ok, I
// guess. This just done to avoid having to pass KInstIterator everywhere
@@ -1300,6 +1292,23 @@ Function* Executor::getCalledFunction(CallSite &cs, ExecutionState &state) {
return f;
}
+static bool isDebugIntrinsic(const Function *f, KModule *KM) {
+ // Fast path, getIntrinsicID is slow.
+ if (f == KM->dbgStopPointFn)
+ return true;
+
+ switch (f->getIntrinsicID()) {
+ case Intrinsic::dbg_stoppoint:
+ case Intrinsic::dbg_region_start:
+ case Intrinsic::dbg_region_end:
+ case Intrinsic::dbg_func_start:
+ case Intrinsic::dbg_declare:
+ return true;
+
+ default:
+ return false;
+ }
+}
void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
Instruction *i = ki->inst;
@@ -1511,7 +1520,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
unsigned numArgs = cs.arg_size();
Function *f = getCalledFunction(cs, state);
-
+
+ // Skip debug intrinsics, we can't evaluate their metadata arguments.
+ if (f && isDebugIntrinsic(f, kmodule))
+ break;
+
// evaluate arguments
std::vector< ref<Expr> > arguments;
arguments.reserve(numArgs);