void visit(TypeInfoEnumDeclaration *decl) override { IF_LOG Logger::println("TypeInfoEnumDeclaration::llvmDefine() %s", decl->toChars()); LOG_SCOPE; RTTIBuilder b(getEnumTypeInfoType()); assert(decl->tinfo->ty == Tenum); TypeEnum *tc = static_cast<TypeEnum *>(decl->tinfo); EnumDeclaration *sd = tc->sym; // TypeInfo base b.push_typeinfo(sd->memtype); // char[] name b.push_string(sd->toPrettyChars()); // void[] init // the array is null if the default initializer is zero if (!sd->members || decl->tinfo->isZeroInit(decl->loc)) { b.push_null_void_array(); } // otherwise emit a void[] with the default initializer else { Expression *defaultval = sd->getDefaultValue(decl->loc); LLConstant *c = toConstElem(defaultval, gIR); b.push_void_array(c, sd->memtype, sd); } // finish b.finalize(gvar); }
void visit(TypeInfoEnumDeclaration *decl) override { IF_LOG Logger::println("TypeInfoEnumDeclaration::llvmDefine() %s", decl->toChars()); LOG_SCOPE; RTTIBuilder b(Type::typeinfoenum); assert(decl->tinfo->ty == Tenum); TypeEnum *tc = static_cast<TypeEnum *>(decl->tinfo); EnumDeclaration *sd = tc->sym; // TypeInfo base b.push_typeinfo(sd->memtype); // char[] name b.push_string(sd->toPrettyChars()); // void[] init // emit void[] with the default initialier, the array is null if the default // initializer is zero if (!sd->members || decl->tinfo->isZeroInit(decl->loc)) { b.push_null_void_array(); } // otherwise emit a void[] with the default initializer else { Type *memtype = sd->memtype; LLType *memty = DtoType(memtype); LLConstant *C; Expression *defaultval = sd->getDefaultValue(decl->loc); if (memtype->isintegral()) { C = LLConstantInt::get(memty, defaultval->toInteger(), !isLLVMUnsigned(memtype)); } else if (memtype->isString()) { C = DtoConstString( static_cast<const char *>(defaultval->toStringExp()->string)); } else if (memtype->isfloating()) { C = LLConstantFP::get(memty, defaultval->toReal()); } else { llvm_unreachable("Unsupported type"); } b.push_void_array(C, memtype, sd); } // finish b.finalize(getIrGlobal(decl)); }
void visit(TypeInfoEnumDeclaration *d) { //printf("TypeInfoEnumDeclaration::toDt()\n"); verifyStructSize(Type::typeinfoenum, 7 * Target::ptrsize); dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0); // vtbl for TypeInfo_Enum dtsize_t(pdt, 0); // monitor assert(d->tinfo->ty == Tenum); TypeEnum *tc = (TypeEnum *)d->tinfo; EnumDeclaration *sd = tc->sym; /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ if (sd->memtype) { sd->memtype->genTypeInfo(NULL); dtxoff(pdt, toSymbol(sd->memtype->vtinfo), 0); // TypeInfo for enum members } else dtsize_t(pdt, 0); const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, 0, namelen + 1, name); // void[] init; if (!sd->members || d->tinfo->isZeroInit()) { // 0 initializer, or the same as the base type dtsize_t(pdt, 0); // init.length dtsize_t(pdt, 0); // init.ptr } else { dtsize_t(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0); // init.ptr } }
void TypeInfoEnumDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoEnumDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum dtdword(pdt, 0); // monitor assert(tinfo->ty == Tenum); TypeEnum *tc = (TypeEnum *)tinfo; EnumDeclaration *sd = tc->sym; /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ if (sd->memtype) { sd->memtype->getTypeInfo(NULL); dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members } else dtdword(pdt, 0); char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; if (!sd->defaultval || tinfo->isZeroInit()) { // 0 initializer, or the same as the base type dtdword(pdt, 0); // init.length dtdword(pdt, 0); // init.ptr } else { dtdword(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr } }
void TypeInfoEnumDeclaration::llvmDefine() { Logger::println("TypeInfoEnumDeclaration::llvmDefine() %s", toChars()); LOG_SCOPE; RTTIBuilder b(Type::typeinfoenum); assert(tinfo->ty == Tenum); TypeEnum *tc = static_cast<TypeEnum *>(tinfo); EnumDeclaration *sd = tc->sym; // TypeInfo base b.push_typeinfo(sd->memtype); // char[] name b.push_string(sd->toPrettyChars()); // void[] init // emit void[] with the default initialier, the array is null if the default // initializer is zero if (!sd->defaultval || tinfo->isZeroInit(0)) { b.push_null_void_array(); } // otherwise emit a void[] with the default initializer else { LLType* memty = DtoType(sd->memtype); #if DMDV2 LLConstant* C = LLConstantInt::get(memty, sd->defaultval->toInteger(), !isLLVMUnsigned(sd->memtype)); #else LLConstant* C = LLConstantInt::get(memty, sd->defaultval, !isLLVMUnsigned(sd->memtype)); #endif b.push_void_array(C, sd->memtype, sd); } // finish b.finalize(ir.irGlobal); }
void EnumDeclaration::semantic(Scope *sc) { uinteger_t number; Type *t; Scope *sce; //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars()); if (!memtype) memtype = Type::tint32; if (symtab) // if already done { if (isdone || !scope) return; // semantic() already completed } else symtab = new DsymbolTable(); Scope *scx = NULL; if (scope) { sc = scope; scx = scope; // save so we don't make redundant copies scope = NULL; } unsigned dprogress_save = Module::dprogress; if (sc->stc & STCdeprecated) isdeprecated = 1; parent = sc->scopesym; memtype = memtype->semantic(loc, sc); /* Check to see if memtype is forward referenced */ if (memtype->ty == Tenum) { EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc); if (!sym->memtype) { error("base enum %s is forward referenced", sym->toChars()); memtype = Type::tint32; } } if (!memtype->isintegral()) { error("base type must be of integral type, not %s", memtype->toChars()); memtype = Type::tint32; } isdone = 1; Module::dprogress++; t = isAnonymous() ? memtype : type; symtab = new DsymbolTable(); sce = sc->push(this); sce->parent = this; number = 0; if (!members) // enum ident; return; if (members->dim == 0) error("enum %s must have at least one member", toChars()); int first = 1; for (size_t i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); Expression *e; if (!em) /* The e->semantic(sce) can insert other symbols, such as * template instances and function literals. */ continue; //printf("Enum member '%s'\n",em->toChars()); e = em->value; if (e) { assert(e->dyncast() == DYNCAST_EXPRESSION); e = e->semantic(sce); e = e->optimize(WANTvalue); // Need to copy it because we're going to change the type e = e->copy(); e = e->implicitCastTo(sc, memtype); e = e->optimize(WANTvalue); number = e->toInteger(); e->type = t; } else { // Default is the previous number plus 1 // Check for overflow if (!first) { switch (t->toBasetype()->ty) { case Tbool: if (number == 2) goto Loverflow; break; case Tint8: if (number == 128) goto Loverflow; break; case Tchar: case Tuns8: if (number == 256) goto Loverflow; break; case Tint16: if (number == 0x8000) goto Loverflow; break; case Twchar: case Tuns16: if (number == 0x10000) goto Loverflow; break; case Tint32: if (number == 0x80000000) goto Loverflow; break; case Tdchar: case Tuns32: if (number == 0x100000000LL) goto Loverflow; break; case Tint64: if (number == 0x8000000000000000LL) goto Loverflow; break; case Tuns64: if (number == 0) goto Loverflow; break; Loverflow: error("overflow of enum value"); break; default: assert(0); } } e = new IntegerExp(em->loc, number, t); } em->value = e; // Add to symbol table only after evaluating 'value' if (isAnonymous()) { //sce->enclosing->insert(em); for (Scope *sct = sce->enclosing; sct; sct = sct->enclosing) { if (sct->scopesym) { if (!sct->scopesym->symtab) sct->scopesym->symtab = new DsymbolTable(); em->addMember(sce, sct->scopesym, 1); break; } } } else em->addMember(sc, this, 1); if (first) { first = 0; defaultval = number; minval = number; maxval = number; } else if (memtype->isunsigned()) { if (number < minval) minval = number; if (number > maxval) maxval = number; } else { if ((sinteger_t)number < (sinteger_t)minval) minval = number; if ((sinteger_t)number > (sinteger_t)maxval) maxval = number; } number++; } //printf("defaultval = %lld\n", defaultval); sce->pop(); //members->print(); }
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) { //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags); //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0; // Look in symbols declared in this module Dsymbol *s = symtab ? symtab->lookup(ident) : NULL; //printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0); if (s) { //printf("\ts = '%s.%s'\n",toChars(),s->toChars()); } else if (imports) { OverloadSet *a = NULL; // Look in imported modules for (size_t i = 0; i < imports->dim; i++) { Dsymbol *ss = (*imports)[i]; Dsymbol *s2; // If private import, don't search it if (flags & 1 && prots[i] == PROTprivate) continue; //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport()); /* Don't find private members if ss is a module */ s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0); if (!s) s = s2; else if (s2 && s != s2) { if (s->toAlias() == s2->toAlias() || s->getType() == s2->getType() && s->getType()) { /* After following aliases, we found the same * symbol, so it's not an ambiguity. But if one * alias is deprecated or less accessible, prefer * the other. */ if (s->isDeprecated() || s2->prot() > s->prot() && s2->prot() != PROTnone) s = s2; } else { /* Two imports of the same module should be regarded as * the same. */ Import *i1 = s->isImport(); Import *i2 = s2->isImport(); if (!(i1 && i2 && (i1->mod == i2->mod || (!i1->parent->isImport() && !i2->parent->isImport() && i1->ident->equals(i2->ident)) ) ) ) { /* Bugzilla 8668: * Public selective import adds AliasDeclaration in module. * To make an overload set, resolve aliases in here and * get actual overload roots which accessible via s and s2. */ s = s->toAlias(); s2 = s2->toAlias(); /* If both s2 and s are overloadable (though we only * need to check s once) */ if (s2->isOverloadable() && (a || s->isOverloadable())) { if (!a) a = new OverloadSet(s->ident); /* Don't add to a[] if s2 is alias of previous sym */ for (size_t j = 0; j < a->a.dim; j++) { Dsymbol *s3 = a->a[j]; if (s2->toAlias() == s3->toAlias()) { if (s3->isDeprecated() || s2->prot() > s3->prot() && s2->prot() != PROTnone) a->a[j] = s2; goto Lcontinue; } } a->push(s2); Lcontinue: continue; } if (flags & 4) // if return NULL on ambiguity return NULL; if (!(flags & 2)) ScopeDsymbol::multiplyDefined(loc, s, s2); break; } } } } /* Build special symbol if we had multiple finds */ if (a) { assert(s); a->push(s); s = a; } if (s) { if (!(flags & 2)) { Declaration *d = s->isDeclaration(); if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin()) error(loc, "%s is private", d->toPrettyChars()); AggregateDeclaration *ad = s->isAggregateDeclaration(); if (ad && ad->protection == PROTprivate && !ad->parent->isTemplateMixin()) error(loc, "%s is private", ad->toPrettyChars()); EnumDeclaration *ed = s->isEnumDeclaration(); if (ed && ed->protection == PROTprivate && !ed->parent->isTemplateMixin()) error(loc, "%s is private", ed->toPrettyChars()); TemplateDeclaration *td = s->isTemplateDeclaration(); if (td && td->protection == PROTprivate && !td->parent->isTemplateMixin()) error(loc, "%s is private", td->toPrettyChars()); } } } return s; }