forked from OSchip/llvm-project
Refactor the return-from-function code into popStackAndReturnValueToCaller().
Make external function calls slightly less special; now they get a stack frame. llvm-svn: 9765
This commit is contained in:
parent
34596d7048
commit
65cac90a92
|
@ -432,9 +432,38 @@ void Interpreter::exitCalled(GenericValue GV) {
|
||||||
ECStack.clear();
|
ECStack.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pop the last stack frame off of ECStack and then copy the result
|
||||||
|
/// back into the result variable if we are not returning void. The
|
||||||
|
/// result variable may be the ExitCode, or the Value of the calling
|
||||||
|
/// CallInst if there was a previous stack frame. This procedure may
|
||||||
|
/// invalidate any ECStack iterators you have.
|
||||||
|
///
|
||||||
|
void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy,
|
||||||
|
GenericValue Result) {
|
||||||
|
// Pop the current stack frame.
|
||||||
|
ECStack.pop_back();
|
||||||
|
|
||||||
|
if (ECStack.empty()) { // Finished main. Put result into exit code...
|
||||||
|
if (RetTy && RetTy->isIntegral()) { // Nonvoid return type?
|
||||||
|
ExitCode = Result.IntVal; // Capture the exit code of the program
|
||||||
|
} else {
|
||||||
|
ExitCode = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If we have a previous stack frame, and we have a previous call,
|
||||||
|
// fill in the return value...
|
||||||
|
ExecutionContext &CallingSF = ECStack.back();
|
||||||
|
if (CallingSF.Caller) {
|
||||||
|
if (CallingSF.Caller->getType() != Type::VoidTy) // Save result...
|
||||||
|
SetValue(CallingSF.Caller, Result, CallingSF);
|
||||||
|
CallingSF.Caller = 0; // We returned from the call...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Interpreter::visitReturnInst(ReturnInst &I) {
|
void Interpreter::visitReturnInst(ReturnInst &I) {
|
||||||
ExecutionContext &SF = ECStack.back();
|
ExecutionContext &SF = ECStack.back();
|
||||||
const Type *RetTy = 0;
|
const Type *RetTy = Type::VoidTy;
|
||||||
GenericValue Result;
|
GenericValue Result;
|
||||||
|
|
||||||
// Save away the return value... (if we are not 'ret void')
|
// Save away the return value... (if we are not 'ret void')
|
||||||
|
@ -443,25 +472,7 @@ void Interpreter::visitReturnInst(ReturnInst &I) {
|
||||||
Result = getOperandValue(I.getReturnValue(), SF);
|
Result = getOperandValue(I.getReturnValue(), SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop the current stack frame... this invalidates SF
|
popStackAndReturnValueToCaller(RetTy, Result);
|
||||||
ECStack.pop_back();
|
|
||||||
|
|
||||||
if (ECStack.empty()) { // Finished main. Put result into exit code...
|
|
||||||
if (RetTy && RetTy->isIntegral()) { // Nonvoid return type?
|
|
||||||
ExitCode = Result.IntVal; // Capture the exit code of the program
|
|
||||||
} else {
|
|
||||||
ExitCode = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If we have a previous stack frame, and we have a previous call,
|
|
||||||
// fill in the return value...
|
|
||||||
ExecutionContext &NewSF = ECStack.back();
|
|
||||||
if (NewSF.Caller) {
|
|
||||||
if (NewSF.Caller->getType() != Type::VoidTy) // Save result...
|
|
||||||
SetValue(NewSF.Caller, Result, NewSF);
|
|
||||||
NewSF.Caller = 0; // We returned from the call...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::visitBranchInst(BranchInst &I) {
|
void Interpreter::visitBranchInst(BranchInst &I) {
|
||||||
|
@ -796,27 +807,20 @@ void Interpreter::callFunction(Function *F,
|
||||||
assert((ECStack.empty() || ECStack.back().Caller == 0 ||
|
assert((ECStack.empty() || ECStack.back().Caller == 0 ||
|
||||||
ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) &&
|
ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) &&
|
||||||
"Incorrect number of arguments passed into function call!");
|
"Incorrect number of arguments passed into function call!");
|
||||||
if (F->isExternal()) {
|
|
||||||
GenericValue Result = callExternalFunction(F, ArgVals);
|
|
||||||
const Type *RetTy = F->getReturnType();
|
|
||||||
|
|
||||||
// Copy the result back into the result variable if we are not returning
|
|
||||||
// void.
|
|
||||||
if (RetTy != Type::VoidTy) {
|
|
||||||
if (!ECStack.empty() && ECStack.back().Caller) {
|
|
||||||
ExecutionContext &SF = ECStack.back();
|
|
||||||
SetValue(SF.Caller, Result, SF);
|
|
||||||
SF.Caller = 0; // We returned from the call...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a new stack frame... and fill it in.
|
// Make a new stack frame... and fill it in.
|
||||||
ECStack.push_back(ExecutionContext());
|
ECStack.push_back(ExecutionContext());
|
||||||
ExecutionContext &StackFrame = ECStack.back();
|
ExecutionContext &StackFrame = ECStack.back();
|
||||||
StackFrame.CurFunction = F;
|
StackFrame.CurFunction = F;
|
||||||
|
|
||||||
|
// Special handling for external functions.
|
||||||
|
if (F->isExternal()) {
|
||||||
|
GenericValue Result = callExternalFunction (F, ArgVals);
|
||||||
|
// Simulate a 'ret' instruction of the appropriate type.
|
||||||
|
popStackAndReturnValueToCaller (F->getReturnType (), Result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get pointers to first LLVM BB & Instruction in function.
|
||||||
StackFrame.CurBB = F->begin();
|
StackFrame.CurBB = F->begin();
|
||||||
StackFrame.CurInst = StackFrame.CurBB->begin();
|
StackFrame.CurInst = StackFrame.CurBB->begin();
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,7 @@ private: // Helper functions
|
||||||
GenericValue getOperandValue(Value *V, ExecutionContext &SF);
|
GenericValue getOperandValue(Value *V, ExecutionContext &SF);
|
||||||
GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
|
GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
|
||||||
ExecutionContext &SF);
|
ExecutionContext &SF);
|
||||||
|
void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue