annotate gen/classes.cpp @ 825:a70ddd449e7d

Commented some logging that could be '''very''' long, cuts -vv output size of a gtkd gl sample down 1.2GB by 3/4. Fixed wrong pointer type for multidimension "deep" slicing.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 04 Dec 2008 16:11:09 +0100
parents 8f0b24bc55f0
children 482cd74d1c71
rev   line source
lindquist@113 1 #include <sstream>
lindquist@100 2 #include "gen/llvm.h"
lindquist@100 3
lindquist@100 4 #include "mtype.h"
lindquist@100 5 #include "aggregate.h"
lindquist@100 6 #include "init.h"
lindquist@100 7 #include "declaration.h"
lindquist@100 8
lindquist@100 9 #include "gen/irstate.h"
lindquist@100 10 #include "gen/tollvm.h"
lindquist@244 11 #include "gen/llvmhelpers.h"
lindquist@100 12 #include "gen/arrays.h"
lindquist@100 13 #include "gen/logger.h"
lindquist@100 14 #include "gen/classes.h"
lindquist@132 15 #include "gen/structs.h"
lindquist@102 16 #include "gen/functions.h"
lindquist@113 17 #include "gen/runtime.h"
lindquist@113 18 #include "gen/dvalue.h"
lindquist@100 19
lindquist@136 20 #include "ir/irstruct.h"
lindquist@136 21
lindquist@100 22 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 23
tomas@797 24 // adds interface b to target, if newinstance != 0, then target must provide all
tomas@797 25 // functions required to implement b (it reimplements b)
tomas@797 26 static void add_interface(ClassDeclaration* target, BaseClass* b, int newinstance)
lindquist@137 27 {
tomas@797 28 Logger::println("adding interface: %s", b->base->toChars());
tomas@797 29 LOG_SCOPE;
tomas@797 30
tomas@797 31 InterfaceDeclaration* inter = b->base->isInterfaceDeclaration();
tomas@797 32 DtoResolveClass(inter);
tomas@797 33
tomas@797 34 assert(inter);
tomas@797 35 IrStruct* irstruct = target->ir.irStruct;
tomas@797 36 assert(irstruct);
tomas@797 37
tomas@797 38 // add interface to map/list
tomas@797 39 // if it's already inserted in the map, it's because another interface has it as baseclass
tomas@797 40 // but if it appears here, it's because we're reimplementing it, so we overwrite the IrInterface entry
tomas@797 41 IrInterface* iri;
tomas@797 42 bool overwrite = false;
tomas@797 43 if (irstruct->interfaceMap.find(inter) != irstruct->interfaceMap.end())
lindquist@137 44 {
tomas@797 45 overwrite = true;
tomas@797 46 }
lindquist@137 47
tomas@797 48 iri = new IrInterface(b);
tomas@797 49 // add to map
tomas@797 50 if (overwrite)
tomas@797 51 irstruct->interfaceMap[b->base] = iri;
tomas@797 52 else
tomas@797 53 irstruct->interfaceMap.insert(std::make_pair(b->base, iri));
tomas@816 54
tomas@797 55 // add to ordered list
tomas@797 56 irstruct->interfaceVec.push_back(iri);
lindquist@142 57
tomas@816 58 // add to classinfo interfaces
tomas@816 59 if (newinstance)
tomas@816 60 irstruct->classInfoInterfaces.push_back(iri);
tomas@816 61
tomas@797 62 // assign this iri to all base interfaces of this one
tomas@797 63 for (unsigned j = 0; j < b->baseInterfaces_dim; j++)
tomas@797 64 {
tomas@797 65 BaseClass *bc = &b->baseInterfaces[j];
tomas@797 66 // add to map
tomas@797 67 if (irstruct->interfaceMap.find(bc->base) == irstruct->interfaceMap.end())
lindquist@137 68 {
tomas@797 69 irstruct->interfaceMap.insert(std::make_pair(bc->base, iri));
tomas@797 70 }
tomas@797 71 }
lindquist@142 72
tomas@797 73 // build the interface vtable
kamm@806 74 b->fillVtbl(target, &iri->vtblDecls, newinstance);
lindquist@142 75
tomas@797 76 // add the vtable type
tomas@797 77 assert(inter->type->ir.type);
tomas@797 78 irstruct->types.push_back( inter->type->ir.type->get() );
tomas@797 79 // set and increment index
tomas@797 80 iri->index = irstruct->index++;
tomas@797 81 }
tomas@797 82
tomas@809 83 //////////////////////////////////////////////////////////////////////////////////////////
tomas@809 84
tomas@797 85 static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd)
tomas@797 86 {
tomas@797 87 Logger::println("Adding data from class: %s", cd->toChars());
tomas@797 88 LOG_SCOPE;
tomas@797 89
tomas@797 90 // recurse into baseClasses
tomas@797 91 if (cd->baseClass)
tomas@797 92 {
tomas@797 93 add_class_data(target, cd->baseClass);
tomas@797 94 //offset = baseClass->structsize;
tomas@797 95 }
tomas@797 96
tomas@797 97 // add members
tomas@797 98 Array* arr = cd->members;
tomas@797 99 for (int k=0; k < arr->dim; k++) {
tomas@797 100 Dsymbol* s = (Dsymbol*)arr->data[k];
tomas@797 101 s->toObjFile(0);
tomas@797 102 }
tomas@797 103
tomas@797 104 // add interfaces
tomas@797 105 if (cd->vtblInterfaces)
tomas@797 106 {
tomas@797 107 Logger::println("num vtbl interfaces: %u", cd->vtblInterfaces->dim);
tomas@797 108 for (int i = 0; i < cd->vtblInterfaces->dim; i++)
tomas@797 109 {
tomas@797 110 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
tomas@797 111 assert(b);
tomas@797 112 // create new instances only for explicitly derived interfaces
tomas@797 113 add_interface(target, b, (cd == target));
lindquist@137 114 }
lindquist@137 115 }
lindquist@137 116 }
lindquist@137 117
lindquist@137 118 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@137 119
tomas@797 120 static void DtoResolveInterface(InterfaceDeclaration* cd)
lindquist@100 121 {
tomas@797 122 if (cd->ir.resolved) return;
tomas@797 123 cd->ir.resolved = true;
tomas@797 124
tomas@797 125 Logger::println("DtoResolveInterface(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
tomas@797 126 LOG_SCOPE;
tomas@797 127
tomas@797 128 // get the TypeClass
tomas@797 129 assert(cd->type->ty == Tclass);
tomas@797 130 TypeClass* ts = (TypeClass*)cd->type;
tomas@797 131
tomas@797 132 // create the IrStruct, we need somewhere to store the classInfo
tomas@797 133 assert(!cd->ir.irStruct);
tomas@797 134 IrStruct* irstruct = new IrStruct(cd);
tomas@797 135 cd->ir.irStruct = irstruct;
tomas@797 136
tomas@797 137 // handle base interfaces
tomas@797 138 if (cd->baseclasses.dim)
lindquist@100 139 {
tomas@797 140 Logger::println("num baseclasses: %u", cd->baseclasses.dim);
lindquist@100 141 LOG_SCOPE;
lindquist@100 142
tomas@797 143 for (int i=0; i<cd->baseclasses.dim; i++)
tomas@797 144 {
tomas@797 145 BaseClass* bc = (BaseClass*)cd->baseclasses.data[i];
tomas@797 146 Logger::println("baseclass %d: %s", i, bc->base->toChars());
tomas@797 147
tomas@797 148 InterfaceDeclaration* id = bc->base->isInterfaceDeclaration();
tomas@797 149 assert(id);
tomas@797 150
tomas@797 151 DtoResolveInterface(id);
tomas@797 152
tomas@797 153 // add to interfaceInfos
tomas@797 154 IrInterface* iri = new IrInterface(bc);
tomas@797 155 irstruct->interfaceVec.push_back(iri);
tomas@816 156 irstruct->classInfoInterfaces.push_back(iri);
lindquist@132 157 }
lindquist@100 158 }
tomas@797 159
tomas@797 160 // create the type
tomas@797 161 const LLType* t = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim);
tomas@797 162 assert(!ts->ir.type);
tomas@797 163 ts->ir.type = new LLPATypeHolder(getPtrToType(t));
tomas@797 164
tomas@797 165 // request declaration
tomas@797 166 gIR->declareList.push_back(cd);
tomas@797 167
tomas@797 168 // handle members
tomas@797 169 // like "nested" interfaces
tomas@797 170 Array* arr = cd->members;
tomas@797 171 for (int k=0; k < arr->dim; k++) {
tomas@797 172 Dsymbol* s = (Dsymbol*)arr->data[k];
tomas@797 173 s->toObjFile(0);
tomas@797 174 }
lindquist@100 175 }
lindquist@100 176
lindquist@100 177 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 178
tomas@797 179 // FIXME: this needs to be cleaned up
tomas@797 180
lindquist@102 181 void DtoResolveClass(ClassDeclaration* cd)
lindquist@100 182 {
tomas@797 183 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
tomas@797 184 {
tomas@797 185 DtoResolveInterface(id);
tomas@797 186 return;
tomas@797 187 }
tomas@797 188
ChristianK@173 189 if (cd->ir.resolved) return;
ChristianK@173 190 cd->ir.resolved = true;
lindquist@100 191
lindquist@133 192 Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
lindquist@133 193 LOG_SCOPE;
lindquist@133 194
tomas@622 195 //printf("resolve class: %s\n", cd->toPrettyChars());
tomas@622 196
lindquist@133 197 // get the TypeClass
lindquist@133 198 assert(cd->type->ty == Tclass);
lindquist@133 199 TypeClass* ts = (TypeClass*)cd->type;
lindquist@133 200
tomas@797 201 // create the IrStruct
tomas@797 202 assert(!cd->ir.irStruct);
tomas@797 203 IrStruct* irstruct = new IrStruct(cd);
tomas@797 204 cd->ir.irStruct = irstruct;
tomas@797 205
tomas@797 206 // create the type
tomas@797 207 ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
tomas@797 208
tomas@797 209 // if it just a forward declaration?
tomas@797 210 if (cd->sizeok != 1)
tomas@797 211 {
tomas@797 212 // just name the type
tomas@797 213 gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
tomas@797 214 return;
lindquist@133 215 }
lindquist@133 216
lindquist@133 217 // resolve the base class
lindquist@102 218 if (cd->baseClass) {
lindquist@102 219 DtoResolveClass(cd->baseClass);
lindquist@102 220 }
lindquist@113 221
lindquist@193 222 // push state
lindquist@100 223 gIR->structs.push_back(irstruct);
lindquist@193 224
lindquist@100 225 // add vtable
tomas@797 226 irstruct->types.push_back(getPtrToType(irstruct->vtblTy.get()));
tomas@797 227 irstruct->index++;
lindquist@100 228
lindquist@115 229 // add monitor
tomas@797 230 irstruct->types.push_back(getVoidPtrType());
tomas@797 231 irstruct->index++;
lindquist@115 232
tomas@797 233 // add class data fields and interface vtables recursively
tomas@797 234 add_class_data(cd, cd);
lindquist@100 235
tomas@797 236 // check if errors occured while building interface vtables
tomas@797 237 if (global.errors)
tomas@797 238 fatal();
lindquist@137 239
lindquist@137 240 // create type
tomas@797 241 assert(irstruct->index == irstruct->types.size());
tomas@797 242 const LLType* structtype = irstruct->build();
lindquist@137 243
lindquist@100 244 // refine abstract types for stuff like: class C {C next;}
tomas@797 245 llvm::PATypeHolder* spa = ts->ir.type;
tomas@797 246 llvm::cast<llvm::OpaqueType>(spa->get())->refineAbstractTypeTo(structtype);
tomas@797 247 structtype = isaStruct(spa->get());
lindquist@100 248
lindquist@123 249 // name the type
ChristianK@173 250 gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
lindquist@100 251
tomas@797 252 // refine vtable type
tomas@797 253
lindquist@193 254 // void*[vtbl.dim]
tomas@797 255 llvm::cast<llvm::OpaqueType>(irstruct->vtblTy.get())->refineAbstractTypeTo(LLArrayType::get(getVoidPtrType(), cd->vtbl.dim));
lindquist@193 256
lindquist@193 257 // log
tomas@825 258 // if (Logger::enabled())
tomas@825 259 // Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n';
lindquist@193 260
lindquist@193 261 // pop state
lindquist@102 262 gIR->structs.pop_back();
lindquist@100 263
lindquist@193 264 // queue declare
lindquist@102 265 gIR->declareList.push_back(cd);
lindquist@102 266 }
lindquist@102 267
lindquist@102 268 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@102 269
tomas@797 270 static void DtoDeclareInterface(InterfaceDeclaration* cd)
lindquist@102 271 {
ChristianK@173 272 if (cd->ir.declared) return;
ChristianK@173 273 cd->ir.declared = true;
lindquist@102 274
tomas@797 275 Logger::println("DtoDeclareInterface(%s): %s", cd->toPrettyChars(), cd->locToChars());
tomas@797 276 LOG_SCOPE;
tomas@797 277
tomas@797 278 assert(cd->ir.irStruct);
tomas@797 279 IrStruct* irstruct = cd->ir.irStruct;
tomas@797 280
tomas@797 281 // get interface info type
tomas@797 282 const llvm::StructType* infoTy = DtoInterfaceInfoType();
tomas@797 283
tomas@797 284 // interface info array
tomas@797 285 if (!irstruct->interfaceVec.empty()) {
tomas@797 286 // symbol name
tomas@797 287 std::string nam = "_D";
tomas@797 288 nam.append(cd->mangle());
tomas@797 289 nam.append("16__interfaceInfosZ");
tomas@797 290
tomas@797 291 llvm::GlobalValue::LinkageTypes linkage = DtoLinkage(cd);
tomas@797 292
tomas@797 293 // resolve array type
tomas@797 294 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
tomas@797 295 // declare global
tomas@797 296 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, linkage, NULL, nam, gIR->module);
tomas@797 297
tomas@797 298 // do each interface info
tomas@797 299 unsigned idx = 0;
tomas@797 300 size_t n = irstruct->interfaceVec.size();
tomas@797 301 for (size_t i=0; i < n; i++)
tomas@797 302 {
tomas@797 303 IrInterface* iri = irstruct->interfaceVec[i];
tomas@797 304 ClassDeclaration* id = iri->decl;
tomas@797 305
tomas@797 306 // always create interfaceinfos
tomas@797 307 LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
tomas@797 308 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
tomas@797 309 idx++;
tomas@797 310 }
tomas@797 311 }
tomas@797 312
tomas@797 313 // declare the classinfo
tomas@797 314 DtoDeclareClassInfo(cd);
tomas@797 315
tomas@797 316 // request const init
tomas@797 317 gIR->constInitList.push_back(cd);
tomas@797 318
tomas@797 319 // emit typeinfo and request definition
tomas@797 320 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
tomas@797 321 {
tomas@797 322 gIR->defineList.push_back(cd);
tomas@797 323 DtoTypeInfoOf(cd->type, false);
tomas@797 324 }
tomas@797 325 }
tomas@797 326
tomas@797 327 //////////////////////////////////////////////////////////////////////////////////////////
tomas@797 328
tomas@797 329 // FIXME: this needs to be cleaned up
tomas@797 330
tomas@797 331 void DtoDeclareClass(ClassDeclaration* cd)
tomas@797 332 {
tomas@797 333 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
tomas@797 334 {
tomas@797 335 DtoDeclareInterface(id);
tomas@797 336 return;
tomas@797 337 }
tomas@797 338
tomas@797 339 if (cd->ir.declared) return;
tomas@797 340 cd->ir.declared = true;
tomas@797 341
tomas@797 342 Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->locToChars());
lindquist@102 343 LOG_SCOPE;
lindquist@102 344
tomas@622 345 //printf("declare class: %s\n", cd->toPrettyChars());
tomas@622 346
lindquist@102 347 assert(cd->type->ty == Tclass);
lindquist@102 348 TypeClass* ts = (TypeClass*)cd->type;
lindquist@102 349
ChristianK@173 350 assert(cd->ir.irStruct);
ChristianK@173 351 IrStruct* irstruct = cd->ir.irStruct;
lindquist@102 352
lindquist@102 353 gIR->structs.push_back(irstruct);
lindquist@102 354
lindquist@102 355 bool needs_definition = false;
ChristianK@147 356 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd)) {
lindquist@123 357 needs_definition = true;
lindquist@100 358 }
lindquist@100 359
lindquist@149 360 llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
lindquist@136 361
tomas@797 362 // create vtbl symbol
tomas@797 363 std::string varname("_D");
tomas@797 364 varname.append(cd->mangle());
tomas@797 365 varname.append("6__vtblZ");
tomas@797 366 irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, 0, varname, gIR->module);
lindquist@102 367
lindquist@136 368 // get interface info type
lindquist@136 369 const llvm::StructType* infoTy = DtoInterfaceInfoType();
lindquist@102 370
lindquist@136 371 // interface info array
tomas@797 372 if (!irstruct->interfaceVec.empty()) {
lindquist@136 373 // symbol name
lindquist@136 374 std::string nam = "_D";
lindquist@136 375 nam.append(cd->mangle());
lindquist@136 376 nam.append("16__interfaceInfosZ");
lindquist@136 377 // resolve array type
tomas@797 378 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
lindquist@136 379 // declare global
lindquist@136 380 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module);
lindquist@136 381 }
lindquist@102 382
tomas@797 383 // DMD gives abstract classes a full ClassInfo, so we do it as well
lindquist@113 384
tomas@797 385 // interface vtables
tomas@797 386 unsigned idx = 0;
tomas@797 387 for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
tomas@797 388 {
tomas@797 389 IrInterface* iri = *i;
tomas@797 390 ClassDeclaration* id = iri->decl;
lindquist@113 391
tomas@797 392 std::string nam("_D");
tomas@797 393 nam.append(cd->mangle());
tomas@797 394 nam.append("11__interface");
tomas@797 395 nam.append(id->mangle());
tomas@797 396 nam.append("6__vtblZ");
lindquist@113 397
tomas@797 398 iri->vtbl = new llvm::GlobalVariable(iri->vtblInitTy.get(), true, _linkage, 0, nam, gIR->module);
tomas@797 399
tomas@816 400 // always set the interface info as it's need as the first vtbl entry
tomas@797 401 LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
tomas@797 402 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
tomas@797 403 idx++;
lindquist@113 404 }
lindquist@100 405
tomas@797 406 // initZ init
tomas@797 407 std::string initname("_D");
tomas@797 408 initname.append(cd->mangle());
tomas@797 409 initname.append("6__initZ");
tomas@797 410
tomas@797 411 // initZ global
tomas@797 412 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
tomas@797 413 irstruct->init = initvar;
tomas@797 414
lindquist@100 415 gIR->structs.pop_back();
lindquist@100 416
tomas@797 417 // request const init
lindquist@102 418 gIR->constInitList.push_back(cd);
tomas@797 419
tomas@797 420 // define ? (set initializers)
lindquist@100 421 if (needs_definition)
lindquist@102 422 gIR->defineList.push_back(cd);
lindquist@103 423
lindquist@103 424 // classinfo
lindquist@103 425 DtoDeclareClassInfo(cd);
lindquist@106 426
tomas@797 427 // do typeinfo ?
lindquist@123 428 if (needs_definition)
lindquist@275 429 DtoTypeInfoOf(cd->type, false);
lindquist@100 430 }
lindquist@100 431
tomas@797 432 //////////////////////////////////////////////////////////////////////////////
tomas@797 433
tomas@797 434 // adds data fields and interface vtables to the constant initializer of class cd
tomas@797 435 static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDeclaration* target, ClassDeclaration* cd, size_t offsetbegin)
tomas@797 436 {
tomas@797 437 // first do baseclasses
tomas@797 438 if (cd->baseClass)
tomas@797 439 {
tomas@797 440 offsetbegin = init_class_initializer(inits, target, cd->baseClass, offsetbegin);
tomas@797 441 }
tomas@797 442
tomas@812 443 Logger::println("adding data of %s to %s starting at %lu", cd->toChars(), target->toChars(), offsetbegin);
tomas@797 444 LOG_SCOPE;
tomas@797 445
tomas@797 446 // add default fields
tomas@797 447 VarDeclaration** fields = (VarDeclaration**)cd->fields.data;
tomas@797 448 size_t nfields = cd->fields.dim;
tomas@797 449
tomas@797 450 std::vector<VarDeclaration*> defVars;
tomas@797 451 defVars.reserve(nfields);
tomas@797 452
tomas@809 453 size_t lastoffset = offsetbegin;
tomas@797 454 size_t lastsize = 0;
tomas@797 455
tomas@797 456 // find fields that contribute to default
tomas@797 457 for (size_t i=0; i<nfields; i++)
tomas@797 458 {
tomas@797 459 VarDeclaration* var = fields[i];
tomas@797 460 // only add vars that don't overlap
tomas@797 461 size_t offset = var->offset;
tomas@797 462 size_t size = var->type->size();
tomas@797 463 if (offset >= lastoffset+lastsize)
tomas@797 464 {
tomas@809 465 Logger::println(" added %s", var->toChars());
tomas@797 466 lastoffset = offset;
tomas@797 467 lastsize = size;
tomas@797 468 defVars.push_back(var);
tomas@797 469 }
tomas@809 470 else
tomas@809 471 {
tomas@812 472 Logger::println(" skipped %s at offset %u, current pos is %lu", var->toChars(), var->offset, lastoffset+lastsize);
tomas@809 473 }
tomas@797 474 }
tomas@797 475
tomas@809 476 // reset offsets, we're going from beginning again
tomas@809 477 lastoffset = offsetbegin;
tomas@809 478 lastsize = 0;
tomas@809 479
tomas@797 480 // go through the default vars and build the default constant initializer
tomas@797 481 // adding zeros along the way to live up to alignment expectations
tomas@797 482 size_t nvars = defVars.size();
tomas@797 483 for (size_t i=0; i<nvars; i++)
tomas@797 484 {
tomas@797 485 VarDeclaration* var = defVars[i];
tomas@797 486
tomas@797 487 Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
tomas@797 488
tomas@797 489 // get offset and size
tomas@797 490 size_t offset = var->offset;
tomas@797 491 size_t size = var->type->size();
tomas@797 492
tomas@797 493 // is there space in between last last offset and this one?
tomas@797 494 // if so, fill it with zeros
tomas@797 495 if (offset > lastoffset+lastsize)
tomas@797 496 {
tomas@797 497 size_t pos = lastoffset + lastsize;
tomas@797 498 addZeros(inits, pos, offset);
tomas@797 499 }
tomas@797 500
tomas@797 501 // add the field
tomas@800 502 // and build its constant initializer lazily
tomas@800 503 if (!var->ir.irField->constInit)
tomas@803 504 var->ir.irField->constInit = DtoConstInitializer(var->loc, var->type, var->init);
tomas@797 505 inits.push_back(var->ir.irField->constInit);
tomas@797 506
tomas@797 507 lastoffset = offset;
tomas@797 508 lastsize = var->type->size();
tomas@797 509 }
tomas@797 510
kamm@806 511 // if it's a class, and it implements interfaces, add the vtables - as found in the target class!
kamm@806 512 IrStruct* irstruct = target->ir.irStruct;
tomas@797 513
tomas@797 514 size_t nvtbls = cd->vtblInterfaces->dim;
tomas@797 515 for(size_t i=0; i<nvtbls; i++)
tomas@797 516 {
tomas@797 517 BaseClass* bc = (BaseClass*)cd->vtblInterfaces->data[i];
tomas@797 518 IrStruct::InterfaceMap::iterator iter = irstruct->interfaceMap.find(bc->base);
tomas@797 519 assert(iter != irstruct->interfaceMap.end());
tomas@797 520
tomas@797 521 IrInterface* iri = iter->second;
tomas@797 522 if (iri->vtbl)
tomas@797 523 inits.push_back(iri->vtbl);
tomas@797 524 else // abstract impl
tomas@797 525 inits.push_back(getNullPtr(getVoidPtrType()));
tomas@797 526
tomas@812 527 lastoffset += lastsize;
tomas@797 528 lastsize = PTRSIZE;
tomas@797 529 }
tomas@797 530
tomas@797 531 // return next offset
tomas@797 532 return lastoffset + lastsize;
tomas@797 533 }
tomas@797 534
tomas@797 535 //////////////////////////////////////////////////////////////////////////////
tomas@797 536
tomas@797 537 // build the vtable initializer for class cd
tomas@797 538 static void init_class_vtbl_initializer(ClassDeclaration* cd)
tomas@797 539 {
tomas@797 540 // generate vtable initializer
tomas@797 541 std::vector<LLConstant*> sinits(cd->vtbl.dim, NULL);
tomas@797 542
tomas@797 543 IrStruct* irstruct = cd->ir.irStruct;
tomas@797 544
tomas@797 545 assert(cd->vtbl.dim > 1);
tomas@797 546
tomas@797 547 // first entry always classinfo
tomas@797 548 assert(irstruct->classInfo);
tomas@797 549 sinits[0] = DtoBitCast(irstruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
tomas@797 550
tomas@797 551 // add virtual functions
tomas@797 552 for (int k=1; k < cd->vtbl.dim; k++)
tomas@797 553 {
tomas@797 554 Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
tomas@797 555 assert(dsym);
tomas@797 556
tomas@797 557 // Logger::println("vtbl[%d] = %s", k, dsym->toChars());
tomas@797 558
tomas@797 559 FuncDeclaration* fd = dsym->isFuncDeclaration();
tomas@797 560 assert(fd);
tomas@797 561
tomas@802 562 // if function is abstract,
tomas@802 563 // or class is abstract, and func has no body,
tomas@802 564 // emit a null vtbl entry
kamm@799 565 if (fd->isAbstract() || (cd->isAbstract() && !fd->fbody))
tomas@797 566 {
tomas@797 567 sinits[k] = getNullPtr(getVoidPtrType());
tomas@797 568 }
tomas@797 569 else
tomas@797 570 {
tomas@797 571 DtoForceDeclareDsymbol(fd);
tomas@797 572 assert(fd->ir.irFunc->func);
tomas@797 573 sinits[k] = fd->ir.irFunc->func;
tomas@797 574 }
tomas@797 575
tomas@797 576 // if (Logger::enabled())
tomas@797 577 // Logger::cout() << "vtbl[" << k << "] = " << *sinits[k] << std::endl;
tomas@797 578 }
tomas@797 579
tomas@797 580 irstruct->constVtbl = LLConstantStruct::get(sinits);
tomas@797 581
tomas@797 582 // refine type
tomas@797 583 llvm::cast<llvm::OpaqueType>(irstruct->vtblInitTy.get())->refineAbstractTypeTo(irstruct->constVtbl->getType());
tomas@797 584
tomas@825 585 // if (Logger::enabled())
tomas@825 586 // Logger::cout() << "vtbl initializer: " << *irstruct->constVtbl << std::endl;
tomas@797 587 }
tomas@797 588
tomas@797 589 //////////////////////////////////////////////////////////////////////////////
tomas@797 590
tomas@797 591 static void init_class_interface_vtbl_initializers(ClassDeclaration* cd)
tomas@797 592 {
tomas@797 593 IrStruct* irstruct = cd->ir.irStruct;
tomas@797 594
tomas@797 595 // don't do anything if list is empty
tomas@797 596 if (irstruct->interfaceVec.empty())
tomas@797 597 return;
tomas@797 598
tomas@797 599 std::vector<LLConstant*> inits;
tomas@797 600 std::vector<LLConstant*> infoInits(3);
tomas@797 601
tomas@797 602 // go through each interface
tomas@797 603 size_t ninter = irstruct->interfaceVec.size();
tomas@797 604 for (size_t i=0; i<ninter; i++)
tomas@797 605 {
tomas@797 606 IrInterface* iri = irstruct->interfaceVec[i];
tomas@797 607 Logger::println("interface %s", iri->decl->toChars());
tomas@797 608
tomas@797 609 // build vtable intializer for this interface implementation
kamm@806 610 Array& arr = iri->vtblDecls;
tomas@797 611 size_t narr = arr.dim;
tomas@797 612
tomas@797 613 if (narr > 0)
tomas@797 614 {
tomas@797 615 inits.resize(narr, NULL);
tomas@797 616
tomas@797 617 // first is always the interface info
tomas@797 618 assert(iri->info);
tomas@797 619 inits[0] = iri->info;
tomas@797 620
tomas@797 621 // build vtable
tomas@797 622 for (size_t j=1; j < narr; j++)
tomas@797 623 {
tomas@797 624 Dsymbol* dsym = (Dsymbol*)arr.data[j];
tomas@797 625 if (!dsym)
tomas@797 626 {
tomas@797 627 inits[j] = getNullPtr(getVoidPtrType());
tomas@797 628 continue;
tomas@797 629 }
tomas@797 630
tomas@797 631 //Logger::println("ivtbl[%d] = %s", j, dsym->toChars());
tomas@797 632
tomas@797 633 // must all be functions
tomas@797 634 FuncDeclaration* fd = dsym->isFuncDeclaration();
tomas@797 635 assert(fd);
tomas@797 636
tomas@797 637 if (fd->isAbstract())
tomas@797 638 inits[j] = getNullPtr(getVoidPtrType());
tomas@797 639 else
tomas@797 640 {
tomas@797 641 DtoForceDeclareDsymbol(fd);
tomas@797 642
tomas@797 643 assert(fd->ir.irFunc->func);
tomas@797 644 inits[j] = fd->ir.irFunc->func;
tomas@797 645 }
tomas@797 646
tomas@797 647 //if (Logger::enabled())
tomas@797 648 // Logger::cout() << "ivtbl[" << j << "] = " << *inits[j] << std::endl;
tomas@797 649 }
tomas@797 650
tomas@797 651 // build the constant
tomas@797 652 iri->vtblInit = LLConstantStruct::get(inits);
tomas@797 653 }
tomas@797 654
tomas@797 655 // build the interface info for ClassInfo
tomas@797 656 // generate interface info initializer
tomas@797 657
tomas@797 658 DtoForceDeclareDsymbol(iri->decl);
tomas@797 659
tomas@797 660 // classinfo
tomas@797 661 IrStruct* iris = iri->decl->ir.irStruct;
tomas@797 662 assert(iris);
tomas@797 663 assert(iris->classInfo);
tomas@797 664 infoInits[0] = DtoBitCast(iris->classInfo, DtoType(ClassDeclaration::classinfo->type));
tomas@797 665
tomas@797 666 // vtbl
tomas@797 667 LLConstant* c;
tomas@797 668 if (iri->vtbl)
tomas@797 669 c = llvm::ConstantExpr::getBitCast(iri->vtbl, getPtrToType(getVoidPtrType()));
tomas@797 670 else
tomas@797 671 c = getNullPtr(getPtrToType(getVoidPtrType()));
tomas@797 672 infoInits[1] = DtoConstSlice(DtoConstSize_t(narr), c);
tomas@797 673
tomas@797 674 // offset
tomas@797 675 size_t ioff;
tomas@797 676 if (iri->index == 0)
tomas@797 677 ioff = 0;
tomas@797 678 else
tomas@797 679 ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index);
tomas@797 680
tomas@797 681 Logger::println("DMD interface offset: %d, LLVM interface offset: %lu", iri->base->offset, ioff);
tomas@797 682 assert(iri->base->offset == ioff);
tomas@797 683 infoInits[2] = DtoConstUint(ioff);
tomas@797 684
tomas@797 685 // create interface info initializer constant
tomas@797 686 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(infoInits));
tomas@797 687 }
tomas@797 688 }
tomas@797 689
tomas@797 690 //////////////////////////////////////////////////////////////////////////////
tomas@797 691
tomas@797 692 static void DtoConstInitInterface(InterfaceDeclaration* cd)
lindquist@100 693 {
ChristianK@173 694 if (cd->ir.initialized) return;
ChristianK@173 695 cd->ir.initialized = true;
lindquist@100 696
lindquist@132 697 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
lindquist@100 698 LOG_SCOPE;
lindquist@100 699
tomas@797 700 init_class_interface_vtbl_initializers(cd);
tomas@797 701 }
tomas@797 702
tomas@797 703 //////////////////////////////////////////////////////////////////////////////
tomas@797 704
tomas@797 705 void DtoConstInitClass(ClassDeclaration* cd)
tomas@797 706 {
tomas@797 707 if (InterfaceDeclaration* it = cd->isInterfaceDeclaration())
tomas@797 708 {
tomas@797 709 DtoConstInitInterface(it);
tomas@797 710 return;
tomas@797 711 }
tomas@797 712
tomas@797 713 if (cd->ir.initialized) return;
tomas@797 714 cd->ir.initialized = true;
tomas@797 715
tomas@797 716 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
tomas@797 717 LOG_SCOPE;
tomas@797 718
tomas@797 719 assert(!cd->isInterfaceDeclaration());
tomas@797 720
tomas@797 721 // make sure the baseclass is const initialized
tomas@797 722 if (cd->baseClass)
tomas@797 723 DtoForceConstInitDsymbol(cd->baseClass);
tomas@797 724
tomas@797 725 // get IrStruct
ChristianK@173 726 IrStruct* irstruct = cd->ir.irStruct;
lindquist@100 727 gIR->structs.push_back(irstruct);
lindquist@100 728
tomas@797 729 // get types
tomas@797 730 TypeClass* tc = (TypeClass*)cd->type;
tomas@797 731 const llvm::StructType* structtype = isaStruct(tc->ir.type->get());
tomas@797 732 assert(structtype);
tomas@797 733 const llvm::ArrayType* vtbltype = isaArray(irstruct->vtblTy.get());
tomas@797 734 assert(vtbltype);
lindquist@133 735
tomas@797 736 // build initializer list
tomas@797 737 std::vector<LLConstant*> inits;
tomas@797 738 inits.reserve(irstruct->varDecls.size());
tomas@797 739
tomas@797 740 // vtable is always first
tomas@797 741 assert(irstruct->vtbl != 0);
tomas@797 742 inits.push_back(irstruct->vtbl);
tomas@797 743
tomas@797 744 // then comes monitor
tomas@797 745 inits.push_back(LLConstant::getNullValue(getVoidPtrType()));
tomas@797 746
tomas@797 747 // recursively do data and interface vtables
tomas@797 748 init_class_initializer(inits, cd, cd, 2 * PTRSIZE);
tomas@797 749
tomas@797 750 // build vtable initializer
tomas@797 751 init_class_vtbl_initializer(cd);
tomas@797 752
tomas@797 753 // build interface vtables
tomas@797 754 init_class_interface_vtbl_initializers(cd);
tomas@797 755
tomas@797 756 // build constant from inits
tomas@812 757 assert(!irstruct->constInit);
tomas@797 758 irstruct->constInit = LLConstantStruct::get(inits); // classes are never packed
tomas@797 759
tomas@797 760 // refine __initZ global type to the one of the initializer
tomas@797 761 llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
tomas@797 762
tomas@825 763 // if (Logger::enabled())
tomas@825 764 // {
tomas@825 765 // Logger::cout() << "class " << cd->toChars() << std::endl;
tomas@825 766 // Logger::cout() << "type " << *cd->type->ir.type->get() << std::endl;
tomas@825 767 // Logger::cout() << "initializer " << *irstruct->constInit << std::endl;
tomas@825 768 // }
lindquist@100 769
lindquist@100 770 gIR->structs.pop_back();
lindquist@100 771 }
lindquist@100 772
lindquist@100 773 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 774
tomas@797 775 static void DefineInterfaceInfos(IrStruct* irstruct)
tomas@797 776 {
tomas@797 777 // always do interface info array when possible
tomas@797 778 std::vector<LLConstant*> infoInits;
tomas@797 779
tomas@809 780 size_t n = irstruct->interfaceVec.size();
tomas@809 781 infoInits.reserve(n);
tomas@809 782
tomas@809 783 for (size_t i=0; i < n; i++)
tomas@797 784 {
tomas@809 785 IrInterface* iri = irstruct->interfaceVec[i];
tomas@797 786 assert(iri->infoInit);
tomas@797 787 infoInits.push_back(iri->infoInit);
tomas@797 788 }
tomas@797 789
tomas@797 790 // set initializer
tomas@797 791 if (!infoInits.empty())
tomas@797 792 {
tomas@797 793 const LLArrayType* arrty = LLArrayType::get(infoInits[0]->getType(), infoInits.size());
tomas@797 794 LLConstant* arrInit = llvm::ConstantArray::get(arrty, infoInits);
tomas@797 795 irstruct->interfaceInfos->setInitializer(arrInit);
tomas@797 796 }
tomas@797 797 else
tomas@797 798 {
tomas@797 799 assert(irstruct->interfaceInfos == NULL);
tomas@797 800 }
tomas@797 801 }
tomas@797 802
tomas@797 803 //////////////////////////////////////////////////////////////////////////////////////////
tomas@797 804
tomas@797 805 static void DtoDefineInterface(InterfaceDeclaration* cd)
tomas@797 806 {
tomas@797 807 if (cd->ir.defined) return;
tomas@797 808 cd->ir.defined = true;
tomas@797 809
tomas@797 810 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
tomas@797 811 LOG_SCOPE;
tomas@797 812
tomas@797 813 // defined interface infos
tomas@797 814 DefineInterfaceInfos(cd->ir.irStruct);
tomas@797 815
tomas@797 816 // define the classinfo
tomas@797 817 if (cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd))
tomas@797 818 {
tomas@797 819 DtoDefineClassInfo(cd);
tomas@797 820 }
tomas@797 821 }
tomas@797 822
tomas@797 823 //////////////////////////////////////////////////////////////////////////////////////////
tomas@797 824
tomas@797 825 // FIXME: clean this up
tomas@797 826
lindquist@100 827 void DtoDefineClass(ClassDeclaration* cd)
lindquist@100 828 {
tomas@797 829 if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
tomas@797 830 {
tomas@797 831 DtoDefineInterface(id);
tomas@797 832 return;
tomas@797 833 }
tomas@797 834
ChristianK@173 835 if (cd->ir.defined) return;
ChristianK@173 836 cd->ir.defined = true;
lindquist@100 837
lindquist@132 838 Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
lindquist@100 839 LOG_SCOPE;
lindquist@100 840
lindquist@100 841 // get the struct (class) type
lindquist@100 842 assert(cd->type->ty == Tclass);
lindquist@100 843 TypeClass* ts = (TypeClass*)cd->type;
lindquist@100 844
tomas@797 845 IrStruct* irstruct = cd->ir.irStruct;
lindquist@177 846
tomas@797 847 assert(cd->getModule() == gIR->dmodule || DtoIsTemplateInstance(cd));
lindquist@113 848
tomas@797 849 // sanity check
tomas@797 850 assert(irstruct->init);
tomas@797 851 assert(irstruct->constInit);
tomas@797 852 assert(irstruct->vtbl);
tomas@797 853 assert(irstruct->constVtbl);
lindquist@177 854
tomas@809 855 // if (Logger::enabled())
tomas@809 856 // {
tomas@809 857 // Logger::cout() << "initZ: " << *irstruct->init << std::endl;
tomas@809 858 // Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl;
tomas@809 859 // Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl;
tomas@809 860 // Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl;
tomas@809 861 // }
lindquist@123 862
tomas@797 863 // set initializers
tomas@797 864 irstruct->init->setInitializer(irstruct->constInit);
tomas@797 865 irstruct->vtbl->setInitializer(irstruct->constVtbl);
tomas@797 866
tomas@797 867 // initialize interface vtables
tomas@797 868 size_t n = irstruct->interfaceVec.size();
tomas@797 869 for (size_t i=0; i<n; i++)
tomas@797 870 {
tomas@797 871 IrInterface* iri = irstruct->interfaceVec[i];
tomas@797 872 Logger::println("interface %s", iri->base->base->toChars());
tomas@797 873 assert(iri->vtblInit);
tomas@797 874
tomas@797 875 // refine the init type
tomas@797 876 llvm::cast<llvm::OpaqueType>(iri->vtblInitTy.get())->refineAbstractTypeTo(iri->vtblInit->getType());
tomas@797 877
tomas@797 878 // apply initializer
tomas@797 879 assert(iri->vtbl);
tomas@797 880 iri->vtbl->setInitializer(iri->vtblInit);
lindquist@100 881 }
tomas@797 882
tomas@797 883 DefineInterfaceInfos(irstruct);
tomas@797 884
tomas@797 885 // generate classinfo
tomas@797 886 DtoDefineClassInfo(cd);
lindquist@100 887 }
lindquist@100 888
lindquist@100 889 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@100 890
tomas@486 891 DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
lindquist@133 892 {
lindquist@133 893 // resolve type
lindquist@133 894 DtoForceDeclareDsymbol(tc->sym);
lindquist@133 895
lindquist@133 896 // allocate
lindquist@213 897 LLValue* mem;
lindquist@133 898 if (newexp->onstack)
lindquist@133 899 {
kamm@479 900 mem = DtoAlloca(DtoType(tc)->getContainedType(0), ".newclass_alloca");
lindquist@133 901 }
lindquist@284 902 // custom allocator
lindquist@284 903 else if (newexp->allocator)
lindquist@284 904 {
tomas@414 905 DtoForceDeclareDsymbol(newexp->allocator);
tomas@414 906 DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
kamm@422 907 DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
tomas@414 908 mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
lindquist@284 909 }
lindquist@284 910 // default allocator
lindquist@133 911 else
lindquist@133 912 {
kamm@728 913 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass");
tomas@797 914 LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
tomas@797 915 mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc")->get();
tomas@414 916 mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
lindquist@133 917 }
lindquist@133 918
lindquist@133 919 // init
lindquist@133 920 DtoInitClass(tc, mem);
lindquist@133 921
lindquist@133 922 // init inner-class outer reference
lindquist@133 923 if (newexp->thisexp)
lindquist@133 924 {
lindquist@133 925 Logger::println("Resolving outer class");
lindquist@133 926 LOG_SCOPE;
lindquist@133 927 DValue* thisval = newexp->thisexp->toElem(gIR);
tomas@797 928 size_t idx = tc->sym->vthis->ir.irField->index;
lindquist@213 929 LLValue* src = thisval->getRVal();
lindquist@213 930 LLValue* dst = DtoGEPi(mem,0,idx,"tmp");
tomas@622 931 if (Logger::enabled())
tomas@622 932 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n';
lindquist@169 933 DtoStore(src, dst);
lindquist@133 934 }
lindquist@133 935 // set the context for nested classes
tomas@486 936 else if (tc->sym->isNested() && tc->sym->vthis)
lindquist@133 937 {
lindquist@133 938 Logger::println("Resolving nested context");
lindquist@133 939 LOG_SCOPE;
ChristianK@369 940
tomas@486 941 // get context
tomas@486 942 LLValue* nest = DtoNestedContext(loc, tc->sym);
tomas@486 943
tomas@486 944 // store into right location
tomas@797 945 size_t idx = tc->sym->vthis->ir.irField->index;
ChristianK@370 946 LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
tomas@486 947 DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
lindquist@133 948 }
lindquist@133 949
lindquist@133 950 // call constructor
lindquist@160 951 if (newexp->member)
lindquist@160 952 {
lindquist@160 953 assert(newexp->arguments != NULL);
tomas@414 954 DtoForceDeclareDsymbol(newexp->member);
tomas@414 955 DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
kamm@422 956 return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
lindquist@160 957 }
lindquist@133 958
lindquist@133 959 // return default constructed class
tomas@486 960 return new DImValue(tc, mem);
lindquist@133 961 }
lindquist@133 962
lindquist@133 963 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@133 964
lindquist@213 965 void DtoInitClass(TypeClass* tc, LLValue* dst)
lindquist@133 966 {
tomas@797 967 DtoForceConstInitDsymbol(tc->sym);
tomas@797 968
lindquist@133 969 size_t presz = 2*getABITypeSize(DtoSize_t());
ChristianK@173 970 uint64_t n = getABITypeSize(tc->ir.type->get()) - presz;
lindquist@133 971
lindquist@133 972 // set vtable field seperately, this might give better optimization
ChristianK@173 973 assert(tc->sym->ir.irStruct->vtbl);
tomas@797 974 LLValue* tmp = DtoGEPi(dst,0,0,"vtbl");
tomas@797 975 LLValue* val = DtoBitCast(tc->sym->ir.irStruct->vtbl, tmp->getType()->getContainedType(0));
tomas@797 976 DtoStore(val, tmp);
lindquist@133 977
lindquist@133 978 // monitor always defaults to zero
tomas@797 979 tmp = DtoGEPi(dst,0,1,"monitor");
tomas@797 980 val = llvm::Constant::getNullValue(tmp->getType()->getContainedType(0));
tomas@797 981 DtoStore(val, tmp);
lindquist@133 982
lindquist@133 983 // done?
lindquist@133 984 if (n == 0)
lindquist@133 985 return;
lindquist@133 986
lindquist@133 987 // copy the rest from the static initializer
ChristianK@173 988 assert(tc->sym->ir.irStruct->init);
lindquist@133 989
lindquist@244 990 LLValue* dstarr = DtoGEPi(dst,0,2,"tmp");
lindquist@244 991 LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->init,0,2,"tmp");
lindquist@133 992
lindquist@244 993 DtoMemCpy(dstarr, srcarr, DtoConstSize_t(n));
lindquist@133 994 }
lindquist@133 995
lindquist@133 996 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@133 997
lindquist@213 998 void DtoFinalizeClass(LLValue* inst)
lindquist@209 999 {
lindquist@209 1000 // get runtime function
lindquist@209 1001 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_callfinalizer");
lindquist@209 1002 // build args
lindquist@213 1003 LLSmallVector<LLValue*,1> arg;
lindquist@209 1004 arg.push_back(DtoBitCast(inst, fn->getFunctionType()->getParamType(0), ".tmp"));
lindquist@209 1005 // call
ChristianK@315 1006 gIR->CreateCallOrInvoke(fn, arg.begin(), arg.end(), "");
lindquist@209 1007 }
lindquist@209 1008
lindquist@209 1009 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@209 1010
lindquist@114 1011 DValue* DtoCastClass(DValue* val, Type* _to)
lindquist@114 1012 {
lindquist@138 1013 Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars());
lindquist@138 1014 LOG_SCOPE;
lindquist@138 1015
tomas@486 1016 Type* to = _to->toBasetype();
tomas@797 1017
tomas@797 1018 // class -> pointer
lindquist@114 1019 if (to->ty == Tpointer) {
kamm@778 1020 Logger::println("to pointer");
lindquist@213 1021 const LLType* tolltype = DtoType(_to);
lindquist@213 1022 LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
lindquist@114 1023 return new DImValue(_to, rval);
lindquist@114 1024 }
tomas@797 1025 // class -> bool
kamm@778 1026 else if (to->ty == Tbool) {
kamm@778 1027 Logger::println("to bool");
kamm@778 1028 LLValue* llval = val->getRVal();
kamm@778 1029 LLValue* zero = LLConstant::getNullValue(llval->getType());
kamm@778 1030 return new DImValue(_to, gIR->ir->CreateICmpNE(llval, zero, "tmp"));
kamm@778 1031 }
lindquist@114 1032
tomas@797 1033 // must be class/interface
lindquist@114 1034 assert(to->ty == Tclass);
lindquist@114 1035 TypeClass* tc = (TypeClass*)to;
lindquist@114 1036
tomas@797 1037 // from type
tomas@486 1038 Type* from = val->getType()->toBasetype();
lindquist@114 1039 TypeClass* fc = (TypeClass*)from;
lindquist@114 1040
tomas@797 1041 // x -> interface
tomas@797 1042 if (InterfaceDeclaration* it = tc->sym->isInterfaceDeclaration()) {
lindquist@138 1043 Logger::println("to interface");
tomas@797 1044 // interface -> interface
lindquist@133 1045 if (fc->sym->isInterfaceDeclaration()) {
lindquist@138 1046 Logger::println("from interface");
lindquist@133 1047 return DtoDynamicCastInterface(val, _to);
lindquist@133 1048 }
tomas@797 1049 // class -> interface - static cast
tomas@797 1050 else if (it->isBaseOf(fc->sym,NULL)) {
tomas@797 1051 Logger::println("static down cast)");
tomas@797 1052 // get the from class
tomas@797 1053 ClassDeclaration* cd = fc->sym->isClassDeclaration();
tomas@797 1054 IrStruct* irstruct = cd->ir.irStruct;
tomas@797 1055 // find interface impl
tomas@797 1056 IrStruct::InterfaceMapIter iriter = irstruct->interfaceMap.find(it);
tomas@797 1057 assert(iriter != irstruct->interfaceMap.end());
tomas@797 1058 IrInterface* iri = iriter->second;
tomas@797 1059 // offset pointer
tomas@797 1060 LLValue* v = val->getRVal();
tomas@797 1061 v = DtoGEPi(v, 0, iri->index);
tomas@797 1062 if (Logger::enabled())
tomas@797 1063 {
tomas@797 1064 Logger::cout() << "V = " << *v << std::endl;
tomas@797 1065 Logger::cout() << "T = " << *DtoType(_to) << std::endl;
tomas@797 1066 }
tomas@797 1067 v = DtoBitCast(v, DtoType(_to));
tomas@797 1068 // return r-value
tomas@797 1069 return new DImValue(_to, v);
tomas@797 1070 }
tomas@797 1071 // class -> interface
lindquist@133 1072 else {
lindquist@138 1073 Logger::println("from object");
lindquist@133 1074 return DtoDynamicCastObject(val, _to);
lindquist@133 1075 }
lindquist@114 1076 }
tomas@797 1077 // x -> class
lindquist@114 1078 else {
kamm@778 1079 Logger::println("to class");
lindquist@114 1080 int poffset;
tomas@797 1081 // interface -> class
lindquist@114 1082 if (fc->sym->isInterfaceDeclaration()) {
lindquist@138 1083 Logger::println("interface cast");
lindquist@114 1084 return DtoCastInterfaceToObject(val, _to);
lindquist@114 1085 }
tomas@797 1086 // class -> class - static down cast
tomas@797 1087 else if (tc->sym->isBaseOf(fc->sym,NULL)) {
lindquist@138 1088 Logger::println("static down cast)");
lindquist@213 1089 const LLType* tolltype = DtoType(_to);
lindquist@213 1090 LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
lindquist@114 1091 return new DImValue(_to, rval);
lindquist@114 1092 }
tomas@797 1093 // class -> class - dynamic up cast
lindquist@114 1094 else {
lindquist@138 1095 Logger::println("dynamic up cast");
lindquist@114 1096 return DtoDynamicCastObject(val, _to);
lindquist@114 1097 }
lindquist@114 1098 }
lindquist@114 1099 }
lindquist@114 1100
lindquist@114 1101 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@114 1102
lindquist@114 1103 DValue* DtoDynamicCastObject(DValue* val, Type* _to)
lindquist@113 1104 {
lindquist@113 1105 // call:
lindquist@113 1106 // Object _d_dynamic_cast(Object o, ClassInfo c)
lindquist@113 1107
lindquist@114 1108 DtoForceDeclareDsymbol(ClassDeclaration::object);
lindquist@114 1109 DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
lindquist@114 1110
lindquist@113 1111 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
lindquist@113 1112 const llvm::FunctionType* funcTy = func->getFunctionType();
lindquist@113 1113
lindquist@213 1114 std::vector<LLValue*> args;
lindquist@113 1115
lindquist@113 1116 // Object o
lindquist@217 1117 LLValue* obj = val->getRVal();
lindquist@217 1118 obj = DtoBitCast(obj, funcTy->getParamType(0));
lindquist@217 1119 assert(funcTy->getParamType(0) == obj->getType());
lindquist@113 1120
lindquist@113 1121 // ClassInfo c
tomas@486 1122 TypeClass* to = (TypeClass*)_to->toBasetype();
lindquist@113 1123 DtoForceDeclareDsymbol(to->sym);
ChristianK@173 1124 assert(to->sym->ir.irStruct->classInfo);
lindquist@217 1125 LLValue* cinfo = to->sym->ir.irStruct->classInfo;
lindquist@114 1126 // unfortunately this is needed as the implementation of object differs somehow from the declaration
lindquist@114 1127 // this could happen in user code as well :/
lindquist@217 1128 cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
lindquist@217 1129 assert(funcTy->getParamType(1) == cinfo->getType());
lindquist@113 1130
lindquist@113 1131 // call it
ChristianK@315 1132 LLValue* ret = gIR->CreateCallOrInvoke2(func, obj, cinfo, "tmp")->get();
lindquist@114 1133
lindquist@114 1134 // cast return value
lindquist@113 1135 ret = DtoBitCast(ret, DtoType(_to));
lindquist@114 1136
lindquist@113 1137 return new DImValue(_to, ret);
lindquist@113 1138 }
lindquist@113 1139
lindquist@113 1140 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@113 1141
lindquist@114 1142 DValue* DtoCastInterfaceToObject(DValue* val, Type* to)
lindquist@113 1143 {
lindquist@113 1144 // call:
lindquist@113 1145 // Object _d_toObject(void* p)
lindquist@113 1146
lindquist@113 1147 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
lindquist@113 1148 const llvm::FunctionType* funcTy = func->getFunctionType();
lindquist@113 1149
lindquist@113 1150 // void* p
lindquist@213 1151 LLValue* tmp = val->getRVal();
lindquist@113 1152 tmp = DtoBitCast(tmp, funcTy->getParamType(0));
lindquist@113 1153
lindquist@113 1154 // call it
ChristianK@315 1155 LLValue* ret = gIR->CreateCallOrInvoke(func, tmp, "tmp")->get();
lindquist@114 1156
lindquist@114 1157 // cast return value
lindquist@114 1158 if (to != NULL)
lindquist@114 1159 ret = DtoBitCast(ret, DtoType(to));
lindquist@114 1160 else
lindquist@114 1161 to = ClassDeclaration::object->type;
lindquist@114 1162
lindquist@114 1163 return new DImValue(to, ret);
lindquist@113 1164 }
lindquist@113 1165
lindquist@113 1166 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@113 1167
lindquist@133 1168 DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
lindquist@133 1169 {
lindquist@133 1170 // call:
lindquist@133 1171 // Object _d_interface_cast(void* p, ClassInfo c)
lindquist@133 1172
lindquist@133 1173 DtoForceDeclareDsymbol(ClassDeclaration::object);
lindquist@133 1174 DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
lindquist@133 1175
lindquist@133 1176 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
lindquist@133 1177 const llvm::FunctionType* funcTy = func->getFunctionType();
lindquist@133 1178
lindquist@213 1179 std::vector<LLValue*> args;
lindquist@133 1180
lindquist@133 1181 // void* p
lindquist@217 1182 LLValue* ptr = val->getRVal();
lindquist@217 1183 ptr = DtoBitCast(ptr, funcTy->getParamType(0));
lindquist@133 1184
lindquist@133 1185 // ClassInfo c
tomas@486 1186 TypeClass* to = (TypeClass*)_to->toBasetype();
lindquist@133 1187 DtoForceDeclareDsymbol(to->sym);
ChristianK@173 1188 assert(to->sym->ir.irStruct->classInfo);
lindquist@217 1189 LLValue* cinfo = to->sym->ir.irStruct->classInfo;
lindquist@133 1190 // unfortunately this is needed as the implementation of object differs somehow from the declaration
lindquist@133 1191 // this could happen in user code as well :/
lindquist@217 1192 cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
lindquist@133 1193
lindquist@133 1194 // call it
ChristianK@315 1195 LLValue* ret = gIR->CreateCallOrInvoke2(func, ptr, cinfo, "tmp")->get();
lindquist@133 1196
lindquist@133 1197 // cast return value
lindquist@133 1198 ret = DtoBitCast(ret, DtoType(_to));
lindquist@133 1199
lindquist@133 1200 return new DImValue(_to, ret);
lindquist@133 1201 }
lindquist@133 1202
lindquist@133 1203 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@133 1204
tomas@705 1205 LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
lindquist@132 1206 {
tomas@705 1207 Logger::println("indexing class field %s:", vd->toPrettyChars());
lindquist@132 1208 LOG_SCOPE;
lindquist@132 1209
tomas@705 1210 if (Logger::enabled())
tomas@705 1211 Logger::cout() << "src: " << *src << '\n';
tomas@705 1212
tomas@705 1213 // vd must be a field
tomas@705 1214 IrField* field = vd->ir.irField;
tomas@705 1215 assert(field);
tomas@705 1216
tomas@797 1217 // get the start pointer
lindquist@213 1218 const LLType* st = DtoType(cd->type);
tomas@797 1219 // cast to the struct type
tomas@705 1220 src = DtoBitCast(src, st);
lindquist@132 1221
tomas@797 1222 // gep to the index
tomas@797 1223 if (Logger::enabled())
tomas@797 1224 {
tomas@797 1225 Logger::cout() << "src2: " << *src << '\n';
tomas@797 1226 Logger::cout() << "index: " << field->index << '\n';
tomas@797 1227 Logger::cout() << "srctype: " << *src->getType() << '\n';
tomas@797 1228 }
tomas@797 1229 LLValue* val = DtoGEPi(src, 0, field->index);
tomas@797 1230
tomas@797 1231 // do we need to offset further? (union area)
tomas@797 1232 if (field->unionOffset)
tomas@797 1233 {
tomas@797 1234 // cast to void*
tomas@797 1235 val = DtoBitCast(val, getVoidPtrType());
tomas@797 1236 // offset
tomas@797 1237 val = DtoGEPi1(val, field->unionOffset);
tomas@797 1238 }
tomas@797 1239
tomas@797 1240 // cast it to the right type
tomas@705 1241 val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
lindquist@132 1242
tomas@705 1243 if (Logger::enabled())
tomas@705 1244 Logger::cout() << "value: " << *val << '\n';
lindquist@132 1245
tomas@705 1246 return val;
lindquist@132 1247 }
lindquist@132 1248
lindquist@132 1249 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@132 1250
lindquist@213 1251 LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
lindquist@133 1252 {
tomas@809 1253 // sanity checks
tomas@809 1254 assert(fdecl->isVirtual());
tomas@809 1255 assert(fdecl->vtblIndex > 0); // 0 is always ClassInfo/Interface*
tomas@486 1256 assert(inst->getType()->toBasetype()->ty == Tclass);
lindquist@133 1257
tomas@809 1258 // get instance
lindquist@213 1259 LLValue* vthis = inst->getRVal();
tomas@622 1260 if (Logger::enabled())
tomas@622 1261 Logger::cout() << "vthis: " << *vthis << '\n';
lindquist@133 1262
tomas@797 1263 LLValue* funcval = vthis;
tomas@809 1264 // get the vtbl for objects
tomas@809 1265 if (!fdecl->isMember()->isInterfaceDeclaration())
tomas@797 1266 funcval = DtoGEPi(funcval, 0, 0, "tmp");
tomas@809 1267 // load vtbl ptr
lindquist@133 1268 funcval = DtoLoad(funcval);
tomas@809 1269 // index vtbl
tomas@804 1270 funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
tomas@809 1271 // load funcptr
lindquist@133 1272 funcval = DtoLoad(funcval);
lindquist@133 1273
tomas@622 1274 if (Logger::enabled())
tomas@622 1275 Logger::cout() << "funcval: " << *funcval << '\n';
lindquist@193 1276
tomas@809 1277 // cast to final funcptr type
lindquist@193 1278 funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
tomas@622 1279 if (Logger::enabled())
tomas@622 1280 Logger::cout() << "funcval casted: " << *funcval << '\n';
lindquist@193 1281
lindquist@133 1282 return funcval;
lindquist@133 1283 }
lindquist@133 1284
lindquist@133 1285 //////////////////////////////////////////////////////////////////////////////////////////
lindquist@133 1286
lindquist@100 1287 void DtoDeclareClassInfo(ClassDeclaration* cd)
lindquist@100 1288 {
tomas@797 1289 IrStruct* irstruct = cd->ir.irStruct;
tomas@797 1290
tomas@797 1291 if (irstruct->classInfoDeclared) return;
tomas@797 1292 irstruct->classInfoDeclared = true;
lindquist@100 1293
lindquist@102 1294 Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
lindquist@100 1295 LOG_SCOPE;
lindquist@100 1296
tomas@809 1297 // resovle ClassInfo
lindquist@100 1298 ClassDeclaration* cinfo = ClassDeclaration::classinfo;
lindquist@102 1299 DtoResolveClass(cinfo);
lindquist@100 1300
tomas@809 1301 // do the mangle
lindquist@100 1302 std::string gname("_D");
lindquist@100 1303 gname.append(cd->mangle());
lindquist@113 1304 if (!cd->isInterfaceDeclaration())
lindquist@113 1305 gname.append("7__ClassZ");
lindquist@113 1306 else
lindquist@113 1307 gname.append("11__InterfaceZ");
lindquist@100 1308
tomas@809 1309 // create global
tomas@797 1310 irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, gname, gIR->module);
lindquist@100 1311 }
lindquist@100 1312
tomas@809 1313 //////////////////////////////////////////////////////////////////////////////////////////
tomas@809 1314
tomas@821 1315 #if GENERATE_OFFTI
tomas@821 1316
tomas@809 1317 // build a single element for the OffsetInfo[] of ClassInfo
lindquist@271 1318 static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)
lindquist@110 1319 {
tomas@809 1320 std::vector<LLConstant*> inits(2);
lindquist@110 1321
tomas@809 1322 // size_t offset;
tomas@809 1323 //
tomas@809 1324 assert(vd->ir.irField);
tomas@809 1325 // grab the offset from llvm and the formal class type
tomas@809 1326 size_t offset = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(vd->ir.irField->index);
tomas@809 1327 // offset nested struct/union fields
tomas@809 1328 offset += vd->ir.irField->unionOffset;
lindquist@110 1329
tomas@809 1330 // assert that it matches DMD
tomas@809 1331 Logger::println("offsets: %lu vs %u", offset, vd->offset);
tomas@809 1332 assert(offset == vd->offset);
lindquist@110 1333
tomas@809 1334 inits[0] = DtoConstSize_t(offset);
lindquist@110 1335
tomas@809 1336 // TypeInfo ti;
tomas@809 1337 inits[1] = DtoTypeInfoOf(vd->type, true);
lindquist@110 1338
tomas@809 1339 // done
tomas@809 1340 return llvm::ConstantStruct::get(inits);
lindquist@110 1341 }
lindquist@110 1342
tomas@809 1343 static LLConstant* build_offti_array(ClassDeclaration* cd, const LLType* arrayT)
lindquist@110 1344 {
tomas@809 1345 IrStruct* irstruct = cd->ir.irStruct;
lindquist@110 1346
tomas@809 1347 size_t nvars = irstruct->varDecls.size();
tomas@809 1348 std::vector<LLConstant*> arrayInits(nvars);
tomas@797 1349
tomas@797 1350 for (size_t i=0; i<nvars; i++)
lindquist@110 1351 {
tomas@809 1352 arrayInits[i] = build_offti_entry(cd, irstruct->varDecls[i]);
lindquist@110 1353 }
lindquist@110 1354
tomas@809 1355 LLConstant* size = DtoConstSize_t(nvars);
lindquist@213 1356 LLConstant* ptr;
lindquist@110 1357
tomas@809 1358 if (nvars == 0)
tomas@809 1359 return LLConstant::getNullValue( arrayT );
lindquist@110 1360
tomas@809 1361 // array type
tomas@809 1362 const llvm::ArrayType* arrTy = llvm::ArrayType::get(arrayInits[0]->getType(), nvars);
tomas@809 1363 LLConstant* arrInit = llvm::ConstantArray::get(arrTy, arrayInits);
lindquist@110 1364
tomas@809 1365 // mangle
tomas@809 1366 std::string name(cd->type->vtinfo->toChars());
tomas@809 1367 name.append("__OffsetTypeInfos");
lindquist@149 1368
tomas@809 1369 // create symbol
tomas@809 1370 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module);
tomas@809 1371 ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));
lindquist@110 1372
lindquist@110 1373 return DtoConstSlice(size, ptr);
lindquist@110 1374 }
lindquist@110 1375
tomas@821 1376 #endif // GENERATE_OFFTI
tomas@821 1377
lindquist@213 1378 static LLConstant* build_class_dtor(ClassDeclaration* cd)
lindquist@112 1379 {
lindquist@268 1380 FuncDeclaration* dtor = cd->dtor;
lindquist@268 1381
lindquist@268 1382 // if no destructor emit a null
lindquist@268 1383 if (!dtor)
lindquist@268 1384 return getNullPtr(getVoidPtrType());
lindquist@268 1385
lindquist@268 1386 DtoForceDeclareDsymbol(dtor);
lindquist@268 1387 return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty));
lindquist@112 1388 }
lindquist@112 1389
lindquist@285 1390 static unsigned build_classinfo_flags(ClassDeclaration* cd)
lindquist@112 1391 {
lindquist@113 1392 // adapted from original dmd code
lindquist@285 1393 unsigned flags = 0;
lindquist@112 1394 //flags |= isCOMclass(); // IUnknown
lindquist@112 1395 bool hasOffTi = false;
lindquist@112 1396 if (cd->ctor) flags |= 8;
lindquist@112 1397 for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
lindquist@112 1398 {
lindquist@112 1399 if (cd2->members)
lindquist@112 1400 {
lindquist@112 1401 for (size_t i = 0; i < cd2->members->dim; i++)
lindquist@112 1402 {
lindquist@112 1403 Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
lindquist@275 1404 if (sm->isVarDeclaration() && !sm->isVarDeclaration()->isDataseg()) // is this enough?
lindquist@112 1405 hasOffTi = true;
lindquist@112 1406 //printf("sm = %s %s\n", sm->kind(), sm->toChars());
lindquist@112 1407 if (sm->hasPointers())
lindquist@112 1408 goto L2;
lindquist@112 1409 }
lindquist@112 1410 }
lindquist@112 1411 }
lindquist@112 1412 flags |= 2; // no pointers
lindquist@112 1413 L2:
lindquist@112 1414 if (hasOffTi)
lindquist@112 1415 flags |= 4;
lindquist@112 1416 return flags;
lindquist@112 1417 }
lindquist@112 1418
lindquist@100 1419 void DtoDefineClassInfo(ClassDeclaration* cd)
lindquist@100 1420 {
lindquist@100 1421 // The layout is:
lindquist@100 1422 // {
lindquist@100 1423 // void **vptr;
lindquist@100 1424 // monitor_t monitor;
lindquist@100 1425 // byte[] initializer; // static initialization data
lindquist@100 1426 // char[] name; // class name
lindquist@100 1427 // void *[] vtbl;
lindquist@100 1428 // Interface[] interfaces;
lindquist@100 1429 // ClassInfo *base; // base class
lindquist@100 1430 // void *destructor;
lindquist@100 1431 // void *invariant; // class invariant
lindquist@100 1432 // uint flags;
lindquist@100 1433 // void *deallocator;
lindquist@100 1434 // OffsetTypeInfo[] offTi;
lindquist@100 1435 // void *defaultConstructor;
lindquist@100 1436 // }
lindquist@100 1437
tomas@797 1438 IrStruct* ir = cd->ir.irStruct;
tomas@797 1439
tomas@797 1440 if (ir->classInfoDefined) return;
tomas@797 1441 ir->classInfoDefined = true;
lindquist@100 1442
lindquist@102 1443 Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
lindquist@100 1444 LOG_SCOPE;
lindquist@102 1445
lindquist@102 1446 assert(cd->type->ty == Tclass);
tomas@797 1447 assert(ir->classInfo);
lindquist@102 1448
lindquist@102 1449 TypeClass* cdty = (TypeClass*)cd->type;
tomas@812 1450 if (!cd->isInterfaceDeclaration())
tomas@809 1451 {
tomas@797 1452 assert(ir->init);
tomas@797 1453 assert(ir->constInit);
tomas@797 1454 assert(ir->vtbl);
tomas@797 1455 assert(ir->constVtbl);
lindquist@113 1456 }
lindquist@100 1457
lindquist@100 1458 // holds the list of initializers for llvm
lindquist@213 1459 std::vector<LLConstant*> inits;
lindquist@100 1460
lindquist@100 1461 ClassDeclaration* cinfo = ClassDeclaration::classinfo;
lindquist@102 1462 DtoForceConstInitDsymbol(cinfo);
lindquist@100 1463
lindquist@213 1464 LLConstant* c;
lindquist@100 1465
tomas@809 1466 const LLType* voidPtr = getVoidPtrType();
tomas@809 1467 const LLType* voidPtrPtr = getPtrToType(voidPtr);
tomas@809 1468
lindquist@100 1469 // own vtable
tomas@809 1470 c = cinfo->ir.irStruct->vtbl;
lindquist@100 1471 assert(c);
lindquist@100 1472 inits.push_back(c);
lindquist@100 1473
lindquist@100 1474 // monitor
tomas@809 1475 c = LLConstant::getNullValue(voidPtr);
lindquist@115 1476 inits.push_back(c);
lindquist@100 1477
lindquist@102 1478 // byte[] init
tomas@809 1479 if (cd->isInterfaceDeclaration())
tomas@809 1480 c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(voidPtr));
tomas@809 1481 else
tomas@809 1482 {
tomas@809 1483 c = DtoBitCast(ir->init, voidPtr);
tomas@797 1484 //Logger::cout() << *ir->constInit->getType() << std::endl;
tomas@812 1485 size_t initsz = getABITypeSize(ir->init->getType()->getContainedType(0));
lindquist@113 1486 c = DtoConstSlice(DtoConstSize_t(initsz), c);
lindquist@113 1487 }
lindquist@100 1488 inits.push_back(c);
lindquist@100 1489
lindquist@100 1490 // class name
lindquist@100 1491 // from dmd
lindquist@100 1492 char *name = cd->ident->toChars();
lindquist@100 1493 size_t namelen = strlen(name);
lindquist@100 1494 if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
lindquist@100 1495 {
lindquist@100 1496 name = cd->toPrettyChars();
lindquist@100 1497 namelen = strlen(name);
lindquist@100 1498 }
lindquist@100 1499 c = DtoConstString(name);
lindquist@100 1500 inits.push_back(c);
lindquist@100 1501
lindquist@100 1502 // vtbl array
tomas@809 1503 if (cd->isInterfaceDeclaration())
tomas@809 1504 c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(getPtrToType(voidPtr)));
lindquist@113 1505 else {
tomas@809 1506 c = DtoBitCast(ir->vtbl, voidPtrPtr);
tomas@809 1507 c = DtoConstSlice(DtoConstSize_t(cd->vtbl.dim), c);
lindquist@113 1508 }
lindquist@100 1509 inits.push_back(c);
lindquist@100 1510
lindquist@100 1511 // interfaces array
tomas@809 1512 VarDeclaration* intersVar = (VarDeclaration*)cinfo->fields.data[3];
tomas@809 1513 const LLType* intersTy = DtoType(intersVar->type);
tomas@809 1514 if (!ir->interfaceInfos)
tomas@809 1515 c = LLConstant::getNullValue(intersTy);
lindquist@113 1516 else {
tomas@809 1517 const LLType* t = intersTy->getContainedType(1); // .ptr
tomas@816 1518 // cast to Interface*
tomas@809 1519 c = DtoBitCast(ir->interfaceInfos, t);
tomas@816 1520 size_t isz = ir->interfaceVec.size();
tomas@816 1521 size_t iisz = ir->classInfoInterfaces.size();
tomas@816 1522 assert(iisz <= isz);
tomas@816 1523 // offset - we only want the 'iisz' last ones
tomas@816 1524 LLConstant* idx = DtoConstUint(isz - iisz);
tomas@816 1525 c = llvm::ConstantExpr::getGetElementPtr(c, &idx, 1);
tomas@816 1526 // make array
lindquist@113 1527 c = DtoConstSlice(DtoConstSize_t(iisz), c);
lindquist@113 1528 }
lindquist@100 1529 inits.push_back(c);
lindquist@100 1530
lindquist@100 1531 // base classinfo
tomas@809 1532 // interfaces never get a base , just the interfaces[]
tomas@809 1533 if (cd->baseClass && !cd->isInterfaceDeclaration()) {
lindquist@102 1534 DtoDeclareClassInfo(cd->baseClass);
ChristianK@173 1535 c = cd->baseClass->ir.irStruct->classInfo;
lindquist@102 1536 assert(c);
lindquist@102 1537 inits.push_back(c);
lindquist@102 1538 }
lindquist@102 1539 else {
lindquist@102 1540 // null
tomas@809 1541 c = LLConstant::getNullValue(DtoType(cinfo->type));
lindquist@102 1542 inits.push_back(c);
lindquist@102 1543 }
lindquist@100 1544
lindquist@100 1545 // destructor
tomas@809 1546 if (cd->isInterfaceDeclaration())
tomas@809 1547 c = LLConstant::getNullValue(voidPtr);
tomas@809 1548 else
lindquist@113 1549 c = build_class_dtor(cd);
lindquist@100 1550 inits.push_back(c);
lindquist@100 1551
lindquist@100 1552 // invariant
tomas@809 1553 VarDeclaration* invVar = (VarDeclaration*)cinfo->fields.data[6];
tomas@809 1554 const LLType* invTy = DtoType(invVar->type);
tomas@809 1555 if (cd->inv)
tomas@809 1556 {
ChristianK@327 1557 DtoForceDeclareDsymbol(cd->inv);
ChristianK@327 1558 c = cd->inv->ir.irFunc->func;
tomas@809 1559 c = DtoBitCast(c, invTy);
ChristianK@327 1560 }
tomas@809 1561 else
tomas@809 1562 c = LLConstant::getNullValue(invTy);
lindquist@100 1563 inits.push_back(c);
lindquist@100 1564
lindquist@113 1565 // uint flags
tomas@809 1566 if (cd->isInterfaceDeclaration())
tomas@809 1567 c = DtoConstUint(0);
lindquist@113 1568 else {
lindquist@285 1569 unsigned flags = build_classinfo_flags(cd);
lindquist@113 1570 c = DtoConstUint(flags);
lindquist@113 1571 }
lindquist@100 1572 inits.push_back(c);
lindquist@100 1573
lindquist@284 1574 // deallocator
tomas@809 1575 if (cd->aggDelete)
tomas@809 1576 {
lindquist@284 1577 DtoForceDeclareDsymbol(cd->aggDelete);
lindquist@284 1578 c = cd->aggDelete->ir.irFunc->func;
tomas@809 1579 c = DtoBitCast(c, voidPtr);
lindquist@284 1580 }
tomas@809 1581 else
tomas@809 1582 c = LLConstant::getNullValue(voidPtr);
lindquist@100 1583 inits.push_back(c);
lindquist@100 1584
lindquist@100 1585 // offset typeinfo
tomas@809 1586 VarDeclaration* offTiVar = (VarDeclaration*)cinfo->fields.data[9];
tomas@809 1587 const LLType* offTiTy = DtoType(offTiVar->type);
tomas@821 1588
tomas@821 1589 #if GENERATE_OFFTI
tomas@821 1590
tomas@809 1591 if (cd->isInterfaceDeclaration())
tomas@809 1592 c = LLConstant::getNullValue(offTiTy);
tomas@809 1593 else
tomas@809 1594 c = build_offti_array(cd, offTiTy);
tomas@821 1595
tomas@821 1596 #else // GENERATE_OFFTI
tomas@821 1597
tomas@821 1598 c = LLConstant::getNullValue(offTiTy);
tomas@821 1599
tomas@821 1600 #endif // GENERATE_OFFTI
tomas@821 1601
lindquist@100 1602 inits.push_back(c);
lindquist@100 1603
lindquist@100 1604 // default constructor
tomas@809 1605 if (cd->defaultCtor)
tomas@809 1606 {
lindquist@111 1607 DtoForceDeclareDsymbol(cd->defaultCtor);
ChristianK@173 1608 c = isaConstant(cd->defaultCtor->ir.irFunc->func);
tomas@809 1609 c = DtoBitCast(c, voidPtr);
lindquist@111 1610 }
tomas@809 1611 else
tomas@809 1612 c = LLConstant::getNullValue(voidPtr);
lindquist@100 1613 inits.push_back(c);
lindquist@100 1614
tomas@758 1615 #if DMDV2
tomas@758 1616
tomas@758 1617 // xgetMembers
tomas@809 1618 VarDeclaration* xgetVar = (VarDeclaration*)cinfo->fields.data[11];
tomas@809 1619 const LLType* xgetTy = DtoType(xgetVar->type);
tomas@809 1620
tomas@809 1621 // FIXME: fill it out!
tomas@809 1622 inits.push_back( LLConstant::getNullValue(xgetTy) );
tomas@758 1623 #endif
tomas@758 1624
lindquist@100 1625 /*size_t n = inits.size();
lindquist@100 1626 for (size_t i=0; i<n; ++i)
lindquist@100 1627 {
lindquist@100 1628 Logger::cout() << "inits[" << i << "]: " << *inits[i] << '\n';
lindquist@100 1629 }*/
lindquist@100 1630
lindquist@100 1631 // build the initializer
tomas@797 1632 LLConstant* finalinit = llvm::ConstantStruct::get(inits);
lindquist@100 1633 //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
tomas@797 1634 ir->constClassInfo = finalinit;
lindquist@100 1635
tomas@797 1636 // refine the type
tomas@797 1637 llvm::cast<llvm::OpaqueType>(ir->classInfoOpaque.get())->refineAbstractTypeTo(finalinit->getType());
tomas@797 1638
tomas@797 1639 // apply initializer
tomas@797 1640 ir->classInfo->setInitializer(finalinit);
lindquist@100 1641 }