/// Return the type returned by DtoUnpaddedStruct called on a value of the /// specified type. /// Union types will get expanded into a struct, with a type for each member. LLType* DtoUnpaddedStructType(Type* dty) { assert(dty->ty == Tstruct); typedef llvm::DenseMap<Type*, llvm::StructType*> CacheT; static llvm::ManagedStatic<CacheT> cache; CacheT::iterator it = cache->find(dty); if (it != cache->end()) return it->second; TypeStruct* sty = static_cast<TypeStruct*>(dty); VarDeclarations& fields = sty->sym->fields; std::vector<LLType*> types; types.reserve(fields.dim); for (unsigned i = 0; i < fields.dim; i++) { LLType* fty; if (fields[i]->type->ty == Tstruct) { // Nested structs are the only members that can contain padding fty = DtoUnpaddedStructType(fields[i]->type); } else { fty = DtoType(fields[i]->type); } types.push_back(fty); } LLStructType* Ty = LLStructType::get(gIR->context(), types); cache->insert(std::make_pair(dty, Ty)); return Ty; }
void fixup(IrFuncTyArg& arg) { assert(arg.type->ty == Tstruct); // TODO: Check that no unions are passed in or returned. LLType* abiTy = DtoUnpaddedStructType(arg.type); if (abiTy && abiTy != arg.ltype) { arg.ltype = abiTy; arg.rewrite = &remove_padding; } }
/// Return the struct value represented by v without the padding fields. /// Unions will be expanded, with a value for each member. /// Note: v must be a pointer to a struct, but the return value will be a /// first-class struct value. LLValue* DtoUnpaddedStruct(Type* dty, LLValue* v) { assert(dty->ty == Tstruct); TypeStruct* sty = static_cast<TypeStruct*>(dty); VarDeclarations& fields = sty->sym->fields; LLValue* newval = llvm::UndefValue::get(DtoUnpaddedStructType(dty)); for (unsigned i = 0; i < fields.dim; i++) { LLValue* fieldptr = DtoIndexAggregate(v, sty->sym, fields[i]); LLValue* fieldval; if (fields[i]->type->ty == Tstruct) { // Nested structs are the only members that can contain padding fieldval = DtoUnpaddedStruct(fields[i]->type, fieldptr); } else { fieldval = DtoLoad(fieldptr); } newval = DtoInsertValue(newval, fieldval, i); } return newval; }
/// Return the struct value represented by v without the padding fields. /// Unions will be expanded, with a value for each member. /// Note: v must be a pointer to a struct, but the return value will be a /// first-class struct value. LLValue* DtoUnpaddedStruct(Type* dty, LLValue* v) { assert(dty->ty == Tstruct); TypeStruct* sty = (TypeStruct*) dty; Array& fields = sty->sym->fields; LLValue* newval = llvm::UndefValue::get(DtoUnpaddedStructType(dty)); for (unsigned i = 0; i < fields.dim; i++) { VarDeclaration* vd = (VarDeclaration*) fields.data[i]; LLValue* fieldptr = DtoIndexStruct(v, sty->sym, vd); LLValue* fieldval; if (vd->type->ty == Tstruct) { // Nested structs are the only members that can contain padding fieldval = DtoUnpaddedStruct(vd->type, fieldptr); } else { fieldval = DtoLoad(fieldptr); } newval = DtoInsertValue(newval, fieldval, i); } return newval; }