blob: 996afe475d4d0eb0119d6185b10ab47e5d8e0e1a [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:
59 cout << "ERROR: Constant unimp for type: " << C->getType() << "\n";
60 }
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:
95 cout << "Cannot store value of type " << Ty << "!\n";
96 }
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:
126 cout << "Cannot store value of type " << Ty << "!\n";
127 }
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);
144 const vector<Use> &Val = CPA->getValues();
145 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()));
156 const vector<Use> &Val = CPS->getValues();
157 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...
173 PointerTy *Result = new PointerTy[InputArgv.size()+1]; // 64 bit assumption
174 DEBUG(std::cerr << "ARGV = " << (void*)Result << "\n");
175
176 for (unsigned i = 0; i < InputArgv.size(); ++i) {
177 unsigned Size = InputArgv[i].size()+1;
178 char *Dest = new char[Size];
179 DEBUG(std::cerr << "ARGV[" << i << "] = " << (void*)Dest << "\n");
180
181 copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
182 Dest[Size-1] = 0;
183
184 // Endian safe: Result[i] = (PointerTy)Dest;
185 StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i),
186 Type::LongTy); // 64 bit assumption
187 }
188
189 Result[InputArgv.size()] = 0;
190 return Result;
191}
192
193/// EmitGlobals - Emit all of the global variables to memory, storing their
194/// addresses into GlobalAddress. This must make sure to copy the contents of
195/// their initializers into the memory.
196///
197void ExecutionEngine::emitGlobals() {
198 const TargetData &TD = getTargetData();
199
200 // Loop over all of the global variables in the program, allocating the memory
201 // to hold them.
202 for (Module::giterator I = getModule().gbegin(), E = getModule().gend();
203 I != E; ++I)
204 if (!I->isExternal()) {
205 // Get the type of the global...
206 const Type *Ty = I->getType()->getElementType();
207
208 // Allocate some memory for it!
209 unsigned Size = TD.getTypeSize(Ty);
210 GlobalAddress[I] = new char[Size];
211 NumInitBytes += Size;
212
213 DEBUG(std::cerr << "Global '" << I->getName() << "' -> "
214 << (void*)GlobalAddress[I] << "\n");
215 } else {
216 assert(0 && "References to external globals not handled yet!");
217 }
218
219 // Now that all of the globals are set up in memory, loop through them all and
220 // initialize their contents.
221 for (Module::giterator I = getModule().gbegin(), E = getModule().gend();
222 I != E; ++I)
223 if (!I->isExternal())
224 InitializeMemory(I->getInitializer(), GlobalAddress[I]);
225}
226