1212#include " dmd/aggregate.h"
1313#include " dmd/declaration.h"
1414#include " dmd/dsymbol.h"
15+ #include " dmd/errors.h"
1516#include " dmd/mtype.h"
1617#include " dmd/target.h"
1718#include " dmd/template.h"
@@ -60,24 +61,34 @@ void IrTypeClass::addClassData(AggrTypeBuilder &builder,
6061}
6162
6263IrTypeClass *IrTypeClass::get (ClassDeclaration *cd) {
64+ const auto t = new IrTypeClass (cd);
65+ getIrType (cd->type ) = t;
66+ return t;
67+ }
68+
69+ llvm::Type *IrTypeClass::getLLType () { return getOpaquePtrType (); }
70+
71+ // Lazily build the actual IR struct type when needed.
72+ // Note that it is this function that initializes most fields!
73+ llvm::Type *IrTypeClass::getMemoryLLType () {
74+ if (!isaStruct (type)->isOpaque ())
75+ return type;
76+
6377 IF_LOG Logger::println (" Building class type %s @ %s" , cd->toPrettyChars (),
6478 cd->loc .toChars ());
6579 LOG_SCOPE;
6680
67- const auto t = new IrTypeClass (cd);
68- getIrType (cd->type ) = t;
69-
7081 const unsigned instanceSize = cd->structsize ;
7182 IF_LOG Logger::println (" Instance size: %u" , instanceSize);
7283
7384 AggrTypeBuilder builder;
7485
7586 // add vtbl
76- builder.addType (llvm::PointerType::get (t-> vtbl_type , 0 ), target.ptrsize );
87+ builder.addType (llvm::PointerType::get (vtbl_type, 0 ), target.ptrsize );
7788
7889 if (cd->isInterfaceDeclaration ()) {
7990 // interfaces are just a vtable
80- t-> num_interface_vtbls =
91+ num_interface_vtbls =
8192 cd->vtblInterfaces ? cd->vtblInterfaces ->length : 0 ;
8293 } else {
8394 // classes have monitor and fields
@@ -87,34 +98,48 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
8798 }
8899
89100 // add data members recursively
90- t-> addClassData (builder, cd);
101+ addClassData (builder, cd);
91102
92103 // add tail padding
93104 if (instanceSize) // can be 0 for opaque classes
94105 builder.addTailPadding (instanceSize);
95106 }
96107
97108 // set struct body and copy GEP indices
98- isaStruct (t-> type )->setBody (builder.defaultTypes (), builder.isPacked ());
99- t-> varGEPIndices = builder.varGEPIndices ();
109+ isaStruct (type)->setBody (builder.defaultTypes (), builder.isPacked ());
110+ varGEPIndices = builder.varGEPIndices ();
100111
101- IF_LOG Logger::cout () << " class type: " << *t->type << std::endl;
102-
103- return t;
104- }
112+ if (!cd->isInterfaceDeclaration () && instanceSize &&
113+ getTypeAllocSize (type) != instanceSize) {
114+ error (cd->loc , " ICE: class IR size does not match the frontend size" );
115+ fatal ();
116+ }
105117
106- llvm::Type * IrTypeClass::getLLType () { return llvm::PointerType::get ( type, 0 ); }
118+ IF_LOG Logger::cout () << " class type: " << * type << std::endl;
107119
108- llvm::Type *IrTypeClass::getMemoryLLType () { return type; }
120+ return type;
121+ }
109122
110123size_t IrTypeClass::getInterfaceIndex (ClassDeclaration *inter) {
124+ getMemoryLLType (); // lazily resolve
125+
111126 auto it = interfaceMap.find (inter);
112127 if (it == interfaceMap.end ()) {
113128 return ~0UL ;
114129 }
115130 return it->second ;
116131}
117132
133+ unsigned IrTypeClass::getNumInterfaceVtbls () {
134+ getMemoryLLType (); // lazily resolve
135+ return num_interface_vtbls;
136+ }
137+
138+ const VarGEPIndices &IrTypeClass::getVarGEPIndices () {
139+ getMemoryLLType (); // lazily resolve
140+ return varGEPIndices;
141+ }
142+
118143void IrTypeClass::addInterfaceToMap (ClassDeclaration *inter, size_t index) {
119144 // don't duplicate work or overwrite indices
120145 if (interfaceMap.find (inter) != interfaceMap.end ()) {
0 commit comments