comparison gen/functions.cpp @ 121:9c79b61fb638 trunk

[svn r125] Renamed/moved a few backend member inside DMD structures for consistency. Unit tests are now implemented.
author lindquist
date Tue, 27 Nov 2007 03:09:36 +0100
parents 79c9ac745fbc
children 7f9a0a58394b
comparison
equal deleted inserted replaced
120:5ce8ab11e75a 121:9c79b61fb638
71 71
72 if (typesafeVararg) { 72 if (typesafeVararg) {
73 ClassDeclaration* ti = Type::typeinfo; 73 ClassDeclaration* ti = Type::typeinfo;
74 ti->toObjFile(); 74 ti->toObjFile();
75 DtoForceConstInitDsymbol(ti); 75 DtoForceConstInitDsymbol(ti);
76 assert(ti->llvmInitZ); 76 assert(ti->llvmConstInit);
77 std::vector<const llvm::Type*> types; 77 std::vector<const llvm::Type*> types;
78 types.push_back(DtoSize_t()); 78 types.push_back(DtoSize_t());
79 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); 79 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmConstInit->getType())));
80 const llvm::Type* t1 = llvm::StructType::get(types); 80 const llvm::Type* t1 = llvm::StructType::get(types);
81 paramvec.push_back(llvm::PointerType::get(t1)); 81 paramvec.push_back(llvm::PointerType::get(t1));
82 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); 82 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
83 } 83 }
84 84
180 { 180 {
181 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { 181 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
182 return DtoVaFunctionType(fdecl); 182 return DtoVaFunctionType(fdecl);
183 } 183 }
184 184
185 // unittest has null type, just build it manually
186 /*if (fdecl->isUnitTestDeclaration()) {
187 std::vector<const llvm::Type*> args;
188 return llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
189 }*/
190
185 // type has already been resolved 191 // type has already been resolved
186 if (fdecl->type->llvmType != 0) { 192 if (fdecl->type->llvmType != 0) {
187 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get()); 193 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get());
188 } 194 }
189 195
236 242
237 ////////////////////////////////////////////////////////////////////////////////////////// 243 //////////////////////////////////////////////////////////////////////////////////////////
238 244
239 void DtoResolveFunction(FuncDeclaration* fdecl) 245 void DtoResolveFunction(FuncDeclaration* fdecl)
240 { 246 {
247 if (!global.params.useUnitTests && fdecl->isUnitTestDeclaration()) {
248 return; // ignore declaration completely
249 }
250
241 if (fdecl->llvmResolved) return; 251 if (fdecl->llvmResolved) return;
242 fdecl->llvmResolved = true; 252 fdecl->llvmResolved = true;
243 253
244 Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars()); 254 Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars());
245 LOG_SCOPE; 255 LOG_SCOPE;
246 256
247 if (fdecl->llvmRunTimeHack) { 257 if (fdecl->llvmRunTimeHack) {
248 gIR->declareList.push_back(fdecl); 258 gIR->declareList.push_back(fdecl);
249 return;
250 }
251
252 if (fdecl->isUnitTestDeclaration()) {
253 Logger::attention("ignoring unittest declaration: %s", fdecl->toChars());
254 return; 259 return;
255 } 260 }
256 261
257 if (fdecl->parent) 262 if (fdecl->parent)
258 if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance()) 263 if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance())
291 Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars()); 296 Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars());
292 LOG_SCOPE; 297 LOG_SCOPE;
293 298
294 assert(!fdecl->isAbstract()); 299 assert(!fdecl->isAbstract());
295 300
301 // intrinsic sanity check
302 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
303 error(fdecl->loc, "intrinsics cannot have function bodies");
304 fatal();
305 }
306
296 if (fdecl->llvmRunTimeHack) { 307 if (fdecl->llvmRunTimeHack) {
297 Logger::println("runtime hack func chars: %s", fdecl->toChars()); 308 Logger::println("runtime hack func chars: %s", fdecl->toChars());
298 if (!fdecl->llvmValue) 309 if (!fdecl->llvmValue)
299 fdecl->llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars()); 310 fdecl->llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars());
300 return; 311 return;
315 char* mangled_name; 326 char* mangled_name;
316 if (fdecl->llvmInternal == LLVMintrinsic) 327 if (fdecl->llvmInternal == LLVMintrinsic)
317 mangled_name = fdecl->llvmInternal1; 328 mangled_name = fdecl->llvmInternal1;
318 else 329 else
319 mangled_name = fdecl->mangle(); 330 mangled_name = fdecl->mangle();
320
321 // unit test special handling
322 if (fdecl->isUnitTestDeclaration())
323 {
324 assert(0 && "no unittests yet");
325 /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false);
326 // make the function
327 llvm::Function* func = gIR->module->getFunction(mangled_name);
328 if (func == 0)
329 func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module);
330 func->setCallingConv(llvm::CallingConv::Fast);
331 fdecl->llvmValue = func;
332 return func;
333 */
334 }
335
336 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
337 error("intrinsics cannot have function bodies");
338 fatal();
339 }
340 331
341 llvm::Function* vafunc = 0; 332 llvm::Function* vafunc = 0;
342 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { 333 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
343 vafunc = DtoDeclareVaFunction(fdecl); 334 vafunc = DtoDeclareVaFunction(fdecl);
344 } 335 }
385 // name parameters 376 // name parameters
386 llvm::Function::arg_iterator iarg = func->arg_begin(); 377 llvm::Function::arg_iterator iarg = func->arg_begin();
387 int k = 0; 378 int k = 0;
388 if (f->llvmRetInPtr) { 379 if (f->llvmRetInPtr) {
389 iarg->setName("retval"); 380 iarg->setName("retval");
390 f->llvmRetArg = iarg; 381 fdecl->llvmRetArg = iarg;
391 ++iarg; 382 ++iarg;
392 } 383 }
393 if (f->llvmUsesThis) { 384 if (f->llvmUsesThis) {
394 iarg->setName("this"); 385 iarg->setName("this");
395 fdecl->llvmThisVar = iarg; 386 fdecl->llvmThisVar = iarg;
420 else { 411 else {
421 iarg->setName("unnamed"); 412 iarg->setName("unnamed");
422 } 413 }
423 } 414 }
424 415
416 if (fdecl->isUnitTestDeclaration())
417 gIR->unitTests.push_back(fdecl);
418
425 if (!declareOnly) 419 if (!declareOnly)
426 gIR->defineList.push_back(fdecl); 420 gIR->defineList.push_back(fdecl);
427 421
428 Logger::cout() << "func decl: " << *func << '\n'; 422 Logger::cout() << "func decl: " << *func << '\n';
429 } 423 }
430 424
431 ////////////////////////////////////////////////////////////////////////////////////////// 425 //////////////////////////////////////////////////////////////////////////////////////////
432 426
433 // TODO split this monster up
434 void DtoDefineFunc(FuncDeclaration* fd) 427 void DtoDefineFunc(FuncDeclaration* fd)
435 { 428 {
436 if (fd->llvmDefined) return; 429 if (fd->llvmDefined) return;
437 fd->llvmDefined = true; 430 fd->llvmDefined = true;
438 431
450 fd->llvmDwarfSubProgram = DtoDwarfSubProgram(fd, mo->llvmCompileUnit); 443 fd->llvmDwarfSubProgram = DtoDwarfSubProgram(fd, mo->llvmCompileUnit);
451 } 444 }
452 445
453 Type* t = DtoDType(fd->type); 446 Type* t = DtoDType(fd->type);
454 TypeFunction* f = (TypeFunction*)t; 447 TypeFunction* f = (TypeFunction*)t;
455
456 assert(f->llvmType); 448 assert(f->llvmType);
449
457 llvm::Function* func = fd->llvmIRFunc->func; 450 llvm::Function* func = fd->llvmIRFunc->func;
458 const llvm::FunctionType* functype = func->getFunctionType(); 451 const llvm::FunctionType* functype = func->getFunctionType();
459 452
460 // only members of the current module or template instances maybe be defined 453 // only members of the current module or template instances maybe be defined
461 if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)) 454 if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent))
477 470
478 //assert(gIR->scopes.empty()); 471 //assert(gIR->scopes.empty());
479 gIR->scopes.push_back(IRScope(beginbb, endbb)); 472 gIR->scopes.push_back(IRScope(beginbb, endbb));
480 473
481 // create alloca point 474 // create alloca point
482 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); 475 llvm::Instruction* allocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
483 gIR->func()->allocapoint = f->llvmAllocaPoint; 476 gIR->func()->allocapoint = allocaPoint;
484 477
485 // need result variable? (not nested) 478 // need result variable? (not nested)
486 if (fd->vresult && !fd->vresult->nestedref) { 479 if (fd->vresult && !fd->vresult->nestedref) {
487 Logger::println("non-nested vresult value"); 480 Logger::println("non-nested vresult value");
488 fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",f->llvmAllocaPoint); 481 fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",allocaPoint);
489 } 482 }
490 483
491 // give arguments storage 484 // give arguments storage
492 size_t n = Argument::dim(f->parameters); 485 size_t n = Argument::dim(f->parameters);
493 for (int i=0; i < n; ++i) { 486 for (int i=0; i < n; ++i) {
499 llvm::Value* a = vd->llvmValue; 492 llvm::Value* a = vd->llvmValue;
500 assert(a); 493 assert(a);
501 std::string s(a->getName()); 494 std::string s(a->getName());
502 Logger::println("giving argument '%s' storage", s.c_str()); 495 Logger::println("giving argument '%s' storage", s.c_str());
503 s.append("_storage"); 496 s.append("_storage");
504 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint); 497 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,allocaPoint);
505 gIR->ir->CreateStore(a,v); 498 gIR->ir->CreateStore(a,v);
506 vd->llvmValue = v; 499 vd->llvmValue = v;
507 } 500 }
508 else { 501 else {
509 Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0); 502 Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0);
544 nestTypes.push_back(DtoType(vd->type)); 537 nestTypes.push_back(DtoType(vd->type));
545 } 538 }
546 } 539 }
547 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); 540 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
548 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType; 541 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
549 fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint); 542 fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint);
550 if (parentNested) { 543 if (parentNested) {
551 assert(fd->llvmThisVar); 544 assert(fd->llvmThisVar);
552 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp"); 545 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp");
553 gIR->ir->CreateStore(ptr, DtoGEPi(fd->llvmNested, 0,0, "tmp")); 546 gIR->ir->CreateStore(ptr, DtoGEPi(fd->llvmNested, 0,0, "tmp"));
554 } 547 }
586 } 579 }
587 } 580 }
588 } 581 }
589 582
590 // erase alloca point 583 // erase alloca point
591 f->llvmAllocaPoint->eraseFromParent(); 584 allocaPoint->eraseFromParent();
592 f->llvmAllocaPoint = 0; 585 allocaPoint = 0;
593 gIR->func()->allocapoint = 0; 586 gIR->func()->allocapoint = 0;
594 587
595 gIR->scopes.pop_back(); 588 gIR->scopes.pop_back();
596 589
597 // get rid of the endentry block, it's never used 590 // get rid of the endentry block, it's never used
647 640
648 // call static ctors 641 // call static ctors
649 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor"); 642 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor");
650 llvm::Instruction* apt = new llvm::CallInst(fn,"",bb); 643 llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
651 644
645 // run unit tests if -unittest is provided
646 if (global.params.useUnitTests) {
647 fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleUnitTests");
648 llvm::Instruction* apt = new llvm::CallInst(fn,"",bb);
649 }
650
652 // call user main function 651 // call user main function
653 const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType(); 652 const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType();
654 llvm::CallInst* call; 653 llvm::CallInst* call;
655 if (mainty->getNumParams() > 0) 654 if (mainty->getNumParams() > 0)
656 { 655 {