Skip to content

Commit

Permalink
Fix to TypeOptimizer to allow literal structs.
Browse files Browse the repository at this point in the history
TypeOptimizer would create new named structs as copies of literal structs. This caused a problem in the case of literal structs that are the result of a cmpxchg instruction. During inlining, these create their original return types, and those would conflict with the ones that went through TypeOptimizer.
In turn, we needed a tiny fix in isJSExportedType in order for the literal structs not to cause a crash.
  • Loading branch information
Maqrkk committed Feb 1, 2024
1 parent 37a8b55 commit ab6efc3
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
21 changes: 17 additions & 4 deletions llvm/lib/CheerpUtils/TypeOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ bool TypeOptimizer::isUnsafeDowncastSource(StructType* st)

bool TypeOptimizer::canCollapseStruct(llvm::StructType* st, llvm::StructType* newStruct, llvm::Type* newType)
{
if (newStruct == nullptr)
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 Expand Up @@ -446,7 +448,9 @@ TypeOptimizer::TypeMappingInfo TypeOptimizer::rewriteType(Type* t)
}

// Generate a new type inconditionally, it may end up being the same as the old one
StructType* newStruct=StructType::create(st->getContext());
StructType* newStruct=nullptr;
if (!st->isLiteral())
newStruct=StructType::create(st->getContext());
#ifndef NDEBUG
newStructTypes.insert(newStruct);
#endif
Expand All @@ -457,7 +461,8 @@ TypeOptimizer::TypeMappingInfo TypeOptimizer::rewriteType(Type* t)
newStruct->setName(name);
}
// Tentatively map the type to the newStruct, it may be overridden if the type is collapsed
typesMapping[t] = TypeMappingInfo(newStruct, TypeMappingInfo::IDENTICAL);
if (!st->isLiteral())
typesMapping[t] = TypeMappingInfo(newStruct, TypeMappingInfo::IDENTICAL);

// Since we can merge arrays of the same type in an struct it is possible that at the end of the process a single type will remain
TypeMappingInfo::MAPPING_KIND newStructKind = TypeMappingInfo::IDENTICAL;
Expand Down Expand Up @@ -556,7 +561,9 @@ TypeOptimizer::TypeMappingInfo TypeOptimizer::rewriteType(Type* t)
std::vector<std::pair<uint32_t, uint8_t>> mergedInts;
uint32_t directBaseLimit=0;
// We may need to update the bases metadata for this type
NamedMDNode* namedBasesMetadata = TypeSupport::getBasesMetadata(newStruct, *module);
NamedMDNode* namedBasesMetadata = nullptr;
if (!st->isLiteral())
namedBasesMetadata = TypeSupport::getBasesMetadata(newStruct, *module);
uint32_t firstBaseBegin, firstBaseEnd;
if(namedBasesMetadata)
{
Expand Down Expand Up @@ -698,7 +705,13 @@ TypeOptimizer::TypeMappingInfo TypeOptimizer::rewriteType(Type* t)
}

StructType* newDirectBase = st->getDirectBase() ? dyn_cast<StructType>(rewriteType(st->getDirectBase()).mappedType) : NULL;
newStruct->setBody(newTypes, st->isPacked(), newDirectBase, st->hasByteLayout(), st->hasAsmJS());
if (st->isLiteral())
{
newStruct = StructType::get(st->getContext(), newTypes, st->isPacked(), newDirectBase, st->hasByteLayout(), st->hasAsmJS());
typesMapping[t] = TypeMappingInfo(newStruct, TypeMappingInfo::IDENTICAL);
}
else
newStruct->setBody(newTypes, st->isPacked(), newDirectBase, st->hasByteLayout(), st->hasAsmJS());

return CacheAndReturn(newStruct, newStructKind);
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CheerpUtils/Utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,8 @@ char TypeSupport::getPrefixCharForMember(const PointerAnalyzer& PA, llvm::Struct

bool TypeSupport::isJSExportedType(StructType* st, const Module& m)
{
if (st->isLiteral())
return false;
return m.getNamedMetadata(llvm::Twine(st->getName(),"_methods"))!=NULL;
}

Expand Down

0 comments on commit ab6efc3

Please sign in to comment.