diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -375,8 +375,9 @@ CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack| // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] - CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] - CST_CODE_POISON = 26, // POISON + CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] + CST_CODE_POISON = 26, // POISON + CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv] }; /// CastOpcodes - These are values used in the bitcode files to encode which diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp @@ -218,6 +218,7 @@ STRINGIFY_CODE(CST_CODE, INLINEASM) STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX) STRINGIFY_CODE(CST_CODE, CE_UNOP) + STRINGIFY_CODE(CST_CODE, DSO_LOCAL_EQUIVALENT) case bitc::CST_CODE_BLOCKADDRESS: return "CST_CODE_BLOCKADDRESS"; STRINGIFY_CODE(CST_CODE, DATA) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2888,6 +2888,20 @@ V = BlockAddress::get(Fn, BB); break; } + case bitc::CST_CODE_DSO_LOCAL_EQUIVALENT: { + if (Record.size() < 2) + return error("Invalid record"); + Type *GVTy = getTypeByID(Record[0]); + if (!GVTy) + return error("Invalid record"); + GlobalValue *GV = dyn_cast_or_null( + ValueList.getConstantFwdRef(Record[1], GVTy)); + if (!GV) + return error("Invalid record"); + + V = DSOLocalEquivalent::get(GV); + break; + } } assert(V->getType() == flattenPointerTypes(CurFullTy) && diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2609,6 +2609,10 @@ Record.push_back(VE.getTypeID(BA->getFunction()->getType())); Record.push_back(VE.getValueID(BA->getFunction())); Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); + } else if (const auto *Equiv = dyn_cast(C)) { + Code = bitc::CST_CODE_DSO_LOCAL_EQUIVALENT; + Record.push_back(VE.getTypeID(Equiv->getGlobalValue()->getType())); + Record.push_back(VE.getValueID(Equiv->getGlobalValue())); } else { #ifndef NDEBUG C->dump(); diff --git a/llvm/test/Bitcode/dso_local_equivalent.ll b/llvm/test/Bitcode/dso_local_equivalent.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/dso_local_equivalent.ll @@ -0,0 +1,86 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; RUN: verify-uselistorder < %s + +declare void @extern_func() + +define void @call_extern_func() { +; CHECK: call void dso_local_equivalent @extern_func() + call void dso_local_equivalent @extern_func() + ret void +} + +declare hidden void @hidden_func() +declare protected void @protected_func() +declare dso_local void @dso_local_func() +define internal void @internal_func() { +entry: + ret void +} +define private void @private_func() { +entry: + ret void +} + +; CHECK: call void dso_local_equivalent @hidden_func() +define void @call_hidden_func() { + call void dso_local_equivalent @hidden_func() + ret void +} + +define void @call_protected_func() { +; CHECK: call void dso_local_equivalent @protected_func() + call void dso_local_equivalent @protected_func() + ret void +} + +define void @call_dso_local_func() { +; CHECK: call void dso_local_equivalent @dso_local_func() + call void dso_local_equivalent @dso_local_func() + ret void +} + +define void @call_internal_func() { +; CHECK: call void dso_local_equivalent @internal_func() + call void dso_local_equivalent @internal_func() + ret void +} + +define void @aliasee_func() { +entry: + ret void +} + +@alias_func = alias void (), void ()* @aliasee_func +@dso_local_alias_func = dso_local alias void (), void ()* @aliasee_func + +define void @call_alias_func() { +; CHECK: call void dso_local_equivalent @alias_func() + call void dso_local_equivalent @alias_func() + ret void +} + +define void @call_dso_local_alias_func() { +; CHECK: call void dso_local_equivalent @dso_local_alias_func() + call void dso_local_equivalent @dso_local_alias_func() + ret void +} + +@ifunc_func = ifunc void (), i64 ()* @resolver +@dso_local_ifunc_func = dso_local ifunc void (), i64 ()* @resolver + +define internal i64 @resolver() { +entry: + ret i64 0 +} + +define void @call_ifunc_func() { +; CHECK: call void dso_local_equivalent @ifunc_func() + call void dso_local_equivalent @ifunc_func() + ret void +} + +define void @call_dso_local_ifunc_func() { +; CHECK: call void dso_local_equivalent @dso_local_ifunc_func() + call void dso_local_equivalent @dso_local_ifunc_func() + ret void +}