| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1 | //===-- Execution.cpp - Implement code to simulate the program ------------===// | 
|  | 2 | // | 
|  | 3 | //  This file contains the actual instruction interpreter. | 
|  | 4 | // | 
|  | 5 | //===----------------------------------------------------------------------===// | 
|  | 6 |  | 
|  | 7 | #include "Interpreter.h" | 
|  | 8 | #include "ExecutionAnnotations.h" | 
| Chris Lattner | 7061dc5 | 2001-12-03 18:02:31 +0000 | [diff] [blame] | 9 | #include "llvm/iPHINode.h" | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 10 | #include "llvm/iOther.h" | 
|  | 11 | #include "llvm/iTerminators.h" | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 12 | #include "llvm/iMemory.h" | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 13 | #include "llvm/Type.h" | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 14 | #include "llvm/ConstantVals.h" | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 15 | #include "llvm/Assembly/Writer.h" | 
| Chris Lattner | 41c2e5c | 2001-09-28 22:56:43 +0000 | [diff] [blame] | 16 | #include "llvm/Target/TargetData.h" | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 17 | #include "llvm/GlobalVariable.h" | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 18 | #include <math.h>  // For fmod | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 19 | #include <signal.h> | 
|  | 20 | #include <setjmp.h> | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 21 |  | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 22 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 23 | // Create a TargetData structure to handle memory addressing and size/alignment | 
|  | 24 | // computations | 
|  | 25 | // | 
|  | 26 | static TargetData TD("lli Interpreter"); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 27 | CachedWriter CW;     // Object to accelerate printing of LLVM | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 28 |  | 
|  | 29 |  | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 30 | #ifdef PROFILE_STRUCTURE_FIELDS | 
| Chris Lattner | cee8f9a | 2001-11-27 00:03:19 +0000 | [diff] [blame] | 31 | #include "Support/CommandLine.h" | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 32 | static cl::Flag ProfileStructureFields("profilestructfields", | 
|  | 33 | "Profile Structure Field Accesses"); | 
|  | 34 | #include <map> | 
|  | 35 | static map<const StructType *, vector<unsigned> > FieldAccessCounts; | 
|  | 36 | #endif | 
|  | 37 |  | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 38 | sigjmp_buf SignalRecoverBuffer; | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 39 | static bool InInstruction = false; | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 40 |  | 
|  | 41 | extern "C" { | 
|  | 42 | static void SigHandler(int Signal) { | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 43 | if (InInstruction) | 
|  | 44 | siglongjmp(SignalRecoverBuffer, Signal); | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 45 | } | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | static void initializeSignalHandlers() { | 
|  | 49 | struct sigaction Action; | 
|  | 50 | Action.sa_handler = SigHandler; | 
|  | 51 | Action.sa_flags   = SA_SIGINFO; | 
|  | 52 | sigemptyset(&Action.sa_mask); | 
|  | 53 | sigaction(SIGSEGV, &Action, 0); | 
|  | 54 | sigaction(SIGBUS, &Action, 0); | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 55 | sigaction(SIGINT, &Action, 0); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 56 | sigaction(SIGFPE, &Action, 0); | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 57 | } | 
|  | 58 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 59 |  | 
|  | 60 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 61 | //                     Value Manipulation code | 
|  | 62 | //===----------------------------------------------------------------------===// | 
|  | 63 |  | 
|  | 64 | static unsigned getOperandSlot(Value *V) { | 
|  | 65 | SlotNumber *SN = (SlotNumber*)V->getAnnotation(SlotNumberAID); | 
|  | 66 | assert(SN && "Operand does not have a slot number annotation!"); | 
|  | 67 | return SN->SlotNum; | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | #define GET_CONST_VAL(TY, CLASS) \ | 
|  | 71 | case Type::TY##TyID: Result.TY##Val = cast<CLASS>(CPV)->getValue(); break | 
|  | 72 |  | 
|  | 73 | static GenericValue getOperandValue(Value *V, ExecutionContext &SF) { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 74 | if (Constant *CPV = dyn_cast<Constant>(V)) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 75 | GenericValue Result; | 
|  | 76 | switch (CPV->getType()->getPrimitiveID()) { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 77 | GET_CONST_VAL(Bool   , ConstantBool); | 
|  | 78 | GET_CONST_VAL(UByte  , ConstantUInt); | 
|  | 79 | GET_CONST_VAL(SByte  , ConstantSInt); | 
|  | 80 | GET_CONST_VAL(UShort , ConstantUInt); | 
|  | 81 | GET_CONST_VAL(Short  , ConstantSInt); | 
|  | 82 | GET_CONST_VAL(UInt   , ConstantUInt); | 
|  | 83 | GET_CONST_VAL(Int    , ConstantSInt); | 
|  | 84 | GET_CONST_VAL(ULong  , ConstantUInt); | 
|  | 85 | GET_CONST_VAL(Long   , ConstantSInt); | 
|  | 86 | GET_CONST_VAL(Float  , ConstantFP); | 
|  | 87 | GET_CONST_VAL(Double , ConstantFP); | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 88 | case Type::PointerTyID: | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 89 | if (isa<ConstantPointerNull>(CPV)) { | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 90 | Result.PointerVal = 0; | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 91 | } else if (ConstantPointerRef *CPR =dyn_cast<ConstantPointerRef>(CPV)) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 92 | assert(0 && "Not implemented!"); | 
|  | 93 | } else { | 
|  | 94 | assert(0 && "Unknown constant pointer type!"); | 
|  | 95 | } | 
|  | 96 | break; | 
|  | 97 | default: | 
|  | 98 | cout << "ERROR: Constant unimp for type: " << CPV->getType() << endl; | 
|  | 99 | } | 
|  | 100 | return Result; | 
|  | 101 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { | 
|  | 102 | GlobalAddress *Address = | 
|  | 103 | (GlobalAddress*)GV->getOrCreateAnnotation(GlobalAddressAID); | 
|  | 104 | GenericValue Result; | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 105 | Result.PointerVal = (PointerTy)(GenericValue*)Address->Ptr; | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 106 | return Result; | 
|  | 107 | } else { | 
|  | 108 | unsigned TyP = V->getType()->getUniqueID();   // TypePlane for value | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 109 | unsigned OpSlot = getOperandSlot(V); | 
|  | 110 | assert(TyP < SF.Values.size() && | 
|  | 111 | OpSlot < SF.Values[TyP].size() && "Value out of range!"); | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 112 | return SF.Values[TyP][getOperandSlot(V)]; | 
|  | 113 | } | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | static void printOperandInfo(Value *V, ExecutionContext &SF) { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 117 | if (isa<Constant>(V)) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 118 | cout << "Constant Pool Value\n"; | 
|  | 119 | } else if (isa<GlobalValue>(V)) { | 
|  | 120 | cout << "Global Value\n"; | 
|  | 121 | } else { | 
|  | 122 | unsigned TyP  = V->getType()->getUniqueID();   // TypePlane for value | 
|  | 123 | unsigned Slot = getOperandSlot(V); | 
|  | 124 | cout << "Value=" << (void*)V << " TypeID=" << TyP << " Slot=" << Slot | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 125 | << " Addr=" << &SF.Values[TyP][Slot] << " SF=" << &SF | 
|  | 126 | << " Contents=0x"; | 
|  | 127 |  | 
|  | 128 | const unsigned char *Buf = (const unsigned char*)&SF.Values[TyP][Slot]; | 
|  | 129 | for (unsigned i = 0; i < sizeof(GenericValue); ++i) { | 
|  | 130 | unsigned char Cur = Buf[i]; | 
|  | 131 | cout << ( Cur     >= 160? char((Cur>>4)+'A'-10) : char((Cur>>4) + '0')) | 
|  | 132 | << ((Cur&15) >=  10? char((Cur&15)+'A'-10) : char((Cur&15) + '0')); | 
|  | 133 | } | 
|  | 134 | cout << endl; | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 135 | } | 
|  | 136 | } | 
|  | 137 |  | 
|  | 138 |  | 
|  | 139 |  | 
|  | 140 | static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { | 
|  | 141 | unsigned TyP = V->getType()->getUniqueID();   // TypePlane for value | 
|  | 142 |  | 
|  | 143 | //cout << "Setting value: " << &SF.Values[TyP][getOperandSlot(V)] << endl; | 
|  | 144 | SF.Values[TyP][getOperandSlot(V)] = Val; | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 |  | 
|  | 148 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 149 | //                    Annotation Wrangling code | 
|  | 150 | //===----------------------------------------------------------------------===// | 
|  | 151 |  | 
|  | 152 | void Interpreter::initializeExecutionEngine() { | 
|  | 153 | AnnotationManager::registerAnnotationFactory(MethodInfoAID, | 
|  | 154 | &MethodInfo::Create); | 
|  | 155 | AnnotationManager::registerAnnotationFactory(GlobalAddressAID, | 
|  | 156 | &GlobalAddress::Create); | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 157 | initializeSignalHandlers(); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 158 | } | 
|  | 159 |  | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 160 | // InitializeMemory - Recursive function to apply a Constant value into the | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 161 | // specified memory location... | 
|  | 162 | // | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 163 | static void InitializeMemory(Constant *Init, char *Addr) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 164 | #define INITIALIZE_MEMORY(TYID, CLASS, TY)  \ | 
|  | 165 | case Type::TYID##TyID: {                  \ | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 166 | TY Tmp = cast<CLASS>(Init)->getValue(); \ | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 167 | memcpy(Addr, &Tmp, sizeof(TY));         \ | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 168 | } return | 
|  | 169 |  | 
|  | 170 | switch (Init->getType()->getPrimitiveID()) { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 171 | INITIALIZE_MEMORY(Bool   , ConstantBool, bool); | 
|  | 172 | INITIALIZE_MEMORY(UByte  , ConstantUInt, unsigned char); | 
|  | 173 | INITIALIZE_MEMORY(SByte  , ConstantSInt, signed   char); | 
|  | 174 | INITIALIZE_MEMORY(UShort , ConstantUInt, unsigned short); | 
|  | 175 | INITIALIZE_MEMORY(Short  , ConstantSInt, signed   short); | 
|  | 176 | INITIALIZE_MEMORY(UInt   , ConstantUInt, unsigned int); | 
|  | 177 | INITIALIZE_MEMORY(Int    , ConstantSInt, signed   int); | 
|  | 178 | INITIALIZE_MEMORY(ULong  , ConstantUInt, uint64_t); | 
|  | 179 | INITIALIZE_MEMORY(Long   , ConstantSInt,  int64_t); | 
|  | 180 | INITIALIZE_MEMORY(Float  , ConstantFP  , float); | 
|  | 181 | INITIALIZE_MEMORY(Double , ConstantFP  , double); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 182 | #undef INITIALIZE_MEMORY | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 183 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 184 | case Type::ArrayTyID: { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 185 | ConstantArray *CPA = cast<ConstantArray>(Init); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 186 | const vector<Use> &Val = CPA->getValues(); | 
|  | 187 | unsigned ElementSize = | 
|  | 188 | TD.getTypeSize(cast<ArrayType>(CPA->getType())->getElementType()); | 
|  | 189 | for (unsigned i = 0; i < Val.size(); ++i) | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 190 | InitializeMemory(cast<Constant>(Val[i].get()), Addr+i*ElementSize); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 191 | return; | 
|  | 192 | } | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 193 |  | 
|  | 194 | case Type::StructTyID: { | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 195 | ConstantStruct *CPS = cast<ConstantStruct>(Init); | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 196 | const StructLayout *SL=TD.getStructLayout(cast<StructType>(CPS->getType())); | 
|  | 197 | const vector<Use> &Val = CPS->getValues(); | 
|  | 198 | for (unsigned i = 0; i < Val.size(); ++i) | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 199 | InitializeMemory(cast<Constant>(Val[i].get()), | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 200 | Addr+SL->MemberOffsets[i]); | 
|  | 201 | return; | 
|  | 202 | } | 
|  | 203 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 204 | case Type::PointerTyID: | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 205 | if (isa<ConstantPointerNull>(Init)) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 206 | *(void**)Addr = 0; | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 207 | } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Init)) { | 
| Chris Lattner | 39bb5b4 | 2001-10-15 13:25:40 +0000 | [diff] [blame] | 208 | GlobalAddress *Address = | 
|  | 209 | (GlobalAddress*)CPR->getValue()->getOrCreateAnnotation(GlobalAddressAID); | 
|  | 210 | *(void**)Addr = (GenericValue*)Address->Ptr; | 
|  | 211 | } else { | 
|  | 212 | assert(0 && "Unknown Constant pointer type!"); | 
|  | 213 | } | 
|  | 214 | return; | 
|  | 215 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 216 | default: | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 217 | CW << "Bad Type: " << Init->getType() << endl; | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 218 | assert(0 && "Unknown constant type to initialize memory with!"); | 
|  | 219 | } | 
|  | 220 | } | 
|  | 221 |  | 
|  | 222 | Annotation *GlobalAddress::Create(AnnotationID AID, const Annotable *O, void *){ | 
|  | 223 | assert(AID == GlobalAddressAID); | 
|  | 224 |  | 
|  | 225 | // This annotation will only be created on GlobalValue objects... | 
|  | 226 | GlobalValue *GVal = cast<GlobalValue>((Value*)O); | 
|  | 227 |  | 
|  | 228 | if (isa<Method>(GVal)) { | 
|  | 229 | // The GlobalAddress object for a method is just a pointer to method itself. | 
|  | 230 | // Don't delete it when the annotation is gone though! | 
|  | 231 | return new GlobalAddress(GVal, false); | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | // Handle the case of a global variable... | 
|  | 235 | assert(isa<GlobalVariable>(GVal) && | 
|  | 236 | "Global value found that isn't a method or global variable!"); | 
|  | 237 | GlobalVariable *GV = cast<GlobalVariable>(GVal); | 
|  | 238 |  | 
|  | 239 | // First off, we must allocate space for the global variable to point at... | 
| Chris Lattner | 7a17675 | 2001-12-04 00:03:30 +0000 | [diff] [blame^] | 240 | const Type *Ty = GV->getType()->getElementType();  // Type to be allocated | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 241 | unsigned NumElements = 1; | 
|  | 242 |  | 
|  | 243 | if (isa<ArrayType>(Ty) && cast<ArrayType>(Ty)->isUnsized()) { | 
|  | 244 | assert(GV->hasInitializer() && "Const val must have an initializer!"); | 
|  | 245 | // Allocating a unsized array type? | 
|  | 246 | Ty = cast<const ArrayType>(Ty)->getElementType();  // Get the actual type... | 
|  | 247 |  | 
|  | 248 | // Get the number of elements being allocated by the array... | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 249 | NumElements =cast<ConstantArray>(GV->getInitializer())->getValues().size(); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 250 | } | 
|  | 251 |  | 
|  | 252 | // Allocate enough memory to hold the type... | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 253 | void *Addr = calloc(NumElements, TD.getTypeSize(Ty)); | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 254 | assert(Addr != 0 && "Null pointer returned by malloc!"); | 
|  | 255 |  | 
|  | 256 | // Initialize the memory if there is an initializer... | 
|  | 257 | if (GV->hasInitializer()) | 
|  | 258 | InitializeMemory(GV->getInitializer(), (char*)Addr); | 
|  | 259 |  | 
|  | 260 | return new GlobalAddress(Addr, true);  // Simply invoke the ctor | 
|  | 261 | } | 
|  | 262 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 263 |  | 
|  | 264 | //===----------------------------------------------------------------------===// | 
|  | 265 | //                    Binary Instruction Implementations | 
|  | 266 | //===----------------------------------------------------------------------===// | 
|  | 267 |  | 
|  | 268 | #define IMPLEMENT_BINARY_OPERATOR(OP, TY) \ | 
|  | 269 | case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; break | 
|  | 270 |  | 
|  | 271 | static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, | 
|  | 272 | const Type *Ty, ExecutionContext &SF) { | 
|  | 273 | GenericValue Dest; | 
|  | 274 | switch (Ty->getPrimitiveID()) { | 
|  | 275 | IMPLEMENT_BINARY_OPERATOR(+, UByte); | 
|  | 276 | IMPLEMENT_BINARY_OPERATOR(+, SByte); | 
|  | 277 | IMPLEMENT_BINARY_OPERATOR(+, UShort); | 
|  | 278 | IMPLEMENT_BINARY_OPERATOR(+, Short); | 
|  | 279 | IMPLEMENT_BINARY_OPERATOR(+, UInt); | 
|  | 280 | IMPLEMENT_BINARY_OPERATOR(+, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 281 | IMPLEMENT_BINARY_OPERATOR(+, ULong); | 
|  | 282 | IMPLEMENT_BINARY_OPERATOR(+, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 283 | IMPLEMENT_BINARY_OPERATOR(+, Float); | 
|  | 284 | IMPLEMENT_BINARY_OPERATOR(+, Double); | 
| Chris Lattner | c259316 | 2001-10-27 08:28:11 +0000 | [diff] [blame] | 285 | IMPLEMENT_BINARY_OPERATOR(+, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 286 | default: | 
|  | 287 | cout << "Unhandled type for Add instruction: " << Ty << endl; | 
|  | 288 | } | 
|  | 289 | return Dest; | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, | 
|  | 293 | const Type *Ty, ExecutionContext &SF) { | 
|  | 294 | GenericValue Dest; | 
|  | 295 | switch (Ty->getPrimitiveID()) { | 
|  | 296 | IMPLEMENT_BINARY_OPERATOR(-, UByte); | 
|  | 297 | IMPLEMENT_BINARY_OPERATOR(-, SByte); | 
|  | 298 | IMPLEMENT_BINARY_OPERATOR(-, UShort); | 
|  | 299 | IMPLEMENT_BINARY_OPERATOR(-, Short); | 
|  | 300 | IMPLEMENT_BINARY_OPERATOR(-, UInt); | 
|  | 301 | IMPLEMENT_BINARY_OPERATOR(-, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 302 | IMPLEMENT_BINARY_OPERATOR(-, ULong); | 
|  | 303 | IMPLEMENT_BINARY_OPERATOR(-, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 304 | IMPLEMENT_BINARY_OPERATOR(-, Float); | 
|  | 305 | IMPLEMENT_BINARY_OPERATOR(-, Double); | 
| Chris Lattner | c259316 | 2001-10-27 08:28:11 +0000 | [diff] [blame] | 306 | IMPLEMENT_BINARY_OPERATOR(-, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 307 | default: | 
|  | 308 | cout << "Unhandled type for Sub instruction: " << Ty << endl; | 
|  | 309 | } | 
|  | 310 | return Dest; | 
|  | 311 | } | 
|  | 312 |  | 
| Chris Lattner | c259316 | 2001-10-27 08:28:11 +0000 | [diff] [blame] | 313 | static GenericValue executeMulInst(GenericValue Src1, GenericValue Src2, | 
|  | 314 | const Type *Ty, ExecutionContext &SF) { | 
|  | 315 | GenericValue Dest; | 
|  | 316 | switch (Ty->getPrimitiveID()) { | 
|  | 317 | IMPLEMENT_BINARY_OPERATOR(*, UByte); | 
|  | 318 | IMPLEMENT_BINARY_OPERATOR(*, SByte); | 
|  | 319 | IMPLEMENT_BINARY_OPERATOR(*, UShort); | 
|  | 320 | IMPLEMENT_BINARY_OPERATOR(*, Short); | 
|  | 321 | IMPLEMENT_BINARY_OPERATOR(*, UInt); | 
|  | 322 | IMPLEMENT_BINARY_OPERATOR(*, Int); | 
|  | 323 | IMPLEMENT_BINARY_OPERATOR(*, ULong); | 
|  | 324 | IMPLEMENT_BINARY_OPERATOR(*, Long); | 
|  | 325 | IMPLEMENT_BINARY_OPERATOR(*, Float); | 
|  | 326 | IMPLEMENT_BINARY_OPERATOR(*, Double); | 
|  | 327 | IMPLEMENT_BINARY_OPERATOR(*, Pointer); | 
|  | 328 | default: | 
|  | 329 | cout << "Unhandled type for Mul instruction: " << Ty << endl; | 
|  | 330 | } | 
|  | 331 | return Dest; | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | static GenericValue executeDivInst(GenericValue Src1, GenericValue Src2, | 
|  | 335 | const Type *Ty, ExecutionContext &SF) { | 
|  | 336 | GenericValue Dest; | 
|  | 337 | switch (Ty->getPrimitiveID()) { | 
|  | 338 | IMPLEMENT_BINARY_OPERATOR(/, UByte); | 
|  | 339 | IMPLEMENT_BINARY_OPERATOR(/, SByte); | 
|  | 340 | IMPLEMENT_BINARY_OPERATOR(/, UShort); | 
|  | 341 | IMPLEMENT_BINARY_OPERATOR(/, Short); | 
|  | 342 | IMPLEMENT_BINARY_OPERATOR(/, UInt); | 
|  | 343 | IMPLEMENT_BINARY_OPERATOR(/, Int); | 
|  | 344 | IMPLEMENT_BINARY_OPERATOR(/, ULong); | 
|  | 345 | IMPLEMENT_BINARY_OPERATOR(/, Long); | 
|  | 346 | IMPLEMENT_BINARY_OPERATOR(/, Float); | 
|  | 347 | IMPLEMENT_BINARY_OPERATOR(/, Double); | 
|  | 348 | IMPLEMENT_BINARY_OPERATOR(/, Pointer); | 
|  | 349 | default: | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 350 | cout << "Unhandled type for Div instruction: " << Ty << endl; | 
|  | 351 | } | 
|  | 352 | return Dest; | 
|  | 353 | } | 
|  | 354 |  | 
|  | 355 | static GenericValue executeRemInst(GenericValue Src1, GenericValue Src2, | 
|  | 356 | const Type *Ty, ExecutionContext &SF) { | 
|  | 357 | GenericValue Dest; | 
|  | 358 | switch (Ty->getPrimitiveID()) { | 
|  | 359 | IMPLEMENT_BINARY_OPERATOR(%, UByte); | 
|  | 360 | IMPLEMENT_BINARY_OPERATOR(%, SByte); | 
|  | 361 | IMPLEMENT_BINARY_OPERATOR(%, UShort); | 
|  | 362 | IMPLEMENT_BINARY_OPERATOR(%, Short); | 
|  | 363 | IMPLEMENT_BINARY_OPERATOR(%, UInt); | 
|  | 364 | IMPLEMENT_BINARY_OPERATOR(%, Int); | 
|  | 365 | IMPLEMENT_BINARY_OPERATOR(%, ULong); | 
|  | 366 | IMPLEMENT_BINARY_OPERATOR(%, Long); | 
|  | 367 | IMPLEMENT_BINARY_OPERATOR(%, Pointer); | 
|  | 368 | case Type::FloatTyID: | 
|  | 369 | Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal); | 
|  | 370 | break; | 
|  | 371 | case Type::DoubleTyID: | 
|  | 372 | Dest.DoubleVal = fmod(Src1.DoubleVal, Src2.DoubleVal); | 
|  | 373 | break; | 
|  | 374 | default: | 
|  | 375 | cout << "Unhandled type for Rem instruction: " << Ty << endl; | 
| Chris Lattner | c259316 | 2001-10-27 08:28:11 +0000 | [diff] [blame] | 376 | } | 
|  | 377 | return Dest; | 
|  | 378 | } | 
|  | 379 |  | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 380 | static GenericValue executeAndInst(GenericValue Src1, GenericValue Src2, | 
| Chris Lattner | 4d0e1f9 | 2001-10-30 20:54:36 +0000 | [diff] [blame] | 381 | const Type *Ty, ExecutionContext &SF) { | 
|  | 382 | GenericValue Dest; | 
|  | 383 | switch (Ty->getPrimitiveID()) { | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 384 | IMPLEMENT_BINARY_OPERATOR(&, UByte); | 
|  | 385 | IMPLEMENT_BINARY_OPERATOR(&, SByte); | 
|  | 386 | IMPLEMENT_BINARY_OPERATOR(&, UShort); | 
|  | 387 | IMPLEMENT_BINARY_OPERATOR(&, Short); | 
|  | 388 | IMPLEMENT_BINARY_OPERATOR(&, UInt); | 
|  | 389 | IMPLEMENT_BINARY_OPERATOR(&, Int); | 
|  | 390 | IMPLEMENT_BINARY_OPERATOR(&, ULong); | 
|  | 391 | IMPLEMENT_BINARY_OPERATOR(&, Long); | 
|  | 392 | IMPLEMENT_BINARY_OPERATOR(&, Pointer); | 
|  | 393 | default: | 
|  | 394 | cout << "Unhandled type for And instruction: " << Ty << endl; | 
|  | 395 | } | 
|  | 396 | return Dest; | 
|  | 397 | } | 
|  | 398 |  | 
|  | 399 |  | 
|  | 400 | static GenericValue executeOrInst(GenericValue Src1, GenericValue Src2, | 
|  | 401 | const Type *Ty, ExecutionContext &SF) { | 
|  | 402 | GenericValue Dest; | 
|  | 403 | switch (Ty->getPrimitiveID()) { | 
|  | 404 | IMPLEMENT_BINARY_OPERATOR(|, UByte); | 
|  | 405 | IMPLEMENT_BINARY_OPERATOR(|, SByte); | 
|  | 406 | IMPLEMENT_BINARY_OPERATOR(|, UShort); | 
|  | 407 | IMPLEMENT_BINARY_OPERATOR(|, Short); | 
|  | 408 | IMPLEMENT_BINARY_OPERATOR(|, UInt); | 
|  | 409 | IMPLEMENT_BINARY_OPERATOR(|, Int); | 
|  | 410 | IMPLEMENT_BINARY_OPERATOR(|, ULong); | 
|  | 411 | IMPLEMENT_BINARY_OPERATOR(|, Long); | 
|  | 412 | IMPLEMENT_BINARY_OPERATOR(|, Pointer); | 
|  | 413 | default: | 
|  | 414 | cout << "Unhandled type for Or instruction: " << Ty << endl; | 
|  | 415 | } | 
|  | 416 | return Dest; | 
|  | 417 | } | 
|  | 418 |  | 
|  | 419 |  | 
|  | 420 | static GenericValue executeXorInst(GenericValue Src1, GenericValue Src2, | 
|  | 421 | const Type *Ty, ExecutionContext &SF) { | 
|  | 422 | GenericValue Dest; | 
|  | 423 | switch (Ty->getPrimitiveID()) { | 
| Chris Lattner | 4d0e1f9 | 2001-10-30 20:54:36 +0000 | [diff] [blame] | 424 | IMPLEMENT_BINARY_OPERATOR(^, UByte); | 
|  | 425 | IMPLEMENT_BINARY_OPERATOR(^, SByte); | 
|  | 426 | IMPLEMENT_BINARY_OPERATOR(^, UShort); | 
|  | 427 | IMPLEMENT_BINARY_OPERATOR(^, Short); | 
|  | 428 | IMPLEMENT_BINARY_OPERATOR(^, UInt); | 
|  | 429 | IMPLEMENT_BINARY_OPERATOR(^, Int); | 
|  | 430 | IMPLEMENT_BINARY_OPERATOR(^, ULong); | 
|  | 431 | IMPLEMENT_BINARY_OPERATOR(^, Long); | 
|  | 432 | IMPLEMENT_BINARY_OPERATOR(^, Pointer); | 
|  | 433 | default: | 
|  | 434 | cout << "Unhandled type for Xor instruction: " << Ty << endl; | 
|  | 435 | } | 
|  | 436 | return Dest; | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 440 | #define IMPLEMENT_SETCC(OP, TY) \ | 
|  | 441 | case Type::TY##TyID: Dest.BoolVal = Src1.TY##Val OP Src2.TY##Val; break | 
|  | 442 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 443 | static GenericValue executeSetEQInst(GenericValue Src1, GenericValue Src2, | 
|  | 444 | const Type *Ty, ExecutionContext &SF) { | 
|  | 445 | GenericValue Dest; | 
|  | 446 | switch (Ty->getPrimitiveID()) { | 
|  | 447 | IMPLEMENT_SETCC(==, UByte); | 
|  | 448 | IMPLEMENT_SETCC(==, SByte); | 
|  | 449 | IMPLEMENT_SETCC(==, UShort); | 
|  | 450 | IMPLEMENT_SETCC(==, Short); | 
|  | 451 | IMPLEMENT_SETCC(==, UInt); | 
|  | 452 | IMPLEMENT_SETCC(==, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 453 | IMPLEMENT_SETCC(==, ULong); | 
|  | 454 | IMPLEMENT_SETCC(==, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 455 | IMPLEMENT_SETCC(==, Float); | 
|  | 456 | IMPLEMENT_SETCC(==, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 457 | IMPLEMENT_SETCC(==, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 458 | default: | 
|  | 459 | cout << "Unhandled type for SetEQ instruction: " << Ty << endl; | 
|  | 460 | } | 
|  | 461 | return Dest; | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | static GenericValue executeSetNEInst(GenericValue Src1, GenericValue Src2, | 
|  | 465 | const Type *Ty, ExecutionContext &SF) { | 
|  | 466 | GenericValue Dest; | 
|  | 467 | switch (Ty->getPrimitiveID()) { | 
|  | 468 | IMPLEMENT_SETCC(!=, UByte); | 
|  | 469 | IMPLEMENT_SETCC(!=, SByte); | 
|  | 470 | IMPLEMENT_SETCC(!=, UShort); | 
|  | 471 | IMPLEMENT_SETCC(!=, Short); | 
|  | 472 | IMPLEMENT_SETCC(!=, UInt); | 
|  | 473 | IMPLEMENT_SETCC(!=, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 474 | IMPLEMENT_SETCC(!=, ULong); | 
|  | 475 | IMPLEMENT_SETCC(!=, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 476 | IMPLEMENT_SETCC(!=, Float); | 
|  | 477 | IMPLEMENT_SETCC(!=, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 478 | IMPLEMENT_SETCC(!=, Pointer); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 479 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 480 | default: | 
|  | 481 | cout << "Unhandled type for SetNE instruction: " << Ty << endl; | 
|  | 482 | } | 
|  | 483 | return Dest; | 
|  | 484 | } | 
|  | 485 |  | 
|  | 486 | static GenericValue executeSetLEInst(GenericValue Src1, GenericValue Src2, | 
|  | 487 | const Type *Ty, ExecutionContext &SF) { | 
|  | 488 | GenericValue Dest; | 
|  | 489 | switch (Ty->getPrimitiveID()) { | 
|  | 490 | IMPLEMENT_SETCC(<=, UByte); | 
|  | 491 | IMPLEMENT_SETCC(<=, SByte); | 
|  | 492 | IMPLEMENT_SETCC(<=, UShort); | 
|  | 493 | IMPLEMENT_SETCC(<=, Short); | 
|  | 494 | IMPLEMENT_SETCC(<=, UInt); | 
|  | 495 | IMPLEMENT_SETCC(<=, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 496 | IMPLEMENT_SETCC(<=, ULong); | 
|  | 497 | IMPLEMENT_SETCC(<=, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 498 | IMPLEMENT_SETCC(<=, Float); | 
|  | 499 | IMPLEMENT_SETCC(<=, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 500 | IMPLEMENT_SETCC(<=, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 501 | default: | 
|  | 502 | cout << "Unhandled type for SetLE instruction: " << Ty << endl; | 
|  | 503 | } | 
|  | 504 | return Dest; | 
|  | 505 | } | 
|  | 506 |  | 
|  | 507 | static GenericValue executeSetGEInst(GenericValue Src1, GenericValue Src2, | 
|  | 508 | const Type *Ty, ExecutionContext &SF) { | 
|  | 509 | GenericValue Dest; | 
|  | 510 | switch (Ty->getPrimitiveID()) { | 
|  | 511 | IMPLEMENT_SETCC(>=, UByte); | 
|  | 512 | IMPLEMENT_SETCC(>=, SByte); | 
|  | 513 | IMPLEMENT_SETCC(>=, UShort); | 
|  | 514 | IMPLEMENT_SETCC(>=, Short); | 
|  | 515 | IMPLEMENT_SETCC(>=, UInt); | 
|  | 516 | IMPLEMENT_SETCC(>=, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 517 | IMPLEMENT_SETCC(>=, ULong); | 
|  | 518 | IMPLEMENT_SETCC(>=, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 519 | IMPLEMENT_SETCC(>=, Float); | 
|  | 520 | IMPLEMENT_SETCC(>=, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 521 | IMPLEMENT_SETCC(>=, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 522 | default: | 
|  | 523 | cout << "Unhandled type for SetGE instruction: " << Ty << endl; | 
|  | 524 | } | 
|  | 525 | return Dest; | 
|  | 526 | } | 
|  | 527 |  | 
|  | 528 | static GenericValue executeSetLTInst(GenericValue Src1, GenericValue Src2, | 
|  | 529 | const Type *Ty, ExecutionContext &SF) { | 
|  | 530 | GenericValue Dest; | 
|  | 531 | switch (Ty->getPrimitiveID()) { | 
|  | 532 | IMPLEMENT_SETCC(<, UByte); | 
|  | 533 | IMPLEMENT_SETCC(<, SByte); | 
|  | 534 | IMPLEMENT_SETCC(<, UShort); | 
|  | 535 | IMPLEMENT_SETCC(<, Short); | 
|  | 536 | IMPLEMENT_SETCC(<, UInt); | 
|  | 537 | IMPLEMENT_SETCC(<, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 538 | IMPLEMENT_SETCC(<, ULong); | 
|  | 539 | IMPLEMENT_SETCC(<, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 540 | IMPLEMENT_SETCC(<, Float); | 
|  | 541 | IMPLEMENT_SETCC(<, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 542 | IMPLEMENT_SETCC(<, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 543 | default: | 
|  | 544 | cout << "Unhandled type for SetLT instruction: " << Ty << endl; | 
|  | 545 | } | 
|  | 546 | return Dest; | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | static GenericValue executeSetGTInst(GenericValue Src1, GenericValue Src2, | 
|  | 550 | const Type *Ty, ExecutionContext &SF) { | 
|  | 551 | GenericValue Dest; | 
|  | 552 | switch (Ty->getPrimitiveID()) { | 
|  | 553 | IMPLEMENT_SETCC(>, UByte); | 
|  | 554 | IMPLEMENT_SETCC(>, SByte); | 
|  | 555 | IMPLEMENT_SETCC(>, UShort); | 
|  | 556 | IMPLEMENT_SETCC(>, Short); | 
|  | 557 | IMPLEMENT_SETCC(>, UInt); | 
|  | 558 | IMPLEMENT_SETCC(>, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 559 | IMPLEMENT_SETCC(>, ULong); | 
|  | 560 | IMPLEMENT_SETCC(>, Long); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 561 | IMPLEMENT_SETCC(>, Float); | 
|  | 562 | IMPLEMENT_SETCC(>, Double); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 563 | IMPLEMENT_SETCC(>, Pointer); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 564 | default: | 
|  | 565 | cout << "Unhandled type for SetGT instruction: " << Ty << endl; | 
|  | 566 | } | 
|  | 567 | return Dest; | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | static void executeBinaryInst(BinaryOperator *I, ExecutionContext &SF) { | 
|  | 571 | const Type *Ty = I->getOperand(0)->getType(); | 
|  | 572 | GenericValue Src1  = getOperandValue(I->getOperand(0), SF); | 
|  | 573 | GenericValue Src2  = getOperandValue(I->getOperand(1), SF); | 
|  | 574 | GenericValue R;   // Result | 
|  | 575 |  | 
|  | 576 | switch (I->getOpcode()) { | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 577 | case Instruction::Add:   R = executeAddInst  (Src1, Src2, Ty, SF); break; | 
|  | 578 | case Instruction::Sub:   R = executeSubInst  (Src1, Src2, Ty, SF); break; | 
|  | 579 | case Instruction::Mul:   R = executeMulInst  (Src1, Src2, Ty, SF); break; | 
|  | 580 | case Instruction::Div:   R = executeDivInst  (Src1, Src2, Ty, SF); break; | 
|  | 581 | case Instruction::Rem:   R = executeRemInst  (Src1, Src2, Ty, SF); break; | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 582 | case Instruction::And:   R = executeAndInst  (Src1, Src2, Ty, SF); break; | 
|  | 583 | case Instruction::Or:    R = executeOrInst   (Src1, Src2, Ty, SF); break; | 
| Chris Lattner | 4d0e1f9 | 2001-10-30 20:54:36 +0000 | [diff] [blame] | 584 | case Instruction::Xor:   R = executeXorInst  (Src1, Src2, Ty, SF); break; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 585 | case Instruction::SetEQ: R = executeSetEQInst(Src1, Src2, Ty, SF); break; | 
|  | 586 | case Instruction::SetNE: R = executeSetNEInst(Src1, Src2, Ty, SF); break; | 
|  | 587 | case Instruction::SetLE: R = executeSetLEInst(Src1, Src2, Ty, SF); break; | 
|  | 588 | case Instruction::SetGE: R = executeSetGEInst(Src1, Src2, Ty, SF); break; | 
|  | 589 | case Instruction::SetLT: R = executeSetLTInst(Src1, Src2, Ty, SF); break; | 
|  | 590 | case Instruction::SetGT: R = executeSetGTInst(Src1, Src2, Ty, SF); break; | 
|  | 591 | default: | 
|  | 592 | cout << "Don't know how to handle this binary operator!\n-->" << I; | 
| Chris Lattner | 4d0e1f9 | 2001-10-30 20:54:36 +0000 | [diff] [blame] | 593 | R = Src1; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 594 | } | 
|  | 595 |  | 
|  | 596 | SetValue(I, R, SF); | 
|  | 597 | } | 
|  | 598 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 599 | //===----------------------------------------------------------------------===// | 
|  | 600 | //                     Terminator Instruction Implementations | 
|  | 601 | //===----------------------------------------------------------------------===// | 
|  | 602 |  | 
| Chris Lattner | a95c699 | 2001-11-12 16:28:48 +0000 | [diff] [blame] | 603 | static void PerformExitStuff() { | 
|  | 604 | #ifdef PROFILE_STRUCTURE_FIELDS | 
|  | 605 | // Print out structure field accounting information... | 
|  | 606 | if (!FieldAccessCounts.empty()) { | 
| Chris Lattner | 84efe09 | 2001-11-12 20:13:14 +0000 | [diff] [blame] | 607 | CW << "Profile Field Access Counts:\n"; | 
| Chris Lattner | a95c699 | 2001-11-12 16:28:48 +0000 | [diff] [blame] | 608 | map<const StructType *, vector<unsigned> >::iterator | 
|  | 609 | I = FieldAccessCounts.begin(), E = FieldAccessCounts.end(); | 
|  | 610 | for (; I != E; ++I) { | 
|  | 611 | vector<unsigned> &OfC = I->second; | 
|  | 612 | CW << "  '" << (Value*)I->first << "'\t- Sum="; | 
|  | 613 |  | 
|  | 614 | unsigned Sum = 0; | 
|  | 615 | for (unsigned i = 0; i < OfC.size(); ++i) | 
|  | 616 | Sum += OfC[i]; | 
|  | 617 | CW << Sum << " - "; | 
|  | 618 |  | 
|  | 619 | for (unsigned i = 0; i < OfC.size(); ++i) { | 
|  | 620 | if (i) CW << ", "; | 
|  | 621 | CW << OfC[i]; | 
|  | 622 | } | 
|  | 623 | CW << endl; | 
|  | 624 | } | 
|  | 625 | CW << endl; | 
| Chris Lattner | 84efe09 | 2001-11-12 20:13:14 +0000 | [diff] [blame] | 626 |  | 
|  | 627 | CW << "Profile Field Access Percentages:\n"; | 
|  | 628 | cout.precision(3); | 
|  | 629 | for (I = FieldAccessCounts.begin(); I != E; ++I) { | 
|  | 630 | vector<unsigned> &OfC = I->second; | 
|  | 631 | unsigned Sum = 0; | 
|  | 632 | for (unsigned i = 0; i < OfC.size(); ++i) | 
|  | 633 | Sum += OfC[i]; | 
|  | 634 |  | 
|  | 635 | CW << "  '" << (Value*)I->first << "'\t- "; | 
|  | 636 | for (unsigned i = 0; i < OfC.size(); ++i) { | 
|  | 637 | if (i) CW << ", "; | 
|  | 638 | CW << double(OfC[i])/Sum; | 
|  | 639 | } | 
|  | 640 | CW << endl; | 
|  | 641 | } | 
|  | 642 | CW << endl; | 
|  | 643 |  | 
| Chris Lattner | a95c699 | 2001-11-12 16:28:48 +0000 | [diff] [blame] | 644 | FieldAccessCounts.clear(); | 
|  | 645 | } | 
|  | 646 | #endif | 
|  | 647 | } | 
|  | 648 |  | 
| Chris Lattner | e43db88 | 2001-10-27 04:15:57 +0000 | [diff] [blame] | 649 | void Interpreter::exitCalled(GenericValue GV) { | 
|  | 650 | cout << "Program returned "; | 
|  | 651 | print(Type::IntTy, GV); | 
|  | 652 | cout << " via 'void exit(int)'\n"; | 
|  | 653 |  | 
|  | 654 | ExitCode = GV.SByteVal; | 
|  | 655 | ECStack.clear(); | 
| Chris Lattner | a95c699 | 2001-11-12 16:28:48 +0000 | [diff] [blame] | 656 | PerformExitStuff(); | 
| Chris Lattner | e43db88 | 2001-10-27 04:15:57 +0000 | [diff] [blame] | 657 | } | 
|  | 658 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 659 | void Interpreter::executeRetInst(ReturnInst *I, ExecutionContext &SF) { | 
|  | 660 | const Type *RetTy = 0; | 
|  | 661 | GenericValue Result; | 
|  | 662 |  | 
|  | 663 | // Save away the return value... (if we are not 'ret void') | 
|  | 664 | if (I->getNumOperands()) { | 
|  | 665 | RetTy  = I->getReturnValue()->getType(); | 
|  | 666 | Result = getOperandValue(I->getReturnValue(), SF); | 
|  | 667 | } | 
|  | 668 |  | 
|  | 669 | // Save previously executing meth | 
|  | 670 | const Method *M = ECStack.back().CurMethod; | 
|  | 671 |  | 
|  | 672 | // Pop the current stack frame... this invalidates SF | 
|  | 673 | ECStack.pop_back(); | 
|  | 674 |  | 
|  | 675 | if (ECStack.empty()) {  // Finished main.  Put result into exit code... | 
|  | 676 | if (RetTy) {          // Nonvoid return type? | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 677 | CW << "Method " << M->getType() << " \"" << M->getName() | 
|  | 678 | << "\" returned "; | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 679 | print(RetTy, Result); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 680 | cout << endl; | 
|  | 681 |  | 
|  | 682 | if (RetTy->isIntegral()) | 
|  | 683 | ExitCode = Result.SByteVal;   // Capture the exit code of the program | 
|  | 684 | } else { | 
|  | 685 | ExitCode = 0; | 
|  | 686 | } | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 687 |  | 
| Chris Lattner | a95c699 | 2001-11-12 16:28:48 +0000 | [diff] [blame] | 688 | PerformExitStuff(); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 689 | return; | 
|  | 690 | } | 
|  | 691 |  | 
|  | 692 | // If we have a previous stack frame, and we have a previous call, fill in | 
|  | 693 | // the return value... | 
|  | 694 | // | 
|  | 695 | ExecutionContext &NewSF = ECStack.back(); | 
|  | 696 | if (NewSF.Caller) { | 
|  | 697 | if (NewSF.Caller->getType() != Type::VoidTy)             // Save result... | 
|  | 698 | SetValue(NewSF.Caller, Result, NewSF); | 
|  | 699 |  | 
|  | 700 | NewSF.Caller = 0;          // We returned from the call... | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 701 | } else { | 
|  | 702 | // This must be a function that is executing because of a user 'call' | 
|  | 703 | // instruction. | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 704 | CW << "Method " << M->getType() << " \"" << M->getName() | 
|  | 705 | << "\" returned "; | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 706 | print(RetTy, Result); | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 707 | cout << endl; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 708 | } | 
|  | 709 | } | 
|  | 710 |  | 
|  | 711 | void Interpreter::executeBrInst(BranchInst *I, ExecutionContext &SF) { | 
|  | 712 | SF.PrevBB = SF.CurBB;               // Update PrevBB so that PHI nodes work... | 
|  | 713 | BasicBlock *Dest; | 
|  | 714 |  | 
|  | 715 | Dest = I->getSuccessor(0);          // Uncond branches have a fixed dest... | 
|  | 716 | if (!I->isUnconditional()) { | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 717 | Value *Cond = I->getCondition(); | 
|  | 718 | GenericValue CondVal = getOperandValue(Cond, SF); | 
|  | 719 | if (CondVal.BoolVal == 0) // If false cond... | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 720 | Dest = I->getSuccessor(1); | 
|  | 721 | } | 
|  | 722 | SF.CurBB   = Dest;                  // Update CurBB to branch destination | 
|  | 723 | SF.CurInst = SF.CurBB->begin();     // Update new instruction ptr... | 
|  | 724 | } | 
|  | 725 |  | 
|  | 726 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 727 | //                     Memory Instruction Implementations | 
|  | 728 | //===----------------------------------------------------------------------===// | 
|  | 729 |  | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 730 | void Interpreter::executeAllocInst(AllocationInst *I, ExecutionContext &SF) { | 
| Chris Lattner | 7a17675 | 2001-12-04 00:03:30 +0000 | [diff] [blame^] | 731 | const Type *Ty = I->getType()->getElementType();  // Type to be allocated | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 732 | unsigned NumElements = 1; | 
|  | 733 |  | 
|  | 734 | if (I->getNumOperands()) {   // Allocating a unsized array type? | 
| Chris Lattner | b00c582 | 2001-10-02 03:41:24 +0000 | [diff] [blame] | 735 | assert(isa<ArrayType>(Ty) && cast<const ArrayType>(Ty)->isUnsized() && | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 736 | "Allocation inst with size operand for !unsized array type???"); | 
| Chris Lattner | b00c582 | 2001-10-02 03:41:24 +0000 | [diff] [blame] | 737 | Ty = cast<const ArrayType>(Ty)->getElementType();  // Get the actual type... | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 738 |  | 
|  | 739 | // Get the number of elements being allocated by the array... | 
|  | 740 | GenericValue NumEl = getOperandValue(I->getOperand(0), SF); | 
|  | 741 | NumElements = NumEl.UIntVal; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | // Allocate enough memory to hold the type... | 
|  | 745 | GenericValue Result; | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 746 | // FIXME: Don't use CALLOC, use a tainted malloc. | 
|  | 747 | Result.PointerVal = (PointerTy)calloc(NumElements, TD.getTypeSize(Ty)); | 
|  | 748 | assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 749 | SetValue(I, Result, SF); | 
|  | 750 |  | 
|  | 751 | if (I->getOpcode() == Instruction::Alloca) { | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 752 | // TODO: FIXME: alloca should keep track of memory to free it later... | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 753 | } | 
|  | 754 | } | 
|  | 755 |  | 
|  | 756 | static void executeFreeInst(FreeInst *I, ExecutionContext &SF) { | 
|  | 757 | assert(I->getOperand(0)->getType()->isPointerType() && "Freeing nonptr?"); | 
|  | 758 | GenericValue Value = getOperandValue(I->getOperand(0), SF); | 
|  | 759 | // TODO: Check to make sure memory is allocated | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 760 | free((void*)Value.PointerVal);   // Free memory | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 761 | } | 
|  | 762 |  | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 763 |  | 
|  | 764 | // getElementOffset - The workhorse for getelementptr, load and store.  This | 
|  | 765 | // function returns the offset that arguments ArgOff+1 -> NumArgs specify for | 
|  | 766 | // the pointer type specified by argument Arg. | 
|  | 767 | // | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 768 | static PointerTy getElementOffset(MemAccessInst *I, ExecutionContext &SF) { | 
|  | 769 | assert(isa<PointerType>(I->getPointerOperand()->getType()) && | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 770 | "Cannot getElementOffset of a nonpointer type!"); | 
|  | 771 |  | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 772 | PointerTy Total = 0; | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 773 | const Type *Ty = | 
| Chris Lattner | 7a17675 | 2001-12-04 00:03:30 +0000 | [diff] [blame^] | 774 | cast<PointerType>(I->getPointerOperand()->getType())->getElementType(); | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 775 |  | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 776 | unsigned ArgOff = I->getFirstIndexOperandNumber(); | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 777 | while (ArgOff < I->getNumOperands()) { | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 778 | if (const StructType *STy = dyn_cast<StructType>(Ty)) { | 
|  | 779 | const StructLayout *SLO = TD.getStructLayout(STy); | 
|  | 780 |  | 
|  | 781 | // Indicies must be ubyte constants... | 
| Chris Lattner | e9bb2df | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 782 | const ConstantUInt *CPU = cast<ConstantUInt>(I->getOperand(ArgOff++)); | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 783 | assert(CPU->getType() == Type::UByteTy); | 
|  | 784 | unsigned Index = CPU->getValue(); | 
|  | 785 |  | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 786 | #ifdef PROFILE_STRUCTURE_FIELDS | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 787 | if (ProfileStructureFields) { | 
|  | 788 | // Do accounting for this field... | 
|  | 789 | vector<unsigned> &OfC = FieldAccessCounts[STy]; | 
|  | 790 | if (OfC.size() == 0) OfC.resize(STy->getElementTypes().size()); | 
|  | 791 | OfC[Index]++; | 
|  | 792 | } | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 793 | #endif | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 794 |  | 
|  | 795 | Total += SLO->MemberOffsets[Index]; | 
|  | 796 | Ty = STy->getElementTypes()[Index]; | 
|  | 797 | } else { | 
|  | 798 | const ArrayType *AT = cast<ArrayType>(Ty); | 
| Chris Lattner | e240906 | 2001-11-12 16:19:45 +0000 | [diff] [blame] | 799 |  | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 800 | // Get the index number for the array... which must be uint type... | 
|  | 801 | assert(I->getOperand(ArgOff)->getType() == Type::UIntTy); | 
|  | 802 | unsigned Idx = getOperandValue(I->getOperand(ArgOff++), SF).UIntVal; | 
|  | 803 | if (AT->isSized() && Idx >= (unsigned)AT->getNumElements()) { | 
|  | 804 | cerr << "Out of range memory access to element #" << Idx | 
|  | 805 | << " of a " << AT->getNumElements() << " element array." | 
|  | 806 | << " Subscript #" << (ArgOff-I->getFirstIndexOperandNumber()) | 
|  | 807 | << "\n"; | 
|  | 808 | // Get outta here!!! | 
|  | 809 | siglongjmp(SignalRecoverBuffer, -1); | 
|  | 810 | } | 
|  | 811 |  | 
|  | 812 | Ty = AT->getElementType(); | 
|  | 813 | unsigned Size = TD.getTypeSize(Ty); | 
|  | 814 | Total += Size*Idx; | 
|  | 815 | } | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 816 | } | 
|  | 817 |  | 
|  | 818 | return Total; | 
|  | 819 | } | 
|  | 820 |  | 
|  | 821 | static void executeGEPInst(GetElementPtrInst *I, ExecutionContext &SF) { | 
| Chris Lattner | 3bcce72 | 2001-11-14 11:28:18 +0000 | [diff] [blame] | 822 | GenericValue SRC = getOperandValue(I->getPointerOperand(), SF); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 823 | PointerTy SrcPtr = SRC.PointerVal; | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 824 |  | 
|  | 825 | GenericValue Result; | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 826 | Result.PointerVal = SrcPtr + getElementOffset(I, SF); | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 827 | SetValue(I, Result, SF); | 
|  | 828 | } | 
|  | 829 |  | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 830 | static void executeLoadInst(LoadInst *I, ExecutionContext &SF) { | 
| Chris Lattner | 3bcce72 | 2001-11-14 11:28:18 +0000 | [diff] [blame] | 831 | GenericValue SRC = getOperandValue(I->getPointerOperand(), SF); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 832 | PointerTy SrcPtr = SRC.PointerVal; | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 833 | PointerTy Offset = getElementOffset(I, SF);  // Handle any structure indices | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 834 | SrcPtr += Offset; | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 835 |  | 
|  | 836 | GenericValue *Ptr = (GenericValue*)SrcPtr; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 837 | GenericValue Result; | 
|  | 838 |  | 
|  | 839 | switch (I->getType()->getPrimitiveID()) { | 
|  | 840 | case Type::BoolTyID: | 
|  | 841 | case Type::UByteTyID: | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 842 | case Type::SByteTyID:   Result.SByteVal   = Ptr->SByteVal; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 843 | case Type::UShortTyID: | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 844 | case Type::ShortTyID:   Result.ShortVal   = Ptr->ShortVal; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 845 | case Type::UIntTyID: | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 846 | case Type::IntTyID:     Result.IntVal     = Ptr->IntVal; break; | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 847 | case Type::ULongTyID: | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 848 | case Type::LongTyID:    Result.ULongVal   = Ptr->ULongVal; break; | 
|  | 849 | case Type::PointerTyID: Result.PointerVal = Ptr->PointerVal; break; | 
|  | 850 | case Type::FloatTyID:   Result.FloatVal   = Ptr->FloatVal; break; | 
|  | 851 | case Type::DoubleTyID:  Result.DoubleVal  = Ptr->DoubleVal; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 852 | default: | 
|  | 853 | cout << "Cannot load value of type " << I->getType() << "!\n"; | 
|  | 854 | } | 
|  | 855 |  | 
|  | 856 | SetValue(I, Result, SF); | 
|  | 857 | } | 
|  | 858 |  | 
|  | 859 | static void executeStoreInst(StoreInst *I, ExecutionContext &SF) { | 
| Chris Lattner | 3bcce72 | 2001-11-14 11:28:18 +0000 | [diff] [blame] | 860 | GenericValue SRC = getOperandValue(I->getPointerOperand(), SF); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 861 | PointerTy SrcPtr = SRC.PointerVal; | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 862 | SrcPtr += getElementOffset(I, SF);  // Handle any structure indices | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 863 |  | 
|  | 864 | GenericValue *Ptr = (GenericValue *)SrcPtr; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 865 | GenericValue Val = getOperandValue(I->getOperand(0), SF); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 866 |  | 
|  | 867 | switch (I->getOperand(0)->getType()->getPrimitiveID()) { | 
|  | 868 | case Type::BoolTyID: | 
|  | 869 | case Type::UByteTyID: | 
|  | 870 | case Type::SByteTyID:   Ptr->SByteVal = Val.SByteVal; break; | 
|  | 871 | case Type::UShortTyID: | 
|  | 872 | case Type::ShortTyID:   Ptr->ShortVal = Val.ShortVal; break; | 
|  | 873 | case Type::UIntTyID: | 
|  | 874 | case Type::IntTyID:     Ptr->IntVal = Val.IntVal; break; | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 875 | case Type::ULongTyID: | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 876 | case Type::LongTyID:    Ptr->LongVal = Val.LongVal; break; | 
|  | 877 | case Type::PointerTyID: Ptr->PointerVal = Val.PointerVal; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 878 | case Type::FloatTyID:   Ptr->FloatVal = Val.FloatVal; break; | 
|  | 879 | case Type::DoubleTyID:  Ptr->DoubleVal = Val.DoubleVal; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 880 | default: | 
|  | 881 | cout << "Cannot store value of type " << I->getType() << "!\n"; | 
|  | 882 | } | 
|  | 883 | } | 
|  | 884 |  | 
|  | 885 |  | 
|  | 886 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 887 | //                 Miscellaneous Instruction Implementations | 
|  | 888 | //===----------------------------------------------------------------------===// | 
|  | 889 |  | 
|  | 890 | void Interpreter::executeCallInst(CallInst *I, ExecutionContext &SF) { | 
|  | 891 | ECStack.back().Caller = I; | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 892 | vector<GenericValue> ArgVals; | 
|  | 893 | ArgVals.reserve(I->getNumOperands()-1); | 
|  | 894 | for (unsigned i = 1; i < I->getNumOperands(); ++i) | 
|  | 895 | ArgVals.push_back(getOperandValue(I->getOperand(i), SF)); | 
|  | 896 |  | 
| Chris Lattner | 070cf5e | 2001-11-07 20:12:30 +0000 | [diff] [blame] | 897 | // To handle indirect calls, we must get the pointer value from the argument | 
|  | 898 | // and treat it as a method pointer. | 
|  | 899 | GenericValue SRC = getOperandValue(I->getCalledValue(), SF); | 
|  | 900 |  | 
|  | 901 | callMethod((Method*)SRC.PointerVal, ArgVals); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 902 | } | 
|  | 903 |  | 
|  | 904 | static void executePHINode(PHINode *I, ExecutionContext &SF) { | 
|  | 905 | BasicBlock *PrevBB = SF.PrevBB; | 
|  | 906 | Value *IncomingValue = 0; | 
|  | 907 |  | 
|  | 908 | // Search for the value corresponding to this previous bb... | 
|  | 909 | for (unsigned i = I->getNumIncomingValues(); i > 0;) { | 
|  | 910 | if (I->getIncomingBlock(--i) == PrevBB) { | 
|  | 911 | IncomingValue = I->getIncomingValue(i); | 
|  | 912 | break; | 
|  | 913 | } | 
|  | 914 | } | 
|  | 915 | assert(IncomingValue && "No PHI node predecessor for current PrevBB!"); | 
|  | 916 |  | 
|  | 917 | // Found the value, set as the result... | 
|  | 918 | SetValue(I, getOperandValue(IncomingValue, SF), SF); | 
|  | 919 | } | 
|  | 920 |  | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 921 | #define IMPLEMENT_SHIFT(OP, TY) \ | 
|  | 922 | case Type::TY##TyID: Dest.TY##Val = Src1.TY##Val OP Src2.UByteVal; break | 
|  | 923 |  | 
|  | 924 | static void executeShlInst(ShiftInst *I, ExecutionContext &SF) { | 
|  | 925 | const Type *Ty = I->getOperand(0)->getType(); | 
|  | 926 | GenericValue Src1  = getOperandValue(I->getOperand(0), SF); | 
|  | 927 | GenericValue Src2  = getOperandValue(I->getOperand(1), SF); | 
|  | 928 | GenericValue Dest; | 
|  | 929 |  | 
|  | 930 | switch (Ty->getPrimitiveID()) { | 
|  | 931 | IMPLEMENT_SHIFT(<<, UByte); | 
|  | 932 | IMPLEMENT_SHIFT(<<, SByte); | 
|  | 933 | IMPLEMENT_SHIFT(<<, UShort); | 
|  | 934 | IMPLEMENT_SHIFT(<<, Short); | 
|  | 935 | IMPLEMENT_SHIFT(<<, UInt); | 
|  | 936 | IMPLEMENT_SHIFT(<<, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 937 | IMPLEMENT_SHIFT(<<, ULong); | 
|  | 938 | IMPLEMENT_SHIFT(<<, Long); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 939 | default: | 
|  | 940 | cout << "Unhandled type for Shl instruction: " << Ty << endl; | 
|  | 941 | } | 
|  | 942 | SetValue(I, Dest, SF); | 
|  | 943 | } | 
|  | 944 |  | 
|  | 945 | static void executeShrInst(ShiftInst *I, ExecutionContext &SF) { | 
|  | 946 | const Type *Ty = I->getOperand(0)->getType(); | 
|  | 947 | GenericValue Src1  = getOperandValue(I->getOperand(0), SF); | 
|  | 948 | GenericValue Src2  = getOperandValue(I->getOperand(1), SF); | 
|  | 949 | GenericValue Dest; | 
|  | 950 |  | 
|  | 951 | switch (Ty->getPrimitiveID()) { | 
|  | 952 | IMPLEMENT_SHIFT(>>, UByte); | 
|  | 953 | IMPLEMENT_SHIFT(>>, SByte); | 
|  | 954 | IMPLEMENT_SHIFT(>>, UShort); | 
|  | 955 | IMPLEMENT_SHIFT(>>, Short); | 
|  | 956 | IMPLEMENT_SHIFT(>>, UInt); | 
|  | 957 | IMPLEMENT_SHIFT(>>, Int); | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 958 | IMPLEMENT_SHIFT(>>, ULong); | 
|  | 959 | IMPLEMENT_SHIFT(>>, Long); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 960 | default: | 
|  | 961 | cout << "Unhandled type for Shr instruction: " << Ty << endl; | 
|  | 962 | } | 
|  | 963 | SetValue(I, Dest, SF); | 
|  | 964 | } | 
|  | 965 |  | 
|  | 966 | #define IMPLEMENT_CAST(DTY, DCTY, STY) \ | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 967 | case Type::STY##TyID: Dest.DTY##Val = DCTY Src.STY##Val; break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 968 |  | 
|  | 969 | #define IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY)    \ | 
|  | 970 | case Type::DESTTY##TyID:                      \ | 
|  | 971 | switch (SrcTy->getPrimitiveID()) {          \ | 
|  | 972 | IMPLEMENT_CAST(DESTTY, DESTCTY, UByte);   \ | 
|  | 973 | IMPLEMENT_CAST(DESTTY, DESTCTY, SByte);   \ | 
|  | 974 | IMPLEMENT_CAST(DESTTY, DESTCTY, UShort);  \ | 
|  | 975 | IMPLEMENT_CAST(DESTTY, DESTCTY, Short);   \ | 
|  | 976 | IMPLEMENT_CAST(DESTTY, DESTCTY, UInt);    \ | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 977 | IMPLEMENT_CAST(DESTTY, DESTCTY, Int);     \ | 
|  | 978 | IMPLEMENT_CAST(DESTTY, DESTCTY, ULong);   \ | 
| Chris Lattner | c259316 | 2001-10-27 08:28:11 +0000 | [diff] [blame] | 979 | IMPLEMENT_CAST(DESTTY, DESTCTY, Long);    \ | 
|  | 980 | IMPLEMENT_CAST(DESTTY, DESTCTY, Pointer); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 981 |  | 
|  | 982 | #define IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY) \ | 
|  | 983 | IMPLEMENT_CAST(DESTTY, DESTCTY, Float);   \ | 
|  | 984 | IMPLEMENT_CAST(DESTTY, DESTCTY, Double) | 
|  | 985 |  | 
|  | 986 | #define IMPLEMENT_CAST_CASE_END()    \ | 
|  | 987 | default: cout << "Unhandled cast: " << SrcTy << " to " << Ty << endl;  \ | 
|  | 988 | break;                                    \ | 
|  | 989 | }                                           \ | 
|  | 990 | break | 
|  | 991 |  | 
|  | 992 | #define IMPLEMENT_CAST_CASE(DESTTY, DESTCTY) \ | 
|  | 993 | IMPLEMENT_CAST_CASE_START(DESTTY, DESTCTY);   \ | 
|  | 994 | IMPLEMENT_CAST_CASE_FP_IMP(DESTTY, DESTCTY); \ | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 995 | IMPLEMENT_CAST_CASE_END() | 
|  | 996 |  | 
|  | 997 | static void executeCastInst(CastInst *I, ExecutionContext &SF) { | 
|  | 998 | const Type *Ty = I->getType(); | 
|  | 999 | const Type *SrcTy = I->getOperand(0)->getType(); | 
|  | 1000 | GenericValue Src  = getOperandValue(I->getOperand(0), SF); | 
|  | 1001 | GenericValue Dest; | 
|  | 1002 |  | 
|  | 1003 | switch (Ty->getPrimitiveID()) { | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1004 | IMPLEMENT_CAST_CASE(UByte  , (unsigned char)); | 
|  | 1005 | IMPLEMENT_CAST_CASE(SByte  , (  signed char)); | 
|  | 1006 | IMPLEMENT_CAST_CASE(UShort , (unsigned short)); | 
|  | 1007 | IMPLEMENT_CAST_CASE(Short  , (  signed char)); | 
|  | 1008 | IMPLEMENT_CAST_CASE(UInt   , (unsigned int )); | 
|  | 1009 | IMPLEMENT_CAST_CASE(Int    , (  signed int )); | 
|  | 1010 | IMPLEMENT_CAST_CASE(ULong  , (uint64_t)); | 
|  | 1011 | IMPLEMENT_CAST_CASE(Long   , ( int64_t)); | 
|  | 1012 | IMPLEMENT_CAST_CASE(Pointer, (PointerTy)(uint32_t)); | 
|  | 1013 | IMPLEMENT_CAST_CASE(Float  , (float)); | 
|  | 1014 | IMPLEMENT_CAST_CASE(Double , (double)); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1015 | default: | 
|  | 1016 | cout << "Unhandled dest type for cast instruction: " << Ty << endl; | 
|  | 1017 | } | 
|  | 1018 | SetValue(I, Dest, SF); | 
|  | 1019 | } | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1020 |  | 
|  | 1021 |  | 
|  | 1022 |  | 
|  | 1023 |  | 
|  | 1024 | //===----------------------------------------------------------------------===// | 
|  | 1025 | //                        Dispatch and Execution Code | 
|  | 1026 | //===----------------------------------------------------------------------===// | 
|  | 1027 |  | 
|  | 1028 | MethodInfo::MethodInfo(Method *M) : Annotation(MethodInfoAID) { | 
|  | 1029 | // Assign slot numbers to the method arguments... | 
|  | 1030 | const Method::ArgumentListType &ArgList = M->getArgumentList(); | 
|  | 1031 | for (Method::ArgumentListType::const_iterator AI = ArgList.begin(), | 
|  | 1032 | AE = ArgList.end(); AI != AE; ++AI) { | 
|  | 1033 | MethodArgument *MA = *AI; | 
|  | 1034 | MA->addAnnotation(new SlotNumber(getValueSlot(MA))); | 
|  | 1035 | } | 
|  | 1036 |  | 
|  | 1037 | // Iterate over all of the instructions... | 
|  | 1038 | unsigned InstNum = 0; | 
|  | 1039 | for (Method::inst_iterator MI = M->inst_begin(), ME = M->inst_end(); | 
|  | 1040 | MI != ME; ++MI) { | 
|  | 1041 | Instruction *I = *MI;                          // For each instruction... | 
|  | 1042 | I->addAnnotation(new InstNumber(++InstNum, getValueSlot(I))); // Add Annote | 
|  | 1043 | } | 
|  | 1044 | } | 
|  | 1045 |  | 
|  | 1046 | unsigned MethodInfo::getValueSlot(const Value *V) { | 
|  | 1047 | unsigned Plane = V->getType()->getUniqueID(); | 
|  | 1048 | if (Plane >= NumPlaneElements.size()) | 
|  | 1049 | NumPlaneElements.resize(Plane+1, 0); | 
|  | 1050 | return NumPlaneElements[Plane]++; | 
|  | 1051 | } | 
|  | 1052 |  | 
|  | 1053 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1054 | //===----------------------------------------------------------------------===// | 
|  | 1055 | // callMethod - Execute the specified method... | 
|  | 1056 | // | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 1057 | void Interpreter::callMethod(Method *M, const vector<GenericValue> &ArgVals) { | 
|  | 1058 | assert((ECStack.empty() || ECStack.back().Caller == 0 || | 
|  | 1059 | ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && | 
|  | 1060 | "Incorrect number of arguments passed into function call!"); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1061 | if (M->isExternal()) { | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1062 | GenericValue Result = callExternalMethod(M, ArgVals); | 
|  | 1063 | const Type *RetTy = M->getReturnType(); | 
|  | 1064 |  | 
|  | 1065 | // Copy the result back into the result variable if we are not returning | 
|  | 1066 | // void. | 
|  | 1067 | if (RetTy != Type::VoidTy) { | 
|  | 1068 | if (!ECStack.empty() && ECStack.back().Caller) { | 
|  | 1069 | ExecutionContext &SF = ECStack.back(); | 
|  | 1070 | CallInst *Caller = SF.Caller; | 
|  | 1071 | SetValue(SF.Caller, Result, SF); | 
|  | 1072 |  | 
|  | 1073 | SF.Caller = 0;          // We returned from the call... | 
|  | 1074 | } else { | 
|  | 1075 | // print it. | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 1076 | CW << "Method " << M->getType() << " \"" << M->getName() | 
|  | 1077 | << "\" returned "; | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1078 | print(RetTy, Result); | 
|  | 1079 | cout << endl; | 
|  | 1080 |  | 
|  | 1081 | if (RetTy->isIntegral()) | 
|  | 1082 | ExitCode = Result.SByteVal;   // Capture the exit code of the program | 
|  | 1083 | } | 
|  | 1084 | } | 
|  | 1085 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1086 | return; | 
|  | 1087 | } | 
|  | 1088 |  | 
|  | 1089 | // Process the method, assigning instruction numbers to the instructions in | 
|  | 1090 | // the method.  Also calculate the number of values for each type slot active. | 
|  | 1091 | // | 
|  | 1092 | MethodInfo *MethInfo = (MethodInfo*)M->getOrCreateAnnotation(MethodInfoAID); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1093 | ECStack.push_back(ExecutionContext());         // Make a new stack frame... | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1094 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1095 | ExecutionContext &StackFrame = ECStack.back(); // Fill it in... | 
|  | 1096 | StackFrame.CurMethod = M; | 
|  | 1097 | StackFrame.CurBB     = M->front(); | 
|  | 1098 | StackFrame.CurInst   = StackFrame.CurBB->begin(); | 
|  | 1099 | StackFrame.MethInfo  = MethInfo; | 
|  | 1100 |  | 
|  | 1101 | // Initialize the values to nothing... | 
|  | 1102 | StackFrame.Values.resize(MethInfo->NumPlaneElements.size()); | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1103 | for (unsigned i = 0; i < MethInfo->NumPlaneElements.size(); ++i) { | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1104 | StackFrame.Values[i].resize(MethInfo->NumPlaneElements[i]); | 
|  | 1105 |  | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1106 | // Taint the initial values of stuff | 
|  | 1107 | memset(&StackFrame.Values[i][0], 42, | 
|  | 1108 | MethInfo->NumPlaneElements[i]*sizeof(GenericValue)); | 
|  | 1109 | } | 
|  | 1110 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1111 | StackFrame.PrevBB = 0;  // No previous BB for PHI nodes... | 
|  | 1112 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1113 |  | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 1114 | // Run through the method arguments and initialize their values... | 
| Chris Lattner | f8f2afb | 2001-10-18 21:55:32 +0000 | [diff] [blame] | 1115 | assert(ArgVals.size() == M->getArgumentList().size() && | 
|  | 1116 | "Invalid number of values passed to method invocation!"); | 
| Chris Lattner | 365a76e | 2001-09-10 04:49:44 +0000 | [diff] [blame] | 1117 | unsigned i = 0; | 
|  | 1118 | for (Method::ArgumentListType::iterator MI = M->getArgumentList().begin(), | 
|  | 1119 | ME = M->getArgumentList().end(); MI != ME; ++MI, ++i) { | 
|  | 1120 | SetValue(*MI, ArgVals[i], StackFrame); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1121 | } | 
|  | 1122 | } | 
|  | 1123 |  | 
|  | 1124 | // executeInstruction - Interpret a single instruction, increment the "PC", and | 
|  | 1125 | // return true if the next instruction is a breakpoint... | 
|  | 1126 | // | 
|  | 1127 | bool Interpreter::executeInstruction() { | 
|  | 1128 | assert(!ECStack.empty() && "No program running, cannot execute inst!"); | 
|  | 1129 |  | 
|  | 1130 | ExecutionContext &SF = ECStack.back();  // Current stack frame | 
|  | 1131 | Instruction *I = *SF.CurInst++;         // Increment before execute | 
|  | 1132 |  | 
| Chris Lattner | 43e3f7c | 2001-10-27 08:43:52 +0000 | [diff] [blame] | 1133 | if (Trace) | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 1134 | CW << "Run:" << I; | 
|  | 1135 |  | 
|  | 1136 | // Set a sigsetjmp buffer so that we can recover if an error happens during | 
|  | 1137 | // instruction execution... | 
|  | 1138 | // | 
|  | 1139 | if (int SigNo = sigsetjmp(SignalRecoverBuffer, 1)) { | 
|  | 1140 | --SF.CurInst;   // Back up to erroring instruction | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 1141 | if (SigNo != SIGINT && SigNo != -1) { | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1142 | cout << "EXCEPTION OCCURRED [" << _sys_siglistp[SigNo] << "]:\n"; | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1143 | printStackTrace(); | 
| Chris Lattner | 782b939 | 2001-11-26 18:18:18 +0000 | [diff] [blame] | 1144 | } else if (SigNo == SIGINT) { | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1145 | cout << "CTRL-C Detected, execution halted.\n"; | 
|  | 1146 | } | 
|  | 1147 | InInstruction = false; | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 1148 | return true; | 
|  | 1149 | } | 
| Chris Lattner | 43e3f7c | 2001-10-27 08:43:52 +0000 | [diff] [blame] | 1150 |  | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1151 | InInstruction = true; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1152 | if (I->isBinaryOp()) { | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1153 | executeBinaryInst(cast<BinaryOperator>(I), SF); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1154 | } else { | 
|  | 1155 | switch (I->getOpcode()) { | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1156 | // Terminators | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1157 | case Instruction::Ret:     executeRetInst  (cast<ReturnInst>(I), SF); break; | 
|  | 1158 | case Instruction::Br:      executeBrInst   (cast<BranchInst>(I), SF); break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1159 | // Memory Instructions | 
|  | 1160 | case Instruction::Alloca: | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1161 | case Instruction::Malloc:  executeAllocInst((AllocationInst*)I, SF); break; | 
|  | 1162 | case Instruction::Free:    executeFreeInst (cast<FreeInst> (I), SF); break; | 
|  | 1163 | case Instruction::Load:    executeLoadInst (cast<LoadInst> (I), SF); break; | 
|  | 1164 | case Instruction::Store:   executeStoreInst(cast<StoreInst>(I), SF); break; | 
| Chris Lattner | 95c3af5 | 2001-10-29 19:32:19 +0000 | [diff] [blame] | 1165 | case Instruction::GetElementPtr: | 
|  | 1166 | executeGEPInst(cast<GetElementPtrInst>(I), SF); break; | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1167 |  | 
|  | 1168 | // Miscellaneous Instructions | 
| Chris Lattner | bb76f02 | 2001-10-30 20:27:31 +0000 | [diff] [blame] | 1169 | case Instruction::Call:    executeCallInst (cast<CallInst> (I), SF); break; | 
|  | 1170 | case Instruction::PHINode: executePHINode  (cast<PHINode>  (I), SF); break; | 
|  | 1171 | case Instruction::Shl:     executeShlInst  (cast<ShiftInst>(I), SF); break; | 
|  | 1172 | case Instruction::Shr:     executeShrInst  (cast<ShiftInst>(I), SF); break; | 
|  | 1173 | case Instruction::Cast:    executeCastInst (cast<CastInst> (I), SF); break; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1174 | default: | 
|  | 1175 | cout << "Don't know how to execute this instruction!\n-->" << I; | 
|  | 1176 | } | 
|  | 1177 | } | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1178 | InInstruction = false; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1179 |  | 
|  | 1180 | // Reset the current frame location to the top of stack | 
|  | 1181 | CurFrame = ECStack.size()-1; | 
|  | 1182 |  | 
|  | 1183 | if (CurFrame == -1) return false;  // No breakpoint if no code | 
|  | 1184 |  | 
|  | 1185 | // Return true if there is a breakpoint annotation on the instruction... | 
|  | 1186 | return (*ECStack[CurFrame].CurInst)->getAnnotation(BreakpointAID) != 0; | 
|  | 1187 | } | 
|  | 1188 |  | 
|  | 1189 | void Interpreter::stepInstruction() {  // Do the 'step' command | 
|  | 1190 | if (ECStack.empty()) { | 
|  | 1191 | cout << "Error: no program running, cannot step!\n"; | 
|  | 1192 | return; | 
|  | 1193 | } | 
|  | 1194 |  | 
|  | 1195 | // Run an instruction... | 
|  | 1196 | executeInstruction(); | 
|  | 1197 |  | 
|  | 1198 | // Print the next instruction to execute... | 
|  | 1199 | printCurrentInstruction(); | 
|  | 1200 | } | 
|  | 1201 |  | 
|  | 1202 | // --- UI Stuff... | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1203 | void Interpreter::nextInstruction() {  // Do the 'next' command | 
|  | 1204 | if (ECStack.empty()) { | 
|  | 1205 | cout << "Error: no program running, cannot 'next'!\n"; | 
|  | 1206 | return; | 
|  | 1207 | } | 
|  | 1208 |  | 
|  | 1209 | // If this is a call instruction, step over the call instruction... | 
|  | 1210 | // TODO: ICALL, CALL WITH, ... | 
|  | 1211 | if ((*ECStack.back().CurInst)->getOpcode() == Instruction::Call) { | 
| Chris Lattner | a74a6b5 | 2001-10-29 14:08:33 +0000 | [diff] [blame] | 1212 | unsigned StackSize = ECStack.size(); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1213 | // Step into the function... | 
|  | 1214 | if (executeInstruction()) { | 
|  | 1215 | // Hit a breakpoint, print current instruction, then return to user... | 
|  | 1216 | cout << "Breakpoint hit!\n"; | 
|  | 1217 | printCurrentInstruction(); | 
|  | 1218 | return; | 
|  | 1219 | } | 
|  | 1220 |  | 
| Chris Lattner | a74a6b5 | 2001-10-29 14:08:33 +0000 | [diff] [blame] | 1221 | // If we we able to step into the function, finish it now.  We might not be | 
|  | 1222 | // able the step into a function, if it's external for example. | 
|  | 1223 | if (ECStack.size() != StackSize) | 
|  | 1224 | finish(); // Finish executing the function... | 
| Chris Lattner | 069aa25 | 2001-10-29 16:05:19 +0000 | [diff] [blame] | 1225 | else | 
|  | 1226 | printCurrentInstruction(); | 
| Chris Lattner | a74a6b5 | 2001-10-29 14:08:33 +0000 | [diff] [blame] | 1227 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1228 | } else { | 
|  | 1229 | // Normal instruction, just step... | 
|  | 1230 | stepInstruction(); | 
|  | 1231 | } | 
|  | 1232 | } | 
|  | 1233 |  | 
|  | 1234 | void Interpreter::run() { | 
|  | 1235 | if (ECStack.empty()) { | 
|  | 1236 | cout << "Error: no program running, cannot run!\n"; | 
|  | 1237 | return; | 
|  | 1238 | } | 
|  | 1239 |  | 
|  | 1240 | bool HitBreakpoint = false; | 
|  | 1241 | while (!ECStack.empty() && !HitBreakpoint) { | 
|  | 1242 | // Run an instruction... | 
|  | 1243 | HitBreakpoint = executeInstruction(); | 
|  | 1244 | } | 
|  | 1245 |  | 
|  | 1246 | if (HitBreakpoint) { | 
|  | 1247 | cout << "Breakpoint hit!\n"; | 
|  | 1248 | } | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1249 | // Print the next instruction to execute... | 
|  | 1250 | printCurrentInstruction(); | 
|  | 1251 | } | 
|  | 1252 |  | 
|  | 1253 | void Interpreter::finish() { | 
|  | 1254 | if (ECStack.empty()) { | 
|  | 1255 | cout << "Error: no program running, cannot run!\n"; | 
|  | 1256 | return; | 
|  | 1257 | } | 
|  | 1258 |  | 
|  | 1259 | unsigned StackSize = ECStack.size(); | 
|  | 1260 | bool HitBreakpoint = false; | 
|  | 1261 | while (ECStack.size() >= StackSize && !HitBreakpoint) { | 
|  | 1262 | // Run an instruction... | 
|  | 1263 | HitBreakpoint = executeInstruction(); | 
|  | 1264 | } | 
|  | 1265 |  | 
|  | 1266 | if (HitBreakpoint) { | 
|  | 1267 | cout << "Breakpoint hit!\n"; | 
|  | 1268 | } | 
|  | 1269 |  | 
|  | 1270 | // Print the next instruction to execute... | 
|  | 1271 | printCurrentInstruction(); | 
|  | 1272 | } | 
|  | 1273 |  | 
|  | 1274 |  | 
|  | 1275 |  | 
|  | 1276 | // printCurrentInstruction - Print out the instruction that the virtual PC is | 
|  | 1277 | // at, or fail silently if no program is running. | 
|  | 1278 | // | 
|  | 1279 | void Interpreter::printCurrentInstruction() { | 
|  | 1280 | if (!ECStack.empty()) { | 
| Chris Lattner | f5b2ec1 | 2001-10-29 20:44:34 +0000 | [diff] [blame] | 1281 | if (ECStack.back().CurBB->begin() == ECStack.back().CurInst)  // print label | 
|  | 1282 | WriteAsOperand(cout, ECStack.back().CurBB) << ":\n"; | 
|  | 1283 |  | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1284 | Instruction *I = *ECStack.back().CurInst; | 
|  | 1285 | InstNumber *IN = (InstNumber*)I->getAnnotation(SlotNumberAID); | 
|  | 1286 | assert(IN && "Instruction has no numbering annotation!"); | 
|  | 1287 | cout << "#" << IN->InstNum << I; | 
|  | 1288 | } | 
|  | 1289 | } | 
|  | 1290 |  | 
|  | 1291 | void Interpreter::printValue(const Type *Ty, GenericValue V) { | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1292 | switch (Ty->getPrimitiveID()) { | 
|  | 1293 | case Type::BoolTyID:   cout << (V.BoolVal?"true":"false"); break; | 
|  | 1294 | case Type::SByteTyID:  cout << V.SByteVal;  break; | 
|  | 1295 | case Type::UByteTyID:  cout << V.UByteVal;  break; | 
|  | 1296 | case Type::ShortTyID:  cout << V.ShortVal;  break; | 
|  | 1297 | case Type::UShortTyID: cout << V.UShortVal; break; | 
|  | 1298 | case Type::IntTyID:    cout << V.IntVal;    break; | 
|  | 1299 | case Type::UIntTyID:   cout << V.UIntVal;   break; | 
| Chris Lattner | 7b851ab | 2001-10-15 19:18:26 +0000 | [diff] [blame] | 1300 | case Type::LongTyID:   cout << V.LongVal;   break; | 
|  | 1301 | case Type::ULongTyID:  cout << V.ULongVal;  break; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1302 | case Type::FloatTyID:  cout << V.FloatVal;  break; | 
|  | 1303 | case Type::DoubleTyID: cout << V.DoubleVal; break; | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1304 | case Type::PointerTyID:cout << (void*)V.PointerVal; break; | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1305 | default: | 
|  | 1306 | cout << "- Don't know how to print value of this type!"; | 
|  | 1307 | break; | 
|  | 1308 | } | 
|  | 1309 | } | 
|  | 1310 |  | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 1311 | void Interpreter::print(const Type *Ty, GenericValue V) { | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 1312 | CW << Ty << " "; | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 1313 | printValue(Ty, V); | 
|  | 1314 | } | 
|  | 1315 |  | 
|  | 1316 | void Interpreter::print(const string &Name) { | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1317 | Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); | 
|  | 1318 | if (!PickedVal) return; | 
|  | 1319 |  | 
| Chris Lattner | 9636a91 | 2001-10-01 16:18:37 +0000 | [diff] [blame] | 1320 | if (const Method *M = dyn_cast<const Method>(PickedVal)) { | 
| Chris Lattner | 5af0c48 | 2001-11-07 04:23:00 +0000 | [diff] [blame] | 1321 | CW << M;  // Print the method | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1322 | } else if (const Type *Ty = dyn_cast<const Type>(PickedVal)) { | 
|  | 1323 | CW << "type %" << Name << " = " << Ty->getDescription() << endl; | 
|  | 1324 | } else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(PickedVal)) { | 
|  | 1325 | CW << BB;   // Print the basic block | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1326 | } else {      // Otherwise there should be an annotation for the slot# | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 1327 | print(PickedVal->getType(), | 
|  | 1328 | getOperandValue(PickedVal, ECStack[CurFrame])); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1329 | cout << endl; | 
|  | 1330 | } | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1331 | } | 
|  | 1332 |  | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1333 | void Interpreter::infoValue(const string &Name) { | 
|  | 1334 | Value *PickedVal = ChooseOneOption(Name, LookupMatchingNames(Name)); | 
|  | 1335 | if (!PickedVal) return; | 
|  | 1336 |  | 
|  | 1337 | cout << "Value: "; | 
| Chris Lattner | 2e42d3a | 2001-10-15 05:51:48 +0000 | [diff] [blame] | 1338 | print(PickedVal->getType(), | 
|  | 1339 | getOperandValue(PickedVal, ECStack[CurFrame])); | 
| Chris Lattner | 8666098 | 2001-08-27 05:16:50 +0000 | [diff] [blame] | 1340 | cout << endl; | 
|  | 1341 | printOperandInfo(PickedVal, ECStack[CurFrame]); | 
|  | 1342 | } | 
|  | 1343 |  | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1344 | // printStackFrame - Print information about the specified stack frame, or -1 | 
|  | 1345 | // for the default one. | 
|  | 1346 | // | 
|  | 1347 | void Interpreter::printStackFrame(int FrameNo = -1) { | 
|  | 1348 | if (FrameNo == -1) FrameNo = CurFrame; | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1349 | Method *Meth = ECStack[FrameNo].CurMethod; | 
| Chris Lattner | ea38c0e | 2001-11-07 19:46:27 +0000 | [diff] [blame] | 1350 | const Type *RetTy = Meth->getReturnType(); | 
|  | 1351 |  | 
|  | 1352 | CW << ((FrameNo == CurFrame) ? '>' : '-') << "#" << FrameNo << ". " | 
|  | 1353 | << (Value*)RetTy << " \"" << Meth->getName() << "\"("; | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1354 |  | 
|  | 1355 | Method::ArgumentListType &Args = Meth->getArgumentList(); | 
|  | 1356 | for (unsigned i = 0; i < Args.size(); ++i) { | 
|  | 1357 | if (i != 0) cout << ", "; | 
|  | 1358 | CW << (Value*)Args[i] << "="; | 
|  | 1359 |  | 
|  | 1360 | printValue(Args[i]->getType(), getOperandValue(Args[i], ECStack[FrameNo])); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1361 | } | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1362 |  | 
|  | 1363 | cout << ")" << endl; | 
|  | 1364 | CW << *(ECStack[FrameNo].CurInst-(FrameNo != int(ECStack.size()-1))); | 
| Chris Lattner | 92101ac | 2001-08-23 17:05:04 +0000 | [diff] [blame] | 1365 | } | 
| Chris Lattner | 461f02f | 2001-11-07 05:31:27 +0000 | [diff] [blame] | 1366 |  |