Skip to content

Commit

Permalink
Lazily define class *memory* IR type
Browse files Browse the repository at this point in the history
To break remaining cycles in DtoType() - a class *ref* is an opaque
IR pointer nowadays.
  • Loading branch information
kinke committed Aug 18, 2024
1 parent 0496358 commit 34c353d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 15 deletions.
3 changes: 2 additions & 1 deletion ir/irtypeaggr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,11 @@ IrTypeAggr::IrTypeAggr(AggregateDeclaration *ad)
LLStructType::create(gIR->context(), ad->toPrettyChars())),
aggr(ad) {}

unsigned IrTypeAggr::getMemberLocation(VarDeclaration *var, bool& isFieldIdx) const {
unsigned IrTypeAggr::getMemberLocation(VarDeclaration *var, bool& isFieldIdx) {
// Note: The interface is a bit more general than what we actually return.
// Specifically, the frontend offset information we use for overlapping
// fields is always based at the object start.
const auto &varGEPIndices = getVarGEPIndices();
auto it = varGEPIndices.find(var);
if (it != varGEPIndices.end()) {
isFieldIdx = true;
Expand Down
4 changes: 3 additions & 1 deletion ir/irtypeaggr.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class IrTypeAggr : public IrType {
/// Returns the index of the field in the LLVM struct type that corresponds
/// to the given member variable, plus the offset to the actual field start
/// due to overlapping (union) fields, if any.
unsigned getMemberLocation(VarDeclaration *var, bool& isFieldIdx) const;
unsigned getMemberLocation(VarDeclaration *var, bool& isFieldIdx);

protected:
///
Expand All @@ -90,6 +90,8 @@ class IrTypeAggr : public IrType {
/// the field index of a variable in the frontend, it only stores the byte
/// offset.
VarGEPIndices varGEPIndices;

virtual const VarGEPIndices &getVarGEPIndices() { return varGEPIndices; }
};

// A helper for aggregating consecutive bit fields to a group.
Expand Down
41 changes: 29 additions & 12 deletions ir/irtypeclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,26 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
const auto t = new IrTypeClass(cd);
getIrType(cd->type) = t;

return t;
}

llvm::Type *IrTypeClass::getLLType() { return getOpaquePtrType(); }

llvm::Type *IrTypeClass::getMemoryLLType() {
if (!isaStruct(type)->isOpaque())
return type;

const unsigned instanceSize = cd->structsize;
IF_LOG Logger::println("Instance size: %u", instanceSize);

AggrTypeBuilder builder;

// add vtbl
builder.addType(llvm::PointerType::get(t->vtbl_type, 0), target.ptrsize);
builder.addType(llvm::PointerType::get(vtbl_type, 0), target.ptrsize);

if (cd->isInterfaceDeclaration()) {
// interfaces are just a vtable
t->num_interface_vtbls =
num_interface_vtbls =
cd->vtblInterfaces ? cd->vtblInterfaces->length : 0;
} else {
// classes have monitor and fields
Expand All @@ -88,40 +97,48 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
}

// add data members recursively
t->addClassData(builder, cd);
addClassData(builder, cd);

// add tail padding
if (instanceSize) // can be 0 for opaque classes
builder.addTailPadding(instanceSize);
}

// set struct body and copy GEP indices
isaStruct(t->type)->setBody(builder.defaultTypes(), builder.isPacked());
t->varGEPIndices = builder.varGEPIndices();
isaStruct(type)->setBody(builder.defaultTypes(), builder.isPacked());
varGEPIndices = builder.varGEPIndices();

if (!cd->isInterfaceDeclaration() && instanceSize &&
getTypeAllocSize(t->type) != instanceSize) {
getTypeAllocSize(type) != instanceSize) {
error(cd->loc, "ICE: class IR size does not match the frontend size");
fatal();
}

IF_LOG Logger::cout() << "class type: " << *t->type << std::endl;
IF_LOG Logger::cout() << "class type: " << *type << std::endl;

return t;
return type;
}

llvm::Type *IrTypeClass::getLLType() { return llvm::PointerType::get(type, 0); }

llvm::Type *IrTypeClass::getMemoryLLType() { return type; }

size_t IrTypeClass::getInterfaceIndex(ClassDeclaration *inter) {
getMemoryLLType(); // lazily resolve

auto it = interfaceMap.find(inter);
if (it == interfaceMap.end()) {
return ~0UL;
}
return it->second;
}

unsigned IrTypeClass::getNumInterfaceVtbls() {
getMemoryLLType(); // lazily resolve
return num_interface_vtbls;
}

const VarGEPIndices &IrTypeClass::getVarGEPIndices() {
getMemoryLLType(); // lazily resolve
return varGEPIndices;
}

void IrTypeClass::addInterfaceToMap(ClassDeclaration *inter, size_t index) {
// don't duplicate work or overwrite indices
if (interfaceMap.find(inter) != interfaceMap.end()) {
Expand Down
4 changes: 3 additions & 1 deletion ir/irtypeclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class IrTypeClass : public IrTypeAggr {

/// Returns the number of interface implementations (vtables) in this
/// class.
unsigned getNumInterfaceVtbls() { return num_interface_vtbls; }
unsigned getNumInterfaceVtbls();

protected:
///
Expand All @@ -73,6 +73,8 @@ class IrTypeClass : public IrTypeAggr {

//////////////////////////////////////////////////////////////////////////

const VarGEPIndices &getVarGEPIndices() override;

/// Adds the data members for the given class to the type builder, including
/// those inherited from base classes/interfaces.
void addClassData(AggrTypeBuilder &builder, ClassDeclaration *currCd);
Expand Down

0 comments on commit 34c353d

Please sign in to comment.