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