Refactor builtin function evaluation code into its own function.

llvm-svn: 81061
This commit is contained in:
Zhongxing Xu 2009-09-05 05:00:57 +00:00
parent 7f20002993
commit 88f07cd49c
2 changed files with 47 additions and 33 deletions

View File

@ -579,6 +579,9 @@ protected:
return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X; return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X;
} }
bool EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
public: public:
SVal EvalBinOp(BinaryOperator::Opcode op, NonLoc L, NonLoc R, QualType T) { SVal EvalBinOp(BinaryOperator::Opcode op, NonLoc L, NonLoc R, QualType T) {

View File

@ -1503,6 +1503,46 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
} }
} }
bool GRExprEngine::EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (!FD)
return false;
unsigned id = FD->getBuiltinID(getContext());
if (!id)
return false;
const GRState *state = Pred->getState();
switch (id) {
case Builtin::BI__builtin_expect: {
// For __builtin_expect, just return the value of the subexpression.
assert (CE->arg_begin() != CE->arg_end());
SVal X = state->getSVal(*(CE->arg_begin()));
MakeNode(Dst, CE, Pred, state->BindExpr(CE, X));
return true;
}
case Builtin::BI__builtin_alloca: {
// FIXME: Refactor into StoreManager itself?
MemRegionManager& RM = getStateManager().getRegionManager();
const MemRegion* R =
RM.getAllocaRegion(CE, Builder->getCurrentBlockCount());
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
// cannot represent values like symbol*8.
SVal Extent = state->getSVal(*(CE->arg_begin()));
state = getStoreManager().setExtent(state, R, Extent);
MakeNode(Dst, CE, Pred, state->BindExpr(CE, loc::MemRegionVal(R)));
return true;
}
}
return false;
}
void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L,
ExplodedNode* Pred) { ExplodedNode* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined."); assert (Builder && "GRStmtNodeBuilder must be defined.");
@ -1571,7 +1611,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
} }
// Finally, evaluate the function call. // Finally, evaluate the function call.
for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) { for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
DI != DE; ++DI) {
const GRState* state = GetState(*DI); const GRState* state = GetState(*DI);
SVal L = state->getSVal(Callee); SVal L = state->getSVal(Callee);
@ -1587,38 +1628,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
MarkNoReturnFunction(FD, CE, state, Builder); MarkNoReturnFunction(FD, CE, state, Builder);
// Evaluate the call. // Evaluate the call.
if (EvalBuiltinFunction(FD, CE, Pred, Dst))
if (FD) { continue;
if (unsigned id = FD->getBuiltinID(getContext()))
switch (id) {
case Builtin::BI__builtin_expect: {
// For __builtin_expect, just return the value of the subexpression.
assert (CE->arg_begin() != CE->arg_end());
SVal X = state->getSVal(*(CE->arg_begin()));
MakeNode(Dst, CE, *DI, state->BindExpr(CE, X));
continue;
}
case Builtin::BI__builtin_alloca: {
// FIXME: Refactor into StoreManager itself?
MemRegionManager& RM = getStateManager().getRegionManager();
const MemRegion* R =
RM.getAllocaRegion(CE, Builder->getCurrentBlockCount());
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
// cannot represent values like symbol*8.
SVal Extent = state->getSVal(*(CE->arg_begin()));
state = getStoreManager().setExtent(state, R, Extent);
MakeNode(Dst, CE, *DI, state->BindExpr(CE, loc::MemRegionVal(R)));
continue;
}
default:
break;
}
}
// Dispatch to the plug-in transfer function. // Dispatch to the plug-in transfer function.