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; } 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 8cae549..9e2c380 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 @@ -453,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 ) { @@ -737,6 +740,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 { @@ -758,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"); @@ -930,6 +946,7 @@ PreservedAnalyses EDDI::run(Module &Md, ModuleAnalysisManager &AM) { I2rm->eraseFromParent(); } + fixGlobalCtors(Md); persistCompiledFunctions(CompiledFuncs, "compiled_eddi_functions.csv"); /* if (Function *mainFunc = Md.getFunction("main")) { @@ -941,6 +958,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 //-----------------------------------------------------------------------------