Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -462,13 +462,16 @@ /// Returns a stable mangling for the type specified for use in the name /// mangling scheme used by 'any' types in intrinsic signatures. The mangling /// of named types is simply their name. Manglings for unnamed types consist -/// of a prefix ('p' for pointers, 'a' for arrays, 'f_' for functions) -/// combined with the mangling of their component types. A vararg function -/// type will have a suffix of 'vararg'. Since function types can contain -/// other function types, we close a function type mangling with suffix 'f' -/// which can't be confused with it's prefix. This ensures we don't have -/// collisions between two unrelated function types. Otherwise, you might -/// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.) +/// of a prefix ('p' for pointers, 'a' for arrays, 's_' or 'ls_' for structs, +/// and 'f_' for functions) combined with the mangling of their component types. +/// A vararg function type will have a suffix of 'vararg'. +/// +/// Since function/struct types can contain other function/struct types, we +/// close a function/struct type mangling with suffix 'f'/'s' which can't be +/// confused with its prefix. This ensures we don't have collisions between two +/// unrelated function/struct types. Otherwise, you might parse ffXX as f(fXX) +/// or f(fX)X. (X is a placeholder for any other type.) +/// /// Manglings of integers, floats, and vectors ('i', 'f', and 'v' prefix in most /// cases) fall back to the MVT codepath, where they could be mangled to /// 'x86mmx', for example; matching on derived types is not sufficient to mangle @@ -482,8 +485,14 @@ Result += "a" + llvm::utostr(ATyp->getNumElements()) + getMangledTypeStr(ATyp->getElementType()); } else if (StructType* STyp = dyn_cast(Ty)) { - assert(!STyp->isLiteral() && "TODO: implement literal types"); - Result += STyp->getName(); + if (STyp->isLiteral()) { + Result += "ls_"; + for (Type* Ty : STyp->elements()) + Result += getMangledTypeStr(Ty); + } else + Result += "s_" + STyp->getName().str(); + // Ensure nested struct types are distinguishable. + Result += "s"; } else if (FunctionType* FT = dyn_cast(Ty)) { Result += "f_" + getMangledTypeStr(FT->getReturnType()); for (size_t i = 0; i < FT->getNumParams(); i++) Index: test/CodeGen/Generic/overloaded-intrinsic-name.ll =================================================================== --- test/CodeGen/Generic/overloaded-intrinsic-name.ll +++ test/CodeGen/Generic/overloaded-intrinsic-name.ll @@ -44,14 +44,25 @@ ; struct define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" { %tok = call i32 (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(i32 %tok, i32 7, i32 7) + %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0s_struct.tests(i32 %tok, i32 7, i32 7) ret %struct.test* %v-new } +; struct literal +define { i64, float } @test_struct_literal(i64 %v0, float %v1) gc "statepoint-example" { + %tok = call i32 (i64, i32, { i64, float } ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_ls_i64f32sf(i64 0, i32 0, { i64, float } ()* @return_ls, i32 0, i32 0, i32 0, i32 0) + %v-new = call { i64, float } @llvm.experimental.gc.result.ls_i64f32s(i32 %tok) + ret { i64, float } %v-new +} + declare zeroext i1 @return_i1() declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) declare i32* @llvm.experimental.gc.relocate.p0i32(i32, i32, i32) declare float* @llvm.experimental.gc.relocate.p0f32(i32, i32, i32) declare [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32, i32, i32) declare <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32, i32, i32) -declare %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32, i32, i32) +declare %struct.test* @llvm.experimental.gc.relocate.p0s_struct.tests(i32, i32, i32) + +declare { i64, float } @return_ls() +declare i32 @llvm.experimental.gc.statepoint.p0f_ls_i64f32sf(i64, i32, { i64, float } ()*, i32, i32, ...) +declare { i64, float } @llvm.experimental.gc.result.ls_i64f32s(i32) Index: test/CodeGen/X86/statepoint-call-lowering.ll =================================================================== --- test/CodeGen/X86/statepoint-call-lowering.ll +++ test/CodeGen/X86/statepoint-call-lowering.ll @@ -71,8 +71,8 @@ ; CHECK: popq %rcx ; CHECK: retq entry: - %safepoint_token = tail call i32 (i64, i32, %struct ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_structf(i64 0, i32 0, %struct ()* @return_struct, i32 0, i32 0, i32 0, i32 0) - %call1 = call %struct @llvm.experimental.gc.result.struct(i32 %safepoint_token) + %safepoint_token = tail call i32 (i64, i32, %struct ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_s_structsf(i64 0, i32 0, %struct ()* @return_struct, i32 0, i32 0, i32 0, i32 0) + %call1 = call %struct @llvm.experimental.gc.result.s_structs(i32 %safepoint_token) ret %struct %call1 } @@ -152,8 +152,8 @@ declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(i64, i32, float ()*, i32, i32, ...) declare float @llvm.experimental.gc.result.f32(i32) -declare i32 @llvm.experimental.gc.statepoint.p0f_structf(i64, i32, %struct ()*, i32, i32, ...) -declare %struct @llvm.experimental.gc.result.struct(i32) +declare i32 @llvm.experimental.gc.statepoint.p0f_s_structsf(i64, i32, %struct ()*, i32, i32, ...) +declare %struct @llvm.experimental.gc.result.s_structs(i32) declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64, i32, void (i32, ...)*, i32, i32, ...)