Mercurial > projects > ldc
comparison gen/typinf.cpp @ 1375:63f4afd01036
Cleaned up TypeInfo_Struct.
Fixed problem with DtoConstSize_t taking a size_t argument, this is not enough for cross compiling from 32bit host to a 64bit target. It now takes uint64_t. There's probably a lot of similar case around to code ...
author | Tomas Lindquist Olsen <tomas.l.olsen gmail com> |
---|---|
date | Sun, 17 May 2009 04:41:10 +0200 |
parents | e630ff79e10d |
children | a5d0e04298a8 |
comparison
equal
deleted
inserted
replaced
1374:e630ff79e10d | 1375:63f4afd01036 |
---|---|
545 b.finalize(ir.irGlobal); | 545 b.finalize(ir.irGlobal); |
546 } | 546 } |
547 | 547 |
548 /* ========================================================================= */ | 548 /* ========================================================================= */ |
549 | 549 |
550 static FuncDeclaration* find_method_overload(AggregateDeclaration* ad, Identifier* id, TypeFunction* tf, Module* mod) | |
551 { | |
552 Dsymbol *s = search_function(ad, id); | |
553 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; | |
554 if (fdx) | |
555 { | |
556 FuncDeclaration *fd = fdx->overloadExactMatch(tf, mod); | |
557 if (fd) | |
558 { | |
559 return fd; | |
560 } | |
561 } | |
562 return NULL; | |
563 } | |
564 | |
550 void TypeInfoStructDeclaration::llvmDefine() | 565 void TypeInfoStructDeclaration::llvmDefine() |
551 { | 566 { |
552 Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars()); | 567 Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars()); |
553 LOG_SCOPE; | 568 LOG_SCOPE; |
554 | 569 |
563 sd->error("cannot emit TypeInfo for forward declaration"); | 578 sd->error("cannot emit TypeInfo for forward declaration"); |
564 fatal(); | 579 fatal(); |
565 } | 580 } |
566 | 581 |
567 sd->codegen(Type::sir); | 582 sd->codegen(Type::sir); |
568 | 583 IrStruct* irstruct = sd->ir.irStruct; |
569 ClassDeclaration* base = Type::typeinfostruct; | 584 |
570 base->codegen(Type::sir); | 585 TypeInfoBuilder b(Type::typeinfostruct); |
571 | |
572 const LLStructType* stype = isaStruct(base->type->irtype->getPA()); | |
573 | |
574 // vtbl | |
575 std::vector<LLConstant*> sinits; | |
576 sinits.push_back(base->ir.irStruct->getVtblSymbol()); | |
577 | |
578 // monitor | |
579 sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty))); | |
580 | 586 |
581 // char[] name | 587 // char[] name |
582 char *name = sd->toPrettyChars(); | 588 b.push_string(sd->toPrettyChars()); |
583 sinits.push_back(DtoConstString(name)); | |
584 //Logger::println("************** A"); | |
585 assert(sinits.back()->getType() == stype->getElementType(2)); | |
586 | 589 |
587 // void[] init | 590 // void[] init |
588 const LLPointerType* initpt = getPtrToType(LLType::Int8Ty); | 591 // never emit a null array, even for zero initialized typeinfo |
589 #if 0 | 592 // the size() method uses this array! |
590 // the implementation of TypeInfo_Struct uses this to determine size. :/ | 593 size_t init_size = getTypeStoreSize(tc->irtype->getPA()); |
591 if (sd->zeroInit) // 0 initializer, or the same as the base type | 594 b.push_void_array(init_size, irstruct->getInitSymbol()); |
592 { | |
593 sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); | |
594 } | |
595 else | |
596 #endif | |
597 { | |
598 size_t cisize = getTypeStoreSize(tc->irtype->getPA().get()); | |
599 LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->getInitSymbol(), initpt); | |
600 sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); | |
601 } | |
602 | 595 |
603 // toX functions ground work | 596 // toX functions ground work |
604 FuncDeclaration *fd; | |
605 FuncDeclaration *fdx; | |
606 TypeFunction *tf; | |
607 Type *ta; | |
608 Dsymbol *s; | |
609 | |
610 static TypeFunction *tftohash; | 597 static TypeFunction *tftohash; |
611 static TypeFunction *tftostring; | 598 static TypeFunction *tftostring; |
612 | 599 |
613 if (!tftohash) | 600 if (!tftohash) |
614 { | 601 { |
615 Scope sc; | 602 Scope sc; |
616 | 603 tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); |
617 tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); | 604 tftohash = (TypeFunction *)tftohash->semantic(0, &sc); |
618 tftohash = (TypeFunction *)tftohash->semantic(0, &sc); | 605 tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); |
619 | 606 tftostring = (TypeFunction *)tftostring->semantic(0, &sc); |
620 tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); | 607 } |
621 tftostring = (TypeFunction *)tftostring->semantic(0, &sc); | 608 |
622 } | 609 // this one takes a parameter, so we need to build a new one each time |
623 | 610 // to get the right type. can we avoid this? |
624 TypeFunction *tfeqptr; | 611 TypeFunction *tfeqptr; |
625 { | 612 { |
626 Scope sc; | 613 Scope sc; |
627 Arguments *arguments = new Arguments; | 614 Arguments *arguments = new Arguments; |
628 Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); | 615 Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); |
629 | 616 arguments->push(arg); |
630 arguments->push(arg); | 617 tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); |
631 tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); | 618 tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); |
632 tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); | 619 } |
633 } | 620 |
634 | 621 // well use this module for all overload lookups |
635 #if 0 | 622 Module *gm = getModule(); |
636 TypeFunction *tfeq; | 623 |
637 { | 624 // toHash |
638 Scope sc; | 625 FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash, gm); |
639 Array *arguments = new Array; | 626 b.push_funcptr(fd); |
640 Argument *arg = new Argument(In, tc, NULL, NULL); | 627 |
641 | 628 // opEquals |
642 arguments->push(arg); | 629 fd = find_method_overload(sd, Id::eq, tfeqptr, gm); |
643 tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); | 630 b.push_funcptr(fd); |
644 tfeq = (TypeFunction *)tfeq->semantic(0, &sc); | 631 |
645 } | 632 // opCmp |
633 fd = find_method_overload(sd, Id::cmp, tfeqptr, gm); | |
634 b.push_funcptr(fd); | |
635 | |
636 // toString | |
637 fd = find_method_overload(sd, Id::tostring, tftostring, gm); | |
638 b.push_funcptr(fd); | |
639 | |
640 // uint m_flags; | |
641 unsigned hasptrs = tc->hasPointers() ? 1 : 0; | |
642 b.push_uint(hasptrs); | |
643 | |
644 #if DMDV2 | |
645 // just (void*)null for now | |
646 | |
647 // const(MemberInfo[]) function(in char[]) xgetMembers; | |
648 b.push_null_vp(); | |
649 | |
650 //void function(void*) xdtor; | |
651 b.push_null_vp(); | |
652 | |
653 //void function(void*) xpostblit; | |
654 b.push_null_vp(); | |
646 #endif | 655 #endif |
647 | 656 |
648 //Logger::println("************** B"); | 657 // finish |
649 const LLPointerType* ptty = isaPointer(stype->getElementType(4)); | 658 b.finalize(ir.irGlobal); |
650 assert(ptty); | |
651 | |
652 s = search_function(sd, Id::tohash); | |
653 fdx = s ? s->isFuncDeclaration() : NULL; | |
654 if (fdx) | |
655 { | |
656 fd = fdx->overloadExactMatch(tftohash, getModule()); | |
657 if (fd) { | |
658 fd->codegen(Type::sir); | |
659 assert(fd->ir.irFunc->func != 0); | |
660 LLConstant* c = isaConstant(fd->ir.irFunc->func); | |
661 assert(c); | |
662 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
663 sinits.push_back(c); | |
664 } | |
665 else { | |
666 //fdx->error("must be declared as extern (D) uint toHash()"); | |
667 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
668 } | |
669 } | |
670 else { | |
671 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
672 } | |
673 | |
674 s = search_function(sd, Id::eq); | |
675 fdx = s ? s->isFuncDeclaration() : NULL; | |
676 for (int i = 0; i < 2; i++) | |
677 { | |
678 //Logger::println("************** C %d", i); | |
679 ptty = isaPointer(stype->getElementType(5+i)); | |
680 if (fdx) | |
681 { | |
682 fd = fdx->overloadExactMatch(tfeqptr, getModule()); | |
683 if (fd) { | |
684 fd->codegen(Type::sir); | |
685 assert(fd->ir.irFunc->func != 0); | |
686 LLConstant* c = isaConstant(fd->ir.irFunc->func); | |
687 assert(c); | |
688 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
689 sinits.push_back(c); | |
690 } | |
691 else { | |
692 //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); | |
693 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
694 } | |
695 } | |
696 else { | |
697 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
698 } | |
699 | |
700 s = search_function(sd, Id::cmp); | |
701 fdx = s ? s->isFuncDeclaration() : NULL; | |
702 } | |
703 | |
704 //Logger::println("************** D"); | |
705 ptty = isaPointer(stype->getElementType(7)); | |
706 s = search_function(sd, Id::tostring); | |
707 fdx = s ? s->isFuncDeclaration() : NULL; | |
708 if (fdx) | |
709 { | |
710 fd = fdx->overloadExactMatch(tftostring, getModule()); | |
711 if (fd) { | |
712 fd->codegen(Type::sir); | |
713 assert(fd->ir.irFunc->func != 0); | |
714 LLConstant* c = isaConstant(fd->ir.irFunc->func); | |
715 assert(c); | |
716 c = llvm::ConstantExpr::getBitCast(c, ptty); | |
717 sinits.push_back(c); | |
718 } | |
719 else { | |
720 //fdx->error("must be declared as extern (D) char[] toString()"); | |
721 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
722 } | |
723 } | |
724 else { | |
725 sinits.push_back(llvm::ConstantPointerNull::get(ptty)); | |
726 } | |
727 | |
728 // uint m_flags; | |
729 sinits.push_back(DtoConstUint(tc->hasPointers())); | |
730 | |
731 #if DMDV2 | |
732 | |
733 // const(MemberInfo[]) function(in char[]) xgetMembers; | |
734 sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); | |
735 | |
736 //void function(void*) xdtor; | |
737 sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); | |
738 | |
739 //void function(void*) xpostblit; | |
740 sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); | |
741 | |
742 #endif | |
743 | |
744 // create the inititalizer | |
745 LLConstant* tiInit = llvm::ConstantStruct::get(sinits); | |
746 | |
747 // refine global type | |
748 llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType()); | |
749 | |
750 // set the initializer | |
751 isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit); | |
752 } | 659 } |
753 | 660 |
754 /* ========================================================================= */ | 661 /* ========================================================================= */ |
755 | 662 |
756 void TypeInfoClassDeclaration::llvmDefine() | 663 void TypeInfoClassDeclaration::llvmDefine() |