Yuri
2012-Jun-17 11:47 UTC
[LLVMdev] BlockAddress instruction is copied instead of cloned during module link?
I have a module having the blockaddress instruction. When I link it into another module and delete the original, blockaddress disappears and is replaced by inttoptr (i32 1 to i8*). Please compile and run the attached program to see the demo of this problem. Right after linking modules, blockaddress still exists: @switch.bbs = internal global [3 x i8*] [i8* blockaddress(@my_func, %switch.body.begin), i8* blockaddress(@my_func, %switch.body.begin1), i8* inttoptr (i32 1 to i8*)] But once the original module is deleted, the same line in destination is replaced by the one with inttoptr: @switch.bbs = internal global [3 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] So it looks like BlockAddress instruction is copied instead of cloned into the destination module? rev.158596 Yuri --- testcase.cpp --- #include <llvm/LLVMContext.h> #include <llvm/Module.h> #include <llvm/DerivedTypes.h> #include <llvm/Constants.h> #include <llvm/GlobalVariable.h> #include <llvm/Function.h> #include <llvm/CallingConv.h> #include <llvm/BasicBlock.h> #include <llvm/Instructions.h> #include <llvm/InlineAsm.h> #include <llvm/Support/FormattedStream.h> #include <llvm/Support/MathExtras.h> #include <llvm/Pass.h> #include <llvm/PassManager.h> #include <llvm/ADT/SmallVector.h> #include <llvm/Analysis/Verifier.h> #include <llvm/Assembly/PrintModulePass.h> #include <llvm/Linker.h> #include <algorithm> using namespace llvm; Module* makeLLVMModule(); int main(int argc, char**argv) { Module* Mod = makeLLVMModule(); verifyModule(*Mod, PrintMessageAction); PassManager PM; PM.add(createPrintModulePass(&outs())); printf("===original==\n"); PM.run(*Mod); Module* ModL = new Module("xL.ll", getGlobalContext()); llvm::Linker::LinkModules(ModL, Mod, Linker::PreserveSource, 0); printf("===linked: before original delete==\n"); PM.run(*ModL); delete Mod; printf("===linked: after original delete==\n"); PM.run(*ModL); return 0; } Module* makeLLVMModule() { // Module Construction Module* mod = new Module("x.ll", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"); mod->setTargetTriple("x86_64-unknown-freebsd8.2"); // Type Definitions PointerType* PointerTy_1 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0); ArrayType* ArrayTy_0 = ArrayType::get(PointerTy_1, 3); PointerType* PointerTy_2 = PointerType::get(ArrayTy_0, 0); std::vector<Type*>FuncTy_3_args; FuncTy_3_args.push_back(IntegerType::get(mod->getContext(), 32)); FunctionType* FuncTy_3 = FunctionType::get( /*Result=*/PointerTy_1, /*Params=*/FuncTy_3_args, /*isVarArg=*/false); PointerType* PointerTy_4 = PointerType::get(PointerTy_1, 0); // Function Declarations Function* func_my_func = mod->getFunction("my_func"); if (!func_my_func) { func_my_func = Function::Create( /*Type=*/FuncTy_3, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"my_func", mod); func_my_func->setCallingConv(CallingConv::C); } AttrListPtr func_my_func_PAL; func_my_func->setAttributes(func_my_func_PAL); BasicBlock* label_issue_top = BasicBlock::Create(mod->getContext(), "issue.top",func_my_func,0); BasicBlock* label_switch_body_begin = BasicBlock::Create(mod->getContext(), "switch.body.begin",func_my_func,0); BasicBlock* label_switch_body_begin1 = BasicBlock::Create(mod->getContext(), "switch.body.begin1",func_my_func,0); BasicBlock* label_switch_end = BasicBlock::Create(mod->getContext(), "switch.end",func_my_func,0); // Global Variable Declarations GlobalVariable* gvar_array_switch_bbs = new GlobalVariable(/*Module=*/*mod, /*Type=*/ArrayTy_0, /*isConstant=*/false, /*Linkage=*/GlobalValue::InternalLinkage, /*Initializer=*/0, // has initializer, specified below /*Name=*/"switch.bbs"); // Constant Definitions std::vector<Constant*> const_array_5_elems; Constant* const_ptr_6 = BlockAddress::get(label_switch_body_begin); const_array_5_elems.push_back(const_ptr_6); Constant* const_ptr_7 = BlI have a module having the blockaddress instruction. When I link it into another module and delete the original, blockaddress disappears and is replaced by inttoptr (i32 1 to i8*). Please compile and run the attached program to see the demo of this problem. Right after linking modules, blockaddress still exists: @switch.bbs = internal global [3 x i8*] [i8* blockaddress(@my_func, %switch.body.begin), i8* blockaddress(@my_func, %switch.body.begin1), i8* inttoptr (i32 1 to i8*)] But once the original module is deleted, the same line in destination is replaced by the one with inttoptr: @switch.bbs = internal global [3 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] So it looks like BlockAddress instruction is copied instead of cloned into the destination module? rev.158596 Yuri --- testcase.cpp --- #include <llvm/LLVMContext.h> #include <llvm/Module.h> #include <llvm/DerivedTypes.h> #include <llvm/Constants.h> #include <llvm/GlobalVariable.h> #include <llvm/Function.h> #include <llvm/CallingConv.h> #include <llvm/BasicBlock.h> #include <llvm/Instructions.h> #include <llvm/InlineAsm.h> #include <llvm/Support/FormattedStream.h> #include <llvm/Support/MathExtras.h> #include <llvm/Pass.h> #include <llvm/PassManager.h> #include <llvm/ADT/SmallVector.h> #include <llvm/Analysis/Verifier.h> #include <llvm/Assembly/PrintModulePass.h> #include <llvm/Linker.h> #include <algorithm> using namespace llvm; Module* makeLLVMModule(); int main(int argc, char**argv) { Module* Mod = makeLLVMModule(); verifyModule(*Mod, PrintMessageAction); PassManager PM; PM.add(createPrintModulePass(&outs())); printf("===original==\n"); PM.run(*Mod); Module* ModL = new Module("xL.ll", getGlobalContext()); llvm::Linker::LinkModules(ModL, Mod, Linker::PreserveSource, 0); printf("===linked: before original delete==\n"); PM.run(*ModL); delete Mod; printf("===linked: after original delete==\n"); PM.run(*ModL); return 0; } Module* makeLLVMModule() { // Module Construction Module* mod = new Module("x.ll", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"); mod->setTargetTriple("x86_64-unknown-freebsd8.2"); // Type Definitions PointerType* PointerTy_1 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0); ArrayType* ArrayTy_0 = ArrayType::get(PointerTy_1, 3); PointerType* PointerTy_2 = PointerType::get(ArrayTy_0, 0); std::vector<Type*>FuncTy_3_args; FuncTy_3_args.push_back(IntegerType::get(mod->getContext(), 32)); FunctionType* FuncTy_3 = FunctionType::get( /*Result=*/PointerTy_1, /*Params=*/FuncTy_3_args, /*isVarArg=*/false); PointerType* PointerTy_4 = PointerType::get(PointerTy_1, 0); // Function Declarations Function* func_my_func = mod->getFunction("my_func"); if (!func_my_func) { func_my_func = Function::Create( /*Type=*/FuncTy_3, /*Linkage=*/GlobalValue::ExternalLinkage, /*Name=*/"my_func", mod); func_my_func->setCallingConv(CallingConv::C); } AttrListPtr func_my_func_PAL; func_my_func->setAttributes(func_my_func_PAL); BasicBlock* label_issue_top = BasicBlock::Create(mod->getContext(), "issue.top",func_my_func,0); BasicBlock* label_switch_body_begin = BasicBlock::Create(mod->getContext(), "switch.body.begin",func_my_func,0); BasicBlock* label_switch_body_begin1 = BasicBlock::Create(mod->getContext(), "switch.body.begin1",func_my_func,0); BasicBlock* label_switch_end = BasicBlock::Create(mod->getContext(), "switch.end",func_my_func,0); // Global Variable Declarations GlobalVariable* gvar_array_switch_bbs = new GlobalVariable(/*Module=*/*mod, /*Type=*/ArrayTy_0, /*isConstant=*/false, /*Linkage=*/GlobalValue::InternalLinkage, /*Initializer=*/0, // has initializer, specified below /*Name=*/"switch.bbs"); // Constant Definitions std::vector<Constant*> const_array_5_elems; Constant* const_ptr_6 = BlockAddress::get(label_switch_body_begin); const_array_5_elems.push_back(const_ptr_6); Constant* const_ptr_7 = BlockAddress::get(label_switch_body_begin1); const_array_5_elems.push_back(const_ptr_7); ConstantInt* const_int32_9 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10)); Constant* const_ptr_8 = ConstantExpr::getCast(Instruction::IntToPtr, const_int32_9, PointerTy_1); const_array_5_elems.push_back(const_ptr_8); Constant* const_array_5 = ConstantArray::get(ArrayTy_0, const_array_5_elems); ConstantInt* const_int32_10 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10)); ConstantPointerNull* const_ptr_11 = ConstantPointerNull::get(PointerTy_1); // Global Variable Definitions gvar_array_switch_bbs->setInitializer(const_array_5); // Function Definitions // Function: my_func (func_my_func) { Function::arg_iterator args = func_my_func->arg_begin(); Value* int32_12 = args++; // Block issue.top (label_issue_top) std::vector<Value*> ptr_switch_gep_indices; ptr_switch_gep_indices.push_back(const_int32_10); ptr_switch_gep_indices.push_back(int32_12); Instruction* ptr_switch_gep = GetElementPtrInst::Create(gvar_array_switch_bbs, ptr_switch_gep_indices, "switch.gep", label_issue_top); LoadInst* ptr_switch_load = new LoadInst(ptr_switch_gep, "switch.load", false, label_issue_top); ReturnInst::Create(mod->getContext(), ptr_switch_load, label_issue_top); // Block switch.body.begin (label_switch_body_begin) BranchInst::Create(label_switch_end, label_switch_body_begin); // Block switch.body.begin1 (label_switch_body_begin1) BranchInst::Create(label_switch_end, label_switch_body_begin1); // Block switch.end (label_switch_end) ReturnInst::Create(mod->getContext(), const_ptr_11, label_switch_end); } return mod; } ockAddress::get(label_switch_body_begin1); const_array_5_elems.push_back(const_ptr_7); ConstantInt* const_int32_9 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10)); Constant* const_ptr_8 = ConstantExpr::getCast(Instruction::IntToPtr, const_int32_9, PointerTy_1); const_array_5_elems.push_back(const_ptr_8); Constant* const_array_5 = ConstantArray::get(ArrayTy_0, const_array_5_elems); ConstantInt* const_int32_10 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10)); ConstantPointerNull* const_ptr_11 = ConstantPointerNull::get(PointerTy_1); // Global Variable Definitions gvar_array_switch_bbs->setInitializer(const_array_5); // Function Definitions // Function: my_func (func_my_func) { Function::arg_iterator args = func_my_func->arg_begin(); Value* int32_12 = args++; // Block issue.top (label_issue_top) std::vector<Value*> ptr_switch_gep_indices; ptr_switch_gep_indices.push_back(const_int32_10); ptr_switch_gep_indices.push_back(int32_12); Instruction* ptr_switch_gep = GetElementPtrInst::Create(gvar_array_switch_bbs, ptr_switch_gep_indices, "switch.gep", label_issue_top); LoadInst* ptr_switch_load = new LoadInst(ptr_switch_gep, "switch.load", false, label_issue_top); ReturnInst::Create(mod->getContext(), ptr_switch_load, label_issue_top); // Block switch.body.begin (label_switch_body_begin) BranchInst::Create(label_switch_end, label_switch_body_begin); // Block switch.body.begin1 (label_switch_body_begin1) BranchInst::Create(label_switch_end, label_switch_body_begin1); // Block switch.end (label_switch_end) ReturnInst::Create(mod->getContext(), const_ptr_11, label_switch_end); } return mod; }
Yuri
2012-Jun-17 20:03 UTC
[LLVMdev] BlockAddress instruction is copied instead of cloned during module link?
BasicBlock::~BasicBlock() has the line: BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(Replacement, BA->getType())); It replaces all uses with: Constant *Replacement = ConstantInt::get(llvm::Type::getInt32Ty(getContext()), 1); When it is called on link source module, BasicBlocks there are destroyed but their uses are in the link destination module. Value::replaceAllUsesWith should have an assert checking if the use is in the same module as the current value. Yuri
Yuri
2012-Jun-21 09:59 UTC
[LLVMdev] BlockAddress instruction is copied instead of cloned during module link?
Since I got no response, I filed the PR for this problem: http://llvm.org/bugs/show_bug.cgi?id=13163 Yuri