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()