blob: 3d190aa0f81d5d66dbc892baff8023b2037c14a2 [file] [log] [blame]
Chris Lattnerbd199fb2002-12-24 00:01:05 +00001//===-- ExecutionEngine.cpp - Common Implementation shared by EE's --------===//
2//
3// This file defines the common interface used by the various execution engine
4// subclasses.
5//
6//===----------------------------------------------------------------------===//
7
8#include "ExecutionEngine.h"
9#include "GenericValue.h"
10#include "llvm/DerivedTypes.h"
11#include "llvm/Constants.h"
12#include "llvm/Module.h"
13#include "llvm/Target/TargetData.h"
14#include "Support/Statistic.h"
15
16Statistic<> NumInitBytes("lli", "Number of bytes of global vars initialized");
17
18// getPointerToGlobal - This returns the address of the specified global
19// value. This may involve code generation if it's a function.
20//
21void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
22 if (const Function *F = dyn_cast<Function>(GV))
23 return getPointerToFunction(F);
24
25 assert(GlobalAddress[GV] && "Global hasn't had an address allocated yet?");
26 return GlobalAddress[GV];
27}
28
29
30GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
31 GenericValue Result;
32#define GET_CONST_VAL(TY, CLASS) \
33 case Type::TY##TyID: Result.TY##Val = cast<CLASS>(C)->getValue(); break
34
35 switch (C->getType()->getPrimitiveID()) {
36 GET_CONST_VAL(Bool , ConstantBool);
37 GET_CONST_VAL(UByte , ConstantUInt);
38 GET_CONST_VAL(SByte , ConstantSInt);
39 GET_CONST_VAL(UShort , ConstantUInt);
40 GET_CONST_VAL(Short , ConstantSInt);
41 GET_CONST_VAL(UInt , ConstantUInt);
42 GET_CONST_VAL(Int , ConstantSInt);
43 GET_CONST_VAL(ULong , ConstantUInt);
44 GET_CONST_VAL(Long , ConstantSInt);
45 GET_CONST_VAL(Float , ConstantFP);
46 GET_CONST_VAL(Double , ConstantFP);
47#undef GET_CONST_VAL
48 case Type::PointerTyID:
49 if (isa<ConstantPointerNull>(C)) {
50 Result.PointerVal = 0;
51 } else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)){
52 Result = PTOGV(getPointerToGlobal(CPR->getValue()));
53
54 } else {
55 assert(0 && "Unknown constant pointer type!");
56 }
57 break;
58 default:
Chris Lattnerd6840ac2002-12-24 00:39:16 +000059 std::cout << "ERROR: Constant unimp for type: " << C->getType() << "\n";
Chris Lattnerbd199fb2002-12-24 00:01:05 +000060 }
61 return Result;
62}
63
64void ExecutionEngine::StoreValueToMemory(GenericValue Val, GenericValue *Ptr,
65 const Type *Ty) {
66 if (getTargetData().isLittleEndian()) {
67 switch (Ty->getPrimitiveID()) {
68 case Type::BoolTyID:
69 case Type::UByteTyID:
70 case Type::SByteTyID: Ptr->Untyped[0] = Val.UByteVal; break;
71 case Type::UShortTyID:
72 case Type::ShortTyID: Ptr->Untyped[0] = Val.UShortVal & 255;
73 Ptr->Untyped[1] = (Val.UShortVal >> 8) & 255;
74 break;
75 case Type::FloatTyID:
76 case Type::UIntTyID:
77 case Type::IntTyID: Ptr->Untyped[0] = Val.UIntVal & 255;
78 Ptr->Untyped[1] = (Val.UIntVal >> 8) & 255;
79 Ptr->Untyped[2] = (Val.UIntVal >> 16) & 255;
80 Ptr->Untyped[3] = (Val.UIntVal >> 24) & 255;
81 break;
82 case Type::DoubleTyID:
83 case Type::ULongTyID:
84 case Type::LongTyID:
85 case Type::PointerTyID: Ptr->Untyped[0] = Val.ULongVal & 255;
86 Ptr->Untyped[1] = (Val.ULongVal >> 8) & 255;
87 Ptr->Untyped[2] = (Val.ULongVal >> 16) & 255;
88 Ptr->Untyped[3] = (Val.ULongVal >> 24) & 255;
89 Ptr->Untyped[4] = (Val.ULongVal >> 32) & 255;
90 Ptr->Untyped[5] = (Val.ULongVal >> 40) & 255;
91 Ptr->Untyped[6] = (Val.ULongVal >> 48) & 255;
92 Ptr->Untyped[7] = (Val.ULongVal >> 56) & 255;
93 break;
94 default:
Chris Lattnerd6840ac2002-12-24 00:39:16 +000095 std::cout << "Cannot store value of type " << Ty << "!\n";
Chris Lattnerbd199fb2002-12-24 00:01:05 +000096 }
97 } else {
98 switch (Ty->getPrimitiveID()) {
99 case Type::BoolTyID:
100 case Type::UByteTyID:
101 case Type::SByteTyID: Ptr->Untyped[0] = Val.UByteVal; break;
102 case Type::UShortTyID:
103 case Type::ShortTyID: Ptr->Untyped[1] = Val.UShortVal & 255;
104 Ptr->Untyped[0] = (Val.UShortVal >> 8) & 255;
105 break;
106 case Type::FloatTyID:
107 case Type::UIntTyID:
108 case Type::IntTyID: Ptr->Untyped[3] = Val.UIntVal & 255;
109 Ptr->Untyped[2] = (Val.UIntVal >> 8) & 255;
110 Ptr->Untyped[1] = (Val.UIntVal >> 16) & 255;
111 Ptr->Untyped[0] = (Val.UIntVal >> 24) & 255;
112 break;
113 case Type::DoubleTyID:
114 case Type::ULongTyID:
115 case Type::LongTyID:
116 case Type::PointerTyID: Ptr->Untyped[7] = Val.ULongVal & 255;
117 Ptr->Untyped[6] = (Val.ULongVal >> 8) & 255;
118 Ptr->Untyped[5] = (Val.ULongVal >> 16) & 255;
119 Ptr->Untyped[4] = (Val.ULongVal >> 24) & 255;
120 Ptr->Untyped[3] = (Val.ULongVal >> 32) & 255;
121 Ptr->Untyped[2] = (Val.ULongVal >> 40) & 255;
122 Ptr->Untyped[1] = (Val.ULongVal >> 48) & 255;
123 Ptr->Untyped[0] = (Val.ULongVal >> 56) & 255;
124 break;
125 default:
Chris Lattnerd6840ac2002-12-24 00:39:16 +0000126 std::cout << "Cannot store value of type " << Ty << "!\n";
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000127 }
128 }
129}
130
131// InitializeMemory - Recursive function to apply a Constant value into the
132// specified memory location...
133//
134void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
135 if (Init->getType()->isFirstClassType()) {
136 GenericValue Val = getConstantValue(Init);
137 StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType());
138 return;
139 }
140
141 switch (Init->getType()->getPrimitiveID()) {
142 case Type::ArrayTyID: {
143 const ConstantArray *CPA = cast<ConstantArray>(Init);
Chris Lattnerd6840ac2002-12-24 00:39:16 +0000144 const std::vector<Use> &Val = CPA->getValues();
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000145 unsigned ElementSize =
146 getTargetData().getTypeSize(cast<ArrayType>(CPA->getType())->getElementType());
147 for (unsigned i = 0; i < Val.size(); ++i)
148 InitializeMemory(cast<Constant>(Val[i].get()), (char*)Addr+i*ElementSize);
149 return;
150 }
151
152 case Type::StructTyID: {
153 const ConstantStruct *CPS = cast<ConstantStruct>(Init);
154 const StructLayout *SL =
155 getTargetData().getStructLayout(cast<StructType>(CPS->getType()));
Chris Lattnerd6840ac2002-12-24 00:39:16 +0000156 const std::vector<Use> &Val = CPS->getValues();
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000157 for (unsigned i = 0; i < Val.size(); ++i)
158 InitializeMemory(cast<Constant>(Val[i].get()),
159 (char*)Addr+SL->MemberOffsets[i]);
160 return;
161 }
162
163 default:
164 std::cerr << "Bad Type: " << Init->getType() << "\n";
165 assert(0 && "Unknown constant type to initialize memory with!");
166 }
167}
168
169
170
171void *ExecutionEngine::CreateArgv(const std::vector<std::string> &InputArgv) {
172 // Pointers are 64 bits...
Chris Lattner92798d72003-01-13 00:58:06 +0000173 // FIXME: Assumes 64 bit target
174 PointerTy *Result = new PointerTy[InputArgv.size()+1];
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000175 DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
176
177 for (unsigned i = 0; i < InputArgv.size(); ++i) {
178 unsigned Size = InputArgv[i].size()+1;
179 char *Dest = new char[Size];
180 DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
181
182 copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
183 Dest[Size-1] = 0;
184
185 // Endian safe: Result[i] = (PointerTy)Dest;
186 StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
187 Type::LongTy); // 64 bit assumption
188 }
189
190 Result[InputArgv.size()] = 0;
191 return Result;
192}
193
194/// EmitGlobals - Emit all of the global variables to memory, storing their
195/// addresses into GlobalAddress. This must make sure to copy the contents of
196/// their initializers into the memory.
197///
198void ExecutionEngine::emitGlobals() {
199 const TargetData &TD = getTargetData();
200
201 // Loop over all of the global variables in the program, allocating the memory
202 // to hold them.
203 for (Module::giterator I = getModule().gbegin(), E = getModule().gend();
204 I != E; ++I)
205 if (!I->isExternal()) {
206 // Get the type of the global...
207 const Type *Ty = I->getType()->getElementType();
208
209 // Allocate some memory for it!
210 unsigned Size = TD.getTypeSize(Ty);
211 GlobalAddress[I] = new char[Size];
212 NumInitBytes += Size;
213
214 DEBUG(std::cerr << "Global '" << I->getName() << "' -> "
215 << (void*)GlobalAddress[I] << "\n");
Chris Lattner59ee0ee2003-04-21 22:44:36 +0000216 } else if (I->getName() == "stdout") {
217 GlobalAddress[I] = &stdout;
218 } else if (I->getName() == "stderr") {
219 GlobalAddress[I] = &stderr;
220 } else if (I->getName() == "stdin") {
221 GlobalAddress[I] = &stdin;
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000222 } else {
Chris Lattner623a2222002-12-28 20:00:15 +0000223 std::cerr << "Global: " << I->getName() << "\n";
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000224 assert(0 && "References to external globals not handled yet!");
225 }
226
227 // Now that all of the globals are set up in memory, loop through them all and
228 // initialize their contents.
229 for (Module::giterator I = getModule().gbegin(), E = getModule().gend();
230 I != E; ++I)
231 if (!I->isExternal())
232 InitializeMemory(I->getInitializer(), GlobalAddress[I]);
233}
234