Mercurial > projects > ldc
comparison gen/tollvm.c @ 4:e116aa1488e6 trunk
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
fixed passing string literals as array parameters
few other fixes
moved some array routines into gen/arrays
author | lindquist |
---|---|
date | Mon, 03 Sep 2007 17:34:30 +0200 |
parents | c53b6e3fe49a |
children | 35d93ce68cf4 |
comparison
equal
deleted
inserted
replaced
3:069cf4b0ec67 | 4:e116aa1488e6 |
---|---|
11 #include "dsymbol.h" | 11 #include "dsymbol.h" |
12 #include "aggregate.h" | 12 #include "aggregate.h" |
13 #include "declaration.h" | 13 #include "declaration.h" |
14 #include "init.h" | 14 #include "init.h" |
15 | 15 |
16 #include "tollvm.h" | 16 #include "gen/tollvm.h" |
17 #include "irstate.h" | 17 #include "gen/irstate.h" |
18 #include "logger.h" | 18 #include "gen/logger.h" |
19 #include "runtime.h" | 19 #include "gen/runtime.h" |
20 #include "elem.h" | 20 #include "gen/elem.h" |
21 #include "gen/arrays.h" | |
21 | 22 |
22 const llvm::Type* LLVM_DtoType(Type* t) | 23 const llvm::Type* LLVM_DtoType(Type* t) |
23 { | 24 { |
24 assert(t); | 25 assert(t); |
25 switch (t->ty) | 26 switch (t->ty) |
310 assert(0); | 311 assert(0); |
311 std::vector<const llvm::Type*> types; | 312 std::vector<const llvm::Type*> types; |
312 return llvm::StructType::get(types); | 313 return llvm::StructType::get(types); |
313 } | 314 } |
314 | 315 |
315 ////////////////////////////////////////////////////////////////////////////////////////// | |
316 | |
317 llvm::StructType* LLVM_DtoArrayType(Type* t) | |
318 { | |
319 assert(t->next); | |
320 const llvm::Type* at = LLVM_DtoType(t->next); | |
321 const llvm::Type* arrty; | |
322 | |
323 /*if (t->ty == Tsarray) { | |
324 TypeSArray* tsa = (TypeSArray*)t; | |
325 assert(tsa->dim->type->isintegral()); | |
326 arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
327 } | |
328 else { | |
329 arrty = llvm::ArrayType::get(at,0); | |
330 }*/ | |
331 if (at == llvm::Type::VoidTy) { | |
332 at = llvm::Type::Int8Ty; | |
333 } | |
334 arrty = llvm::PointerType::get(at); | |
335 | |
336 std::vector<const llvm::Type*> members; | |
337 if (global.params.is64bit) | |
338 members.push_back(llvm::Type::Int64Ty); | |
339 else | |
340 members.push_back(llvm::Type::Int32Ty); | |
341 | |
342 members.push_back(arrty); | |
343 | |
344 return llvm::StructType::get(members); | |
345 } | |
346 | |
347 ////////////////////////////////////////////////////////////////////////////////////////// | |
348 | |
349 llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) | |
350 { | |
351 if (t->llvmType) | |
352 return llvm::cast<llvm::ArrayType>(t->llvmType); | |
353 | |
354 assert(t->ty == Tsarray); | |
355 assert(t->next); | |
356 | |
357 const llvm::Type* at = LLVM_DtoType(t->next); | |
358 | |
359 TypeSArray* tsa = (TypeSArray*)t; | |
360 assert(tsa->dim->type->isintegral()); | |
361 llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); | |
362 | |
363 tsa->llvmType = arrty; | |
364 return arrty; | |
365 } | |
366 | 316 |
367 ////////////////////////////////////////////////////////////////////////////////////////// | 317 ////////////////////////////////////////////////////////////////////////////////////////// |
368 | 318 |
369 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false) | 319 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false) |
370 { | 320 { |
389 } | 339 } |
390 | 340 |
391 ////////////////////////////////////////////////////////////////////////////////////////// | 341 ////////////////////////////////////////////////////////////////////////////////////////// |
392 | 342 |
393 // llvm.memset.i32 | 343 // llvm.memset.i32 |
394 static llvm::Function* LLVM_DeclareMemSet32() | 344 llvm::Function* LLVM_DeclareMemSet32() |
395 { | 345 { |
396 static llvm::Function* _func = 0; | 346 static llvm::Function* _func = 0; |
397 if (_func == 0) { | 347 if (_func == 0) { |
398 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true); | 348 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i32", 32, true); |
399 } | 349 } |
400 return _func; | 350 return _func; |
401 } | 351 } |
402 | 352 |
403 ////////////////////////////////////////////////////////////////////////////////////////// | 353 ////////////////////////////////////////////////////////////////////////////////////////// |
404 | 354 |
405 static llvm::Function* LLVM_DeclareMemSet64() | 355 llvm::Function* LLVM_DeclareMemSet64() |
406 { | 356 { |
407 static llvm::Function* _func = 0; | 357 static llvm::Function* _func = 0; |
408 if (_func == 0) { | 358 if (_func == 0) { |
409 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true); | 359 _func = LLVM_DeclareMemIntrinsic("llvm.memset.i64", 64, true); |
410 } | 360 } |
412 } | 362 } |
413 | 363 |
414 ////////////////////////////////////////////////////////////////////////////////////////// | 364 ////////////////////////////////////////////////////////////////////////////////////////// |
415 | 365 |
416 // llvm.memcpy.i32 | 366 // llvm.memcpy.i32 |
417 static llvm::Function* LLVM_DeclareMemCpy32() | 367 llvm::Function* LLVM_DeclareMemCpy32() |
418 { | 368 { |
419 static llvm::Function* _func = 0; | 369 static llvm::Function* _func = 0; |
420 if (_func == 0) { | 370 if (_func == 0) { |
421 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32); | 371 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i32", 32); |
422 } | 372 } |
424 } | 374 } |
425 | 375 |
426 ////////////////////////////////////////////////////////////////////////////////////////// | 376 ////////////////////////////////////////////////////////////////////////////////////////// |
427 | 377 |
428 // llvm.memcpy.i64 | 378 // llvm.memcpy.i64 |
429 static llvm::Function* LLVM_DeclareMemCpy64() | 379 llvm::Function* LLVM_DeclareMemCpy64() |
430 { | 380 { |
431 static llvm::Function* _func = 0; | 381 static llvm::Function* _func = 0; |
432 if (_func == 0) { | 382 if (_func == 0) { |
433 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64); | 383 _func = LLVM_DeclareMemIntrinsic("llvm.memcpy.i64", 64); |
434 } | 384 } |
554 } | 504 } |
555 | 505 |
556 return llvm::ConstantStruct::get(structtype, inits); | 506 return llvm::ConstantStruct::get(structtype, inits); |
557 } | 507 } |
558 | 508 |
559 ////////////////////////////////////////////////////////////////////////////////////////// | 509 |
560 | 510 |
561 llvm::Value* LLVM_DtoNullArray(llvm::Value* v) | 511 ////////////////////////////////////////////////////////////////////////////////////////// |
512 | |
513 llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v) | |
562 { | 514 { |
563 assert(gIR); | 515 assert(gIR); |
564 d_uns64 n = (global.params.is64bit) ? 16 : 8; | 516 d_uns64 n = (global.params.is64bit) ? 16 : 8; |
565 | 517 |
566 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | 518 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); |
573 llargs[0] = arr; | 525 llargs[0] = arr; |
574 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | 526 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); |
575 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | 527 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); |
576 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | 528 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); |
577 | 529 |
578 //Logger::cout() << *fn << '|' << *fn->getType() << '\n'; | |
579 //Logger::cout() << "to null array call: " << *llargs[0] << '|' << *llargs[1] << '|' << *llargs[2] << '|' << *llargs[3] << '\n'; | |
580 | |
581 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
582 | |
583 return ret; | |
584 } | |
585 | |
586 ////////////////////////////////////////////////////////////////////////////////////////// | |
587 | |
588 llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v) | |
589 { | |
590 assert(gIR); | |
591 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
592 | |
593 llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
594 | |
595 llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); | |
596 | |
597 llvm::Function* fn = LLVM_DeclareMemSet32(); | |
598 std::vector<llvm::Value*> llargs; | |
599 llargs.resize(4); | |
600 llargs[0] = arr; | |
601 llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); | |
602 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
603 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
604 | |
605 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | 530 llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); |
606 | 531 |
607 return ret; | 532 return ret; |
608 } | 533 } |
609 | 534 |
630 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | 555 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); |
631 | 556 |
632 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | 557 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); |
633 } | 558 } |
634 | 559 |
635 ////////////////////////////////////////////////////////////////////////////////////////// | 560 |
636 | |
637 llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src) | |
638 { | |
639 assert(gIR); | |
640 if (dst->getType() == src->getType()) | |
641 { | |
642 d_uns64 n = (global.params.is64bit) ? 16 : 8; | |
643 | |
644 llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
645 | |
646 llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); | |
647 llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); | |
648 | |
649 llvm::Function* fn = LLVM_DeclareMemCpy32(); | |
650 std::vector<llvm::Value*> llargs; | |
651 llargs.resize(4); | |
652 llargs[0] = dstarr; | |
653 llargs[1] = srcarr; | |
654 llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); | |
655 llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
656 | |
657 return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); | |
658 } | |
659 else | |
660 { | |
661 if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0))) | |
662 { | |
663 Logger::cout() << "invalid: " << *src << '\n'; | |
664 assert(0); | |
665 } | |
666 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0)); | |
667 llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType()); | |
668 | |
669 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
670 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
671 | |
672 llvm::Value* dstlen = new llvm::GetElementPtrInst(dst,zero,zero,"tmp",gIR->scopebb()); | |
673 llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
674 new llvm::StoreInst(srclen, dstlen, gIR->scopebb()); | |
675 | |
676 llvm::Value* dstptr = new llvm::GetElementPtrInst(dst,zero,one,"tmp",gIR->scopebb()); | |
677 llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb()); | |
678 new llvm::StoreInst(srcptr, dstptr, gIR->scopebb()); | |
679 } | |
680 } | |
681 | |
682 ////////////////////////////////////////////////////////////////////////////////////////// | |
683 | |
684 void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r) | |
685 { | |
686 const llvm::PointerType* ptrty = llvm::cast<llvm::PointerType>(l->getType()); | |
687 if (llvm::isa<llvm::ArrayType>(ptrty->getContainedType(0))) | |
688 { | |
689 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(ptrty->getContainedType(0)); | |
690 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
691 | |
692 std::vector<llvm::Value*> args; | |
693 args.resize(3); | |
694 args[0] = new llvm::GetElementPtrInst(l,zero,zero,"tmp",gIR->scopebb()); | |
695 args[1] = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false); | |
696 args[2] = r; | |
697 | |
698 const char* funcname = NULL; | |
699 | |
700 if (llvm::isa<llvm::PointerType>(arrty->getElementType())) { | |
701 funcname = "_d_array_init_pointer"; | |
702 | |
703 const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
704 if (args[0]->getType() != dstty) | |
705 args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb()); | |
706 | |
707 const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
708 if (args[2]->getType() != valty) | |
709 args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb()); | |
710 } | |
711 else if (r->getType() == llvm::Type::Int1Ty) { | |
712 funcname = "_d_array_init_i1"; | |
713 } | |
714 else if (r->getType() == llvm::Type::Int8Ty) { | |
715 funcname = "_d_array_init_i8"; | |
716 } | |
717 else if (r->getType() == llvm::Type::Int16Ty) { | |
718 funcname = "_d_array_init_i16"; | |
719 } | |
720 else if (r->getType() == llvm::Type::Int32Ty) { | |
721 funcname = "_d_array_init_i32"; | |
722 } | |
723 else if (r->getType() == llvm::Type::Int64Ty) { | |
724 funcname = "_d_array_init_i64"; | |
725 } | |
726 else if (r->getType() == llvm::Type::FloatTy) { | |
727 funcname = "_d_array_init_float"; | |
728 } | |
729 else if (r->getType() == llvm::Type::DoubleTy) { | |
730 funcname = "_d_array_init_double"; | |
731 } | |
732 else { | |
733 assert(0); | |
734 } | |
735 | |
736 Logger::cout() << *args[0] << '|' << *args[2] << '\n'; | |
737 | |
738 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); | |
739 assert(fn); | |
740 llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb()); | |
741 call->setCallingConv(llvm::CallingConv::C); | |
742 | |
743 Logger::println("array init call ok"); | |
744 } | |
745 else if (llvm::isa<llvm::StructType>(ptrty->getContainedType(0))) | |
746 { | |
747 assert(0 && "Only static arrays support initialisers atm"); | |
748 } | |
749 else | |
750 assert(0); | |
751 } | |
752 | |
753 ////////////////////////////////////////////////////////////////////////////////////////// | |
754 | |
755 void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr) | |
756 { | |
757 const llvm::StructType* st = llvm::cast<llvm::StructType>(arr->getType()->getContainedType(0)); | |
758 //const llvm::PointerType* pt = llvm::cast<llvm::PointerType>(r->getType()); | |
759 | |
760 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); | |
761 llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); | |
762 | |
763 llvm::Value* arrdim = new llvm::GetElementPtrInst(arr,zero,zero,"tmp",gIR->scopebb()); | |
764 new llvm::StoreInst(dim, arrdim, gIR->scopebb()); | |
765 | |
766 llvm::Value* arrptr = new llvm::GetElementPtrInst(arr,zero,one,"tmp",gIR->scopebb()); | |
767 new llvm::StoreInst(ptr, arrptr, gIR->scopebb()); | |
768 } | |
769 | |
770 ////////////////////////////////////////////////////////////////////////////////////////// | |
771 llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit) | |
772 { | |
773 Logger::println("arr init begin"); | |
774 assert(arrinit->type->ty == Tsarray); | |
775 TypeSArray* t = (TypeSArray*)arrinit->type; | |
776 integer_t tdim = t->dim->toInteger(); | |
777 | |
778 std::vector<llvm::Constant*> inits(tdim, 0); | |
779 | |
780 const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next); | |
781 | |
782 assert(arrinit->index.dim == arrinit->value.dim); | |
783 for (int i=0,j=0; i < tdim; ++i) | |
784 { | |
785 Initializer* init = 0; | |
786 Expression* idx = (Expression*)arrinit->index.data[j]; | |
787 | |
788 if (idx) | |
789 { | |
790 integer_t k = idx->toInteger(); | |
791 if (i == k) | |
792 { | |
793 init = (Initializer*)arrinit->value.data[j]; | |
794 assert(init); | |
795 ++j; | |
796 } | |
797 } | |
798 else | |
799 { | |
800 init = (Initializer*)arrinit->value.data[j]; | |
801 ++j; | |
802 } | |
803 | |
804 llvm::Constant* v = 0; | |
805 | |
806 if (!init) | |
807 { | |
808 elem* e = t->next->defaultInit()->toElem(gIR); | |
809 v = llvm::cast<llvm::Constant>(e->val); | |
810 delete e; | |
811 } | |
812 else if (ExpInitializer* ex = init->isExpInitializer()) | |
813 { | |
814 elem* e = ex->exp->toElem(gIR); | |
815 v = llvm::cast<llvm::Constant>(e->val); | |
816 delete e; | |
817 } | |
818 else if (StructInitializer* si = init->isStructInitializer()) | |
819 { | |
820 v = LLVM_DtoStructInitializer(si); | |
821 } | |
822 else if (ArrayInitializer* ai = init->isArrayInitializer()) | |
823 { | |
824 v = LLVM_DtoArrayInitializer(ai); | |
825 } | |
826 else if (init->isVoidInitializer()) | |
827 { | |
828 v = llvm::UndefValue::get(elemty); | |
829 } | |
830 else | |
831 assert(v); | |
832 | |
833 inits[i] = v; | |
834 } | |
835 | |
836 llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t); | |
837 return llvm::ConstantArray::get(arrty, inits); | |
838 } | |
839 | |
840 ////////////////////////////////////////////////////////////////////////////////////////// | |
841 void LLVM_DtoArrayCopy(elem* dst, elem* src) | |
842 { | |
843 assert(0); | |
844 } | |
845 | 561 |
846 ////////////////////////////////////////////////////////////////////////////////////////// | 562 ////////////////////////////////////////////////////////////////////////////////////////// |
847 | 563 |
848 llvm::GlobalValue::LinkageTypes LLVM_DtoLinkage(PROT prot, uint stc) | 564 llvm::GlobalValue::LinkageTypes LLVM_DtoLinkage(PROT prot, uint stc) |
849 { | 565 { |