Skip to content

Commit

Permalink
Prevent collapsing of secondary bases used inside a hierarchy where a…
Browse files Browse the repository at this point in the history
… downcast is done

When a class is used inside a hierarchy where a downcast is performed on it cannot be collapsed. If it is collapsed the offset given by the downcast builtin will no longer be correct, causing unexpected behaviour
  • Loading branch information
rvan-mee authored and yuri91 committed Jul 8, 2024
1 parent 074fb60 commit 8e10a60
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 0 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/Cheerp/TypeOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class TypeOptimizer

llvm::Module* module;
const llvm::DataLayout* DL;
std::unordered_set<const llvm::Type*> uncollapsibleSecondaryBases;
std::unordered_map<const llvm::StructType*,std::set<llvm::StructType*>> downcastSourceToDestinationsMapping;
std::unordered_map<const llvm::StructType*, std::vector<std::pair<uint32_t, uint32_t>>> membersMappingData;
std::unordered_map<llvm::GlobalValue*, llvm::Constant*> globalsMapping;
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/CheerpUtils/TypeOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,21 @@ void TypeOptimizer::gatherAllTypesInfo(const Module& M)
uint32_t fieldIndex = cast<ConstantInt>(*std::prev(GEP->op_end()))->getZExtValue();
escapingFields.emplace(containerStructType, fieldIndex, TypeAndIndex::STRUCT_MEMBER);
}

// Mark classes that cannot be collapsed because they are used as a secondary base
for (const auto sTy : M.getIdentifiedStructTypes())
{
uint32_t firstBase;
uint32_t baseCount;
if (TypeSupport::getBasesInfo(M, sTy, firstBase, baseCount))
{
for (uint32_t i = firstBase; i< (firstBase + baseCount); i++)
{
assert(sTy->getElementType(i)->isStructTy());
uncollapsibleSecondaryBases.insert(sTy->getElementType(i));
}
}
}
}

/**
Expand Down Expand Up @@ -294,6 +309,9 @@ bool TypeOptimizer::canCollapseStruct(llvm::StructType* st, llvm::StructType* ne
assert(st->isLiteral());
return true;
}
// Secondary bases used inside a hierarchy where a downcast is performed on cannot safely be collapsed
if (uncollapsibleSecondaryBases.count(st))
return false;
// Stop if the element is just a int8, we may be dealing with an empty struct
// Empty structs are unsafe as the int8 inside is just a placeholder and will be replaced
// by a different type in a derived class
Expand Down

0 comments on commit 8e10a60

Please sign in to comment.