summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp19
-rw-r--r--llvm/lib/IR/Function.cpp16
-rw-r--r--llvm/test/CodeGen/Generic/overloaded-intrinsic-name.ll31
-rw-r--r--llvm/test/LTO/X86/remangle_intrinsics_tbaa.ll2
-rw-r--r--llvm/unittests/Linker/LinkModulesTest.cpp18
5 files changed, 68 insertions, 18 deletions
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index b68bc3f0561..41f4159c559 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -489,6 +489,12 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
break;
}
}
+ // Remangle our intrinsic since we upgrade the mangling
+ auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F);
+ if (Result != None) {
+ NewFn = Result.getValue();
+ return true;
+ }
// This may not belong here. This function is effectively being overloaded
// to both detect an intrinsic which needs upgrading, and to provide the
@@ -1821,8 +1827,17 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
CI->setName(Name + ".old");
switch (NewFn->getIntrinsicID()) {
- default:
- llvm_unreachable("Unknown function for CallInst upgrade.");
+ default: {
+ // Handle generic mangling change, but nothing else
+ assert(
+ (CI->getCalledFunction()->getName() != NewFn->getName()) &&
+ "Unknown function for CallInst upgrade and isn't just a name change");
+ SmallVector<Value *, 4> Args(CI->arg_operands().begin(),
+ CI->arg_operands().end());
+ CI->replaceAllUsesWith(Builder.CreateCall(NewFn, Args));
+ CI->eraseFromParent();
+ return;
+ }
case Intrinsic::arm_neon_vld1:
case Intrinsic::arm_neon_vld2:
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 62e8717a0f1..0c6b3520dad 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -505,10 +505,18 @@ static std::string getMangledTypeStr(Type* Ty) {
} else if (ArrayType* ATyp = dyn_cast<ArrayType>(Ty)) {
Result += "a" + llvm::utostr(ATyp->getNumElements()) +
getMangledTypeStr(ATyp->getElementType());
- } else if (StructType* STyp = dyn_cast<StructType>(Ty)) {
- assert(!STyp->isLiteral() && "TODO: implement literal types");
- Result += STyp->getName();
- } else if (FunctionType* FT = dyn_cast<FunctionType>(Ty)) {
+ } else if (StructType *STyp = dyn_cast<StructType>(Ty)) {
+ if (!STyp->isLiteral()) {
+ Result += "s_";
+ Result += STyp->getName();
+ } else {
+ Result += "sl_";
+ for (auto Elem : STyp->elements())
+ Result += getMangledTypeStr(Elem);
+ }
+ // Ensure nested structs are distinguishable.
+ Result += "s";
+ } else if (FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
Result += "f_" + getMangledTypeStr(FT->getReturnType());
for (size_t i = 0; i < FT->getNumParams(); i++)
Result += getMangledTypeStr(FT->getParamType(i));
diff --git a/llvm/test/CodeGen/Generic/overloaded-intrinsic-name.ll b/llvm/test/CodeGen/Generic/overloaded-intrinsic-name.ll
index 65fc9c1184c..60068adc5da 100644
--- a/llvm/test/CodeGen/Generic/overloaded-intrinsic-name.ll
+++ b/llvm/test/CodeGen/Generic/overloaded-intrinsic-name.ll
@@ -44,14 +44,41 @@ define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" {
; struct
define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" {
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %struct.test* %v)
- %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(token %tok, i32 7, i32 7)
+ %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0s_struct.tests(token %tok, i32 7, i32 7)
ret %struct.test* %v-new
}
+; literal struct with nested literal struct
+define {i64, i64, {i64} }* @test_literal_struct({i64, i64, {i64}}* %v) gc "statepoint-example" {
+ %tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, {i64, i64, {i64}} *%v)
+ %v-new = call {i64, i64, {i64}}* @llvm.experimental.gc.relocate.p0sl_i64i64sl_i64ss.test(token %tok, i32 7, i32 7)
+ ret {i64, i64, {i64}}* %v-new
+}
+; struct with a horrible name, broken when structs were unprefixed
+%i32 = type { i32 }
+
+define %i32* @test_i32_struct(%i32* %v) gc "statepoint-example" {
+entry:
+ %tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %i32* %v)
+ %v-new = call %i32* @llvm.experimental.gc.relocate.p0s_i32s(token %tok, i32 7, i32 7)
+ ret %i32* %v-new
+}
+; completely broken intrinsic naming due to needing remangling. Just use random naming to test
+
+define %i32* @test_broken_names(%i32* %v) gc "statepoint-example" {
+entry:
+ %tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.deadbeef(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %i32* %v)
+ %v-new = call %i32* @llvm.experimental.gc.relocate.beefdead(token %tok, i32 7, i32 7)
+ ret %i32* %v-new
+}
declare zeroext i1 @return_i1()
declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
declare i32* @llvm.experimental.gc.relocate.p0i32(token, i32, i32)
declare float* @llvm.experimental.gc.relocate.p0f32(token, i32, i32)
declare [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(token, i32, i32)
declare <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(token, i32, i32)
-declare %struct.test* @llvm.experimental.gc.relocate.p0struct.test(token, i32, i32)
+declare %struct.test* @llvm.experimental.gc.relocate.p0s_struct.tests(token, i32, i32)
+declare {i64, i64, {i64}}* @llvm.experimental.gc.relocate.p0sl_i64i64sl_i64ss.test(token, i32, i32)
+declare %i32* @llvm.experimental.gc.relocate.p0s_i32s(token, i32, i32)
+declare %i32* @llvm.experimental.gc.relocate.beefdead(token, i32, i32)
+declare token @llvm.experimental.gc.statepoint.deadbeef(i64, i32, i1 ()*, i32, i32, ...)
diff --git a/llvm/test/LTO/X86/remangle_intrinsics_tbaa.ll b/llvm/test/LTO/X86/remangle_intrinsics_tbaa.ll
index 189674b5b06..cac72f4330b 100644
--- a/llvm/test/LTO/X86/remangle_intrinsics_tbaa.ll
+++ b/llvm/test/LTO/X86/remangle_intrinsics_tbaa.ll
@@ -3,7 +3,7 @@
; RUN: llvm-link -disable-lazy-loading %t2.bc %t1.bc -S | FileCheck %s
; Verify that we correctly rename the intrinsic and don't crash
-; CHECK: @llvm.masked.store.v4p0some_named_struct.0.p0v4p0some_named_struct.0
+; CHECK: @llvm.masked.store.v4p0s_some_named_struct.0s.p0v4p0s_some_named_struct.0s
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.11.0"
diff --git a/llvm/unittests/Linker/LinkModulesTest.cpp b/llvm/unittests/Linker/LinkModulesTest.cpp
index 92c483278be..f31409c5012 100644
--- a/llvm/unittests/Linker/LinkModulesTest.cpp
+++ b/llvm/unittests/Linker/LinkModulesTest.cpp
@@ -317,34 +317,34 @@ TEST_F(LinkModuleTest, RemangleIntrinsics) {
const char *FooStr =
"%struct.rtx_def = type { i16 }\n"
"define void @foo(%struct.rtx_def* %a, i8 %b, i32 %c) {\n"
- " call void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def* %a, i8 %b, i32 %c, i32 4, i1 true)\n"
+ " call void @llvm.memset.p0s_struct.rtx_defs.i32(%struct.rtx_def* %a, i8 %b, i32 %c, i32 4, i1 true)\n"
" ret void\n"
"}\n"
- "declare void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def*, i8, i32, i32, i1)\n";
+ "declare void @llvm.memset.p0s_struct.rtx_defs.i32(%struct.rtx_def*, i8, i32, i32, i1)\n";
const char *BarStr =
"%struct.rtx_def = type { i16 }\n"
"define void @bar(%struct.rtx_def* %a, i8 %b, i32 %c) {\n"
- " call void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def* %a, i8 %b, i32 %c, i32 4, i1 true)\n"
+ " call void @llvm.memset.p0s_struct.rtx_defs.i32(%struct.rtx_def* %a, i8 %b, i32 %c, i32 4, i1 true)\n"
" ret void\n"
"}\n"
- "declare void @llvm.memset.p0struct.rtx_def.i32(%struct.rtx_def*, i8, i32, i32, i1)\n";
+ "declare void @llvm.memset.p0s_struct.rtx_defs.i32(%struct.rtx_def*, i8, i32, i32, i1)\n";
std::unique_ptr<Module> Foo = parseAssemblyString(FooStr, Err, C);
assert(Foo);
ASSERT_TRUE(Foo.get());
// Foo is loaded first, so the type and the intrinsic have theis original
// names.
- ASSERT_TRUE(Foo->getFunction("llvm.memset.p0struct.rtx_def.i32"));
- ASSERT_FALSE(Foo->getFunction("llvm.memset.p0struct.rtx_def.0.i32"));
+ ASSERT_TRUE(Foo->getFunction("llvm.memset.p0s_struct.rtx_defs.i32"));
+ ASSERT_FALSE(Foo->getFunction("llvm.memset.p0s_struct.rtx_defs.0.i32"));
std::unique_ptr<Module> Bar = parseAssemblyString(BarStr, Err, C);
assert(Bar);
ASSERT_TRUE(Bar.get());
// Bar is loaded after Foo, so the type is renamed to struct.rtx_def.0. Check
// that the intrinsic is also renamed.
- ASSERT_FALSE(Bar->getFunction("llvm.memset.p0struct.rtx_def.i32"));
- ASSERT_TRUE(Bar->getFunction("llvm.memset.p0struct.rtx_def.0.i32"));
+ ASSERT_FALSE(Bar->getFunction("llvm.memset.p0s_struct.rtx_defs.i32"));
+ ASSERT_TRUE(Bar->getFunction("llvm.memset.p0s_struct.rtx_def.0s.i32"));
// Link two modules together.
auto Dst = llvm::make_unique<Module>("Linked", C);
@@ -356,7 +356,7 @@ TEST_F(LinkModuleTest, RemangleIntrinsics) {
// "struct.rtx_def" from Foo and "struct.rtx_def.0" from Bar are isomorphic
// types, so they must be uniquified by linker. Check that they use the same
// intrinsic definition.
- Function *F = Foo->getFunction("llvm.memset.p0struct.rtx_def.i32");
+ Function *F = Foo->getFunction("llvm.memset.p0s_struct.rtx_defs.i32");
ASSERT_EQ(F->getNumUses(), (unsigned)2);
}
OpenPOWER on IntegriCloud