Add fixme
[oota-llvm.git] / lib / ExecutionEngine / ExecutionEngine.cpp
1 //===-- 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
16 Statistic<> 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 //
21 void *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
30 GenericValue 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     std::cout << "ERROR: Constant unimp for type: " << C->getType() << "\n";
60   }
61   return Result;
62 }
63
64 void 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       std::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       std::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 //
134 void 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 std::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 std::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
171 void *ExecutionEngine::CreateArgv(const std::vector<std::string> &InputArgv) {
172   // Pointers are 64 bits...
173   // FIXME: Assumes 64 bit target
174   PointerTy *Result = new PointerTy[InputArgv.size()+1];
175   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 ///
198 void 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");
216     } else {
217       std::cerr << "Global: " << I->getName() << "\n";
218       assert(0 && "References to external globals not handled yet!");
219     }
220   
221   // Now that all of the globals are set up in memory, loop through them all and
222   // initialize their contents.
223   for (Module::giterator I = getModule().gbegin(), E = getModule().gend();
224        I != E; ++I)
225     if (!I->isExternal())
226       InitializeMemory(I->getInitializer(), GlobalAddress[I]);
227 }
228