mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-17 04:24:00 +00:00
switch main LLI core execution to use an InstVisitor instead of a switch statement
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6081 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -486,7 +486,8 @@ static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2,
|
|||||||
return Dest;
|
return Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void executeBinaryInst(BinaryOperator &I, ExecutionContext &SF) {
|
void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
const Type *Ty = I.getOperand(0)->getType();
|
const Type *Ty = I.getOperand(0)->getType();
|
||||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||||
@ -577,7 +578,8 @@ void Interpreter::exitCalled(GenericValue GV) {
|
|||||||
PerformExitStuff();
|
PerformExitStuff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) {
|
void Interpreter::visitReturnInst(ReturnInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
const Type *RetTy = 0;
|
const Type *RetTy = 0;
|
||||||
GenericValue Result;
|
GenericValue Result;
|
||||||
|
|
||||||
@ -631,7 +633,8 @@ void Interpreter::executeRetInst(ReturnInst &I, ExecutionContext &SF) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) {
|
void Interpreter::visitBranchInst(BranchInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
BasicBlock *Dest;
|
BasicBlock *Dest;
|
||||||
|
|
||||||
Dest = I.getSuccessor(0); // Uncond branches have a fixed dest...
|
Dest = I.getSuccessor(0); // Uncond branches have a fixed dest...
|
||||||
@ -643,7 +646,8 @@ void Interpreter::executeBrInst(BranchInst &I, ExecutionContext &SF) {
|
|||||||
SwitchToNewBasicBlock(Dest, SF);
|
SwitchToNewBasicBlock(Dest, SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::executeSwitchInst(SwitchInst &I, ExecutionContext &SF) {
|
void Interpreter::visitSwitchInst(SwitchInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
GenericValue CondVal = getOperandValue(I.getOperand(0), SF);
|
GenericValue CondVal = getOperandValue(I.getOperand(0), SF);
|
||||||
const Type *ElTy = I.getOperand(0)->getType();
|
const Type *ElTy = I.getOperand(0)->getType();
|
||||||
|
|
||||||
@ -681,6 +685,8 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
|
|||||||
std::vector<GenericValue> ResultValues;
|
std::vector<GenericValue> ResultValues;
|
||||||
|
|
||||||
for (; PHINode *PN = dyn_cast<PHINode>(SF.CurInst); ++SF.CurInst) {
|
for (; PHINode *PN = dyn_cast<PHINode>(SF.CurInst); ++SF.CurInst) {
|
||||||
|
if (Trace) CW << "Run:" << PN;
|
||||||
|
|
||||||
// Search for the value corresponding to this previous bb...
|
// Search for the value corresponding to this previous bb...
|
||||||
int i = PN->getBasicBlockIndex(PrevBB);
|
int i = PN->getBasicBlockIndex(PrevBB);
|
||||||
assert(i != -1 && "PHINode doesn't contain entry for predecessor??");
|
assert(i != -1 && "PHINode doesn't contain entry for predecessor??");
|
||||||
@ -702,7 +708,9 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
|
|||||||
// Memory Instruction Implementations
|
// Memory Instruction Implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) {
|
void Interpreter::visitAllocationInst(AllocationInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
|
|
||||||
const Type *Ty = I.getType()->getElementType(); // Type to be allocated
|
const Type *Ty = I.getType()->getElementType(); // Type to be allocated
|
||||||
|
|
||||||
// Get the number of elements being allocated by the array...
|
// Get the number of elements being allocated by the array...
|
||||||
@ -720,7 +728,8 @@ void Interpreter::executeAllocInst(AllocationInst &I, ExecutionContext &SF) {
|
|||||||
ECStack.back().Allocas.add(Memory);
|
ECStack.back().Allocas.add(Memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void executeFreeInst(FreeInst &I, ExecutionContext &SF) {
|
void Interpreter::visitFreeInst(FreeInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?");
|
assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?");
|
||||||
GenericValue Value = getOperandValue(I.getOperand(0), SF);
|
GenericValue Value = getOperandValue(I.getOperand(0), SF);
|
||||||
// TODO: Check to make sure memory is allocated
|
// TODO: Check to make sure memory is allocated
|
||||||
@ -784,19 +793,22 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void executeGEPInst(GetElementPtrInst &I, ExecutionContext &SF) {
|
void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(),
|
SetValue(&I, TheEE->executeGEPOperation(I.getPointerOperand(),
|
||||||
I.idx_begin(), I.idx_end(), SF), SF);
|
I.idx_begin(), I.idx_end(), SF), SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::executeLoadInst(LoadInst &I, ExecutionContext &SF) {
|
void Interpreter::visitLoadInst(LoadInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
|
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
|
||||||
GenericValue *Ptr = (GenericValue*)GVTOP(SRC);
|
GenericValue *Ptr = (GenericValue*)GVTOP(SRC);
|
||||||
GenericValue Result = LoadValueFromMemory(Ptr, I.getType());
|
GenericValue Result = LoadValueFromMemory(Ptr, I.getType());
|
||||||
SetValue(&I, Result, SF);
|
SetValue(&I, Result, SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) {
|
void Interpreter::visitStoreInst(StoreInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
GenericValue Val = getOperandValue(I.getOperand(0), SF);
|
GenericValue Val = getOperandValue(I.getOperand(0), SF);
|
||||||
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
|
GenericValue SRC = getOperandValue(I.getPointerOperand(), SF);
|
||||||
StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC),
|
StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC),
|
||||||
@ -809,8 +821,9 @@ void Interpreter::executeStoreInst(StoreInst &I, ExecutionContext &SF) {
|
|||||||
// Miscellaneous Instruction Implementations
|
// Miscellaneous Instruction Implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) {
|
void Interpreter::visitCallInst(CallInst &I) {
|
||||||
ECStack.back().Caller = &I;
|
ExecutionContext &SF = ECStack.back();
|
||||||
|
SF.Caller = &I;
|
||||||
std::vector<GenericValue> ArgVals;
|
std::vector<GenericValue> ArgVals;
|
||||||
ArgVals.reserve(I.getNumOperands()-1);
|
ArgVals.reserve(I.getNumOperands()-1);
|
||||||
for (unsigned i = 1; i < I.getNumOperands(); ++i) {
|
for (unsigned i = 1; i < I.getNumOperands(); ++i) {
|
||||||
@ -838,15 +851,15 @@ void Interpreter::executeCallInst(CallInst &I, ExecutionContext &SF) {
|
|||||||
|
|
||||||
// To handle indirect calls, we must get the pointer value from the argument
|
// To handle indirect calls, we must get the pointer value from the argument
|
||||||
// and treat it as a function pointer.
|
// and treat it as a function pointer.
|
||||||
GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
|
GenericValue SRC = getOperandValue(I.getCalledValue(), SF);
|
||||||
|
|
||||||
callFunction((Function*)GVTOP(SRC), ArgVals);
|
callFunction((Function*)GVTOP(SRC), ArgVals);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPLEMENT_SHIFT(OP, TY) \
|
#define IMPLEMENT_SHIFT(OP, TY) \
|
||||||
case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break
|
case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break
|
||||||
|
|
||||||
static void executeShlInst(ShiftInst &I, ExecutionContext &SF) {
|
void Interpreter::visitShl(ShiftInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
const Type *Ty = I.getOperand(0)->getType();
|
const Type *Ty = I.getOperand(0)->getType();
|
||||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||||
@ -867,7 +880,8 @@ static void executeShlInst(ShiftInst &I, ExecutionContext &SF) {
|
|||||||
SetValue(&I, Dest, SF);
|
SetValue(&I, Dest, SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void executeShrInst(ShiftInst &I, ExecutionContext &SF) {
|
void Interpreter::visitShr(ShiftInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
const Type *Ty = I.getOperand(0)->getType();
|
const Type *Ty = I.getOperand(0)->getType();
|
||||||
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
GenericValue Src1 = getOperandValue(I.getOperand(0), SF);
|
||||||
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
GenericValue Src2 = getOperandValue(I.getOperand(1), SF);
|
||||||
@ -948,11 +962,14 @@ static GenericValue executeCastOperation(Value *SrcVal, const Type *Ty,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void executeCastInst(CastInst &I, ExecutionContext &SF) {
|
void Interpreter::visitCastInst(CastInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
|
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void executeVarArgInst(VarArgInst &I, ExecutionContext &SF) {
|
void Interpreter::visitVarArgInst(VarArgInst &I) {
|
||||||
|
ExecutionContext &SF = ECStack.back();
|
||||||
|
|
||||||
// Get the pointer to the valist element. LLI treats the valist in memory as
|
// Get the pointer to the valist element. LLI treats the valist in memory as
|
||||||
// an integer.
|
// an integer.
|
||||||
GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF);
|
GenericValue VAListPtr = getOperandValue(I.getOperand(0), SF);
|
||||||
@ -1081,8 +1098,7 @@ bool Interpreter::executeInstruction() {
|
|||||||
ExecutionContext &SF = ECStack.back(); // Current stack frame
|
ExecutionContext &SF = ECStack.back(); // Current stack frame
|
||||||
Instruction &I = *SF.CurInst++; // Increment before execute
|
Instruction &I = *SF.CurInst++; // Increment before execute
|
||||||
|
|
||||||
if (Trace)
|
if (Trace) CW << "Run:" << I;
|
||||||
CW << "Run:" << I;
|
|
||||||
|
|
||||||
// Track the number of dynamic instructions executed.
|
// Track the number of dynamic instructions executed.
|
||||||
++NumDynamicInsts;
|
++NumDynamicInsts;
|
||||||
@ -1107,37 +1123,7 @@ bool Interpreter::executeInstruction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InInstruction = true;
|
InInstruction = true;
|
||||||
if (I.isBinaryOp()) {
|
visit(I); // Dispatch to one of the visit* methods...
|
||||||
executeBinaryInst(cast<BinaryOperator>(I), SF);
|
|
||||||
} else {
|
|
||||||
switch (I.getOpcode()) {
|
|
||||||
// Terminators
|
|
||||||
case Instruction::Ret: executeRetInst (cast<ReturnInst>(I), SF); break;
|
|
||||||
case Instruction::Br: executeBrInst (cast<BranchInst>(I), SF); break;
|
|
||||||
case Instruction::Switch: executeSwitchInst(cast<SwitchInst>(I), SF);break;
|
|
||||||
// Invoke not handled!
|
|
||||||
|
|
||||||
// Memory Instructions
|
|
||||||
case Instruction::Alloca:
|
|
||||||
case Instruction::Malloc: executeAllocInst((AllocationInst&)I, SF); break;
|
|
||||||
case Instruction::Free: executeFreeInst (cast<FreeInst> (I), SF); break;
|
|
||||||
case Instruction::Load: executeLoadInst (cast<LoadInst> (I), SF); break;
|
|
||||||
case Instruction::Store: executeStoreInst(cast<StoreInst>(I), SF); break;
|
|
||||||
case Instruction::GetElementPtr:
|
|
||||||
executeGEPInst(cast<GetElementPtrInst>(I), SF); break;
|
|
||||||
|
|
||||||
// Miscellaneous Instructions
|
|
||||||
case Instruction::Call: executeCallInst (cast<CallInst> (I), SF); break;
|
|
||||||
case Instruction::PHINode: assert(0 && "PHI nodes already handled!");
|
|
||||||
case Instruction::Cast: executeCastInst (cast<CastInst> (I), SF); break;
|
|
||||||
case Instruction::Shl: executeShlInst (cast<ShiftInst>(I), SF); break;
|
|
||||||
case Instruction::Shr: executeShrInst (cast<ShiftInst>(I), SF); break;
|
|
||||||
case Instruction::VarArg: executeVarArgInst(cast<VarArgInst>(I),SF); break;
|
|
||||||
default:
|
|
||||||
std::cout << "Don't know how to execute this instruction!\n-->" << I;
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InInstruction = false;
|
InInstruction = false;
|
||||||
|
|
||||||
// Reset the current frame location to the top of stack
|
// Reset the current frame location to the top of stack
|
||||||
|
@ -11,22 +11,16 @@
|
|||||||
//#define PROFILE_STRUCTURE_FIELDS 1
|
//#define PROFILE_STRUCTURE_FIELDS 1
|
||||||
|
|
||||||
#include "../ExecutionEngine.h"
|
#include "../ExecutionEngine.h"
|
||||||
|
#include "../GenericValue.h"
|
||||||
#include "Support/DataTypes.h"
|
#include "Support/DataTypes.h"
|
||||||
#include "llvm/Assembly/CachedWriter.h"
|
#include "llvm/Assembly/CachedWriter.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/BasicBlock.h"
|
#include "llvm/BasicBlock.h"
|
||||||
#include "../GenericValue.h"
|
#include "llvm/Support/InstVisitor.h"
|
||||||
|
|
||||||
extern CachedWriter CW; // Object to accelerate printing of LLVM
|
extern CachedWriter CW; // Object to accelerate printing of LLVM
|
||||||
|
|
||||||
struct FunctionInfo; // Defined in ExecutionAnnotations.h
|
struct FunctionInfo; // Defined in ExecutionAnnotations.h
|
||||||
class CallInst;
|
|
||||||
class ReturnInst;
|
|
||||||
class BranchInst;
|
|
||||||
class SwitchInst;
|
|
||||||
class LoadInst;
|
|
||||||
class StoreInst;
|
|
||||||
class AllocationInst;
|
|
||||||
|
|
||||||
// AllocaHolder - Object to track all of the blocks of memory allocated by
|
// AllocaHolder - Object to track all of the blocks of memory allocated by
|
||||||
// alloca. When the function returns, this object is poped off the execution
|
// alloca. When the function returns, this object is poped off the execution
|
||||||
@ -78,7 +72,7 @@ struct ExecutionContext {
|
|||||||
|
|
||||||
// Interpreter - This class represents the entirety of the interpreter.
|
// Interpreter - This class represents the entirety of the interpreter.
|
||||||
//
|
//
|
||||||
class Interpreter : public ExecutionEngine {
|
class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
|
||||||
int ExitCode; // The exit code to be returned by the lli util
|
int ExitCode; // The exit code to be returned by the lli util
|
||||||
bool Debug; // Debug mode enabled?
|
bool Debug; // Debug mode enabled?
|
||||||
bool Profile; // Profiling enabled?
|
bool Profile; // Profiling enabled?
|
||||||
@ -134,11 +128,28 @@ public:
|
|||||||
void finish(); // Do the 'finish' command
|
void finish(); // Do the 'finish' command
|
||||||
|
|
||||||
// Opcode Implementations
|
// Opcode Implementations
|
||||||
void executeCallInst(CallInst &I, ExecutionContext &SF);
|
void visitReturnInst(ReturnInst &I);
|
||||||
void executeRetInst(ReturnInst &I, ExecutionContext &SF);
|
void visitBranchInst(BranchInst &I);
|
||||||
void executeBrInst(BranchInst &I, ExecutionContext &SF);
|
void visitSwitchInst(SwitchInst &I);
|
||||||
void executeSwitchInst(SwitchInst &I, ExecutionContext &SF);
|
|
||||||
void executeAllocInst(AllocationInst &I, ExecutionContext &SF);
|
void visitBinaryOperator(BinaryOperator &I);
|
||||||
|
void visitAllocationInst(AllocationInst &I);
|
||||||
|
void visitFreeInst(FreeInst &I);
|
||||||
|
void visitLoadInst(LoadInst &I);
|
||||||
|
void visitStoreInst(StoreInst &I);
|
||||||
|
void visitGetElementPtrInst(GetElementPtrInst &I);
|
||||||
|
|
||||||
|
void visitPHINode(PHINode &PN) { assert(0 && "PHI nodes already handled!"); }
|
||||||
|
void visitCastInst(CastInst &I);
|
||||||
|
void visitCallInst(CallInst &I);
|
||||||
|
void visitShl(ShiftInst &I);
|
||||||
|
void visitShr(ShiftInst &I);
|
||||||
|
void visitVarArgInst(VarArgInst &I);
|
||||||
|
void visitInstruction(Instruction &I) {
|
||||||
|
std::cerr << I;
|
||||||
|
assert(0 && "Instruction not interpretable yet!");
|
||||||
|
}
|
||||||
|
|
||||||
GenericValue callExternalFunction(Function *F,
|
GenericValue callExternalFunction(Function *F,
|
||||||
const std::vector<GenericValue> &ArgVals);
|
const std::vector<GenericValue> &ArgVals);
|
||||||
void exitCalled(GenericValue GV);
|
void exitCalled(GenericValue GV);
|
||||||
@ -157,9 +168,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
|
GenericValue executeGEPOperation(Value *Ptr, User::op_iterator I,
|
||||||
User::op_iterator E, ExecutionContext &SF);
|
User::op_iterator E, ExecutionContext &SF);
|
||||||
void executeLoadInst(LoadInst &I, ExecutionContext &SF);
|
|
||||||
void executeStoreInst(StoreInst &I, ExecutionContext &SF);
|
|
||||||
|
|
||||||
|
|
||||||
private: // Helper functions
|
private: // Helper functions
|
||||||
// SwitchToNewBasicBlock - Start execution in a new basic block and run any
|
// SwitchToNewBasicBlock - Start execution in a new basic block and run any
|
||||||
|
Reference in New Issue
Block a user