From ce5764bdc8f682a5c26672807b630302c85f3641 Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Mon, 2 Dec 2024 17:04:53 +0100 Subject: [PATCH 1/6] [EDDI] Fixes how addConsistencyChecks handles the new verification basic block Fixes HEAPLab/ASPIS#2. When creating a VerificationBB between the exception handling and the call of __clang_call_terminate, the invoke landing pad address was substituted with the verificationBB address instead of the exception handler address. This lead to the invoke unwind label jumping after the exception handling part, leading to the "The unwind destination does not have an exception handling instruction!" error. --- passes/EDDI.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 8cae549..1246eaa 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -253,11 +253,13 @@ void EDDI::addConsistencyChecks( std::vector CmpInstructions; // split and add the verification BB - I.getParent()->splitBasicBlockBefore(&I); + auto BBpred = I.getParent()->splitBasicBlockBefore(&I); BasicBlock *VerificationBB = BasicBlock::Create(I.getContext(), "VerificationBB", I.getParent()->getParent(), I.getParent()); - I.getParent()->replaceUsesWithIf(VerificationBB, IsNotAPHINode); + I.getParent()->replaceUsesWithIf(BBpred, IsNotAPHINode); + auto BI = cast(BBpred->getTerminator()); + BI->setSuccessor(0, VerificationBB); IRBuilder<> B(VerificationBB); // add a comparison for each operand From dc42678831baa0fea73a12cb743878eaa15d78ac Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Mon, 2 Dec 2024 17:04:53 +0100 Subject: [PATCH 2/6] [EDDI] Removing `sret` attribute from duplicated function arguments --- passes/EDDI.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 1246eaa..f075d87 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -739,6 +739,10 @@ EDDI::duplicateFnArgs(Function &Fn, Module &Md, Fn.getName() + "_dup", Fn.getParent()); ValueToValueMapTy Params; for (int i = 0; i < Fn.arg_size(); i++) { + if (Fn.getArg(i)->hasStructRetAttr()) { + Fn.getArg(i)->removeAttr(Attribute::AttrKind::StructRet); + } + if (AlternateMemMapEnabled == false) { Params[Fn.getArg(i)] = ClonedFunc->getArg(Fn.arg_size() + i); } else { From d2fb6c207ed6c4e2799c8059e18c445ddae5103d Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Mon, 2 Dec 2024 17:04:53 +0100 Subject: [PATCH 3/6] [EDDI] Not duplicating global variables with reserved name --- passes/EDDI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index f075d87..66b2ae1 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -455,11 +455,12 @@ void EDDI::duplicateGlobals( bool endsWithDup = GV->getName().endswith("_dup"); bool hasInternalLinkage = GV->hasInternalLinkage(); bool isMetadataInfo = GV->getSection() == "llvm.metadata"; + bool isReservedName = GV->getName().starts_with("llvm."); bool toExclude = !isa(GV) && FuncAnnotations.find(GV) != FuncAnnotations.end() && (FuncAnnotations.find(GV))->second.startswith("exclude"); - if (! (isFunction || isConstant || endsWithDup || isMetadataInfo || toExclude) // is not function, constant, struct and does not end with _dup + if (! (isFunction || isConstant || endsWithDup || isMetadataInfo || isReservedName || toExclude) // is not function, constant, struct and does not end with _dup /* && ((hasInternalLinkage && (!isArray || (isArray && !cast(GV.getValueType())->getArrayElementType()->isAggregateType() ))) // has internal linkage and is not an array, or is an array but the element type is not aggregate || !isArray) */ // if it does not have internal linkage, it is not an array or a pointer ) { From f29198076601d086ac418424dd66c08614d2e610 Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Mon, 2 Dec 2024 17:04:53 +0100 Subject: [PATCH 4/6] [Test] Enhanced cpp test Added tests for: - Potentially throwing operation called in a `noexcept` function - Function returning a struct (generating a `sret` parameter) - static class, generating an `llvm.global_ctors` --- examples/cpp-benchmarks/full_test.cpp | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/examples/cpp-benchmarks/full_test.cpp b/examples/cpp-benchmarks/full_test.cpp index dc02a26..6aa9481 100644 --- a/examples/cpp-benchmarks/full_test.cpp +++ b/examples/cpp-benchmarks/full_test.cpp @@ -98,7 +98,46 @@ void riskyFunction(bool throwException) { std::cout << "RiskyFunction executed successfully." << std::endl; } +// Sret +struct State +{ + double x0; + float x1; + float x2; + float x3; +}; + +class Class +{ +public: + Class() { + std::cout << "Class constructor" << std::endl; + state = {1.0, 2.f, 3.f, 4.f}; + } + + State testSretDuplication(){ + return state; + } + +private: + State state; +}; + + +// noexcept +void TestNoExcept() noexcept +{ + volatile MyClass m_data(1,2); +} + +// testing unexpected special variable +static Class staticClass; + int main() { + std::cout << "Starting main" << std::endl; + + std::cout << "staticClass: " << staticClass.testSretDuplication().x3 << std::endl; + // Call simple function simpleFunction(); @@ -144,5 +183,11 @@ int main() { std::cerr << "Caught exception: " << e.what() << std::endl; } + TestNoExcept(); + + // Test sret + Class sretTest; + std::cout << "test sret: " << sretTest.testSretDuplication().x0 << std::endl; + return 0; } From 6ce5fa54af8864152929fed618a92cc392d4ebe6 Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Tue, 3 Dec 2024 12:14:18 +0100 Subject: [PATCH 5/6] [EDDI] Added `fixGlobalCtors` function Now the global constructor called are the dup versions if they exist --- passes/ASPIS.h | 1 + passes/EDDI.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/passes/ASPIS.h b/passes/ASPIS.h index bfe628e..51585f8 100644 --- a/passes/ASPIS.h +++ b/passes/ASPIS.h @@ -49,6 +49,7 @@ class EDDI : public PassInfoMixin { bool isValueDuplicated(std::map &DuplicatedInstructionMap, Instruction &V); Function *duplicateFnArgs(Function &Fn, Module &Md, std::map &DuplicatedInstructionMap); + void fixGlobalCtors(Module &M); public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &); diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 66b2ae1..94c7354 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -937,6 +937,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { I2rm->eraseFromParent(); } + fixGlobalCtors(Md); persistCompiledFunctions(CompiledFuncs, "compiled_eddi_functions.csv"); /* if (Function *mainFunc = Md.getFunction("main")) { @@ -948,6 +949,75 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { return PreservedAnalyses::none(); } +void EDDI::fixGlobalCtors(Module &M) { + LLVM_DEBUG(dbgs() << "[EDDI] Fixing global constructors\n"); + LLVMContext &Context = M.getContext(); + + // Retrieve the existing @llvm.global_ctors. + GlobalVariable *GlobalCtors = M.getGlobalVariable("llvm.global_ctors"); + if (!GlobalCtors) { + llvm::errs() << "Error: @llvm.global_ctors not found in the module.\n"; + return; + } + + // Get the constantness and the section name of the existing global variable. + bool isConstant = GlobalCtors->isConstant(); + StringRef Section = GlobalCtors->getSection(); + + // Get the type of the annotations array and struct. + ArrayType *CtorsArrayType = cast(GlobalCtors->getValueType()); + StructType *CtorStructType = cast(CtorsArrayType->getElementType()); + + // Create the new Ctor struct fields. + PointerType *Int8PtrType = Type::getInt8Ty(Context)->getPointerTo(); + Constant *IntegerConstant = ConstantInt::get(Type::getInt32Ty(Context), 65535); + Constant *NullPtr = ConstantPointerNull::get(Int8PtrType); // Null pointer for other fields. + + // Retrieve existing annotations and append the new one. + std::vector Ctors; + if (ConstantArray *ExistingArray = dyn_cast(GlobalCtors->getInitializer())) { + for (unsigned i = 0; i < ExistingArray->getNumOperands(); ++i) { + auto *ctorStr = ExistingArray->getOperand(i); + + auto *ctor = ctorStr->getOperand(1); + if(isa(ctor)){ + Function *dupCtor = getFunctionDuplicate(cast(ctor)); + // If there isn't the duplicated constructor, use the original one + if(dupCtor == NULL) { + dupCtor = cast(ctor); + } + + Constant *CtorAsConstant = ConstantExpr::getBitCast(dupCtor, Int8PtrType);; + // Create the new Ctor struct. + Constant *NewCtor = ConstantStruct::get( + CtorStructType, + {IntegerConstant, CtorAsConstant, NullPtr}); + Ctors.push_back(NewCtor); + } + } + } + + // Create a new array with the correct type and size. + ArrayType *NewCtorArrayType = ArrayType::get(CtorStructType, Ctors.size()); + Constant *NewCtorArray = ConstantArray::get(NewCtorArrayType, Ctors); + + // Remove the old global variable from the module's symbol table. + GlobalCtors->removeFromParent(); + delete GlobalCtors; + + // Create a new global variable with the exact name "llvm.global_ctors". + GlobalVariable *NewGlobalCtors = new GlobalVariable( + M, + NewCtorArray->getType(), + isConstant, + GlobalValue::AppendingLinkage, // Must use appending linkage for @llvm.global_ctors. + NewCtorArray, + "llvm.global_ctors"); + + // Set the section to match the original. + NewGlobalCtors->setSection(Section); +} + //----------------------------------------------------------------------------- // New PM Registration //----------------------------------------------------------------------------- From 1d6ef19ab9157ebd5a3cbd3850d73637086ee7f1 Mon Sep 17 00:00:00 2001 From: Emilio Corigliano Date: Tue, 3 Dec 2024 14:28:39 +0100 Subject: [PATCH 6/6] [EDDI] Resolving all the aliases with aliasees --- passes/EDDI.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/passes/EDDI.cpp b/passes/EDDI.cpp index 94c7354..9e2c380 100755 --- a/passes/EDDI.cpp +++ b/passes/EDDI.cpp @@ -765,6 +765,15 @@ EDDI::duplicateFnArgs(Function &Fn, Module &Md, PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { LLVM_DEBUG(dbgs() << "Initializing EDDI...\n"); + // Replace all uses of alias to aliasee + for (auto &alias : Md.aliases()) { + auto aliasee = alias.getAliaseeObject(); + if(isa(aliasee)){ + LLVM_DEBUG(dbgs() << "[EDDI] Replacing uses of " << alias.getName() << " to " << aliasee->getName() << "\n"); + alias.replaceAllUsesWith(aliasee); + } + } + LLVM_DEBUG(dbgs() << "Getting annotations... "); getFuncAnnotations(Md, FuncAnnotations); LLVM_DEBUG(dbgs() << "[done]\n");