/****************************************************************************** * SetTypeCurrentAttrib */ short API::SetTypeCurrentAttrib(long filePosition, long typePosition) { #ifdef SHAREWARE return RC_NO_LICENSE; #endif if (apiView == NULL) return RC_NO_ACTIVE_DOC; CCEtoODBDoc *doc = apiView->GetDocument(); POSITION pos = (POSITION)filePosition; if (!AfxIsValidAddress(pos, 3 * sizeof(void*))) return RC_ILLEGAL_POSITION; FileStruct *file = doc->getFileList().GetAt(pos); pos = (POSITION)typePosition; if (!AfxIsValidAddress(pos, 3 * sizeof(void*))) return RC_ILLEGAL_POSITION; TypeStruct *type = file->getTypeList().GetAt(pos); currentAttribMap = &type->getAttributesRef(); currentDoc = doc; return RC_SUCCESS; }
TypeStruct* CDeviceTypeDirectory::addType(const TypeStruct& otherTypeStruct,int entityNumber) { TypeStruct* typeStruct = m_deviceTypeList.addType(otherTypeStruct,entityNumber); // if more than one type has the same name, the last added type is in the map getDeviceTypeMap().add(typeStruct->getName(),typeStruct); return typeStruct; }
void CDeviceTypeDirectory::takeData(CDeviceTypeDirectory& other) { for (POSITION pos = other.getHeadPosition();pos != NULL;) { POSITION oldPos = pos; TypeStruct* typeStruct = other.getNext(pos); other.removeAt(oldPos); TypeStruct* newTypeStruct = this->addType(*typeStruct,typeStruct->getEntityNumber()); newTypeStruct->getTypePinList().takeData(typeStruct->getTypePinList()); } }
void CDeviceTypeDirectory::removeUnusedDeviceTypes() { for (POSITION pos = getHeadPosition();pos != NULL;) { POSITION oldPos = pos; TypeStruct* typeStruct = getNext(pos); if (typeStruct->getBlockNumber() < 0) { deleteAt(oldPos); } } }
void CDeviceTypeDirectory::reallocateMap() const { delete m_deviceTypeMap; int size = max(100,(int)(1.3 * m_deviceTypeList.GetCount())); m_deviceTypeMap = new CDeviceTypeArrayWithMap(size,false); for (POSITION pos = m_deviceTypeList.GetHeadPosition();pos != NULL;) { TypeStruct* typeStruct = m_deviceTypeList.GetNext(pos); m_deviceTypeMap->add(typeStruct->getName(),typeStruct); } }
TypeStruct& CDeviceTypeDirectory::getDefinedType(const CString& deviceName) { TypeStruct* typeStruct = getType(deviceName); if (typeStruct == NULL) { typeStruct = m_deviceTypeList.addType(deviceName,m_camCadData.allocateEntityNumber()); typeStruct->setBlockNumber( -1); // no name assigned getDeviceTypeMap().add(deviceName,typeStruct); } return *typeStruct; }
// does not copy the CTypePinList TypeStruct::TypeStruct(const TypeStruct& other,int entityNumber) : m_parentList(other.m_parentList) , m_attributes(NULL) , m_blockNumber(other.getBlockNumber()) , m_entityNumber(entityNumber) , m_name(other.getName()) , m_typePinList(*this) { if (m_entityNumber < 0) { m_entityNumber = getCamCadData().allocateEntityNumber(); } if (other.getAttributes() != NULL) { attributes() = *(other.getAttributes()); } }
void CDeviceTypeDirectory::deleteAt(POSITION pos) { TypeStruct* listTypeStruct = getAt(pos); if (m_deviceTypeMap != NULL) { TypeStruct* mapTypeStruct = getDeviceTypeMap().getAt(listTypeStruct->getName()); // If the map contains a different TypeStruct, no need to deallocate map. // If the map contains this TypeStruct, deallocate it so that when it is rebuilt, another TypeStruct with the same name // will be put into the map. if (mapTypeStruct == listTypeStruct) { deallocateMap(); } } m_deviceTypeList.deleteAt(pos); }
TypeStruct* CDeviceTypeList::findType(const CString& name) const { TypeStruct* typeStruct = NULL; for (POSITION pos = m_typeList.GetHeadPosition();;) { if (pos == NULL) { typeStruct = NULL; break; } typeStruct = m_typeList.GetNext(pos); if (typeStruct->getName().Compare(name) == 0) { break; } } return typeStruct; }
void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); unsigned offset = Type::typeinfostruct->structsize; dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; /* Put out: * char[] name; * void[] init; * hash_t function(in void*) xtoHash; * bool function(in void*, in void*) xopEquals; * int function(in void*, in void*) xopCmp; * string function(const(void)*) xtoString; * uint m_flags; * xgetMembers; * xdtor; * xpostblit; * uint m_align; * version (X86_64) * TypeInfo m_arg1; * TypeInfo m_arg2; * * name[] */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); //dtabytes(pdt, TYnptr, 0, namelen + 1, name); dtxoff(pdt, toSymbol(), offset, TYnptr); offset += namelen + 1; // void[] init; dtsize_t(pdt, sd->structsize); // init.length if (sd->zeroInit) dtsize_t(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr FuncDeclaration *fd; FuncDeclaration *fdx; TypeFunction *tf; Type *ta; Dsymbol *s; static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash->mod = MODconst; tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->invariantOf()->arrayOf(), 0, LINKd); tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfcmpptr; { Scope sc; Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfcmpptr->mod = MODconst; tfcmpptr = (TypeFunction *)tfcmpptr->semantic(0, &sc); } s = search_function(sd, Id::tohash); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) uint toHash()"); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); if (sd->eq) dtxoff(pdt, sd->eq->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { //printf("test1 %s, %s, %s\n", fdx->toChars(), fdx->type->toChars(), tfeqptr->toChars()); fd = fdx->overloadExactMatch(tfcmpptr); if (fd) { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); //printf("test2\n"); } else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftostring); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) char[] toString()"); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); // uint m_flags; dtsize_t(pdt, tc->hasPointers()); #if DMDV2 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xgetMembers // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit && !(spostblit->storage_class & STCdisable)) dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xpostblit #endif // uint m_align; dtsize_t(pdt, tc->alignsize()); if (global.params.is64bit) { TypeTuple *tup = tc->toArgTypes(); assert(tup->arguments->dim <= 2); for (int i = 0; i < 2; i++) { if (i < tup->arguments->dim) { Type *targ = (tup->arguments->tdata()[i])->type; targ = targ->merge(); targ->getTypeInfo(NULL); dtxoff(pdt, targ->vtinfo->toSymbol(), 0, TYnptr); // m_argi } else dtsize_t(pdt, 0); // m_argi } } // name[] dtnbytes(pdt, namelen + 1, name); }
LLType* DtoType(Type* t) { t = stripModifiers( t ); if (t->ctype) { return t->ctype->getLLType(); } IF_LOG Logger::println("Building type: %s", t->toChars()); LOG_SCOPE; assert(t); switch (t->ty) { // basic types case Tvoid: case Tint8: case Tuns8: case Tint16: case Tuns16: case Tint32: case Tuns32: case Tint64: case Tuns64: case Tint128: case Tuns128: case Tfloat32: case Tfloat64: case Tfloat80: case Timaginary32: case Timaginary64: case Timaginary80: case Tcomplex32: case Tcomplex64: case Tcomplex80: //case Tbit: case Tbool: case Tchar: case Twchar: case Tdchar: { return IrTypeBasic::get(t)->getLLType(); } // pointers case Tnull: case Tpointer: { return IrTypePointer::get(t)->getLLType(); } // arrays case Tarray: { return IrTypeArray::get(t)->getLLType(); } case Tsarray: { return IrTypeSArray::get(t)->getLLType(); } // aggregates case Tstruct: { TypeStruct* ts = static_cast<TypeStruct*>(t); if (ts->sym->type->ctype) { // This should not happen, but the frontend seems to be buggy. Not // sure if this is the best way to handle the situation, but we // certainly don't want to override ts->sym->type->ctype. IF_LOG Logger::cout() << "Struct with multiple Types detected: " << ts->toChars() << " (" << ts->sym->locToChars() << ")" << std::endl; return ts->sym->type->ctype->getLLType(); } return IrTypeStruct::get(ts->sym)->getLLType(); } case Tclass: { TypeClass* tc = static_cast<TypeClass*>(t); if (tc->sym->type->ctype) { // See Tstruct case. IF_LOG Logger::cout() << "Class with multiple Types detected: " << tc->toChars() << " (" << tc->sym->locToChars() << ")" << std::endl; return tc->sym->type->ctype->getLLType(); } return IrTypeClass::get(tc->sym)->getLLType(); } // functions case Tfunction: { return IrTypeFunction::get(t)->getLLType(); } // delegates case Tdelegate: { return IrTypeDelegate::get(t)->getLLType(); } // typedefs // enum // FIXME: maybe just call toBasetype first ? case Tenum: { Type* bt = t->toBasetype(); assert(bt); return DtoType(bt); } // associative arrays case Taarray: return getVoidPtrType(); case Tvector: { return IrTypeVector::get(t)->getLLType(); } /* Not needed atm as VarDecls for tuples are rewritten as a string of VarDecls for the fields (u -> _u_field_0, ...) case Ttuple: { TypeTuple* ttupl = static_cast<TypeTuple*>(t); return DtoStructTypeFromArguments(ttupl->arguments); } */ default: llvm_unreachable("Unknown class of D Type!"); } return 0; }
void VarDeclaration::semantic(Scope *sc) { #if 0 printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); printf(" type = %s\n", type ? type->toChars() : "null"); printf(" stc = x%x\n", sc->stc); printf(" storage_class = x%x\n", storage_class); printf("linkage = %d\n", sc->linkage); //if (strcmp(toChars(), "mul") == 0) halt(); #endif storage_class |= sc->stc; if (storage_class & STCextern && init) error("extern symbols cannot have initializers"); AggregateDeclaration *ad = isThis(); if (ad) storage_class |= ad->storage_class & STC_TYPECTOR; /* If auto type inference, do the inference */ int inferred = 0; if (!type) { inuse++; type = init->inferType(sc); inuse--; inferred = 1; /* This is a kludge to support the existing syntax for RAII * declarations. */ storage_class &= ~STCauto; originalType = type; } else { if (!originalType) originalType = type; type = type->semantic(loc, sc); } //printf(" semantic type = %s\n", type ? type->toChars() : "null"); type->checkDeprecated(loc, sc); linkage = sc->linkage; this->parent = sc->parent; //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); protection = sc->protection; //printf("sc->stc = %x\n", sc->stc); //printf("storage_class = x%x\n", storage_class); #if DMDV2 if (storage_class & STCgshared && global.params.safe && !sc->module->safe) { error("__gshared not allowed in safe mode; use shared"); } #endif Dsymbol *parent = toParent(); FuncDeclaration *fd = parent->isFuncDeclaration(); Type *tb = type->toBasetype(); if (tb->ty == Tvoid && !(storage_class & STClazy)) { error("voids have no value"); type = Type::terror; tb = type; } if (tb->ty == Tfunction) { error("cannot be declared to be a function"); type = Type::terror; tb = type; } if (tb->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tb; if (!ts->sym->members) { error("no definition of struct %s", ts->toChars()); } } if ((storage_class & STCauto) && !inferred) error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?"); if (tb->ty == Ttuple) { /* Instead, declare variables for each of the tuple elements * and add those. */ TypeTuple *tt = (TypeTuple *)tb; size_t nelems = Parameter::dim(tt->arguments); Objects *exps = new Objects(); exps->setDim(nelems); Expression *ie = init ? init->toExpression() : NULL; for (size_t i = 0; i < nelems; i++) { Parameter *arg = Parameter::getNth(tt->arguments, i); OutBuffer buf; buf.printf("_%s_field_%zu", ident->toChars(), i); buf.writeByte(0); const char *name = (const char *)buf.extractData(); Identifier *id = Lexer::idPool(name); Expression *einit = ie; if (ie && ie->op == TOKtuple) { einit = (Expression *)((TupleExp *)ie)->exps->data[i]; } Initializer *ti = init; if (einit) { ti = new ExpInitializer(einit->loc, einit); } VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); v->semantic(sc); #if !IN_LLVM // removed for LDC since TupleDeclaration::toObj already creates the fields; // adding them to the scope again leads to duplicates if (sc->scopesym) { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); if (sc->scopesym->members) sc->scopesym->members->push(v); } #endif Expression *e = new DsymbolExp(loc, v); exps->data[i] = e; } TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); v2->isexp = 1; aliassym = v2; return; } if (storage_class & STCconst && !init && !fd) // Initialize by constructor only storage_class = (storage_class & ~STCconst) | STCctorinit; if (isConst()) { } else if (isStatic()) { } else if (isSynchronized()) { error("variable %s cannot be synchronized", toChars()); } else if (isOverride()) { error("override cannot be applied to variable"); } else if (isAbstract()) { error("abstract cannot be applied to variable"); } else if (storage_class & STCtemplateparameter) { } else if (storage_class & STCctfe) { } else { AggregateDeclaration *aad = sc->anonAgg; if (!aad) aad = parent->isAggregateDeclaration(); if (aad) { #if DMDV2 assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); if (storage_class & (STCconst | STCimmutable) && init) { if (!type->toBasetype()->isTypeBasic()) storage_class |= STCstatic; } else #endif aad->addField(sc, this); } InterfaceDeclaration *id = parent->isInterfaceDeclaration(); if (id) { error("field not allowed in interface"); } /* Templates cannot add fields to aggregates */ TemplateInstance *ti = parent->isTemplateInstance(); if (ti) { // Take care of nested templates while (1) { TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); if (!ti2) break; ti = ti2; } // If it's a member template AggregateDeclaration *ad = ti->tempdecl->isMember(); if (ad && storage_class != STCundefined) { error("cannot use template to add field to aggregate '%s'", ad->toChars()); } } } #if DMDV2 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && ident != Id::This) { error("only parameters or foreach declarations can be ref"); } #endif if (type->isscope() && !noscope) { if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) { error("globals, statics, fields, ref and out parameters cannot be auto"); } if (!(storage_class & STCscope)) { if (!(storage_class & STCparameter) && ident != Id::withSym) error("reference to scope class must be scope"); } } enum TOK op = TOKconstruct; if (!init && !sc->inunion && !isStatic() && !isConst() && fd && !(storage_class & (STCfield | STCin | STCforeach)) && type->size() != 0) { // Provide a default initializer //printf("Providing default initializer for '%s'\n", toChars()); if (type->ty == Tstruct && ((TypeStruct *)type)->sym->zeroInit == 1) { /* If a struct is all zeros, as a special case * set it's initializer to the integer 0. * In AssignExp::toElem(), we check for this and issue * a memset() to initialize the struct. * Must do same check in interpreter. */ Expression *e = new IntegerExp(loc, 0, Type::tint32); Expression *e1; e1 = new VarExp(loc, this); e = new AssignExp(loc, e1, e); e->op = TOKconstruct; e->type = e1->type; // don't type check this, it would fail init = new ExpInitializer(loc, e); return; } else if (type->ty == Ttypedef) { TypeTypedef *td = (TypeTypedef *)type; if (td->sym->init) { init = td->sym->init; ExpInitializer *ie = init->isExpInitializer(); if (ie) // Make copy so we can modify it init = new ExpInitializer(ie->loc, ie->exp); } else init = getExpInitializer(); } else { init = getExpInitializer(); } // Default initializer is always a blit op = TOKblit; } if (init) { sc = sc->push(); sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref); ArrayInitializer *ai = init->isArrayInitializer(); if (ai && tb->ty == Taarray) { init = ai->toAssocArrayInitializer(); } StructInitializer *si = init->isStructInitializer(); ExpInitializer *ei = init->isExpInitializer(); // See if initializer is a NewExp that can be allocated on the stack if (ei && isScope() && ei->exp->op == TOKnew) { NewExp *ne = (NewExp *)ei->exp; if (!(ne->newargs && ne->newargs->dim)) { ne->onstack = 1; onstack = 1; if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) onstack = 2; } } // If inside function, there is no semantic3() call if (sc->func) { // If local variable, use AssignExp to handle all the various // possibilities. if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) { //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); if (!ei) { Expression *e = init->toExpression(); if (!e) { init = init->semantic(sc, type); e = init->toExpression(); if (!e) { error("is not a static and cannot have static initializer"); return; } } ei = new ExpInitializer(init->loc, e); init = ei; } Expression *e1 = new VarExp(loc, this); Type *t = type->toBasetype(); if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) { ei->exp = ei->exp->semantic(sc); if (!ei->exp->implicitConvTo(type)) { int dim = ((TypeSArray *)t)->dim->toInteger(); // If multidimensional static array, treat as one large array while (1) { t = t->nextOf()->toBasetype(); if (t->ty != Tsarray) break; dim *= ((TypeSArray *)t)->dim->toInteger(); e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); } } e1 = new SliceExp(loc, e1, NULL, NULL); } else if (t->ty == Tstruct) { ei->exp = ei->exp->semantic(sc); ei->exp = resolveProperties(sc, ei->exp); StructDeclaration *sd = ((TypeStruct *)t)->sym; #if DMDV2 /* Look to see if initializer is a call to the constructor */ if (sd->ctor && // there are constructors ei->exp->type->ty == Tstruct && // rvalue is the same struct ((TypeStruct *)ei->exp->type)->sym == sd && ei->exp->op == TOKstar) { /* Look for form of constructor call which is: * *__ctmp.ctor(arguments...) */ PtrExp *pe = (PtrExp *)ei->exp; if (pe->e1->op == TOKcall) { CallExp *ce = (CallExp *)pe->e1; if (ce->e1->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)ce->e1; if (dve->var->isCtorDeclaration()) { /* It's a constructor call, currently constructing * a temporary __ctmp. */ /* Before calling the constructor, initialize * variable with a bit copy of the default * initializer */ Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc)); e->op = TOKblit; e->type = t; ei->exp = new CommaExp(loc, e, ei->exp); /* Replace __ctmp being constructed with e1 */ dve->e1 = e1; return; } } } } #endif if (!ei->exp->implicitConvTo(type)) { /* Look for opCall * See bugzilla 2702 for more discussion */ Type *ti = ei->exp->type->toBasetype(); // Don't cast away invariant or mutability in initializer if (search_function(sd, Id::call) && /* Initializing with the same type is done differently */ !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) { // Rewrite as e1.call(arguments) Expression * eCall = new DotIdExp(loc, e1, Id::call); ei->exp = new CallExp(loc, eCall, ei->exp); } } } ei->exp = new AssignExp(loc, e1, ei->exp); ei->exp->op = TOKconstruct; canassign++; ei->exp = ei->exp->semantic(sc); canassign--; ei->exp->optimize(WANTvalue); } else { init = init->semantic(sc, type); if (fd && isConst() && !isStatic()) { // Make it static storage_class |= STCstatic; } } } else if (isConst() || isFinal() || parent->isAggregateDeclaration()) { /* Because we may need the results of a const declaration in a * subsequent type, such as an array dimension, before semantic2() * gets ordinarily run, try to run semantic2() now. * Ignore failure. */ if (!global.errors && !inferred) { unsigned errors = global.errors; global.gag++; //printf("+gag\n"); Expression *e; Initializer *i2 = init; inuse++; if (ei) { e = ei->exp->syntaxCopy(); e = e->semantic(sc); e = e->implicitCastTo(sc, type); } else if (si || ai) { i2 = init->syntaxCopy(); i2 = i2->semantic(sc, type); } inuse--; global.gag--; //printf("-gag\n"); if (errors != global.errors) // if errors happened { if (global.gag == 0) global.errors = errors; // act as if nothing happened #if DMDV2 /* Save scope for later use, to try again */ scope = new Scope(*sc); scope->setNoFree(); #endif } else if (ei) { if (isDataseg() || (storage_class & STCmanifest)) e = e->optimize(WANTvalue | WANTinterpret); else e = e->optimize(WANTvalue); switch (e->op) { case TOKint64: case TOKfloat64: case TOKstring: case TOKarrayliteral: case TOKassocarrayliteral: case TOKstructliteral: case TOKnull: ei->exp = e; // no errors, keep result break; default: #if DMDV2 /* Save scope for later use, to try again */ scope = new Scope(*sc); scope->setNoFree(); #endif break; } } else init = i2; // no errors, keep result } } sc = sc->pop(); } }
void TypeInfoStructDeclaration::llvmDefine() { Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars()); LOG_SCOPE; // make sure struct is resolved assert(tinfo->ty == Tstruct); TypeStruct *tc = static_cast<TypeStruct *>(tinfo); StructDeclaration *sd = tc->sym; // can't emit typeinfo for forward declarations if (sd->sizeok != 1) { sd->error("cannot emit TypeInfo for forward declaration"); fatal(); } sd->codegen(Type::sir); IrStruct* irstruct = sd->ir.irStruct; RTTIBuilder b(Type::typeinfostruct); // char[] name b.push_string(sd->toPrettyChars()); // void[] init // never emit a null array, even for zero initialized typeinfo // the size() method uses this array! size_t init_size = getTypeStoreSize(tc->irtype->getType()); b.push_void_array(init_size, irstruct->getInitSymbol()); // toX functions ground work static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); #if DMDV2 tftohash ->mod = MODconst; #endif tftohash = static_cast<TypeFunction *>(tftohash->semantic(0, &sc)); #if DMDV2 Type *retType = Type::tchar->invariantOf()->arrayOf(); #else Type *retType = Type::tchar->arrayOf(); #endif tftostring = new TypeFunction(NULL, retType, 0, LINKd); tftostring = static_cast<TypeFunction *>(tftostring->semantic(0, &sc)); } // this one takes a parameter, so we need to build a new one each time // to get the right type. can we avoid this? TypeFunction *tfcmpptr; { Scope sc; Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); #if DMDV2 tfcmpptr->mod = MODconst; #endif tfcmpptr = static_cast<TypeFunction *>(tfcmpptr->semantic(0, &sc)); } // well use this module for all overload lookups Module *gm = getModule(); // toHash FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash, gm); b.push_funcptr(fd); // opEquals #if DMDV2 fd = sd->xeq; #else fd = find_method_overload(sd, Id::eq, tfcmpptr, gm); #endif b.push_funcptr(fd); // opCmp fd = find_method_overload(sd, Id::cmp, tfcmpptr, gm); b.push_funcptr(fd); // toString fd = find_method_overload(sd, Id::tostring, tftostring, gm); b.push_funcptr(fd); // uint m_flags; unsigned hasptrs = tc->hasPointers() ? 1 : 0; b.push_uint(hasptrs); #if DMDV2 ClassDeclaration* tscd = Type::typeinfostruct; assert((!global.params.is64bit && tscd->fields.dim == 11) || (global.params.is64bit && tscd->fields.dim == 13)); //void function(void*) xdtor; b.push_funcptr(sd->dtor); //void function(void*) xpostblit; FuncDeclaration *xpostblit = sd->postblit; if (xpostblit && sd->postblit->storage_class & STCdisable) xpostblit = 0; b.push_funcptr(xpostblit); //uint m_align; b.push_uint(tc->alignsize()); if (global.params.is64bit) { // TypeInfo m_arg1; // TypeInfo m_arg2; TypeTuple *tup = tc->toArgTypes(); assert(tup->arguments->dim <= 2); for (unsigned i = 0; i < 2; i++) { if (i < tup->arguments->dim) { Type *targ = static_cast<Parameter *>(tup->arguments->data[i])->type; targ = targ->merge(); b.push_typeinfo(targ); } else b.push_null(Type::typeinfo->type); } } // immutable(void)* m_RTInfo; // The cases where getRTInfo is null are not quite here, but the code is // modelled after what DMD does. if (sd->getRTInfo) b.push(sd->getRTInfo->toConstElem(gIR)); else if (!tc->hasPointers()) b.push_size_as_vp(0); // no pointers else b.push_size_as_vp(1); // has pointers #endif // finish b.finalize(ir.irGlobal); }
void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); if (global.params.is64bit) verifyStructSize(Type::typeinfostruct, 17 * PTRSIZE); else verifyStructSize(Type::typeinfostruct, 15 * PTRSIZE); dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; /* Put out: * char[] name; * void[] init; * hash_t function(in void*) xtoHash; * bool function(in void*, in void*) xopEquals; * int function(in void*, in void*) xopCmp; * string function(const(void)*) xtoString; * uint m_flags; * //xgetMembers; * xdtor; * xpostblit; * uint m_align; * version (X86_64) * TypeInfo m_arg1; * TypeInfo m_arg2; * xgetRTInfo */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; dtsize_t(pdt, sd->structsize); // init.length if (sd->zeroInit) dtsize_t(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr FuncDeclaration *fd; FuncDeclaration *fdx; Dsymbol *s; static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; /* const hash_t toHash(); */ tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash->mod = MODconst; tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->invariantOf()->arrayOf(), 0, LINKd); tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfcmpptr; { Scope sc; /* const int opCmp(ref const KeyType s); */ Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfcmpptr->mod = MODconst; tfcmpptr = (TypeFunction *)tfcmpptr->semantic(0, &sc); } s = search_function(sd, Id::tohash); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); TypeFunction *tf = (TypeFunction *)fd->type; assert(tf->ty == Tfunction); /* I'm a little unsure this is the right way to do it. Perhaps a better * way would to automatically add these attributes to any struct member * function with the name "toHash". * So I'm leaving this here as an experiment for the moment. */ if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/) warning(fd->loc, "toHash() must be declared as extern (D) size_t toHash() const nothrow @safe, not %s", tf->toChars()); } else { //fdx->error("must be declared as extern (D) uint toHash()"); dtsize_t(pdt, 0); } } else dtsize_t(pdt, 0); if (sd->xeq) dtxoff(pdt, sd->xeq->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { //printf("test1 %s, %s, %s\n", fdx->toChars(), fdx->type->toChars(), tfeqptr->toChars()); fd = fdx->overloadExactMatch(tfcmpptr); if (fd) { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); //printf("test2\n"); } else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftostring); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) char[] toString()"); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); // uint m_flags; size_t m_flags = tc->hasPointers(); dtsize_t(pdt, m_flags); #if DMDV2 #if 0 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xgetMembers #endif // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit && !(spostblit->storage_class & STCdisable)) dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xpostblit #endif // uint m_align; dtsize_t(pdt, tc->alignsize()); if (global.params.is64bit) { Type *t = sd->arg1type; for (int i = 0; i < 2; i++) { // m_argi if (t) { t->getTypeInfo(NULL); dtxoff(pdt, t->vtinfo->toSymbol(), 0, TYnptr); } else dtsize_t(pdt, 0); t = sd->arg2type; } } // xgetRTInfo if (sd->getRTInfo) sd->getRTInfo->toDt(pdt); else if (m_flags) dtsize_t(pdt, 1); // has pointers else dtsize_t(pdt, 0); // no pointers }
void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); unsigned offset = Type::typeinfostruct->structsize; dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtdword(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; /* Put out: * char[] name; * void[] init; * hash_t function(void*) xtoHash; * int function(void*,void*) xopEquals; * int function(void*,void*) xopCmp; * char[] function(void*) xtoString; * uint m_flags; * * name[] */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); //dtabytes(pdt, TYnptr, 0, namelen + 1, name); dtxoff(pdt, toSymbol(), offset, TYnptr); offset += namelen + 1; // void[] init; dtdword(pdt, sd->structsize); // init.length if (sd->zeroInit) dtdword(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr FuncDeclaration *fd; FuncDeclaration *fdx; TypeFunction *tf; Type *ta; Dsymbol *s; static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfeqptr; { Scope sc; Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); } #if 0 TypeFunction *tfeq; { Scope sc; Array *arguments = new Array; Parameter *arg = new Parameter(In, tc, NULL, NULL); arguments->push(arg); tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfeq = (TypeFunction *)tfeq->semantic(0, &sc); } #endif s = search_function(sd, Id::tohash); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) uint toHash()"); dtdword(pdt, 0); } else dtdword(pdt, 0); s = search_function(sd, Id::eq); fdx = s ? s->isFuncDeclaration() : NULL; for (int i = 0; i < 2; i++) { if (fdx) { fd = fdx->overloadExactMatch(tfeqptr); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtdword(pdt, 0); } else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtdword(pdt, 0); s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; } s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftostring); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) char[] toString()"); dtdword(pdt, 0); } else dtdword(pdt, 0); // uint m_flags; dtdword(pdt, tc->hasPointers()); #if DMDV2 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xgetMembers // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit) dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr); else dtdword(pdt, 0); // xpostblit #endif // name[] dtnbytes(pdt, namelen + 1, name); }
void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); if (global.params.is64bit) verifyStructSize(Type::typeinfostruct, 17 * Target::ptrsize); else verifyStructSize(Type::typeinfostruct, 15 * Target::ptrsize); dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0); // vtbl for TypeInfo_Struct dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; if (!sd->members) return; /* Put out: * char[] name; * void[] init; * hash_t function(in void*) xtoHash; * bool function(in void*, in void*) xopEquals; * int function(in void*, in void*) xopCmp; * string function(const(void)*) xtoString; * StructFlags m_flags; * //xgetMembers; * xdtor; * xpostblit; * uint m_align; * version (X86_64) * TypeInfo m_arg1; * TypeInfo m_arg2; * xgetRTInfo */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, 0, namelen + 1, name); // void[] init; dtsize_t(pdt, sd->structsize); // init.length if (sd->zeroInit) dtsize_t(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0); // init.ptr if (FuncDeclaration *fd = search_toHash(sd)) { dtxoff(pdt, fd->toSymbol(), 0); TypeFunction *tf = (TypeFunction *)fd->type; assert(tf->ty == Tfunction); /* I'm a little unsure this is the right way to do it. Perhaps a better * way would to automatically add these attributes to any struct member * function with the name "toHash". * So I'm leaving this here as an experiment for the moment. */ if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/) warning(fd->loc, "toHash() must be declared as extern (D) size_t toHash() const nothrow @safe, not %s", tf->toChars()); } else dtsize_t(pdt, 0); if (sd->xeq) dtxoff(pdt, sd->xeq->toSymbol(), 0); else dtsize_t(pdt, 0); if (sd->xcmp) dtxoff(pdt, sd->xcmp->toSymbol(), 0); else dtsize_t(pdt, 0); if (FuncDeclaration *fd = search_toString(sd)) { dtxoff(pdt, fd->toSymbol(), 0); } else dtsize_t(pdt, 0); // StructFlags m_flags; StructFlags::Type m_flags = 0; if (tc->hasPointers()) m_flags |= StructFlags::hasPointers; dtsize_t(pdt, m_flags); #if DMDV2 #if 0 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0); else dtsize_t(pdt, 0); // xgetMembers #endif // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0); else dtsize_t(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit && !(spostblit->storage_class & STCdisable)) dtxoff(pdt, spostblit->toSymbol(), 0); else dtsize_t(pdt, 0); // xpostblit #endif // uint m_align; dtsize_t(pdt, tc->alignsize()); if (global.params.is64bit) { Type *t = sd->arg1type; for (int i = 0; i < 2; i++) { // m_argi if (t) { t->getTypeInfo(NULL); dtxoff(pdt, t->vtinfo->toSymbol(), 0); } else dtsize_t(pdt, 0); t = sd->arg2type; } } // xgetRTInfo if (sd->getRTInfo) sd->getRTInfo->toDt(pdt); else if (m_flags & StructFlags::hasPointers) dtsize_t(pdt, 1); else dtsize_t(pdt, 0); }
LLType *DtoType(Type *t) { t = stripModifiers(t); if (t->ctype) { return t->ctype->getLLType(); } IF_LOG Logger::println("Building type: %s", t->toChars()); LOG_SCOPE; assert(t); switch (t->ty) { // basic types case Tvoid: case Tint8: case Tuns8: case Tint16: case Tuns16: case Tint32: case Tuns32: case Tint64: case Tuns64: case Tint128: case Tuns128: case Tfloat32: case Tfloat64: case Tfloat80: case Timaginary32: case Timaginary64: case Timaginary80: case Tcomplex32: case Tcomplex64: case Tcomplex80: // case Tbit: case Tbool: case Tchar: case Twchar: case Tdchar: { return IrTypeBasic::get(t)->getLLType(); } // pointers case Tnull: case Tpointer: case Treference: { // CALYPSO return IrTypePointer::get(t)->getLLType(); } // arrays case Tarray: { return IrTypeArray::get(t)->getLLType(); } case Tsarray: { return IrTypeSArray::get(t)->getLLType(); } // aggregates case Tstruct: { TypeStruct *ts = static_cast<TypeStruct *>(t); if (ts->sym->type->ctype) { // This should not happen, but the frontend seems to be buggy. Not // sure if this is the best way to handle the situation, but we // certainly don't want to override ts->sym->type->ctype. IF_LOG Logger::cout() << "Struct with multiple Types detected: " << ts->toChars() << " (" << ts->sym->locToChars() << ")" << std::endl; return ts->sym->type->ctype->getLLType(); } return IrTypeStruct::get(ts->sym)->getLLType(); } case Tclass: { TypeClass *tc = static_cast<TypeClass *>(t); if (tc->sym->type->ctype) { // See Tstruct case. IF_LOG Logger::cout() << "Class with multiple Types detected: " << tc->toChars() << " (" << tc->sym->locToChars() << ")" << std::endl; return tc->sym->type->ctype->getLLType(); } return IrTypeClass::get(tc->sym)->getLLType(); } // functions case Tfunction: { return IrTypeFunction::get(t)->getLLType(); } // delegates case Tdelegate: { return IrTypeDelegate::get(t)->getLLType(); } // typedefs // enum // FIXME: maybe just call toBasetype first ? case Tenum: { Type *bt = t->toBasetype(); assert(bt); if (t == bt) { // This is an enum forward reference that is only legal when referenced // through an indirection (e.g. "enum E; void foo(E* p);"). For lack of a // better choice, make the outer indirection a void pointer. return getVoidPtrType()->getContainedType(0); } return DtoType(bt); } // associative arrays case Taarray: return getVoidPtrType(); case Tvector: { return IrTypeVector::get(t)->getLLType(); } default: llvm_unreachable("Unknown class of D Type!"); } return nullptr; }
void visit(TypeInfoStructDeclaration *decl) override { IF_LOG Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", decl->toChars()); LOG_SCOPE; // make sure struct is resolved assert(decl->tinfo->ty == Tstruct); TypeStruct *tc = static_cast<TypeStruct *>(decl->tinfo); StructDeclaration *sd = tc->sym; // check declaration in object.d const auto structTypeInfoType = getStructTypeInfoType(); const auto structTypeInfoDecl = Type::typeinfostruct; // On x86_64, class TypeInfo_Struct contains 2 additional fields // (m_arg1/m_arg2) which are used for the X86_64 System V ABI varargs // implementation. They are not present on any other cpu/os. const bool isX86_64 = global.params.targetTriple->getArch() == llvm::Triple::x86_64; const unsigned expectedFields = 11 + (isX86_64 ? 2 : 0); const unsigned actualFields = structTypeInfoDecl->fields.dim - 1; // union of xdtor/xdtorti counts as 2 overlapping fields if (actualFields != expectedFields) { error(Loc(), "Unexpected number of `object.TypeInfo_Struct` fields; " "druntime version does not match compiler"); fatal(); } RTTIBuilder b(structTypeInfoType); // handle opaque structs if (!sd->members) { Logger::println("is opaque struct, emitting dummy TypeInfo_Struct"); b.push_null_void_array(); // name b.push_null_void_array(); // m_init b.push_null_vp(); // xtoHash b.push_null_vp(); // xopEquals b.push_null_vp(); // xopCmp b.push_null_vp(); // xtoString b.push_uint(0); // m_flags b.push_null_vp(); // xdtor/xdtorti b.push_null_vp(); // xpostblit b.push_uint(0); // m_align if (isX86_64) { b.push_null_vp(); // m_arg1 b.push_null_vp(); // m_arg2 } b.push_null_vp(); // m_RTInfo b.finalize(gvar); return; } // can't emit typeinfo for forward declarations if (sd->sizeok != SIZEOKdone) { sd->error("cannot emit `TypeInfo` for forward declaration"); fatal(); } DtoResolveStruct(sd); if (TemplateInstance *ti = sd->isInstantiated()) { if (!ti->needsCodegen()) { assert(ti->minst || sd->requestTypeInfo); // We won't emit ti, so emit the special member functions in here. if (sd->xeq && sd->xeq != StructDeclaration::xerreq && sd->xeq->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->xeq); } if (sd->xcmp && sd->xcmp != StructDeclaration::xerrcmp && sd->xcmp->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->xcmp); } if (FuncDeclaration *ftostr = search_toString(sd)) { if (ftostr->semanticRun >= PASSsemantic3) Declaration_codegen(ftostr); } if (sd->xhash && sd->xhash->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->xhash); } if (sd->postblit && sd->postblit->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->postblit); } if (sd->dtor && sd->dtor->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->dtor); } if (sd->tidtor && sd->tidtor->semanticRun >= PASSsemantic3) { Declaration_codegen(sd->tidtor); } } } IrAggr *iraggr = getIrAggr(sd); // string name b.push_string(sd->toPrettyChars()); // void[] m_init // The protocol is to write a null pointer for zero-initialized arrays. The // length field is always needed for tsize(). llvm::Constant *initPtr; if (tc->isZeroInit(Loc())) { initPtr = getNullValue(getVoidPtrType()); } else { initPtr = iraggr->getInitSymbol(); } b.push_void_array(getTypeStoreSize(DtoType(tc)), initPtr); // function xtoHash FuncDeclaration *fd = sd->xhash; b.push_funcptr(fd); // function xopEquals fd = sd->xeq; b.push_funcptr(fd); // function xopCmp fd = sd->xcmp; b.push_funcptr(fd); // function xtoString fd = search_toString(sd); b.push_funcptr(fd); // uint m_flags unsigned hasptrs = tc->hasPointers() ? 1 : 0; b.push_uint(hasptrs); // function xdtor/xdtorti b.push_funcptr(sd->tidtor); // function xpostblit FuncDeclaration *xpostblit = sd->postblit; if (xpostblit && sd->postblit->storage_class & STCdisable) { xpostblit = nullptr; } b.push_funcptr(xpostblit); // uint m_align b.push_uint(DtoAlignment(tc)); if (isX86_64) { // TypeInfo m_arg1 // TypeInfo m_arg2 Type *t = sd->arg1type; for (unsigned i = 0; i < 2; i++) { if (t) { t = merge(t); b.push_typeinfo(t); } else { b.push_null(getTypeInfoType()); } t = sd->arg2type; } } // immutable(void)* m_RTInfo // The cases where getRTInfo is null are not quite here, but the code is // modelled after what DMD does. if (sd->getRTInfo) { b.push(toConstElem(sd->getRTInfo, gIR)); } else if (!tc->hasPointers()) { b.push_size_as_vp(0); // no pointers } else { b.push_size_as_vp(1); // has pointers } // finish b.finalize(gvar); }
void visit(TypeInfoStructDeclaration *decl) { IF_LOG Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", decl->toChars()); LOG_SCOPE; // make sure struct is resolved assert(decl->tinfo->ty == Tstruct); TypeStruct *tc = static_cast<TypeStruct *>(decl->tinfo); StructDeclaration *sd = tc->sym; // handle opaque structs if (!sd->members) { RTTIBuilder b(Type::typeinfostruct); b.finalize(getIrGlobal(decl)); return; } // can't emit typeinfo for forward declarations if (sd->sizeok != SIZEOKdone) { sd->error("cannot emit TypeInfo for forward declaration"); fatal(); } DtoResolveStruct(sd); IrAggr* iraggr = getIrAggr(sd); RTTIBuilder b(Type::typeinfostruct); // char[] name b.push_string(sd->toPrettyChars()); // void[] init // The protocol is to write a null pointer for zero-initialized arrays. The // length field is always needed for tsize(). llvm::Constant *initPtr; if (tc->isZeroInit(Loc())) initPtr = getNullValue(getVoidPtrType()); else initPtr = iraggr->getInitSymbol(); b.push_void_array(getTypeStoreSize(DtoType(tc)), initPtr); // well use this module for all overload lookups // toHash FuncDeclaration* fd = sd->xhash; b.push_funcptr(fd); // opEquals fd = sd->xeq; b.push_funcptr(fd); // opCmp fd = sd->xcmp; b.push_funcptr(fd); // toString fd = search_toString(sd); b.push_funcptr(fd); // uint m_flags; unsigned hasptrs = tc->hasPointers() ? 1 : 0; b.push_uint(hasptrs); // On x86_64, class TypeInfo_Struct contains 2 additional fields // (m_arg1/m_arg2) which are used for the X86_64 System V ABI varargs // implementation. They are not present on any other cpu/os. assert((global.params.targetTriple.getArch() != llvm::Triple::x86_64 && Type::typeinfostruct->fields.dim == 11) || (global.params.targetTriple.getArch() == llvm::Triple::x86_64 && Type::typeinfostruct->fields.dim == 13)); //void function(void*) xdtor; b.push_funcptr(sd->dtor); //void function(void*) xpostblit; FuncDeclaration *xpostblit = sd->postblit; if (xpostblit && sd->postblit->storage_class & STCdisable) xpostblit = 0; b.push_funcptr(xpostblit); //uint m_align; b.push_uint(tc->alignsize()); if (global.params.is64bit) { // TypeInfo m_arg1; // TypeInfo m_arg2; Type *t = sd->arg1type; for (unsigned i = 0; i < 2; i++) { if (t) { t = t->merge(); b.push_typeinfo(t); } else b.push_null(Type::dtypeinfo->type); t = sd->arg2type; } } // immutable(void)* m_RTInfo; // The cases where getRTInfo is null are not quite here, but the code is // modelled after what DMD does. if (sd->getRTInfo) b.push(toConstElem(sd->getRTInfo, gIR)); else if (!tc->hasPointers()) b.push_size_as_vp(0); // no pointers else b.push_size_as_vp(1); // has pointers // finish b.finalize(getIrGlobal(decl)); }