Mercurial > projects > ldc
comparison gen/toobj.cpp @ 116:fd7ad91fd713 trunk
[svn r120] ModuleInfo implementation is now almost complete.
Fixed some nasty static array-initializer bugs.
Fixed bug in DtoArrayLen and DtoArrayPtr for full slices of static arrays.
author | lindquist |
---|---|
date | Sun, 25 Nov 2007 18:55:52 +0100 |
parents | 5ba6d286c941 |
children | 56a21f3e5d3e |
comparison
equal
deleted
inserted
replaced
115:5ba6d286c941 | 116:fd7ad91fd713 |
---|---|
104 assert(dsym); | 104 assert(dsym); |
105 dsym->toObjFile(); | 105 dsym->toObjFile(); |
106 } | 106 } |
107 | 107 |
108 // main driver loop | 108 // main driver loop |
109 for(;;) | 109 DtoEmptyAllLists(); |
110 { | |
111 Dsymbol* dsym; | |
112 if (!ir.resolveList.empty()) { | |
113 dsym = ir.resolveList.front(); | |
114 ir.resolveList.pop_front(); | |
115 DtoResolveDsymbol(dsym); | |
116 } | |
117 else if (!ir.declareList.empty()) { | |
118 dsym = ir.declareList.front(); | |
119 ir.declareList.pop_front(); | |
120 DtoDeclareDsymbol(dsym); | |
121 } | |
122 else if (!ir.constInitList.empty()) { | |
123 dsym = ir.constInitList.front(); | |
124 ir.constInitList.pop_front(); | |
125 DtoConstInitDsymbol(dsym); | |
126 } | |
127 else if (!ir.defineList.empty()) { | |
128 dsym = ir.defineList.front(); | |
129 ir.defineList.pop_front(); | |
130 DtoDefineDsymbol(dsym); | |
131 } | |
132 else { | |
133 break; | |
134 } | |
135 } | |
136 | |
137 // generate ModuleInfo | 110 // generate ModuleInfo |
138 genmoduleinfo(); | 111 genmoduleinfo(); |
112 // do this again as moduleinfo might have pulled something in! | |
113 DtoEmptyAllLists(); | |
139 | 114 |
140 gTargetData = 0; | 115 gTargetData = 0; |
141 | 116 |
142 // emit the llvm main function if necessary | 117 // emit the llvm main function if necessary |
143 if (ir.emitMain) { | 118 if (ir.emitMain) { |
179 gIR = NULL; | 154 gIR = NULL; |
180 } | 155 } |
181 | 156 |
182 /* ================================================================== */ | 157 /* ================================================================== */ |
183 | 158 |
159 // build module ctor | |
160 | |
161 static llvm::Function* build_module_ctor() | |
162 { | |
163 if (gIR->ctors.empty()) | |
164 return NULL; | |
165 | |
166 size_t n = gIR->ctors.size(); | |
167 if (n == 1) | |
168 return llvm::cast<llvm::Function>(gIR->ctors[0]->llvmValue); | |
169 | |
170 std::string name("_D"); | |
171 name.append(gIR->dmodule->mangle()); | |
172 name.append("6__ctorZ"); | |
173 | |
174 std::vector<const llvm::Type*> argsTy; | |
175 const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false); | |
176 llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); | |
177 fn->setCallingConv(llvm::CallingConv::Fast); | |
178 | |
179 llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn); | |
180 LLVMBuilder builder(bb); | |
181 | |
182 for (size_t i=0; i<n; i++) { | |
183 llvm::Function* f = llvm::cast<llvm::Function>(gIR->ctors[i]->llvmValue); | |
184 llvm::CallInst* call = builder.CreateCall(f,""); | |
185 call->setCallingConv(llvm::CallingConv::Fast); | |
186 } | |
187 | |
188 builder.CreateRetVoid(); | |
189 return fn; | |
190 } | |
191 | |
192 // build module dtor | |
193 | |
194 static llvm::Function* build_module_dtor() | |
195 { | |
196 if (gIR->dtors.empty()) | |
197 return NULL; | |
198 | |
199 size_t n = gIR->dtors.size(); | |
200 if (n == 1) | |
201 return llvm::cast<llvm::Function>(gIR->dtors[0]->llvmValue); | |
202 | |
203 std::string name("_D"); | |
204 name.append(gIR->dmodule->mangle()); | |
205 name.append("6__dtorZ"); | |
206 | |
207 std::vector<const llvm::Type*> argsTy; | |
208 const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false); | |
209 llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); | |
210 fn->setCallingConv(llvm::CallingConv::Fast); | |
211 | |
212 llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn); | |
213 LLVMBuilder builder(bb); | |
214 | |
215 for (size_t i=0; i<n; i++) { | |
216 llvm::Function* f = llvm::cast<llvm::Function>(gIR->dtors[i]->llvmValue); | |
217 llvm::CallInst* call = builder.CreateCall(f,""); | |
218 call->setCallingConv(llvm::CallingConv::Fast); | |
219 } | |
220 | |
221 builder.CreateRetVoid(); | |
222 return fn; | |
223 } | |
224 | |
184 // Put out instance of ModuleInfo for this Module | 225 // Put out instance of ModuleInfo for this Module |
185 | 226 |
186 void Module::genmoduleinfo() | 227 void Module::genmoduleinfo() |
187 { | 228 { |
188 // The layout is: | 229 // The layout is: |
196 // void *ctor; | 237 // void *ctor; |
197 // void *dtor; | 238 // void *dtor; |
198 // void *unitTest; | 239 // void *unitTest; |
199 // } | 240 // } |
200 | 241 |
201 if (moduleinfo) { | 242 // resolve ModuleInfo |
202 Logger::println("moduleinfo"); | 243 assert(moduleinfo); |
203 } | 244 DtoForceConstInitDsymbol(moduleinfo); |
204 if (vmoduleinfo) { | 245 |
205 Logger::println("vmoduleinfo"); | 246 // moduleinfo llvm struct type |
206 } | 247 const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->llvmType->get()); |
207 if (needModuleInfo()) { | 248 |
208 Logger::attention("module info is needed but skipped"); | 249 // classinfo llvm struct type |
209 } | 250 const llvm::StructType* classinfoTy = isaStruct(ClassDeclaration::classinfo->type->llvmType->get()); |
210 | 251 |
211 | 252 // initializer vector |
212 /* | 253 std::vector<llvm::Constant*> initVec; |
213 Symbol *msym = toSymbol(); | 254 llvm::Constant* c = 0; |
214 unsigned offset; | 255 |
215 unsigned sizeof_ModuleInfo = 12 * PTRSIZE; | 256 // vtable |
216 | 257 c = moduleinfo->llvmVtbl; |
217 ////////////////////////////////////////////// | 258 initVec.push_back(c); |
218 | 259 |
219 csym->Sclass = SCglobal; | 260 // monitor |
220 csym->Sfl = FLdata; | 261 c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); |
221 | 262 initVec.push_back(c); |
222 // The layout is: | 263 |
223 // { | 264 // name |
224 // void **vptr; | |
225 // monitor_t monitor; | |
226 // char[] name; // class name | |
227 // ModuleInfo importedModules[]; | |
228 // ClassInfo localClasses[]; | |
229 // uint flags; // initialization state | |
230 // void *ctor; | |
231 // void *dtor; | |
232 // void *unitTest; | |
233 // } | |
234 dt_t *dt = NULL; | |
235 | |
236 if (moduleinfo) | |
237 dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo | |
238 else | |
239 dtdword(&dt, 0); // BUG: should be an assert() | |
240 dtdword(&dt, 0); // monitor | |
241 | |
242 // name[] | |
243 char *name = toPrettyChars(); | 265 char *name = toPrettyChars(); |
244 size_t namelen = strlen(name); | 266 c = DtoConstString(name); |
245 dtdword(&dt, namelen); | 267 initVec.push_back(c); |
246 dtabytes(&dt, TYnptr, 0, namelen + 1, name); | |
247 | |
248 ClassDeclarations aclasses; | |
249 int i; | |
250 | |
251 //printf("members->dim = %d\n", members->dim); | |
252 for (i = 0; i < members->dim; i++) | |
253 { | |
254 Dsymbol *member; | |
255 | |
256 member = (Dsymbol *)members->data[i]; | |
257 //printf("\tmember '%s'\n", member->toChars()); | |
258 member->addLocalClass(&aclasses); | |
259 } | |
260 | 268 |
261 // importedModules[] | 269 // importedModules[] |
262 int aimports_dim = aimports.dim; | 270 int aimports_dim = aimports.dim; |
263 for (i = 0; i < aimports.dim; i++) | 271 std::vector<llvm::Constant*> importInits; |
264 { Module *m = (Module *)aimports.data[i]; | 272 for (size_t i = 0; i < aimports.dim; i++) |
265 if (!m->needModuleInfo()) | 273 { |
266 aimports_dim--; | 274 Module *m = (Module *)aimports.data[i]; |
267 } | 275 if (!m->needModuleInfo()) |
268 dtdword(&dt, aimports_dim); | 276 aimports_dim--; |
269 if (aimports.dim) | 277 else { // declare |
270 dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr); | 278 // create name |
279 std::string m_name("_D"); | |
280 m_name.append(m->mangle()); | |
281 m_name.append("8__ModuleZ"); | |
282 llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name, gIR->module); | |
283 importInits.push_back(m_gvar); | |
284 } | |
285 } | |
286 // has import array? | |
287 if (!importInits.empty()) { | |
288 const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(moduleinfoTy), importInits.size()); | |
289 c = llvm::ConstantArray::get(importArrTy, importInits); | |
290 std::string m_name("_D"); | |
291 m_name.append(mangle()); | |
292 m_name.append("9__importsZ"); | |
293 llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(importArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module); | |
294 c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(importArrTy->getElementType())); | |
295 c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); | |
296 } | |
271 else | 297 else |
272 dtdword(&dt, 0); | 298 c = moduleinfo->llvmInitZ->getOperand(3); |
299 initVec.push_back(c); | |
273 | 300 |
274 // localClasses[] | 301 // localClasses[] |
275 dtdword(&dt, aclasses.dim); | 302 ClassDeclarations aclasses; |
276 if (aclasses.dim) | 303 //printf("members->dim = %d\n", members->dim); |
277 dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr); | 304 for (size_t i = 0; i < members->dim; i++) |
305 { | |
306 Dsymbol *member; | |
307 | |
308 member = (Dsymbol *)members->data[i]; | |
309 //printf("\tmember '%s'\n", member->toChars()); | |
310 member->addLocalClass(&aclasses); | |
311 } | |
312 // fill inits | |
313 std::vector<llvm::Constant*> classInits; | |
314 for (size_t i = 0; i < aclasses.dim; i++) | |
315 { | |
316 ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; | |
317 assert(cd->llvmClass); | |
318 classInits.push_back(cd->llvmClass); | |
319 } | |
320 // has class array? | |
321 if (!classInits.empty()) { | |
322 const llvm::ArrayType* classArrTy = llvm::ArrayType::get(llvm::PointerType::get(classinfoTy), classInits.size()); | |
323 c = llvm::ConstantArray::get(classArrTy, classInits); | |
324 std::string m_name("_D"); | |
325 m_name.append(mangle()); | |
326 m_name.append("9__classesZ"); | |
327 llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(classArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module); | |
328 c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(classArrTy->getElementType())); | |
329 c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); | |
330 } | |
278 else | 331 else |
279 dtdword(&dt, 0); | 332 c = moduleinfo->llvmInitZ->getOperand(4); |
280 | 333 initVec.push_back(c); |
334 | |
335 // flags | |
281 if (needmoduleinfo) | 336 if (needmoduleinfo) |
282 dtdword(&dt, 0); // flags (4 means MIstandalone) | 337 c = DtoConstUint(0); // flags (4 means MIstandalone) |
283 else | 338 else |
284 dtdword(&dt, 4); // flags (4 means MIstandalone) | 339 c = DtoConstUint(4); // flags (4 means MIstandalone) |
285 | 340 initVec.push_back(c); |
286 if (sctor) | 341 |
287 dtxoff(&dt, sctor, 0, TYnptr); | 342 // ctor |
288 else | 343 llvm::Function* fctor = build_module_ctor(); |
289 dtdword(&dt, 0); | 344 c = fctor ? fctor : moduleinfo->llvmInitZ->getOperand(6); |
290 | 345 initVec.push_back(c); |
291 if (sdtor) | 346 |
292 dtxoff(&dt, sdtor, 0, TYnptr); | 347 // dtor |
293 else | 348 llvm::Function* fdtor = build_module_dtor(); |
294 dtdword(&dt, 0); | 349 c = fdtor ? fdtor : moduleinfo->llvmInitZ->getOperand(7); |
295 | 350 initVec.push_back(c); |
296 if (stest) | 351 |
297 dtxoff(&dt, stest, 0, TYnptr); | 352 // unitTest |
298 else | 353 c = moduleinfo->llvmInitZ->getOperand(8); |
299 dtdword(&dt, 0); | 354 initVec.push_back(c); |
300 | 355 |
301 ////////////////////////////////////////////// | 356 // create initializer |
302 | 357 llvm::Constant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec); |
303 for (i = 0; i < aimports.dim; i++) | 358 |
304 { | 359 // create name |
305 Module *m; | 360 std::string MIname("_D"); |
306 | 361 MIname.append(mangle()); |
307 m = (Module *)aimports.data[i]; | 362 MIname.append("8__ModuleZ"); |
308 if (m->needModuleInfo()) | 363 |
309 { Symbol *s = m->toSymbol(); | 364 // declare |
310 s->Sflags |= SFLweak; | 365 // flags will be modified at runtime so can't make it constant |
311 dtxoff(&dt, s, 0, TYnptr); | 366 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module); |
312 } | |
313 } | |
314 | |
315 for (i = 0; i < aclasses.dim; i++) | |
316 { | |
317 ClassDeclaration *cd; | |
318 | |
319 cd = (ClassDeclaration *)aclasses.data[i]; | |
320 dtxoff(&dt, cd->toSymbol(), 0, TYnptr); | |
321 } | |
322 | |
323 csym->Sdt = dt; | |
324 #if ELFOBJ | |
325 // Cannot be CONST because the startup code sets flag bits in it | |
326 csym->Sseg = DATA; | |
327 #endif | |
328 outdata(csym); | |
329 | |
330 ////////////////////////////////////////////// | |
331 | |
332 obj_moduleinfo(msym); | |
333 */ | |
334 } | 367 } |
335 | 368 |
336 /* ================================================================== */ | 369 /* ================================================================== */ |
337 | 370 |
338 void Dsymbol::toObjFile() | 371 void Dsymbol::toObjFile() |