mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Reduce the number of #includes.
CurFrame, TraceMode, and the CachedWriter are history. ArrayChecksEnabled and non-QuietMode are history. The ExecutionAnnotations (SlotNumber, InstNumber, and FunctionInfo) are history. ExecutionContext now keeps Values for each stack frame in a std::map. Stop pre-initializing Values on the stack to 42. Remove some dead variables, excess whitespace and commented-out code. executeInstruction() is now part of run(). printValue() and print() are history. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9489 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20a277e162
commit
03e43dcfe7
@ -12,13 +12,10 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "Interpreter.h"
|
#include "Interpreter.h"
|
||||||
#include "ExecutionAnnotations.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/Assembly/Writer.h"
|
|
||||||
#include "Support/CommandLine.h"
|
|
||||||
#include "Support/Statistic.h"
|
#include "Support/Statistic.h"
|
||||||
#include <cmath> // For fmod
|
#include <cmath> // For fmod
|
||||||
|
|
||||||
@ -26,41 +23,18 @@ Interpreter *TheEE = 0;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Statistic<> NumDynamicInsts("lli", "Number of dynamic instructions executed");
|
Statistic<> NumDynamicInsts("lli", "Number of dynamic instructions executed");
|
||||||
|
|
||||||
cl::opt<bool>
|
|
||||||
QuietMode("quiet", cl::desc("Do not emit any non-program output"),
|
|
||||||
cl::init(true));
|
|
||||||
|
|
||||||
cl::alias
|
|
||||||
QuietModeA("q", cl::desc("Alias for -quiet"), cl::aliasopt(QuietMode));
|
|
||||||
|
|
||||||
cl::opt<bool>
|
|
||||||
ArrayChecksEnabled("array-checks", cl::desc("Enable array bound checks"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a TargetData structure to handle memory addressing and size/alignment
|
|
||||||
// computations
|
|
||||||
//
|
|
||||||
CachedWriter CW; // Object to accelerate printing of LLVM
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Value Manipulation code
|
// Value Manipulation code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
static unsigned getOperandSlot(Value *V) {
|
|
||||||
SlotNumber *SN = (SlotNumber*)V->getAnnotation(SlotNumberAID);
|
|
||||||
assert(SN && "Operand does not have a slot number annotation!");
|
|
||||||
return SN->SlotNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operations used by constant expr implementations...
|
// Operations used by constant expr implementations...
|
||||||
static GenericValue executeCastOperation(Value *Src, const Type *DestTy,
|
static GenericValue executeCastOperation(Value *Src, const Type *DestTy,
|
||||||
ExecutionContext &SF);
|
ExecutionContext &SF);
|
||||||
static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
|
static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2,
|
||||||
const Type *Ty);
|
const Type *Ty);
|
||||||
|
|
||||||
|
|
||||||
GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) {
|
GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) {
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
|
||||||
switch (CE->getOpcode()) {
|
switch (CE->getOpcode()) {
|
||||||
@ -83,19 +57,12 @@ GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) {
|
|||||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||||
return PTOGV(TheEE->getPointerToGlobal(GV));
|
return PTOGV(TheEE->getPointerToGlobal(GV));
|
||||||
} else {
|
} else {
|
||||||
unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value
|
return SF.Values[V];
|
||||||
unsigned OpSlot = getOperandSlot(V);
|
|
||||||
assert(TyP < SF.Values.size() &&
|
|
||||||
OpSlot < SF.Values[TyP].size() && "Value out of range!");
|
|
||||||
return SF.Values[TyP][getOperandSlot(V)];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) {
|
static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) {
|
||||||
unsigned TyP = V->getType()->getUniqueID(); // TypePlane for value
|
SF.Values[V] = Val;
|
||||||
|
|
||||||
//std::cout << "Setting value: " << &SF.Values[TyP][getOperandSlot(V)]<< "\n";
|
|
||||||
SF.Values[TyP][getOperandSlot(V)] = Val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -242,7 +209,6 @@ static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2,
|
|||||||
return Dest;
|
return Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
||||||
const Type *Ty) {
|
const Type *Ty) {
|
||||||
GenericValue Dest;
|
GenericValue Dest;
|
||||||
@ -263,7 +229,6 @@ static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2,
|
|||||||
return Dest;
|
return Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
||||||
const Type *Ty) {
|
const Type *Ty) {
|
||||||
GenericValue Dest;
|
GenericValue Dest;
|
||||||
@ -284,7 +249,6 @@ static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2,
|
|||||||
return Dest;
|
return Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define IMPLEMENT_SETCC(OP, TY) \
|
#define IMPLEMENT_SETCC(OP, TY) \
|
||||||
case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break
|
case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break
|
||||||
|
|
||||||
@ -465,12 +429,6 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void Interpreter::exitCalled(GenericValue GV) {
|
void Interpreter::exitCalled(GenericValue GV) {
|
||||||
if (!QuietMode) {
|
|
||||||
std::cout << "Program returned ";
|
|
||||||
print(Type::IntTy, GV);
|
|
||||||
std::cout << " via 'void exit(int)'\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
ExitCode = GV.SByteVal;
|
ExitCode = GV.SByteVal;
|
||||||
ECStack.clear();
|
ECStack.clear();
|
||||||
}
|
}
|
||||||
@ -486,45 +444,24 @@ void Interpreter::visitReturnInst(ReturnInst &I) {
|
|||||||
Result = getOperandValue(I.getReturnValue(), SF);
|
Result = getOperandValue(I.getReturnValue(), SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save previously executing meth
|
|
||||||
const Function *M = ECStack.back().CurFunction;
|
|
||||||
|
|
||||||
// Pop the current stack frame... this invalidates SF
|
// Pop the current stack frame... this invalidates SF
|
||||||
ECStack.pop_back();
|
ECStack.pop_back();
|
||||||
|
|
||||||
if (ECStack.empty()) { // Finished main. Put result into exit code...
|
if (ECStack.empty()) { // Finished main. Put result into exit code...
|
||||||
if (RetTy) { // Nonvoid return type?
|
if (RetTy && RetTy->isIntegral()) { // Nonvoid return type?
|
||||||
if (!QuietMode) {
|
ExitCode = Result.IntVal; // Capture the exit code of the program
|
||||||
CW << "Function " << M->getType() << " \"" << M->getName()
|
|
||||||
<< "\" returned ";
|
|
||||||
print(RetTy, Result);
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RetTy->isIntegral())
|
|
||||||
ExitCode = Result.IntVal; // Capture the exit code of the program
|
|
||||||
} else {
|
} else {
|
||||||
ExitCode = 0;
|
ExitCode = 0;
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
// If we have a previous stack frame, and we have a previous call,
|
||||||
|
// fill in the return value...
|
||||||
// If we have a previous stack frame, and we have a previous call, fill in
|
ExecutionContext &NewSF = ECStack.back();
|
||||||
// the return value...
|
if (NewSF.Caller) {
|
||||||
//
|
if (NewSF.Caller->getType() != Type::VoidTy) // Save result...
|
||||||
ExecutionContext &NewSF = ECStack.back();
|
SetValue(NewSF.Caller, Result, NewSF);
|
||||||
if (NewSF.Caller) {
|
NewSF.Caller = 0; // We returned from the call...
|
||||||
if (NewSF.Caller->getType() != Type::VoidTy) // Save result...
|
}
|
||||||
SetValue(NewSF.Caller, Result, NewSF);
|
|
||||||
|
|
||||||
NewSF.Caller = 0; // We returned from the call...
|
|
||||||
} else if (!QuietMode) {
|
|
||||||
// This must be a function that is executing because of a user 'call'
|
|
||||||
// instruction.
|
|
||||||
CW << "Function " << M->getType() << " \"" << M->getName()
|
|
||||||
<< "\" returned ";
|
|
||||||
print(RetTy, Result);
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,8 +517,6 @@ 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??");
|
||||||
@ -598,7 +533,6 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
|
|||||||
SetValue(PN, ResultValues[i], SF);
|
SetValue(PN, ResultValues[i], SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Memory Instruction Implementations
|
// Memory Instruction Implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -631,7 +565,6 @@ void Interpreter::visitFreeInst(FreeInst &I) {
|
|||||||
free(GVTOP(Value)); // Free memory
|
free(GVTOP(Value)); // Free memory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// getElementOffset - The workhorse for getelementptr.
|
// getElementOffset - The workhorse for getelementptr.
|
||||||
//
|
//
|
||||||
GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
|
GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
|
||||||
@ -655,22 +588,13 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, User::op_iterator I,
|
|||||||
Total += SLO->MemberOffsets[Index];
|
Total += SLO->MemberOffsets[Index];
|
||||||
Ty = STy->getElementTypes()[Index];
|
Ty = STy->getElementTypes()[Index];
|
||||||
} else if (const SequentialType *ST = cast<SequentialType>(Ty)) {
|
} else if (const SequentialType *ST = cast<SequentialType>(Ty)) {
|
||||||
|
|
||||||
// Get the index number for the array... which must be long type...
|
// Get the index number for the array... which must be long type...
|
||||||
assert((*I)->getType() == Type::LongTy);
|
assert((*I)->getType() == Type::LongTy);
|
||||||
unsigned Idx = getOperandValue(*I, SF).LongVal;
|
unsigned Idx = getOperandValue(*I, SF).LongVal;
|
||||||
if (const ArrayType *AT = dyn_cast<ArrayType>(ST))
|
|
||||||
if (Idx >= AT->getNumElements() && ArrayChecksEnabled) {
|
|
||||||
std::cerr << "Out of range memory access to element #" << Idx
|
|
||||||
<< " of a " << AT->getNumElements() << " element array."
|
|
||||||
<< " Subscript #" << *I << "\n";
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ty = ST->getElementType();
|
Ty = ST->getElementType();
|
||||||
unsigned Size = TD.getTypeSize(Ty);
|
unsigned Size = TD.getTypeSize(Ty);
|
||||||
Total += Size*Idx;
|
Total += Size*Idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue Result;
|
GenericValue Result;
|
||||||
@ -700,8 +624,6 @@ void Interpreter::visitStoreInst(StoreInst &I) {
|
|||||||
I.getOperand(0)->getType());
|
I.getOperand(0)->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Miscellaneous Instruction Implementations
|
// Miscellaneous Instruction Implementations
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -846,7 +768,6 @@ GenericValue Interpreter::executeCastOperation(Value *SrcVal, const Type *Ty,
|
|||||||
return Dest;
|
return Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Interpreter::visitCastInst(CastInst &I) {
|
void Interpreter::visitCastInst(CastInst &I) {
|
||||||
ExecutionContext &SF = ECStack.back();
|
ExecutionContext &SF = ECStack.back();
|
||||||
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
|
SetValue(&I, executeCastOperation(I.getOperand(0), I.getType(), SF), SF);
|
||||||
@ -869,27 +790,6 @@ void Interpreter::visitVANextInst(VANextInst &I) {
|
|||||||
// Dispatch and Execution Code
|
// Dispatch and Execution Code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
FunctionInfo::FunctionInfo(Function *F) {
|
|
||||||
// Assign slot numbers to the function arguments...
|
|
||||||
for (Function::const_aiterator AI = F->abegin(), E = F->aend(); AI != E; ++AI)
|
|
||||||
AI->addAnnotation(new SlotNumber(getValueSlot(AI)));
|
|
||||||
|
|
||||||
// Iterate over all of the instructions...
|
|
||||||
unsigned InstNum = 0;
|
|
||||||
for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
|
|
||||||
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II)
|
|
||||||
// For each instruction... Add Annote
|
|
||||||
II->addAnnotation(new InstNumber(++InstNum, getValueSlot(II)));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned FunctionInfo::getValueSlot(const Value *V) {
|
|
||||||
unsigned Plane = V->getType()->getUniqueID();
|
|
||||||
if (Plane >= NumPlaneElements.size())
|
|
||||||
NumPlaneElements.resize(Plane+1, 0);
|
|
||||||
return NumPlaneElements[Plane]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// callFunction - Execute the specified function...
|
// callFunction - Execute the specified function...
|
||||||
//
|
//
|
||||||
@ -908,17 +808,7 @@ void Interpreter::callFunction(Function *F,
|
|||||||
if (!ECStack.empty() && ECStack.back().Caller) {
|
if (!ECStack.empty() && ECStack.back().Caller) {
|
||||||
ExecutionContext &SF = ECStack.back();
|
ExecutionContext &SF = ECStack.back();
|
||||||
SetValue(SF.Caller, Result, SF);
|
SetValue(SF.Caller, Result, SF);
|
||||||
|
|
||||||
SF.Caller = 0; // We returned from the call...
|
SF.Caller = 0; // We returned from the call...
|
||||||
} else if (!QuietMode) {
|
|
||||||
// print it.
|
|
||||||
CW << "Function " << F->getType() << " \"" << F->getName()
|
|
||||||
<< "\" returned ";
|
|
||||||
print(RetTy, Result);
|
|
||||||
std::cout << "\n";
|
|
||||||
|
|
||||||
if (RetTy->isIntegral())
|
|
||||||
ExitCode = Result.IntVal; // Capture the exit code of the program
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,8 +819,6 @@ void Interpreter::callFunction(Function *F,
|
|||||||
// the function. Also calculate the number of values for each type slot
|
// the function. Also calculate the number of values for each type slot
|
||||||
// active.
|
// active.
|
||||||
//
|
//
|
||||||
FunctionInfo *&FuncInfo = FunctionInfoMap[F];
|
|
||||||
if (!FuncInfo) FuncInfo = new FunctionInfo(F);
|
|
||||||
|
|
||||||
// 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());
|
||||||
@ -938,18 +826,6 @@ void Interpreter::callFunction(Function *F,
|
|||||||
StackFrame.CurFunction = F;
|
StackFrame.CurFunction = F;
|
||||||
StackFrame.CurBB = F->begin();
|
StackFrame.CurBB = F->begin();
|
||||||
StackFrame.CurInst = StackFrame.CurBB->begin();
|
StackFrame.CurInst = StackFrame.CurBB->begin();
|
||||||
StackFrame.FuncInfo = FuncInfo;
|
|
||||||
|
|
||||||
// Initialize the values to nothing...
|
|
||||||
StackFrame.Values.resize(FuncInfo->NumPlaneElements.size());
|
|
||||||
for (unsigned i = 0; i < FuncInfo->NumPlaneElements.size(); ++i) {
|
|
||||||
StackFrame.Values[i].resize(FuncInfo->NumPlaneElements[i]);
|
|
||||||
|
|
||||||
// Taint the initial values of stuff
|
|
||||||
memset(&StackFrame.Values[i][0], 42,
|
|
||||||
FuncInfo->NumPlaneElements[i]*sizeof(GenericValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Run through the function arguments and initialize their values...
|
// Run through the function arguments and initialize their values...
|
||||||
assert((ArgVals.size() == F->asize() ||
|
assert((ArgVals.size() == F->asize() ||
|
||||||
@ -965,55 +841,15 @@ void Interpreter::callFunction(Function *F,
|
|||||||
StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end());
|
StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// executeInstruction - Interpret a single instruction & increment the "PC".
|
|
||||||
//
|
|
||||||
void Interpreter::executeInstruction() {
|
|
||||||
assert(!ECStack.empty() && "No program running, cannot execute inst!");
|
|
||||||
|
|
||||||
ExecutionContext &SF = ECStack.back(); // Current stack frame
|
|
||||||
Instruction &I = *SF.CurInst++; // Increment before execute
|
|
||||||
|
|
||||||
if (Trace) CW << "Run:" << I;
|
|
||||||
|
|
||||||
// Track the number of dynamic instructions executed.
|
|
||||||
++NumDynamicInsts;
|
|
||||||
|
|
||||||
visit(I); // Dispatch to one of the visit* methods...
|
|
||||||
|
|
||||||
// Reset the current frame location to the top of stack
|
|
||||||
CurFrame = ECStack.size()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interpreter::run() {
|
void Interpreter::run() {
|
||||||
while (!ECStack.empty()) {
|
while (!ECStack.empty()) {
|
||||||
// Run an instruction...
|
// Interpret a single instruction & increment the "PC".
|
||||||
executeInstruction();
|
ExecutionContext &SF = ECStack.back(); // Current stack frame
|
||||||
|
Instruction &I = *SF.CurInst++; // Increment before execute
|
||||||
|
|
||||||
|
// Track the number of dynamic instructions executed.
|
||||||
|
++NumDynamicInsts;
|
||||||
|
|
||||||
|
visit(I); // Dispatch to one of the visit* methods...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::printValue(const Type *Ty, GenericValue V) {
|
|
||||||
switch (Ty->getPrimitiveID()) {
|
|
||||||
case Type::BoolTyID: std::cout << (V.BoolVal?"true":"false"); break;
|
|
||||||
case Type::SByteTyID:
|
|
||||||
std::cout << (int)V.SByteVal << " '" << V.SByteVal << "'"; break;
|
|
||||||
case Type::UByteTyID:
|
|
||||||
std::cout << (unsigned)V.UByteVal << " '" << V.UByteVal << "'"; break;
|
|
||||||
case Type::ShortTyID: std::cout << V.ShortVal; break;
|
|
||||||
case Type::UShortTyID: std::cout << V.UShortVal; break;
|
|
||||||
case Type::IntTyID: std::cout << V.IntVal; break;
|
|
||||||
case Type::UIntTyID: std::cout << V.UIntVal; break;
|
|
||||||
case Type::LongTyID: std::cout << (long)V.LongVal; break;
|
|
||||||
case Type::ULongTyID: std::cout << (unsigned long)V.ULongVal; break;
|
|
||||||
case Type::FloatTyID: std::cout << V.FloatVal; break;
|
|
||||||
case Type::DoubleTyID: std::cout << V.DoubleVal; break;
|
|
||||||
case Type::PointerTyID:std::cout << (void*)GVTOP(V); break;
|
|
||||||
default:
|
|
||||||
std::cout << "- Don't know how to print value of this type!";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interpreter::print(const Type *Ty, GenericValue V) {
|
|
||||||
CW << Ty << " ";
|
|
||||||
printValue(Ty, V);
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user