diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 190388ad4f7e..6e8775d2309a 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -357,6 +357,9 @@ class Context { auto clang_decls() -> SemIR::ClangDeclStore& { return sem_ir().clang_decls(); } + auto clang_decl_signatures() -> SemIR::ClangDeclSignatureStore& { + return sem_ir().clang_decl_signatures(); + } auto names() -> SemIR::NameStoreWrapper { return sem_ir().names(); } auto name_scopes() -> SemIR::NameScopeStore& { return sem_ir().name_scopes(); diff --git a/toolchain/check/cpp/impl_lookup.cpp b/toolchain/check/cpp/impl_lookup.cpp index 1bf521c20182..c345f15d5891 100644 --- a/toolchain/check/cpp/impl_lookup.cpp +++ b/toolchain/check/cpp/impl_lookup.cpp @@ -76,7 +76,7 @@ namespace { struct DeclInfo { // If null, no C++ decl was found and no witness can be created. clang::NamedDecl* decl = nullptr; - SemIR::ClangDeclKey::Signature signature; + SemIR::ClangDeclSignatureId signature_id; }; } // namespace @@ -98,7 +98,7 @@ static auto GetFunctionId(Context& context, SemIR::LocId loc_id, } auto fn_id = - ImportCppFunctionDecl(context, loc_id, cpp_fn, decl_info.signature); + ImportCppFunctionDecl(context, loc_id, cpp_fn, decl_info.signature_id); if (fn_id == SemIR::ErrorInst::InstId) { return SemIR::ErrorInst::InstId; } @@ -109,6 +109,18 @@ static auto GetFunctionId(Context& context, SemIR::LocId loc_id, return fn_id; } +// Creates a signature with `Normal` kind and the given parameter passing +// modes, and adds it to the value store. +static auto MakeSignature( + Context& context, + std::initializer_list modes, + SemIR::ClangDeclSignature::PassingMode self_passing_mode = + SemIR::ClangDeclSignature::PassingMode::ByRef) + -> SemIR::ClangDeclSignatureId { + return context.clang_decl_signatures().Add(SemIR::ClangDeclSignature::Make( + modes, SemIR::ClangDeclSignature::Normal, self_passing_mode)); +} + static auto BuildCopyWitness( Context& context, SemIR::LocId loc_id, SemIR::ConstantId query_self_const_id, @@ -131,9 +143,12 @@ static auto BuildCopyWitness( })) { return SemIR::ErrorInst::InstId; } + + SemIR::ClangDeclSignatureId signature_id = MakeSignature( + context, {SemIR::ClangDeclSignature::PassingMode::ByValue}); auto decl_info = DeclInfo{.decl = clang_sema.LookupCopyingConstructor( class_decl, clang::Qualifiers::Const), - .signature = {.num_params = 1}}; + .signature_id = signature_id}; auto fn_id = GetFunctionId(context, loc_id, decl_info); if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) { return fn_id; @@ -168,8 +183,14 @@ static auto BuildCppUnsafeDerefWitness( context.TODO(loc_id, "operator* overload sets not implemented yet"); return SemIR::ErrorInst::InstId; } + + // TODO: Parameterize the interface by the form of the operand and compute the + // appropriate passing mode here. + SemIR::ClangDeclSignatureId signature_id = + MakeSignature(context, {}, SemIR::ClangDeclSignature::PassingMode::ByRef); + auto decl_info = - DeclInfo{.decl = *candidates.begin(), .signature = {.num_params = 0}}; + DeclInfo{.decl = *candidates.begin(), .signature_id = signature_id}; auto fn_id = GetFunctionId(context, loc_id, decl_info); if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) { return fn_id; @@ -204,9 +225,11 @@ static auto BuildDefaultWitness( // That happens if class_decl->hasUninitializedExplicitInitFields() is true. // // TODO: Consider treating such types as not implementing `Default`. + SemIR::ClangDeclSignatureId signature_id = MakeSignature(context, {}); + auto decl_info = DeclInfo{.decl = clang_sema.LookupDefaultConstructor(class_decl), - .signature = {.num_params = 0}}; + .signature_id = signature_id}; auto fn_id = GetFunctionId(context, loc_id, decl_info); if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) { return fn_id; @@ -227,8 +250,10 @@ static auto BuildDestroyWitness( if (!class_decl) { return SemIR::InstId::None; } + SemIR::ClangDeclSignatureId signature_id = MakeSignature(context, {}); + auto decl_info = DeclInfo{.decl = clang_sema.LookupDestructor(class_decl), - .signature = {.num_params = 0}}; + .signature_id = signature_id}; auto fn_id = GetFunctionId(context, loc_id, decl_info); if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) { return fn_id; @@ -375,8 +400,8 @@ static auto LookupCppMethod( auto decl_info = DeclInfo{ .decl = *lookup_info.begin(), - .signature = {.num_params = 0}, - }; + .signature_id = MakeSignature( + context, {}, SemIR::ClangDeclSignature::PassingMode::ByValue)}; return GetFunctionId(context, loc_id, decl_info); } diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 73221e581c65..856b41e72f5a 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -70,6 +70,12 @@ namespace Carbon::Check { +auto IsObjectMemberFunction(const clang::FunctionDecl& decl) -> bool { + const auto* method = dyn_cast(&decl); + return method && !method->isStatic() && + !isa(&decl); +} + // Adds the name to the scope with the given `access_kind` and `inst_id`. // `inst_id` must have a value. static auto AddNameToScope(Context& context, SemIR::NameScopeId scope_id, @@ -504,6 +510,7 @@ static auto ImportNamespaceDecl(Context& context, clang::NamespaceDecl* clang_decl) -> SemIR::InstId { auto key = SemIR::ClangDeclKey(clang_decl); + // Check if the declaration is already mapped. if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key); existing_inst_id.has_value()) { @@ -833,6 +840,75 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id, .layout_id = context.custom_layouts().Add(layout)})); } +// Returns the passing mode to use for a given virtual function's object +// parameter. +static auto GetVirtualFunctionSelfPassingMode( + const clang::CXXMethodDecl* method_decl) + -> SemIR::ClangDeclSignature::PassingMode { + if (method_decl->getMethodQualifiers().hasConst()) { + // Map these signatures to pass-by-value: + // + // virtual void f() const; + // virtual void f() const&; + // virtual void f() const&&; + // + // In each case, we expect `self` to not be modified. + return SemIR::ClangDeclSignature::PassingMode::ByValue; + } + + // Map anything else to pass-by-reference. This includes `&&`-qualified + // functions, which we can't map to pass-by-var since that would perform a + // slicing copy at the call site, which would be disastrous for a virtual + // function call. + // TODO: Find a better way to handle such cases, perhaps with a library type + // representing a `&&` parameter. + return SemIR::ClangDeclSignature::PassingMode::ByRef; +} + +// Returns the passing mode to use for a virtual function parameter of the given +// type. +static auto GetVirtualFunctionParamPassingMode(clang::QualType type) + -> SemIR::ClangDeclSignature::PassingMode { + if (type->isReferenceType() && + type.getNonReferenceType().isConstQualified()) { + // For `const &`, `const &&`, use pass by value. + return SemIR::ClangDeclSignature::PassingMode::ByValue; + } + + if (type->isLValueReferenceType()) { + // For non-const `&`, use pass by reference. + return SemIR::ClangDeclSignature::PassingMode::ByRef; + } + + // Map everything else to pass by var. That's the closest match we have to C++ + // parameter semantics, and is necessary to support parameters that are passed + // by move. + return SemIR::ClangDeclSignature::PassingMode::ByVar; +} + +// Computes the signature to use for the given imported virtual function. Unlike +// with regular imported functions, we can only use a single signature here, so +// we pick one conservatively. +static auto MakeVirtualFunctionSignature( + Context& context, const clang::CXXMethodDecl* method_decl) + -> SemIR::ClangDeclSignatureId { + SemIR::ClangDeclSignature signature = { + .kind = SemIR::ClangDeclSignature::Normal, + // Include all parameters. Virtual calls do not support using default + // arguments. + .num_params = static_cast(method_decl->getNumNonObjectParams()), + .self_passing_mode = GetVirtualFunctionSelfPassingMode(method_decl), + }; + signature.passing_modes.reserve(signature.num_params); + for (auto i : llvm::seq(signature.num_params)) { + const auto* param = method_decl->getNonObjectParameter(i); + signature.passing_modes.push_back( + GetVirtualFunctionParamPassingMode(param->getType())); + } + + return context.clang_decl_signatures().Add(signature); +} + // Creates a Carbon class definition based on the information in the given Clang // class declaration, which is assumed to be for a class definition. static auto BuildClassDefinition(Context& context, @@ -879,7 +955,7 @@ static auto BuildClassDefinition(Context& context, vtable.push_back(ImportCppFunctionDecl( context, SemIR::LocId(import_ir_inst_id), const_cast(method_decl), - {.num_params = static_cast(method_decl->getNumParams())})); + MakeVirtualFunctionSignature(context, method_decl))); } vtable.truncate(num_components); auto vtable_id = context.vtables().Add( @@ -1304,47 +1380,38 @@ struct ParameterTypeInfo { }; } // namespace +// Maps a C++ parameter passing mode to a Carbon pattern kind. +static auto GetParamPatternKindForPassingMode( + SemIR::ClangDeclSignature::PassingMode mode) -> ParamPatternKind { + switch (mode) { + case SemIR::ClangDeclSignature::PassingMode::ByValue: + return ParamPatternKind::Value; + case SemIR::ClangDeclSignature::PassingMode::ByVar: + return ParamPatternKind::Var; + case SemIR::ClangDeclSignature::PassingMode::ByRef: + return ParamPatternKind::Ref; + } +} + // Given the type of a C++ function parameter, returns information about the // type to use for the corresponding Carbon parameter. // // Note that if the parameter has a type for which `IsSimpleAbiType` returns // true, we must produce a parameter type that has the same calling convention // as the C++ type. -static auto MapParameterType(Context& context, SemIR::LocId loc_id, - clang::QualType param_type) -> ParameterTypeInfo { - ParameterTypeInfo info = {.type = TypeExpr::None, - .kind = ParamPatternKind::Value}; - - // Perform some custom mapping for parameters of reference type: - // - // * `T& x` -> `ref x: T`. - // * `T&& x` -> `var x: T`. - // * `const T& x` -> `x: T`. - // * `const T&& x` -> `x: T`. +static auto MapParameterType( + Context& context, SemIR::LocId loc_id, clang::QualType param_type, + SemIR::ClangDeclSignature::PassingMode passing_mode) -> ParameterTypeInfo { if (param_type->isReferenceType()) { - clang::QualType pointee_type = param_type->getPointeeType(); - if (pointee_type.isConstQualified()) { - // TODO: Consider only doing this if `const` is the only qualifier. For - // now, any other qualifier will fail when mapping the type. - auto split_type = pointee_type.getSplitUnqualifiedType(); - split_type.Quals.removeConst(); - pointee_type = context.ast_context().getQualifiedType(split_type); - } else if (param_type->isLValueReferenceType()) { - // Lvalue references map to a `ref` pattern. - info.kind = ParamPatternKind::Ref; - } else { - // Rvalue references map to a `var` pattern. When given a value expression - // as an argument, this will result in a copy. However, if the argument is - // of class type, we will map its type to `const T`, which means overload - // resolution won't allow the call anyway, so this only permits passing - // value expressions of non-class type to a `T&&` parameter. - info.kind = ParamPatternKind::Var; - } - param_type = pointee_type; + // TODO: For now, we only remove `const`; any other qualifier will fail when + // mapping the type. + auto split_type = + param_type.getNonReferenceType().getSplitUnqualifiedType(); + split_type.Quals.removeConst(); + param_type = context.ast_context().getQualifiedType(split_type); } - - info.type = MapType(context, loc_id, param_type); - return info; + return {.type = MapType(context, loc_id, param_type), + .kind = GetParamPatternKindForPassingMode(passing_mode)}; } // Returns a block for the implicit parameters of the given function @@ -1354,19 +1421,22 @@ static auto MapParameterType(Context& context, SemIR::LocId loc_id, static auto MakeImplicitParamPatternsBlockId( Context& context, SemIR::LocId loc_id, SemIR::ImportIRInstId import_ir_inst_id, - const clang::FunctionDecl& clang_decl) -> SemIR::InstBlockId { - const auto* method_decl = dyn_cast(&clang_decl); - if (!method_decl || method_decl->isStatic() || - isa(clang_decl)) { + const clang::FunctionDecl& clang_decl, + SemIR::ClangDeclSignatureId signature_id) -> SemIR::InstBlockId { + if (!IsObjectMemberFunction(clang_decl)) { return SemIR::InstBlockId::Empty; } + const auto* method_decl = cast(&clang_decl); // Build a `self` parameter from the object parameter. BeginSubpattern(context); clang::QualType param_type = method_decl->getFunctionObjectParameterReferenceType(); - auto param_info = MapParameterType(context, loc_id, param_type); + const auto& signature = context.clang_decl_signatures().Get(signature_id); + SemIR::ClangDeclSignature::PassingMode passing_mode = + signature.self_passing_mode; + auto param_info = MapParameterType(context, loc_id, param_type, passing_mode); auto [type_inst_id, type_id] = param_info.type; SemIR::ExprRegionId type_expr_region_id = ConsumeSubpatternExpr(context, type_inst_id); @@ -1399,8 +1469,9 @@ static auto MakeImplicitParamPatternsBlockId( static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, SemIR::ImportIRInstId import_ir_inst_id, const clang::FunctionDecl& clang_decl, - SemIR::ClangDeclKey::Signature signature) + SemIR::ClangDeclSignatureId signature_id) -> SemIR::InstBlockId { + const auto& signature = context.clang_decl_signatures().Get(signature_id); llvm::SmallVector param_ids; llvm::SmallVector param_type_ids; param_ids.reserve(signature.num_params); @@ -1411,7 +1482,7 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, clang_decl.getNumNonObjectParams(), signature.num_params); const auto* function_type = clang_decl.getType()->castAs(); - for (int i : llvm::seq(signature.num_params)) { + for (auto i : llvm::seq(signature.num_params)) { const auto* param = clang_decl.getNonObjectParameter(i); clang::QualType orig_param_type = function_type->getParamType( clang_decl.hasCXXExplicitFunctionObjectParameter() + i); @@ -1425,7 +1496,8 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, // Mark the start of a region of insts, needed for the type expression // created later with the call of `ConsumeSubpatternExpr()`. BeginSubpattern(context); - auto param_info = MapParameterType(context, loc_id, param_type); + auto param_info = MapParameterType(context, loc_id, param_type, + signature.GetPassingMode(i)); auto [type_inst_id, type_id] = param_info.type; // Type expression of the binding pattern - a single-entry/single-exit // region that allows control flow in the type expression e.g. fn F(x: if C @@ -1460,12 +1532,12 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, } switch (signature.kind) { - case SemIR::ClangDeclKey::Signature::Normal: { + case SemIR::ClangDeclSignature::Normal: { // Use the converted parameter list as-is. break; } - case SemIR::ClangDeclKey::Signature::TuplePattern: { + case SemIR::ClangDeclSignature::TuplePattern: { // Replace the parameters with a single tuple pattern containing the // converted parameter list. auto param_block_id = context.inst_blocks().Add(param_ids); @@ -1629,18 +1701,18 @@ struct FunctionSignatureInsts { static auto CreateFunctionSignatureInsts( Context& context, SemIR::LocId loc_id, SemIR::ImportIRInstId import_ir_inst_id, clang::FunctionDecl* clang_decl, - SemIR::ClangDeclKey::Signature signature) + SemIR::ClangDeclSignatureId signature_id) -> std::optional { context.full_pattern_stack().StartImplicitParamList(); auto implicit_param_patterns_id = MakeImplicitParamPatternsBlockId( - context, loc_id, import_ir_inst_id, *clang_decl); + context, loc_id, import_ir_inst_id, *clang_decl, signature_id); if (!implicit_param_patterns_id.has_value()) { return std::nullopt; } context.full_pattern_stack().EndImplicitParamList(); context.full_pattern_stack().StartExplicitParamList(); auto param_patterns_id = MakeParamPatternsBlockId( - context, loc_id, import_ir_inst_id, *clang_decl, signature); + context, loc_id, import_ir_inst_id, *clang_decl, signature_id); if (!param_patterns_id.has_value()) { return std::nullopt; } @@ -1705,12 +1777,12 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl) static auto ImportFunction(Context& context, SemIR::LocId loc_id, SemIR::ImportIRInstId import_ir_inst_id, clang::FunctionDecl* clang_decl, - SemIR::ClangDeclKey::Signature signature) + SemIR::ClangDeclSignatureId signature_id) -> std::optional { StartFunctionSignature(context); auto function_params_insts = CreateFunctionSignatureInsts( - context, loc_id, import_ir_inst_id, clang_decl, signature); + context, loc_id, import_ir_inst_id, clang_decl, signature_id); auto [pattern_block_id, decl_block_id] = FinishFunctionSignature(context, /*check_unused=*/false); @@ -1780,9 +1852,9 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, context.imports().push_back(decl_id); context.functions().Get(function_id).clang_decl_id = - context.clang_decls().Add( - {.key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature), - .inst_id = decl_id}); + context.clang_decls().Add({.key = SemIR::ClangDeclKey::ForFunctionDecl( + clang_decl, signature_id), + .inst_id = decl_id}); return function_id; } @@ -1794,9 +1866,9 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, // the trailing parameters. static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, clang::FunctionDecl* clang_decl, - SemIR::ClangDeclKey::Signature signature) + SemIR::ClangDeclSignatureId signature_id) -> SemIR::InstId { - auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature); + auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature_id); // Check if the declaration is already mapped. if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key); @@ -1822,8 +1894,8 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, CARBON_CHECK(clang_decl->getFunctionType()->isFunctionProtoType(), "Not Prototype function (non-C++ code)"); - auto function_id = - ImportFunction(context, loc_id, import_ir_inst_id, clang_decl, signature); + auto function_id = ImportFunction(context, loc_id, import_ir_inst_id, + clang_decl, signature_id); if (!function_id) { MarkFailedDecl(context, key); return SemIR::ErrorInst::InstId; @@ -1840,10 +1912,19 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, if (clang::FunctionDecl* thunk_clang_decl = BuildCppThunk(context, function_info)) { - if (auto thunk_function_id = ImportFunction( - context, loc_id, import_ir_inst_id, thunk_clang_decl, - {.num_params = - static_cast(thunk_clang_decl->getNumParams())})) { + SemIR::ClangDeclSignature thunk_signature; + thunk_signature.kind = SemIR::ClangDeclSignature::Normal; + thunk_signature.num_params = + static_cast(thunk_clang_decl->getNumParams()); + thunk_signature.passing_modes.assign( + thunk_signature.num_params, + SemIR::ClangDeclSignature::PassingMode::ByValue); + SemIR::ClangDeclSignatureId thunk_signature_id = + context.clang_decl_signatures().Add(std::move(thunk_signature)); + + if (auto thunk_function_id = + ImportFunction(context, loc_id, import_ir_inst_id, + thunk_clang_decl, thunk_signature_id)) { auto& thunk_function = context.functions().Get(*thunk_function_id); thunk_function.SetCppThunk(function_info.first_owning_decl_id); SemIR::InstId thunk_function_decl_id = @@ -1922,8 +2003,9 @@ static auto AddDependentUnimportedTypeDecls(Context& context, // and adds them to the given set. static auto AddDependentUnimportedFunctionDecls( Context& context, const clang::FunctionDecl& clang_decl, - SemIR::ClangDeclKey::Signature signature, ImportWorklist& worklist) + SemIR::ClangDeclSignatureId signature_id, ImportWorklist& worklist) -> void { + const auto& signature = context.clang_decl_signatures().Get(signature_id); const auto* function_type = clang_decl.getType()->castAs(); for (int i : llvm::seq(clang_decl.hasCXXExplicitFunctionObjectParameter() + @@ -1943,7 +2025,7 @@ static auto AddDependentUnimportedDecls(Context& context, clang::Decl* clang_decl = key.decl; if (auto* clang_function_decl = clang_decl->getAsFunction()) { AddDependentUnimportedFunctionDecls(context, *clang_function_decl, - key.signature, worklist); + key.signature_id, worklist); } else if (auto* type_decl = dyn_cast(clang_decl)) { if (!isa(clang_decl)) { AddDependentUnimportedTypeDecls( @@ -2063,7 +2145,7 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id, clang::Decl* clang_decl = key.decl; if (auto* clang_function_decl = clang_decl->getAsFunction()) { return ImportFunctionDecl(context, loc_id, clang_function_decl, - key.signature); + key.signature_id); } if (auto* clang_namespace_decl = dyn_cast(clang_decl)) { return ImportNamespaceDecl(context, clang_namespace_decl); diff --git a/toolchain/check/cpp/import.h b/toolchain/check/cpp/import.h index 096f1fb19095..f94a04e0bffa 100644 --- a/toolchain/check/cpp/import.h +++ b/toolchain/check/cpp/import.h @@ -18,6 +18,12 @@ namespace Carbon::Check { +// Returns whether the given function is an object member function. This is true +// if it's a non-static member function and not a constructor. Object member +// functions correspond to Carbon functions with a `self` parameter. +// TODO: Find a better home for this function. +auto IsObjectMemberFunction(const clang::FunctionDecl& decl) -> bool; + // Generates a C++ header that includes the imported cpp files, parses it, // generates the AST from it and links `SemIR::File` to it. Reports C++ errors // and warnings. If successful, adds a `Cpp` namespace. @@ -59,11 +65,11 @@ auto ImportCppDecl(Context& context, SemIR::LocId loc_id, // imported, returns the mapped instruction. inline auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id, clang::FunctionDecl* clang_decl, - SemIR::ClangDeclKey::Signature signature) + SemIR::ClangDeclSignatureId signature_id) -> SemIR::InstId { return ImportCppDecl( context, loc_id, - SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature)); + SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature_id)); } // Imports a function declaration from Clang to Carbon. If successful, returns diff --git a/toolchain/check/cpp/operators.cpp b/toolchain/check/cpp/operators.cpp index b3b87ba1ed37..17d497d6f857 100644 --- a/toolchain/check/cpp/operators.cpp +++ b/toolchain/check/cpp/operators.cpp @@ -19,6 +19,7 @@ #include "toolchain/check/type.h" #include "toolchain/check/type_completion.h" #include "toolchain/sem_ir/builtin_function_kind.h" +#include "toolchain/sem_ir/clang_decl.h" #include "toolchain/sem_ir/cpp_initializer_list.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" @@ -285,44 +286,67 @@ static auto MakeCppStdInitializerListMake(Context& context, SemIR::LocId loc_id, static auto GetConversionSignatureToImport( Context& context, SemIR::InstId source_id, clang::InitializationSequence::StepKind step_kind, - clang::FunctionDecl* function_decl) -> SemIR::ClangDeclKey::Signature { + clang::FunctionDecl* function_decl, clang::DeclAccessPair found_decl, + clang::Expr* arg_expr) -> SemIR::ClangDeclSignatureId { + auto signature_kind = SemIR::ClangDeclSignature::Normal; + clang::Expr* self_expr = nullptr; + llvm::ArrayRef arg_exprs(arg_expr); + // If we're performing a constructor initialization from a list, form a // function signature that takes a single tuple or struct pattern // instead of a function signature with one parameter per C++ parameter. if (step_kind == clang::InitializationSequence::SK_ConstructorInitializationFromList) { + // Initialization from a tuple `(a, b, c)` results in a constructor + // function that takes a tuple pattern: + // + // fn Class.Class((a: A, b: B, c: C)) -> Class; + // // The source type should always be a tuple type, because we don't support // C++ initialization from struct types. auto tuple_type = context.types().TryGetAs( context.insts().Get(source_id).type_id()); CARBON_CHECK(tuple_type, "List initialization from non-tuple type"); - - // Initialization from a tuple `(a, b, c)` results in a constructor - // function that takes a tuple pattern: - // - // fn Class.Class((a: A, b: B, c: C)) -> Class; - return { - .kind = SemIR::ClangDeclKey::Signature::Kind::TuplePattern, - .num_params = static_cast( - context.inst_blocks().Get(tuple_type->type_elements_id).size())}; + arg_exprs = cast(arg_expr)->inits(); + signature_kind = SemIR::ClangDeclSignature::TuplePattern; } - // Any other initialization using a constructor is calling a converting - // constructor: - // - // fn Class.Class(a: A) -> Class; + // In order to determine how to map the parameters, we need to build the + // conversion sequence(s) again. Clang already threw them away. The only way + // to do this is to "redo" overload resolution with our single candidate. + clang::OverloadCandidateSet candidates( + function_decl->getLocation(), + clang::OverloadCandidateSet::CSK_InitByUserDefinedConversion); + if (isa(function_decl)) { - return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal, - .num_params = 1}; + // This is either tuple list initialization as described above or a + // constructor call: + // + // fn Class.Class(a: A) -> Class; + context.clang_sema().AddOverloadCandidate(function_decl, found_decl, + arg_exprs, candidates); + } else { + // Otherwise, the initialization is calling a conversion function + // `Source::operator Dest`: + // + // fn Source.[self: Source]() -> Dest; + auto* conversion_decl = cast(function_decl); + self_expr = arg_expr; + arg_exprs = {}; + context.clang_sema().AddMethodCandidate( + conversion_decl, found_decl, conversion_decl->getParent(), + self_expr->getType(), self_expr->Classify(context.ast_context()), + arg_exprs, candidates); } - // Otherwise, the initialization is calling a conversion function - // `Source::operator Dest`: - // - // fn Source.[self: Source]() -> Dest; - CARBON_CHECK(isa(function_decl)); - return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal, - .num_params = 0}; + clang::OverloadCandidateSet::iterator best; + auto result = candidates.BestViableFunction( + context.clang_sema(), function_decl->getLocation(), best); + CARBON_CHECK(result == clang::OverloadingResult::OR_Success || + result == clang::OverloadingResult::OR_Deleted); + + return ComputeClangDeclSignatureFromBestViableFunction( + context, best, self_expr, arg_exprs, signature_kind); } static auto LookupCppConversion(Context& context, SemIR::LocId loc_id, @@ -402,10 +426,12 @@ static auto LookupCppConversion(Context& context, SemIR::LocId loc_id, sema.MarkFunctionReferenced(loc, step.Function.Function); - auto signature = GetConversionSignatureToImport( - context, source_id, step.Kind, step.Function.Function); + SemIR::ClangDeclSignatureId signature_id = + GetConversionSignatureToImport(context, source_id, step.Kind, + step.Function.Function, + step.Function.FoundDecl, arg_expr); auto result_id = ImportCppFunctionDecl( - context, loc_id, step.Function.Function, signature); + context, loc_id, step.Function.Function, signature_id); if (auto fn_decl = context.insts().TryGetAsWithId( result_id)) { CheckCppOverloadAccess(context, loc_id, step.Function.FoundDecl, @@ -637,14 +663,18 @@ static auto FindClangOperator(Context& context, SemIR::LocId loc_id, sema.MarkFunctionReferenced(loc, best_viable_fn->Function); // If this is an operator method, the first arg will be used as self. - int32_t num_params = arg_exprs.size(); - if (isa(best_viable_fn->Function)) { - --num_params; + clang::Expr* self_expr = nullptr; + auto arg_exprs_for_signature = arg_exprs; + if (IsObjectMemberFunction(*best_viable_fn->Function)) { + self_expr = arg_exprs_for_signature.consume_front(); } - auto result_id = - ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function, - {.num_params = num_params}); + SemIR::ClangDeclSignatureId signature_id = + ComputeClangDeclSignatureFromBestViableFunction( + context, best_viable_fn, self_expr, arg_exprs_for_signature); + + auto result_id = ImportCppFunctionDecl( + context, loc_id, best_viable_fn->Function, signature_id); if (result_id != SemIR::ErrorInst::InstId) { CheckCppOverloadAccess( context, loc_id, best_viable_fn->FoundDecl, diff --git a/toolchain/check/cpp/overload_resolution.cpp b/toolchain/check/cpp/overload_resolution.cpp index e55c4cfe33a4..99419dfd8a33 100644 --- a/toolchain/check/cpp/overload_resolution.cpp +++ b/toolchain/check/cpp/overload_resolution.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/cpp/overload_resolution.h" +#include "clang/AST/DeclCXX.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" @@ -68,9 +69,8 @@ static auto AddOverloadCandidates( auto* fn_decl = template_decl ? template_decl->getTemplatedDecl() : cast(decl); - auto* method_decl = dyn_cast(fn_decl); - if (method_decl && !method_decl->isStatic() && - !isa(fn_decl)) { + if (IsObjectMemberFunction(*fn_decl)) { + auto* method_decl = cast(fn_decl); clang::QualType self_type; clang::Expr::Classification self_classification; if (self_arg) { @@ -130,6 +130,139 @@ auto CheckCppOverloadAccess( .highest_allowed_access = allowed_access_kind}); } +// Computes the passing mode for a C++ function parameter that is a reference. +static auto ComputePassingModeForReferenceBinding( + const clang::StandardConversionSequence& scs) + -> SemIR::ClangDeclSignature::PassingMode { + CARBON_CHECK(scs.ReferenceBinding); + auto pointee_type = scs.getToType(2); + if (pointee_type.isConstQualified() || + (scs.IsLvalueReference && scs.BindsToRvalue)) { + // Reference to const is always mapped to Carbon pass by value. A non-const + // lvalue reference bound to an rvalue only happens when initializing an + // object parameter with no ref-qualifier from an rvalue, which we also + // model as pass-by-value. + return SemIR::ClangDeclSignature::PassingMode::ByValue; + } + // Rvalue reference to non-const is passed as a `var` to force a copy or move + // in the caller. Lvalue reference to non-const is passed by reference. + return scs.IsLvalueReference ? SemIR::ClangDeclSignature::PassingMode::ByRef + : SemIR::ClangDeclSignature::PassingMode::ByVar; +} + +// Returns whether move-construction of type `type` is known to be equivalent to +// a copy. If so, it's safe to map C++ pass-by-value into Carbon pass-by-value +// instead of pass-by-var. +static auto IsMoveEquivalentToCopy(clang::QualType type) { + // We can pass by copy instead of by move if: + // - The type is not a class type. + auto* record_decl = type->getAsCXXRecordDecl(); + if (!record_decl) { + return true; + } + + // - The move constructor is defaulted and deleted or non-existent, in + // which case overload resolution for a move will call the copy + // constructor. + if (!record_decl->hasMoveConstructor() || + (!record_decl->hasUserDeclaredMoveConstructor() && + record_decl->defaultedMoveConstructorIsDeleted())) { + return true; + } + + // - Both move and copy are trivial and not deleted, in which case they + // are equivalent. + if (record_decl->hasTrivialMoveConstructor() && + !record_decl->defaultedMoveConstructorIsDeleted() && + record_decl->hasTrivialCopyConstructor() && + !record_decl->defaultedCopyConstructorIsDeleted()) { + return true; + } + + // Otherwise we need a move, so we pass by var. + return false; +} + +auto GetPassingModeForCppParameter(const clang::ImplicitConversionSequence& ics, + const clang::Expr* arg_expr) + -> SemIR::ClangDeclSignature::PassingMode { + if (ics.isStandard()) { + const auto& scs = ics.Standard; + if (scs.ReferenceBinding) { + return ComputePassingModeForReferenceBinding(scs); + } + + // Most standard conversions can be mapped to Carbon pass by value. The + // exception is where the source is an initializing expression of record + // type, which we map to pass by var, unless a copy would do the same thing. + if (arg_expr->isXValue() && !IsMoveEquivalentToCopy(arg_expr->getType())) { + return SemIR::ClangDeclSignature::PassingMode::ByVar; + } + + return SemIR::ClangDeclSignature::PassingMode::ByValue; + } + + if (ics.isUserDefined()) { + const auto& ucs = ics.UserDefined; + if (ucs.After.ReferenceBinding) { + return ComputePassingModeForReferenceBinding(ucs.After); + } + + const auto* ctor = + dyn_cast_or_null(ucs.ConversionFunction); + if (ctor && ctor->isCopyConstructor()) { + // Overload resolution wanted to call a copy constructor to initialize + // this parameter. Pass by value instead; we'll copy in the thunk. + return SemIR::ClangDeclSignature::PassingMode::ByValue; + } + + // We're calling a user-defined conversion, so we're performing + // initialization. Pass by move unless the type being initialized doesn't + // distinguish moves and copies. + return IsMoveEquivalentToCopy(ucs.After.getToType(2)) + ? SemIR::ClangDeclSignature::PassingMode::ByValue + : SemIR::ClangDeclSignature::PassingMode::ByVar; + } + + // TODO: Support ellipsis conversion sequences. + CARBON_FATAL("Unexpected kind of implicit conversion sequence"); +} + +// Computes the signature for a C++ function candidate based on the conversions +// performed on the arguments. +auto ComputeClangDeclSignatureFromBestViableFunction( + Context& context, clang::OverloadCandidateSet::iterator candidate, + clang::Expr* self_expr, llvm::ArrayRef arg_exprs, + SemIR::ClangDeclSignature::Kind kind) -> SemIR::ClangDeclSignatureId { + SemIR::ClangDeclSignature signature; + signature.kind = kind; + signature.num_params = static_cast(arg_exprs.size()); + signature.passing_modes.reserve(signature.num_params); + + for (auto [i, arg_expr] : llvm::enumerate(arg_exprs)) { + // Compute which conversion sequence corresponds to this argument. + // TODO: Clang should expose a way to compute this. + int conversion_index = i; + if (auto* method = dyn_cast(candidate->Function)) { + if (method->isStatic()) { + // Static methods get an object parameter conversion at index 0, even + // though there's no argument. + ++conversion_index; + } + } + + signature.passing_modes.push_back(GetPassingModeForCppParameter( + candidate->Conversions[conversion_index], arg_expr)); + } + + if (IsObjectMemberFunction(*candidate->Function)) { + signature.self_passing_mode = + GetPassingModeForCppParameter(candidate->Conversions[0], self_expr); + } + + return context.clang_decl_signatures().Add(std::move(signature)); +} + auto PerformCppOverloadResolution( Context& context, SemIR::LocId loc_id, const SemIR::CppOverloadSet& overload_set, @@ -179,9 +312,12 @@ auto PerformCppOverloadResolution( case clang::OverloadingResult::OR_Success: { CARBON_CHECK(best_viable_fn->Function); CARBON_CHECK(!best_viable_fn->RewriteKind); + SemIR::ClangDeclSignatureId signature_id = + ComputeClangDeclSignatureFromBestViableFunction( + context, best_viable_fn, self_expr, arg_exprs); + SemIR::InstId result_id = ImportCppFunctionDecl( - context, loc_id, best_viable_fn->Function, - {.num_params = static_cast(arg_exprs.size())}); + context, loc_id, best_viable_fn->Function, signature_id); if (result_id != SemIR::ErrorInst::InstId) { CheckCppOverloadAccess( context, loc_id, best_viable_fn->FoundDecl, diff --git a/toolchain/check/cpp/overload_resolution.h b/toolchain/check/cpp/overload_resolution.h index ca8f7bb4d53b..39453a780819 100644 --- a/toolchain/check/cpp/overload_resolution.h +++ b/toolchain/check/cpp/overload_resolution.h @@ -20,6 +20,18 @@ auto CheckCppOverloadAccess( SemIR::KnownInstId overload_inst_id, SemIR::NameScopeId parent_scope_id = SemIR::NameScopeId::None) -> void; +// Returns the passing mode to use for a parameter given the implicit +// conversion sequence and the argument expression. +auto GetPassingModeForCppParameter(const clang::ImplicitConversionSequence& ics, + const clang::Expr* arg_expr) + -> SemIR::ClangDeclSignature::PassingMode; + +auto ComputeClangDeclSignatureFromBestViableFunction( + Context& context, clang::OverloadCandidateSet::iterator candidate, + clang::Expr* self_expr, llvm::ArrayRef arg_exprs, + SemIR::ClangDeclSignature::Kind kind = SemIR::ClangDeclSignature::Normal) + -> SemIR::ClangDeclSignatureId; + // Resolves which function to call using Clang overload resolution. Returns an // instruction referring to that function, or an error instruction if overload // resolution failed. diff --git a/toolchain/check/cpp/thunk.cpp b/toolchain/check/cpp/thunk.cpp index aaf7c1b4bbff..5e24b1ba16c3 100644 --- a/toolchain/check/cpp/thunk.cpp +++ b/toolchain/check/cpp/thunk.cpp @@ -15,6 +15,7 @@ #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" #include "toolchain/check/cpp/context.h" +#include "toolchain/check/cpp/import.h" #include "toolchain/check/literal.h" #include "toolchain/check/type.h" #include "toolchain/check/type_completion.h" @@ -74,23 +75,42 @@ static auto GetGlobalDecl(const clang::FunctionDecl* decl) static auto GenerateThunkMangledName( clang::MangleContext& mangle_context, const clang::FunctionDecl& callee_function_decl, - SemIR::ClangDeclKey::Signature::Kind signature_kind, int num_params) - -> std::string { + const SemIR::ClangDeclSignature& signature) -> std::string { RawStringOstream mangled_name_stream; mangle_context.mangleName(GetGlobalDecl(&callee_function_decl), mangled_name_stream); - switch (signature_kind) { - case SemIR::ClangDeclKey::Signature::Normal: + switch (signature.kind) { + case SemIR::ClangDeclSignature::Normal: mangled_name_stream << ".carbon_thunk"; break; - case SemIR::ClangDeclKey::Signature::TuplePattern: + case SemIR::ClangDeclSignature::TuplePattern: mangled_name_stream << ".carbon_thunk_tuple"; break; } - if (num_params != - static_cast(callee_function_decl.getNumNonObjectParams())) { - mangled_name_stream << num_params; + // Append passing modes. + // TODO: Pick one "likely" set of passing modes for the function and omit the + // suffix for that signature. + mangled_name_stream << "."; + auto append_mode = [&](SemIR::ClangDeclSignature::PassingMode mode) { + switch (mode) { + case SemIR::ClangDeclSignature::PassingMode::ByValue: + mangled_name_stream << "_"; + break; + case SemIR::ClangDeclSignature::PassingMode::ByVar: + mangled_name_stream << "v"; + break; + case SemIR::ClangDeclSignature::PassingMode::ByRef: + mangled_name_stream << "r"; + break; + } + }; + + if (IsObjectMemberFunction(callee_function_decl)) { + append_mode(signature.self_passing_mode); + } + for (auto mode : signature.passing_modes) { + append_mode(mode); } return mangled_name_stream.TakeStr(); @@ -143,15 +163,15 @@ namespace { // Information about the callee of a thunk. struct CalleeFunctionInfo { explicit CalleeFunctionInfo(clang::FunctionDecl* decl, - SemIR::ClangDeclKey::Signature signature) + const SemIR::ClangDeclSignature* signature) : decl(decl), - signature_kind(signature.kind), - num_params(signature.num_params + + signature(signature), + num_params(signature->num_params + decl->hasCXXExplicitFunctionObjectParameter()) { auto& ast_context = decl->getASTContext(); const auto* method_decl = dyn_cast(decl); bool is_ctor = isa(decl); - has_object_parameter = method_decl && !method_decl->isStatic() && !is_ctor; + has_object_parameter = IsObjectMemberFunction(*decl); if (has_object_parameter && method_decl->isImplicitObjectMemberFunction()) { implicit_object_parameter_type = method_decl->getFunctionObjectParameterReferenceType(); @@ -195,8 +215,8 @@ struct CalleeFunctionInfo { // The callee function. clang::FunctionDecl* decl; - // The kind of function signature being imported. - SemIR::ClangDeclKey::Signature::Kind signature_kind; + // The signature of the function being imported. + const SemIR::ClangDeclSignature* signature; // The number of explicit parameters to import. This may be less than the // number of parameters that the function has if default arguments are being @@ -229,25 +249,28 @@ auto IsCppThunkRequired(Context& context, const SemIR::Function& function) } const auto& decl_info = context.clang_decls().Get(function.clang_decl_id); + const auto& signature = + context.clang_decl_signatures().Get(decl_info.key.signature_id); auto* decl = cast(decl_info.key.decl); - if (decl_info.key.signature.kind != SemIR::ClangDeclKey::Signature::Normal || - decl_info.key.signature.num_params != - static_cast(decl->getNumNonObjectParams())) { + if (signature.kind != SemIR::ClangDeclSignature::Normal || + signature.num_params != static_cast(decl->getNumNonObjectParams())) { // We require a thunk if the number of parameters we want isn't all of them. // This happens if default arguments are in use, or (eventually) when // calling a varargs function. return true; } - CalleeFunctionInfo callee_info(decl, decl_info.key.signature); + CalleeFunctionInfo callee_info(decl, &signature); if (!callee_info.has_simple_return_type) { return true; } auto& ast_context = context.ast_context(); if (callee_info.has_implicit_object_parameter() && - !IsSimpleAbiType(ast_context, callee_info.implicit_object_parameter_type, - /*for_parameter=*/true)) { + (!IsSimpleAbiType(ast_context, callee_info.implicit_object_parameter_type, + /*for_parameter=*/true) || + signature.self_passing_mode == + SemIR::ClangDeclSignature::PassingMode::ByVar)) { return true; } @@ -255,7 +278,9 @@ auto IsCppThunkRequired(Context& context, const SemIR::Function& function) decl->getType()->castAs(); for (int i : llvm::seq(decl->getNumParams())) { if (!IsSimpleAbiType(ast_context, function_type->getParamType(i), - /*for_parameter=*/true)) { + /*for_parameter=*/true) || + signature.GetPassingMode(i) == + SemIR::ClangDeclSignature::PassingMode::ByVar) { return true; } } @@ -437,10 +462,8 @@ static auto CreateThunkFunctionDecl( // Set asm(".carbon_thunk"). thunk_function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( ast_context, - GenerateThunkMangledName( - context.cpp_context()->clang_mangle_context(), *callee_info.decl, - callee_info.signature_kind, - callee_info.num_params - callee_info.has_explicit_object_parameter()), + GenerateThunkMangledName(context.cpp_context()->clang_mangle_context(), + *callee_info.decl, *callee_info.signature), clang_loc)); // Set function declaration type source info. @@ -453,11 +476,10 @@ static auto CreateThunkFunctionDecl( // Builds a reference to the given parameter thunk. If `type` is specified, that // is the callee parameter type that's being held by the parameter, and // conversions will be performed as necessary to recover a value of that type. -static auto BuildThunkParamRef(clang::Sema& sema, - clang::FunctionDecl* thunk_function_decl, - unsigned thunk_index, - clang::QualType type = clang::QualType()) - -> clang::Expr* { +static auto BuildThunkParamRef( + clang::Sema& sema, clang::FunctionDecl* thunk_function_decl, + unsigned thunk_index, SemIR::ClangDeclSignature::PassingMode passing_mode, + clang::QualType type = clang::QualType()) -> clang::Expr* { clang::ParmVarDecl* thunk_param = thunk_function_decl->getParamDecl(thunk_index); clang::SourceLocation clang_loc = thunk_param->getLocation(); @@ -472,15 +494,10 @@ static auto BuildThunkParamRef(clang::Sema& sema, call_arg = deref_result.get(); } - // Cast to an rvalue when initializing an rvalue reference. The validity of - // the initialization of the reference should be validated by the caller of - // the thunk. - // - // TODO: Consider inserting a cast to an rvalue in more cases. Note that we - // currently pass pointers to non-temporary objects as the argument when - // calling a thunk, so we'll need to either change that or generate - // different thunks depending on whether we're moving from each parameter. - if (!type.isNull() && type->isRValueReferenceType()) { + // Cast to an xvalue when using pass-by-`var` or when initializing an rvalue + // reference (which might be passed by value if it's const-qualified). + if (passing_mode == SemIR::ClangDeclSignature::PassingMode::ByVar || + thunk_param->getType()->isRValueReferenceType()) { call_arg = clang::ImplicitCastExpr::Create( sema.getASTContext(), call_arg->getType(), clang::CK_NoOp, call_arg, nullptr, clang::ExprValueKind::VK_XValue, clang::FPOptionsOverride()); @@ -497,6 +514,7 @@ static auto BuildParamRefForCalleeArg(clang::Sema& sema, unsigned thunk_index = callee_info.GetThunkParamIndex(callee_index); return BuildThunkParamRef( sema, thunk_function_decl, thunk_index, + callee_info.signature->GetPassingMode(callee_index), callee_info.decl->getParamDecl(callee_index)->getType()); } @@ -538,8 +556,9 @@ static auto BuildThunkBody(CppContext& cpp_context, clang::Sema& sema, clang::QualType object_param_type = cast(callee_info.decl) ->getFunctionObjectParameterReferenceType(); - auto* object_param_ref = - BuildThunkParamRef(sema, thunk_function_decl, 0, object_param_type); + auto* object_param_ref = BuildThunkParamRef( + sema, thunk_function_decl, 0, callee_info.signature->self_passing_mode, + object_param_type); constexpr bool IsArrow = false; auto object = sema.PerformMemberExprBaseConversion(object_param_ref, IsArrow); @@ -597,7 +616,8 @@ static auto BuildThunkBody(CppContext& cpp_context, clang::Sema& sema, } auto* return_object_addr = BuildThunkParamRef( - sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex()); + sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex(), + SemIR::ClangDeclSignature::PassingMode::ByValue); auto return_type = callee_info.effective_return_type.getNonReferenceType(); auto* return_type_info = sema.Context.getTrivialTypeSourceInfo(return_type, clang_loc); @@ -635,8 +655,9 @@ auto BuildCppThunk(Context& context, const SemIR::Function& callee_function) // shouldn't consider it here. However, to do that, we would need to cache the // thunks we build so that we don't build the same thunk multiple times if // it's used with multiple different signature kinds. - CalleeFunctionInfo callee_info(callee_function_decl, - clang_decl_key.signature); + const auto& signature = + context.clang_decl_signatures().Get(clang_decl_key.signature_id); + CalleeFunctionInfo callee_info(callee_function_decl, &signature); // Build the thunk function declaration. auto thunk_param_types = diff --git a/toolchain/check/cpp/type_mapping.cpp b/toolchain/check/cpp/type_mapping.cpp index 0ddfd9c84ef7..9c2ed4a29603 100644 --- a/toolchain/check/cpp/type_mapping.cpp +++ b/toolchain/check/cpp/type_mapping.cpp @@ -518,7 +518,10 @@ static auto InventPrimitiveClangArg(Context& context, FormInfo form) case SemIR::ExprCategory::ReprInitializing: case SemIR::ExprCategory::InPlaceInitializing: - value_kind = clang::ExprValueKind::VK_PRValue; + // A Carbon initializing expression is much more similar to a C++ prvalue + // than a C++ xvalue, but we encode it as an xvalue expression to request + // that it be passed through the thunk by move rather than by copy. + value_kind = clang::ExprValueKind::VK_XValue; break; case SemIR::ExprCategory::Mixed: diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index c9d13dfaf4ab..d791ba879b5a 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -2521,7 +2521,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, resolver.import_functions().Get(inst.function_id).first_decl_id()); auto specific_data = GetLocalSpecificData(resolver, inst.specific_id); - if (resolver.HasNewWork() || !fn_val_id.has_value()) { + if (resolver.HasNewWork()) { return ResolveResult::Retry(); } auto fn_type_id = resolver.local_insts().Get(fn_val_id).type_id(); @@ -4150,9 +4150,11 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver, CARBON_CHECK(!const_id.has_value()); auto inst_constant_id = resolver.import_constant_values().Get(inst_id); - if (!inst_constant_id.has_value() || !inst_constant_id.is_constant()) { + if (!inst_constant_id.is_constant()) { // TODO: Import of non-constant BindNames happens when importing `let` // declarations. + CARBON_CHECK(resolver.import_insts().Is(inst_id), + "TryResolveInst on non-constant instruction {0}", inst_id); return ResolveResult::Done(SemIR::ConstantId::NotConstant); } diff --git a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon index d2adf8f18a65..3dc77d6d450b 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon @@ -20,6 +20,7 @@ // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon index 55d4564cbcd3..9bb798af94ad 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/bundle.carbon @@ -34,6 +34,7 @@ fn F(Form:! Core.Form()) ->? Form; // CHECK:STDOUT: import_ir_inst4: {ir_id: import_ir70000003, inst_id: inst50000010} // CHECK:STDOUT: import_ir_inst5: {ir_id: import_ir70000003, inst_id: inst50000011} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst70000011, name0: inst7000003B}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000016}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon index 73120bef862d..5bceae461246 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon @@ -53,15 +53,18 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: import_ir_inst3: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000003} // CHECK:STDOUT: import_ir_inst4: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000004} // CHECK:STDOUT: clang_decls: -// CHECK:STDOUT: clang_decl_id50000000: {key: "namespace Carbon {\n}", inst_id: instF} -// CHECK:STDOUT: clang_decl_id50000001: {key: "", inst_id: inst50000011} -// CHECK:STDOUT: clang_decl_id50000002: {key: "struct X {}", inst_id: inst50000013} -// CHECK:STDOUT: clang_decl_id50000003: {key: "X * _Nonnull p", inst_id: inst50000022} -// CHECK:STDOUT: clang_decl_id50000004: {key: {decl: "void f(X x = {})", kind: normal, num_params: 0}, inst_id: inst5000002D} -// CHECK:STDOUT: clang_decl_id50000005: {key: {decl: "inline void f__carbon_thunk()", kind: normal, num_params: 0}, inst_id: inst50000030} -// CHECK:STDOUT: clang_decl_id50000006: {key: {decl: "void f(X x = {})", kind: normal, num_params: 1}, inst_id: inst5000003B} -// CHECK:STDOUT: clang_decl_id50000007: {key: {decl: "inline void f__carbon_thunk(X * _Nonnull x)", kind: normal, num_params: 1}, inst_id: inst50000043} -// CHECK:STDOUT: clang_decl_id50000008: {key: "X * _Nonnull global", inst_id: inst5000004E} +// CHECK:STDOUT: clang_decl_id50000000: {key: {decl: "namespace Carbon {\n}"}, inst_id: instF} +// CHECK:STDOUT: clang_decl_id50000001: {key: {decl: ""}, inst_id: inst50000011} +// CHECK:STDOUT: clang_decl_id50000002: {key: {decl: "struct X {}"}, inst_id: inst50000013} +// CHECK:STDOUT: clang_decl_id50000003: {key: {decl: "X * _Nonnull p"}, inst_id: inst50000022} +// CHECK:STDOUT: clang_decl_id50000004: {key: {decl: "void f(X x = {})", clang_decl_signature_id: clang_decl_signature_id50000000}, inst_id: inst5000002D} +// CHECK:STDOUT: clang_decl_id50000005: {key: {decl: "inline void f__carbon_thunk()", clang_decl_signature_id: clang_decl_signature_id50000000}, inst_id: inst50000030} +// CHECK:STDOUT: clang_decl_id50000006: {key: {decl: "void f(X x = {})", clang_decl_signature_id: clang_decl_signature_id50000001}, inst_id: inst5000003B} +// CHECK:STDOUT: clang_decl_id50000007: {key: {decl: "inline void f__carbon_thunk(X * _Nonnull x)", clang_decl_signature_id: clang_decl_signature_id50000001}, inst_id: inst50000043} +// CHECK:STDOUT: clang_decl_id50000008: {key: {decl: "X * _Nonnull global"}, inst_id: inst5000004E} +// CHECK:STDOUT: clang_decl_signatures: +// CHECK:STDOUT: clang_decl_signature_id50000000: {kind: normal, num_params: 0} +// CHECK:STDOUT: clang_decl_signature_id50000001: {kind: normal, num_params: 1, modes: [value]} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Cpp): inst50000011, name0: inst5000001C}} // CHECK:STDOUT: name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name2: inst50000013, name3: inst5000002A, name4: inst5000004E}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon index 449f82b7ead4..e95d95fd521e 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon @@ -37,6 +37,7 @@ fn B() { // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000010}} // CHECK:STDOUT: entity_names: {} @@ -141,6 +142,7 @@ fn B() { // CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010} // CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon index a977a4cbe7d2..3fb18a8a4c81 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon @@ -37,6 +37,7 @@ fn B() { // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000010}} // CHECK:STDOUT: entity_names: {} @@ -160,6 +161,7 @@ fn B() { // CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010} // CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}} // CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon b/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon index 860fa0336319..5289c6e6583d 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon @@ -46,6 +46,7 @@ fn UseLocalCopy[T:! Copy](_: T.T1, _: T.T2) {} // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst60000010}} // CHECK:STDOUT: name_scope60000001: {inst: inst60000010, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst60000012}} @@ -210,6 +211,7 @@ fn UseLocalCopy[T:! Copy](_: T.T1, _: T.T2) {} // CHECK:STDOUT: import_ir_instB: {ir_id: import_ir50000002, inst_id: inst6000001C} // CHECK:STDOUT: import_ir_instC: {ir_id: import_ir50000002, inst_id: inst6000001C} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst50000011, name1: inst50000012, name4: inst50000060, name7: inst50000095}} // CHECK:STDOUT: name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name6: inst50000025}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon index 4f41631e4231..eb6c9e5590b2 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon @@ -255,6 +255,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: import_ir_instD6: {ir_id: import_ir78000004, inst_id: inst70000259} // CHECK:STDOUT: import_ir_instD7: {ir_id: import_ir78000004, inst_id: inst7000025A} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst78000011, name0: inst7800003E}} // CHECK:STDOUT: name_scope78000001: {inst: inst78000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst7800004E}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon index 497de519c45e..9480eba1d7c8 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon @@ -28,6 +28,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst5000002A}} // CHECK:STDOUT: entity_names: diff --git a/toolchain/check/testdata/interop/cpp/basics/import/indirect.carbon b/toolchain/check/testdata/interop/cpp/basics/import/indirect.carbon index dd136dadf44f..acc3223d9219 100644 --- a/toolchain/check/testdata/interop/cpp/basics/import/indirect.carbon +++ b/toolchain/check/testdata/interop/cpp/basics/import/indirect.carbon @@ -201,7 +201,8 @@ fn UseZ() -> Cpp.A.Z { // CHECK:STDOUT: %.loc15_12.2: ref %X = temporary %.loc15_12.1, %F.call // CHECK:STDOUT: %g.ref: %X.g.cpp_overload_set.type = name_ref g, imports.%X.g.cpp_overload_set.value [concrete = constants.%X.g.cpp_overload_set.value] // CHECK:STDOUT: %bound_method: = bound_method %.loc15_12.2, %g.ref -// CHECK:STDOUT: %X.g.call: init %i32 = call imports.%X.g.decl(%.loc15_12.2) +// CHECK:STDOUT: %.loc15_12.3: %X = acquire_value %.loc15_12.2 +// CHECK:STDOUT: %X.g.call: init %i32 = call imports.%X.g.decl(%.loc15_12.3) // CHECK:STDOUT: %X.cpp_destructor.bound: = bound_method %.loc15_12.2, constants.%X.cpp_destructor // CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call %X.cpp_destructor.bound(%.loc15_12.2) // CHECK:STDOUT: return %X.g.call diff --git a/toolchain/check/testdata/interop/cpp/class/import/method.carbon b/toolchain/check/testdata/interop/cpp/class/import/method.carbon index abdda8dd7843..2cf35c58add7 100644 --- a/toolchain/check/testdata/interop/cpp/class/import/method.carbon +++ b/toolchain/check/testdata/interop/cpp/class/import/method.carbon @@ -288,12 +288,14 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %const_ref_ref_this__carbon_thunk: %const_ref_ref_this__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.plain.cpp_overload_set [concrete] // CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete] -// CHECK:STDOUT: %HasQualifiers.plain.type: type = fn_type @HasQualifiers.plain [concrete] -// CHECK:STDOUT: %HasQualifiers.plain: %HasQualifiers.plain.type = struct_value () [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.type.b9c87a.1: type = fn_type @HasQualifiers.plain.1 [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.4829ab.1: %HasQualifiers.plain.type.b9c87a.1 = struct_value () [concrete] // CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_this.cpp_overload_set [concrete] // CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.value: %HasQualifiers.ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_this.cpp_overload_set [concrete] // CHECK:STDOUT: %HasQualifiers.ref_this.type: type = fn_type @HasQualifiers.ref_this [concrete] // CHECK:STDOUT: %HasQualifiers.ref_this: %HasQualifiers.ref_this.type = struct_value () [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.type.b9c87a.2: type = fn_type @HasQualifiers.plain.2 [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.4829ab.2: %HasQualifiers.plain.type.b9c87a.2 = struct_value () [concrete] // CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_ref_this.cpp_overload_set [concrete] // CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete] // CHECK:STDOUT: %ref_ref_this__carbon_thunk.type: type = fn_type @ref_ref_this__carbon_thunk [concrete] @@ -337,7 +339,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value] -// CHECK:STDOUT: %HasQualifiers.plain.decl: %HasQualifiers.plain.type = fn_decl @HasQualifiers.plain [concrete = constants.%HasQualifiers.plain] { +// CHECK:STDOUT: %HasQualifiers.plain.decl.020d0d.1: %HasQualifiers.plain.type.b9c87a.1 = fn_decl @HasQualifiers.plain.1 [concrete = constants.%HasQualifiers.plain.4829ab.1] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: @@ -348,6 +350,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: } { // CHECK:STDOUT: // CHECK:STDOUT: } +// CHECK:STDOUT: %HasQualifiers.plain.decl.020d0d.2: %HasQualifiers.plain.type.b9c87a.2 = fn_decl @HasQualifiers.plain.2 [concrete = constants.%HasQualifiers.plain.4829ab.2] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete = constants.%HasQualifiers.ref_ref_this.cpp_overload_set.value] // CHECK:STDOUT: %ref_ref_this__carbon_thunk.decl: %ref_ref_this__carbon_thunk.type = fn_decl @ref_ref_this__carbon_thunk [concrete = constants.%ref_ref_this__carbon_thunk] { // CHECK:STDOUT: @@ -389,7 +396,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %.loc14: ref %HasQualifiers = deref %p.ref.loc14 // CHECK:STDOUT: %plain.ref.loc14: %HasQualifiers.plain.cpp_overload_set.type = name_ref plain, imports.%HasQualifiers.plain.cpp_overload_set.value [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value] // CHECK:STDOUT: %bound_method.loc14: = bound_method %.loc14, %plain.ref.loc14 -// CHECK:STDOUT: %HasQualifiers.plain.call.loc14: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl(%.loc14) +// CHECK:STDOUT: %HasQualifiers.plain.call.loc14: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl.020d0d.1(%.loc14) // CHECK:STDOUT: %p.ref.loc15: %ptr.ec3 = name_ref p, %p // CHECK:STDOUT: %.loc15: ref %HasQualifiers = deref %p.ref.loc15 // CHECK:STDOUT: %ref_this.ref: %HasQualifiers.ref_this.cpp_overload_set.type = name_ref ref_this, imports.%HasQualifiers.ref_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.ref_this.cpp_overload_set.value] @@ -413,7 +420,8 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %.loc19_8.2: ref %HasQualifiers = temporary %.loc19_8.1, %Make.call.loc19 // CHECK:STDOUT: %plain.ref.loc19: %HasQualifiers.plain.cpp_overload_set.type = name_ref plain, imports.%HasQualifiers.plain.cpp_overload_set.value [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value] // CHECK:STDOUT: %bound_method.loc19: = bound_method %.loc19_8.2, %plain.ref.loc19 -// CHECK:STDOUT: %HasQualifiers.plain.call.loc19: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl(%.loc19_8.2) +// CHECK:STDOUT: %.loc19_8.3: %HasQualifiers = acquire_value %.loc19_8.2 +// CHECK:STDOUT: %HasQualifiers.plain.call.loc19: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl.020d0d.2(%.loc19_8.3) // CHECK:STDOUT: %Make.ref.loc20: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make] // CHECK:STDOUT: %.loc20_8.1: ref %HasQualifiers = temporary_storage // CHECK:STDOUT: %Make.call.loc20: init %HasQualifiers to %.loc20_8.1 = call %Make.ref.loc20() @@ -640,8 +648,8 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %F__carbon_thunk: %F__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.type: type = cpp_overload_set_type @ExplicitObjectParam.G.cpp_overload_set [concrete] // CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.value: %ExplicitObjectParam.G.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.G.cpp_overload_set [concrete] -// CHECK:STDOUT: %ExplicitObjectParam.G.type: type = fn_type @ExplicitObjectParam.G [concrete] -// CHECK:STDOUT: %ExplicitObjectParam.G: %ExplicitObjectParam.G.type = struct_value () [concrete] +// CHECK:STDOUT: %G__carbon_thunk.type: type = fn_type @G__carbon_thunk [concrete] +// CHECK:STDOUT: %G__carbon_thunk: %G__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: %ExplicitObjectParam.H.cpp_overload_set.type: type = cpp_overload_set_type @ExplicitObjectParam.H.cpp_overload_set [concrete] // CHECK:STDOUT: %ExplicitObjectParam.H.cpp_overload_set.value: %ExplicitObjectParam.H.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.H.cpp_overload_set [concrete] // CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete] @@ -664,7 +672,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.value: %ExplicitObjectParam.G.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.G.cpp_overload_set [concrete = constants.%ExplicitObjectParam.G.cpp_overload_set.value] -// CHECK:STDOUT: %ExplicitObjectParam.G.decl: %ExplicitObjectParam.G.type = fn_decl @ExplicitObjectParam.G [concrete = constants.%ExplicitObjectParam.G] { +// CHECK:STDOUT: %G__carbon_thunk.decl: %G__carbon_thunk.type = fn_decl @G__carbon_thunk [concrete = constants.%G__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: @@ -690,7 +698,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam] // CHECK:STDOUT: %G.ref: %ExplicitObjectParam.G.cpp_overload_set.type = name_ref G, imports.%ExplicitObjectParam.G.cpp_overload_set.value [concrete = constants.%ExplicitObjectParam.G.cpp_overload_set.value] // CHECK:STDOUT: %bound_method.loc9: = bound_method %n.ref, %G.ref -// CHECK:STDOUT: %ExplicitObjectParam.G.call: init %empty_tuple.type = call imports.%ExplicitObjectParam.G.decl(%n.ref) +// CHECK:STDOUT: %G__carbon_thunk.call: init %empty_tuple.type = call imports.%G__carbon_thunk.decl(%n.ref) // CHECK:STDOUT: %a.ref: %Another = name_ref a, %a // CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam] @@ -715,11 +723,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %ptr.7f5: type = ptr_type %ExplicitObjectParam [concrete] // CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.1: type = fn_type @F__carbon_thunk.1 [concrete] // CHECK:STDOUT: %F__carbon_thunk.0cd6a8.1: %F__carbon_thunk.type.eda1ac.1 = struct_value () [concrete] -// CHECK:STDOUT: %ExplicitObjectParam.F.type.5d25a8.2: type = fn_type @ExplicitObjectParam.F.2 [concrete] -// CHECK:STDOUT: %ExplicitObjectParam.F.28cf2e.2: %ExplicitObjectParam.F.type.5d25a8.2 = struct_value () [concrete] -// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete] // CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.2: type = fn_type @F__carbon_thunk.2 [concrete] // CHECK:STDOUT: %F__carbon_thunk.0cd6a8.2: %F__carbon_thunk.type.eda1ac.2 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete] +// CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.3: type = fn_type @F__carbon_thunk.3 [concrete] +// CHECK:STDOUT: %F__carbon_thunk.0cd6a8.3: %F__carbon_thunk.type.eda1ac.3 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -736,12 +744,12 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: } { // CHECK:STDOUT: // CHECK:STDOUT: } -// CHECK:STDOUT: %ExplicitObjectParam.F.decl.28f5af.2: %ExplicitObjectParam.F.type.5d25a8.2 = fn_decl @ExplicitObjectParam.F.2 [concrete = constants.%ExplicitObjectParam.F.28cf2e.2] { +// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.2: %F__carbon_thunk.type.eda1ac.2 = fn_decl @F__carbon_thunk.2 [concrete = constants.%F__carbon_thunk.0cd6a8.2] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: // CHECK:STDOUT: } -// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.2: %F__carbon_thunk.type.eda1ac.2 = fn_decl @F__carbon_thunk.2 [concrete = constants.%F__carbon_thunk.0cd6a8.2] { +// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.3: %F__carbon_thunk.type.eda1ac.3 = fn_decl @F__carbon_thunk.3 [concrete = constants.%F__carbon_thunk.0cd6a8.3] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: @@ -761,7 +769,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam] // CHECK:STDOUT: %F.ref.loc9: %ExplicitObjectParam.F.cpp_overload_set.type = name_ref F, imports.%ExplicitObjectParam.F.cpp_overload_set.value [concrete = constants.%ExplicitObjectParam.F.cpp_overload_set.value] // CHECK:STDOUT: %bound_method.loc9: = bound_method %n.ref, %F.ref.loc9 -// CHECK:STDOUT: %ExplicitObjectParam.F.call: init %empty_tuple.type = call imports.%ExplicitObjectParam.F.decl.28f5af.2(%n.ref) +// CHECK:STDOUT: %F__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.2(%n.ref) // CHECK:STDOUT: %a.ref: %Another = name_ref a, %a // CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam] @@ -769,7 +777,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: %bound_method.loc10: = bound_method %a.ref, %F.ref.loc10 // CHECK:STDOUT: %.loc10: ref %Another = value_as_ref %a.ref // CHECK:STDOUT: %addr.loc10: %ptr.289 = addr_of %.loc10 -// CHECK:STDOUT: %F__carbon_thunk.call.loc10: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.2(%addr.loc10) +// CHECK:STDOUT: %F__carbon_thunk.call.loc10: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.3(%addr.loc10) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon b/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon index 7dd859fccf47..c7bb5153b039 100644 --- a/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon +++ b/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon @@ -119,7 +119,8 @@ fn G() { // CHECK:STDOUT: %Cpp.ref.loc10_15: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %C.ref.loc10_18: type = name_ref C, imports.%C.decl [concrete = constants.%C] // CHECK:STDOUT: %e.ref: %.bb7 = name_ref e, imports.%int_1.1d6 [concrete = constants.%int_1.1d6] -// CHECK:STDOUT: %C.F.call: init %empty_tuple.type = call imports.%C.F.decl(%.loc10_11.3, %e.ref) +// CHECK:STDOUT: %.loc10_11.4: %C = acquire_value %.loc10_11.3 +// CHECK:STDOUT: %C.F.call: init %empty_tuple.type = call imports.%C.F.decl(%.loc10_11.4, %e.ref) // CHECK:STDOUT: %C.cpp_destructor.bound: = bound_method %.loc10_11.3, constants.%C.cpp_destructor // CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc10_11.3) // CHECK:STDOUT: return diff --git a/toolchain/check/testdata/interop/cpp/function/import/class.carbon b/toolchain/check/testdata/interop/cpp/function/import/class.carbon index 733761e6d3d6..fd70bc1585b3 100644 --- a/toolchain/check/testdata/interop/cpp/function/import/class.carbon +++ b/toolchain/check/testdata/interop/cpp/function/import/class.carbon @@ -142,6 +142,110 @@ fn F(c: Cpp.C) { //@dump-sem-ir-end } +// ============================================================================ +// Move-only class as parameter type +// ============================================================================ + +// --- move_only_param_type.h + +struct C { + C(C&&); +}; + +auto foo(C) -> void; +auto make() -> C; +auto move(C&) -> C&&; + +// --- pass_move_only_param_temporary.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "move_only_param_type.h"; + +fn F() { + //@dump-sem-ir-begin + Cpp.foo(Cpp.make()); + //@dump-sem-ir-end +} + +// --- fail_pass_move_only_param_value.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+12]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^~~ +// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+8]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote] +// CHECK:STDERR: 3 | C(C&&); +// CHECK:STDERR: | ^ +// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^ +import Cpp library "move_only_param_type.h"; + +fn F(c: Cpp.C) { + // CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk] + // CHECK:STDERR: Cpp.foo(c); + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + Cpp.foo(c); +} + +// --- fail_pass_move_only_param_ref.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+12]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^~~ +// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+8]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote] +// CHECK:STDERR: 3 | C(C&&); +// CHECK:STDERR: | ^ +// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^ +import Cpp library "move_only_param_type.h"; + +fn F(ref c: Cpp.C) { + // CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk] + // CHECK:STDERR: Cpp.foo(c); + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + Cpp.foo(c); +} + +// --- fail_todo_pass_move_only_param_ref_by_move.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+12]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^~~ +// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+8]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote] +// CHECK:STDERR: 3 | C(C&&); +// CHECK:STDERR: | ^ +// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote] +// CHECK:STDERR: 6 | auto foo(C) -> void; +// CHECK:STDERR: | ^ +import Cpp library "move_only_param_type.h"; + +fn F(ref c: Cpp.C) { + // CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk] + // CHECK:STDERR: Cpp.foo(Cpp.move(ref c)); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.foo(Cpp.move(ref c)); +} + // ============================================================================ // Defined class with a single data member as parameter type // ============================================================================ @@ -565,6 +669,58 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- pass_move_only_param_temporary.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete] +// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete] +// CHECK:STDOUT: %make.cpp_overload_set.type: type = cpp_overload_set_type @make.cpp_overload_set [concrete] +// CHECK:STDOUT: %make.cpp_overload_set.value: %make.cpp_overload_set.type = cpp_overload_set_value @make.cpp_overload_set [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] +// CHECK:STDOUT: %make__carbon_thunk.type: type = fn_type @make__carbon_thunk [concrete] +// CHECK:STDOUT: %make__carbon_thunk: %make__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] +// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = %foo.cpp_overload_set.value +// CHECK:STDOUT: .make = %make.cpp_overload_set.value +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete = constants.%foo.cpp_overload_set.value] +// CHECK:STDOUT: %make.cpp_overload_set.value: %make.cpp_overload_set.type = cpp_overload_set_value @make.cpp_overload_set [concrete = constants.%make.cpp_overload_set.value] +// CHECK:STDOUT: %make__carbon_thunk.decl: %make__carbon_thunk.type = fn_decl @make__carbon_thunk [concrete = constants.%make__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc8_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value] +// CHECK:STDOUT: %Cpp.ref.loc8_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %make.ref: %make.cpp_overload_set.type = name_ref make, imports.%make.cpp_overload_set.value [concrete = constants.%make.cpp_overload_set.value] +// CHECK:STDOUT: +// CHECK:STDOUT: %addr.loc8_20: %ptr.d9e = addr_of %_.var +// CHECK:STDOUT: %make__carbon_thunk.call: init %empty_tuple.type = call imports.%make__carbon_thunk.decl(%addr.loc8_20) +// CHECK:STDOUT: %.loc8: init %C to %_.var = mark_in_place_init %make__carbon_thunk.call +// CHECK:STDOUT: +// CHECK:STDOUT: %addr.loc8_21: %ptr.d9e = addr_of %_.var +// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- import_definition_single_data_member_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/function/import/default_arg.carbon b/toolchain/check/testdata/interop/cpp/function/import/default_arg.carbon index 426ec89d80c6..3fdb68ca5b8b 100644 --- a/toolchain/check/testdata/interop/cpp/function/import/default_arg.carbon +++ b/toolchain/check/testdata/interop/cpp/function/import/default_arg.carbon @@ -338,6 +338,7 @@ fn Call() { // CHECK:STDOUT: %bound_method.loc10_16: = bound_method %.loc10_7.2, %B.ref [concrete = constants.%bound_method.a5d] // CHECK:STDOUT: %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] // CHECK:STDOUT: %int_2.loc10: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %.loc10_7.3: %X = acquire_value %.loc10_7.2 [concrete = constants.%X.val] // CHECK:STDOUT: %impl.elem0.loc10_19: %.9db = impl_witness_access constants.%ImplicitAs.impl_witness.ac5, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a] // CHECK:STDOUT: %bound_method.loc10_19.1: = bound_method %int_1.loc10, %impl.elem0.loc10_19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d43] // CHECK:STDOUT: %specific_fn.loc10_19: = specific_function %impl.elem0.loc10_19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] @@ -352,7 +353,7 @@ fn Call() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_22: init %i32 = call %bound_method.loc10_22.2(%int_2.loc10) [concrete = constants.%int_2.ef8] // CHECK:STDOUT: %.loc10_22.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_22 [concrete = constants.%int_2.ef8] // CHECK:STDOUT: %.loc10_22.2: %i32 = converted %int_2.loc10, %.loc10_22.1 [concrete = constants.%int_2.ef8] -// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%.loc10_7.2, %.loc10_19.2, %.loc10_22.2) +// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%.loc10_7.3, %.loc10_19.2, %.loc10_22.2) // CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %X.ref.loc11: type = name_ref X, imports.%X.decl [concrete = constants.%X] // CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value] @@ -591,13 +592,13 @@ fn Call() { // CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {} // CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete = constants.%X.B.cpp_overload_set.value] // CHECK:STDOUT: %B__carbon_thunk.decl: %B__carbon_thunk.type = fn_decl @B__carbon_thunk [concrete = constants.%B__carbon_thunk] { -// CHECK:STDOUT: %this.param_patt: %pattern_type.46b = ref_param_pattern [concrete] +// CHECK:STDOUT: %this.param_patt: %pattern_type.46b = value_param_pattern [concrete] // CHECK:STDOUT: %this.patt: %pattern_type.46b = at_binding_pattern this, %this.param_patt [concrete] // CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern [concrete] // CHECK:STDOUT: %a.patt: %pattern_type.7ce = at_binding_pattern a, %a.param_patt [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %this.param: ref %X = ref_param call_param0 -// CHECK:STDOUT: %this: ref %X = ref_binding this, %this.param +// CHECK:STDOUT: %this.param: %X = value_param call_param0 +// CHECK:STDOUT: %this: %X = value_binding this, %this.param // CHECK:STDOUT: %a.param: %i32 = value_param call_param1 // CHECK:STDOUT: %.1: type = splice_block %i32.2 [concrete = constants.%i32] { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] @@ -756,6 +757,7 @@ fn Call() { // CHECK:STDOUT: %B.ref: %X.B.cpp_overload_set.type = name_ref B, imports.%X.B.cpp_overload_set.value [concrete = constants.%X.B.cpp_overload_set.value] // CHECK:STDOUT: %bound_method.loc11_16: = bound_method %.loc11_7.2, %B.ref [concrete = constants.%bound_method.a5d] // CHECK:STDOUT: %int_1.loc11: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %.loc11_7.3: %X = acquire_value %.loc11_7.2 [concrete = constants.%X.val] // CHECK:STDOUT: %impl.elem0.loc11: %.9db = impl_witness_access constants.%ImplicitAs.impl_witness.ac5, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a] // CHECK:STDOUT: %bound_method.loc11_19.1: = bound_method %int_1.loc11, %impl.elem0.loc11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d43] // CHECK:STDOUT: %specific_fn.loc11: = specific_function %impl.elem0.loc11, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] @@ -763,7 +765,7 @@ fn Call() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11: init %i32 = call %bound_method.loc11_19.2(%int_1.loc11) [concrete = constants.%int_1.5d2] // CHECK:STDOUT: %.loc11_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11 [concrete = constants.%int_1.5d2] // CHECK:STDOUT: %.loc11_19.2: %i32 = converted %int_1.loc11, %.loc11_19.1 [concrete = constants.%int_1.5d2] -// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%.loc11_7.2, %.loc11_19.2) +// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%.loc11_7.3, %.loc11_19.2) // CHECK:STDOUT: %Cpp.ref.loc12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %X.ref.loc12: type = name_ref X, imports.%X.decl [concrete = constants.%X] // CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value] @@ -821,9 +823,9 @@ fn Call() { // CHECK:STDOUT: // CHECK:STDOUT: fn @GlobalNoReturn__carbon_thunk.2(%a.param: %i32, %b.param: %i32, %c.param: %i32); // CHECK:STDOUT: -// CHECK:STDOUT: fn @X.B(%self.param: ref %X, %a.param: %i32); +// CHECK:STDOUT: fn @X.B(%self.param: %X, %a.param: %i32); // CHECK:STDOUT: -// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: ref %X, %a.param: %i32); +// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: %X, %a.param: %i32); // CHECK:STDOUT: // CHECK:STDOUT: fn @X.C(%a.param: %i32); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/import/thunk_ast.carbon b/toolchain/check/testdata/interop/cpp/function/import/thunk_ast.carbon index c7d7db7e452a..a706fd14102b 100644 --- a/toolchain/check/testdata/interop/cpp/function/import/thunk_ast.carbon +++ b/toolchain/check/testdata/interop/cpp/function/import/thunk_ast.carbon @@ -31,7 +31,7 @@ auto foo(short a) -> void; // CHECK:STDOUT: | `-DeclRefExpr {{0x[a-f0-9]+}} 'short * _Nonnull':'short *' lvalue ParmVar {{0x[a-f0-9]+}} 'a' 'short * _Nonnull':'short *' // CHECK:STDOUT: |-AlwaysInlineAttr {{0x[a-f0-9]+}} <> Implicit always_inline // CHECK:STDOUT: |-InternalLinkageAttr {{0x[a-f0-9]+}} <> Implicit -// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} Implicit "_Z3foos.carbon_thunk" +// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} Implicit "_Z3foos.carbon_thunk._" // CHECK:STDOUT: TranslationUnitDecl {{0x[a-f0-9]+}} <> // CHECK:STDOUT: |-NamespaceDecl {{0x[a-f0-9]+}} <> Carbon @@ -58,7 +58,7 @@ auto foo() -> short; // CHECK:STDOUT: | `-DeclRefExpr {{0x[a-f0-9]+}} 'short * _Nonnull':'short *' lvalue ParmVar {{0x[a-f0-9]+}} 'return' 'short * _Nonnull':'short *' // CHECK:STDOUT: |-AlwaysInlineAttr {{0x[a-f0-9]+}} <> Implicit always_inline // CHECK:STDOUT: |-InternalLinkageAttr {{0x[a-f0-9]+}} <> Implicit -// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} Implicit "_Z3foov.carbon_thunk" +// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} Implicit "_Z3foov.carbon_thunk." // --- import_return_thunk_required.carbon diff --git a/toolchain/check/testdata/interop/cpp/operators/arithmetic_operators.carbon b/toolchain/check/testdata/interop/cpp/operators/arithmetic_operators.carbon index 17ac6d648a68..1d6acb6a8069 100644 --- a/toolchain/check/testdata/interop/cpp/operators/arithmetic_operators.carbon +++ b/toolchain/check/testdata/interop/cpp/operators/arithmetic_operators.carbon @@ -1128,14 +1128,14 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) { // CHECK:STDOUT: %.0d7: type = fn_type_with_self_type %Negate.WithSelf.Op.type.899, %Negate.facet.758 [symbolic] // CHECK:STDOUT: %impl.elem1.ec8: %.0d7 = impl_witness_access %Negate.lookup_impl_witness.783, element1 [symbolic] // CHECK:STDOUT: %specific_impl_fn.f22: = specific_impl_function %impl.elem1.ec8, @Negate.WithSelf.Op(%Negate.facet.758) [symbolic] -// CHECK:STDOUT: %Int32.cpp_operator.type.49e401.16: type = fn_type @Int32.cpp_operator.16 [concrete] -// CHECK:STDOUT: %Int32.cpp_operator.0010d3.16: %Int32.cpp_operator.type.49e401.16 = struct_value () [concrete] -// CHECK:STDOUT: %custom_witness.934: = custom_witness (%Int32.cpp_operator.0010d3.16), @Inc [concrete] -// CHECK:STDOUT: %Inc.facet.390: %Inc.type = facet_value %Int32, (%custom_witness.934) [concrete] -// CHECK:STDOUT: %Int32.cpp_operator.type.49e401.17: type = fn_type @Int32.cpp_operator.17 [concrete] -// CHECK:STDOUT: %Int32.cpp_operator.0010d3.17: %Int32.cpp_operator.type.49e401.17 = struct_value () [concrete] -// CHECK:STDOUT: %custom_witness.99f: = custom_witness (%Int32.cpp_operator.0010d3.17), @Dec [concrete] -// CHECK:STDOUT: %Dec.facet.961: %Dec.type = facet_value %Int32, (%custom_witness.99f) [concrete] +// CHECK:STDOUT: %Int32.Op.type.68b858.18: type = fn_type @Int32.Op.18 [concrete] +// CHECK:STDOUT: %Int32.Op.6afff1.18: %Int32.Op.type.68b858.18 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.50d: = custom_witness (%Int32.Op.6afff1.18), @Inc [concrete] +// CHECK:STDOUT: %Inc.facet.9db: %Inc.type = facet_value %Int32, (%custom_witness.50d) [concrete] +// CHECK:STDOUT: %Int32.Op.type.68b858.19: type = fn_type @Int32.Op.19 [concrete] +// CHECK:STDOUT: %Int32.Op.6afff1.19: %Int32.Op.type.68b858.19 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.e76: = custom_witness (%Int32.Op.6afff1.19), @Dec [concrete] +// CHECK:STDOUT: %Dec.facet.bed: %Dec.type = facet_value %Int32, (%custom_witness.e76) [concrete] // CHECK:STDOUT: %facet_type.89a: type = facet_type <@Destroy & @Negate where %impl.elem0.f00 = %Int64> [concrete] // CHECK:STDOUT: %Int16.Op.type.180c8b.18: type = fn_type @Int16.Op.18 [concrete] // CHECK:STDOUT: %Int16.Op.c3e49c.18: %Int16.Op.type.180c8b.18 = struct_value () [concrete] @@ -1143,9 +1143,9 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) { // CHECK:STDOUT: %facet_value.70a: %facet_type.89a = facet_value %Int16, (%custom_witness.e5b, %custom_witness.e58) [concrete] // CHECK:STDOUT: %pattern_type.c49: type = pattern_type %facet_type.89a [concrete] // CHECK:STDOUT: %facet_type.d5d: type = facet_type <@Destroy & @Negate where %impl.elem0.f00 = %Int32> [concrete] -// CHECK:STDOUT: %Int32.Op.type.68b858.18: type = fn_type @Int32.Op.18 [concrete] -// CHECK:STDOUT: %Int32.Op.6afff1.18: %Int32.Op.type.68b858.18 = struct_value () [concrete] -// CHECK:STDOUT: %custom_witness.e8a: = custom_witness (%Int32, %Int32.Op.6afff1.18), @Negate [concrete] +// CHECK:STDOUT: %Int32.Op.type.68b858.20: type = fn_type @Int32.Op.20 [concrete] +// CHECK:STDOUT: %Int32.Op.6afff1.20: %Int32.Op.type.68b858.20 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.e8a: = custom_witness (%Int32, %Int32.Op.6afff1.20), @Negate [concrete] // CHECK:STDOUT: %facet_value.396: %facet_type.d5d = facet_value %Int32, (%custom_witness.ce1, %custom_witness.e8a) [concrete] // CHECK:STDOUT: %pattern_type.0ec: type = pattern_type %facet_type.d5d [concrete] // CHECK:STDOUT: %complete_type.f1c: = complete_type_witness %AddWith.type.344 [concrete] @@ -1313,10 +1313,10 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) { // CHECK:STDOUT: %.384: type = fn_type_with_self_type %DivAssignWith.WithSelf.Op.type.646, %DivAssignWith.facet.d3b [concrete] // CHECK:STDOUT: %ModAssignWith.WithSelf.Op.type.a34: type = fn_type @ModAssignWith.WithSelf.Op, @ModAssignWith.WithSelf(%Int32, %ModAssignWith.facet.1c6) [concrete] // CHECK:STDOUT: %.ee0: type = fn_type_with_self_type %ModAssignWith.WithSelf.Op.type.a34, %ModAssignWith.facet.1c6 [concrete] -// CHECK:STDOUT: %Inc.WithSelf.Op.type.eaa: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet.390) [concrete] -// CHECK:STDOUT: %.696: type = fn_type_with_self_type %Inc.WithSelf.Op.type.eaa, %Inc.facet.390 [concrete] -// CHECK:STDOUT: %Dec.WithSelf.Op.type.6fb: type = fn_type @Dec.WithSelf.Op, @Dec.WithSelf(%Dec.facet.961) [concrete] -// CHECK:STDOUT: %.cdd: type = fn_type_with_self_type %Dec.WithSelf.Op.type.6fb, %Dec.facet.961 [concrete] +// CHECK:STDOUT: %Inc.WithSelf.Op.type.755: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet.9db) [concrete] +// CHECK:STDOUT: %.cfd3: type = fn_type_with_self_type %Inc.WithSelf.Op.type.755, %Inc.facet.9db [concrete] +// CHECK:STDOUT: %Dec.WithSelf.Op.type.e71: type = fn_type @Dec.WithSelf.Op, @Dec.WithSelf(%Dec.facet.bed) [concrete] +// CHECK:STDOUT: %.b6e: type = fn_type_with_self_type %Dec.WithSelf.Op.type.e71, %Dec.facet.bed [concrete] // CHECK:STDOUT: %Negate.facet.0a5: %Negate.type = facet_value %Int16, (%custom_witness.e58) [concrete] // CHECK:STDOUT: %Negate.WithSelf.Op.type.d7d: type = fn_type @Negate.WithSelf.Op, @Negate.WithSelf(%Negate.facet.0a5) [concrete] // CHECK:STDOUT: %.3e7: type = fn_type_with_self_type %Negate.WithSelf.Op.type.d7d, %Negate.facet.0a5 [concrete] @@ -3763,32 +3763,32 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) { // CHECK:STDOUT: %pattern_type.loc294_22 => constants.%pattern_type.ece // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @TestInc(constants.%Inc.facet.390) { -// CHECK:STDOUT: %T.loc278_13.1 => constants.%Inc.facet.390 +// CHECK:STDOUT: specific @TestInc(constants.%Inc.facet.9db) { +// CHECK:STDOUT: %T.loc278_13.1 => constants.%Inc.facet.9db // CHECK:STDOUT: %T.as_type.loc278_33.1 => constants.%Int32 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.9c9 // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete => constants.%complete_type.357 -// CHECK:STDOUT: %Inc.WithSelf.Op.type => constants.%Inc.WithSelf.Op.type.eaa -// CHECK:STDOUT: %.loc280 => constants.%.696 -// CHECK:STDOUT: %Inc.lookup_impl_witness => constants.%custom_witness.934 -// CHECK:STDOUT: %impl.elem0.loc280_3.2 => constants.%Int32.cpp_operator.0010d3.16 -// CHECK:STDOUT: %specific_impl_fn.loc280_3.2 => constants.%Int32.cpp_operator.0010d3.16 +// CHECK:STDOUT: %Inc.WithSelf.Op.type => constants.%Inc.WithSelf.Op.type.755 +// CHECK:STDOUT: %.loc280 => constants.%.cfd3 +// CHECK:STDOUT: %Inc.lookup_impl_witness => constants.%custom_witness.50d +// CHECK:STDOUT: %impl.elem0.loc280_3.2 => constants.%Int32.Op.6afff1.18 +// CHECK:STDOUT: %specific_impl_fn.loc280_3.2 => constants.%Int32.Op.6afff1.18 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @TestDec(constants.%Dec.facet.961) { -// CHECK:STDOUT: %T.loc284_13.1 => constants.%Dec.facet.961 +// CHECK:STDOUT: specific @TestDec(constants.%Dec.facet.bed) { +// CHECK:STDOUT: %T.loc284_13.1 => constants.%Dec.facet.bed // CHECK:STDOUT: %T.as_type.loc284_33.1 => constants.%Int32 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.9c9 // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete => constants.%complete_type.357 -// CHECK:STDOUT: %Dec.WithSelf.Op.type => constants.%Dec.WithSelf.Op.type.6fb -// CHECK:STDOUT: %.loc286 => constants.%.cdd -// CHECK:STDOUT: %Dec.lookup_impl_witness => constants.%custom_witness.99f -// CHECK:STDOUT: %impl.elem0.loc286_3.2 => constants.%Int32.cpp_operator.0010d3.17 -// CHECK:STDOUT: %specific_impl_fn.loc286_3.2 => constants.%Int32.cpp_operator.0010d3.17 +// CHECK:STDOUT: %Dec.WithSelf.Op.type => constants.%Dec.WithSelf.Op.type.e71 +// CHECK:STDOUT: %.loc286 => constants.%.b6e +// CHECK:STDOUT: %Dec.lookup_impl_witness => constants.%custom_witness.e76 +// CHECK:STDOUT: %impl.elem0.loc286_3.2 => constants.%Int32.Op.6afff1.19 +// CHECK:STDOUT: %specific_impl_fn.loc286_3.2 => constants.%Int32.Op.6afff1.19 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @TestNegate(constants.%Destroy.facet.b0a, constants.%facet_value.70a) { @@ -3834,8 +3834,8 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) { // CHECK:STDOUT: %Negate.facet => constants.%Negate.facet.3c9 // CHECK:STDOUT: %Negate.WithSelf.Op.type => constants.%Negate.WithSelf.Op.type.1bc // CHECK:STDOUT: %.loc296_3.3 => constants.%.19b -// CHECK:STDOUT: %impl.elem1.loc296_3.2 => constants.%Int32.Op.6afff1.18 -// CHECK:STDOUT: %specific_impl_fn.loc296_3.3 => constants.%Int32.Op.6afff1.18 +// CHECK:STDOUT: %impl.elem1.loc296_3.2 => constants.%Int32.Op.6afff1.20 +// CHECK:STDOUT: %specific_impl_fn.loc296_3.3 => constants.%Int32.Op.6afff1.20 // CHECK:STDOUT: %Destroy.WithSelf.Op.type => constants.%Destroy.WithSelf.Op.type.2e1 // CHECK:STDOUT: %.loc296_3.4 => constants.%.e6c // CHECK:STDOUT: %Destroy.lookup_impl_witness => constants.%custom_witness.ce1 diff --git a/toolchain/check/testdata/interop/cpp/operators/deref.carbon b/toolchain/check/testdata/interop/cpp/operators/deref.carbon index ee279a58e9da..5a374a1c42f3 100644 --- a/toolchain/check/testdata/interop/cpp/operators/deref.carbon +++ b/toolchain/check/testdata/interop/cpp/operators/deref.carbon @@ -175,8 +175,7 @@ fn TestDerefFail(not_ptr: Cpp.NotAPtr) { // CHECK:STDOUT: %bound_method: = bound_method %int_ptr.ref, %impl.elem1 // CHECK:STDOUT: %Op.ref.loc13_43: %ConstDeref.cpp_operator.type = name_ref Op, imports.%ConstDeref.cpp_operator.decl [concrete = constants.%ConstDeref.cpp_operator] // CHECK:STDOUT: %ConstDeref.cpp_operator.bound: = bound_method %int_ptr.ref, %Op.ref.loc13_43 -// CHECK:STDOUT: %.loc13: %ConstDeref = acquire_value %int_ptr.ref -// CHECK:STDOUT: %operator_Star__carbon_thunk.call: ref %i32 = call imports.%operator_Star__carbon_thunk.decl(%.loc13) +// CHECK:STDOUT: %operator_Star__carbon_thunk.call: ref %i32 = call imports.%operator_Star__carbon_thunk.decl(%int_ptr.ref) // CHECK:STDOUT: return %operator_Star__carbon_thunk.call // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/operators/operators.carbon b/toolchain/check/testdata/interop/cpp/operators/operators.carbon index 2479dc0b8d23..a658474419ca 100644 --- a/toolchain/check/testdata/interop/cpp/operators/operators.carbon +++ b/toolchain/check/testdata/interop/cpp/operators/operators.carbon @@ -1189,6 +1189,7 @@ fn F() { // CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %i32.builtin: type = int_type signed, %int_32 [concrete] // CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete] // CHECK:STDOUT: %operator_LessLess__carbon_thunk.type: type = fn_type @operator_LessLess__carbon_thunk [concrete] // CHECK:STDOUT: %operator_LessLess__carbon_thunk: %operator_LessLess__carbon_thunk.type = struct_value () [concrete] @@ -1252,8 +1253,12 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.577: = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a [concrete] // CHECK:STDOUT: %bound_method.cd5: = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %int_42.c68: %i32 = int_value 42 [concrete] -// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete] -// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete] +// CHECK:STDOUT: %.1a9: ref %i32 = temporary invalid, %int_42.c68 [concrete] +// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc48_30.2 [concrete] +// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete] +// CHECK:STDOUT: %Destroy.Op.bound: = bound_method %.1a9, %Destroy.Op.651ba6.2 [concrete] +// CHECK:STDOUT: %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc45 [concrete] +// CHECK:STDOUT: %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete] // CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete] // CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete] // CHECK:STDOUT: %C.Op.type: type = fn_type @C.Op [concrete] @@ -1875,24 +1880,26 @@ fn F() { // CHECK:STDOUT: %specific_fn.loc48: = specific_function %impl.elem0.loc48, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] // CHECK:STDOUT: %bound_method.loc48_30.2: = bound_method %int_42, %specific_fn.loc48 [concrete = constants.%bound_method.cd5] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48: init %i32 = call %bound_method.loc48_30.2(%int_42) [concrete = constants.%int_42.c68] -// CHECK:STDOUT: %.loc48_30.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48 [concrete = constants.%int_42.c68] -// CHECK:STDOUT: %.loc48_30.2: %i32 = converted %int_42, %.loc48_30.1 [concrete = constants.%int_42.c68] -// CHECK:STDOUT: %C.cpp_operator.call: init %i32 = call %C.cpp_operator.bound(%c1.ref.loc48, %.loc48_30.2) +// CHECK:STDOUT: %.loc48_30.1: init %i32 = converted %int_42, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48 [concrete = constants.%int_42.c68] +// CHECK:STDOUT: %.loc48_30.2: ref %i32 = temporary_storage +// CHECK:STDOUT: %.loc48_30.3: ref %i32 = temporary %.loc48_30.2, %.loc48_30.1 [concrete = constants.%.1a9] +// CHECK:STDOUT: %C.cpp_operator.call: init %i32 = call %C.cpp_operator.bound(%c1.ref.loc48, %.loc48_30.3) // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %.loc48_32.1: %i32 = value_of_initializer %C.cpp_operator.call // CHECK:STDOUT: %.loc48_32.2: %i32 = converted %C.cpp_operator.call, %.loc48_32.1 // CHECK:STDOUT: %index: %i32 = value_binding index, %.loc48_32.2 -// CHECK:STDOUT: %Destroy.Op.bound.loc45: = bound_method %.loc45_44.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.call.loc48: init %empty_tuple.type = call constants.%Destroy.Op.bound(constants.%.1a9) +// CHECK:STDOUT: %Destroy.Op.bound.loc45: = bound_method %.loc45_44.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc45: init %empty_tuple.type = call %Destroy.Op.bound.loc45(%.loc45_44.3) -// CHECK:STDOUT: %Destroy.Op.bound.loc44: = bound_method %.loc44_47.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.bound.loc44: = bound_method %.loc44_47.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc44: init %empty_tuple.type = call %Destroy.Op.bound.loc44(%.loc44_47.3) -// CHECK:STDOUT: %Destroy.Op.bound.loc43: = bound_method %.loc43_35.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.bound.loc43: = bound_method %.loc43_35.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc43: init %empty_tuple.type = call %Destroy.Op.bound.loc43(%.loc43_35.3) -// CHECK:STDOUT: %Destroy.Op.bound.loc42: = bound_method %.loc42_38.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.bound.loc42: = bound_method %.loc42_38.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc42: init %empty_tuple.type = call %Destroy.Op.bound.loc42(%.loc42_38.3) -// CHECK:STDOUT: %Destroy.Op.bound.loc41: = bound_method %.loc41_35.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.bound.loc41: = bound_method %.loc41_35.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc41: init %empty_tuple.type = call %Destroy.Op.bound.loc41(%.loc41_35.3) -// CHECK:STDOUT: %Destroy.Op.bound.loc40: = bound_method %.loc40_31.3, constants.%Destroy.Op +// CHECK:STDOUT: %Destroy.Op.bound.loc40: = bound_method %.loc40_31.3, constants.%Destroy.Op.651ba6.3 // CHECK:STDOUT: %Destroy.Op.call.loc40: init %empty_tuple.type = call %Destroy.Op.bound.loc40(%.loc40_31.3) // CHECK:STDOUT: // CHECK:STDOUT: %C.Op.bound.loc23: = bound_method %.loc23_38.3, constants.%C.Op @@ -1946,7 +1953,14 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref bool) = "no_op"; +// CHECK:STDOUT: fn @Destroy.Op.loc48_30.1(%self.param: ref %i32.builtin) = "no_op"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Destroy.Op.loc48_30.2(%self.param: ref %i32) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Destroy.Op.loc45(%self.param: ref bool) = "no_op"; // CHECK:STDOUT: // CHECK:STDOUT: --- multiple_calls.carbon // CHECK:STDOUT: @@ -3175,9 +3189,7 @@ fn F() { // CHECK:STDOUT: %c2.ref: ref %C = name_ref c2, %c2 // CHECK:STDOUT: %C.cpp_operator.bound.loc10: = bound_method %c1.ref.loc10, imports.%C.cpp_operator.decl.828f43.2 // CHECK:STDOUT: %.loc10_3: ref %C = splice_block %c3.var {} -// CHECK:STDOUT: %.loc10_31.1: %C = acquire_value %c2.ref -// CHECK:STDOUT: %.loc10_31.2: ref %C = value_as_ref %.loc10_31.1 -// CHECK:STDOUT: %addr.loc10_29.1: %ptr.d9e = addr_of %.loc10_31.2 +// CHECK:STDOUT: %addr.loc10_29.1: %ptr.d9e = addr_of %c2.ref // CHECK:STDOUT: %addr.loc10_29.2: %ptr.d9e = addr_of %.loc10_3 // CHECK:STDOUT: %operator_Plus__carbon_thunk.call: init %empty_tuple.type = call imports.%operator_Plus__carbon_thunk.decl(%c1.ref.loc10, %addr.loc10_29.1, %addr.loc10_29.2) // CHECK:STDOUT: %.loc10_29: init %C to %.loc10_3 = mark_in_place_init %operator_Plus__carbon_thunk.call diff --git a/toolchain/check/testdata/interop/cpp/operators/ordered_with.carbon b/toolchain/check/testdata/interop/cpp/operators/ordered_with.carbon index d189043e4b8d..dbaf9c00dc9f 100644 --- a/toolchain/check/testdata/interop/cpp/operators/ordered_with.carbon +++ b/toolchain/check/testdata/interop/cpp/operators/ordered_with.carbon @@ -377,26 +377,13 @@ fn Test(missing_less: Cpp.MissingLess, // CHECK:STDERR: OrderedWith(no_relevant_members, no_relevant_members); - // CHECK:STDERR: fail_never_valid.carbon:[[@LINE+20]]:3: error: cannot convert type `Cpp.LessReturnsVoid` into type implementing `Core.OrderedWith(Cpp.LessReturnsVoid)` [ConversionFailureTypeToFacet] + // CHECK:STDERR: fail_never_valid.carbon:[[@LINE+7]]:3: error: cannot convert type `Cpp.LessReturnsVoid` into type implementing `Core.OrderedWith(Cpp.LessReturnsVoid)` [ConversionFailureTypeToFacet] // CHECK:STDERR: OrderedWith(less_returns_void, less_returns_void); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_never_valid.carbon:[[@LINE-62]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] // CHECK:STDERR: fn OrderedWith[U:! type, T:! Core.OrderedWith(U)](x: T, y: U) { // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - // CHECK:STDERR: {{.*}}/prelude/operators/comparison.carbon:26:11: error: value expression passed to reference parameter [ValueForRefParam] - // CHECK:STDERR: fn Less[self: Self](other: Other) -> bool; - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: fail_never_valid.carbon:[[@LINE-76]]:8: note: initializing function parameter [InCallToFunctionParam] - // CHECK:STDERR: auto operator<(LessNonConst) -> bool; - // CHECK:STDERR: ^ - // CHECK:STDERR: {{.*}}/prelude/operators/comparison.carbon:26:3: note: while building thunk to match the signature of this function [ThunkSignature] - // CHECK:STDERR: fn Less[self: Self](other: Other) -> bool; - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_never_valid.carbon:[[@LINE-75]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] - // CHECK:STDERR: fn OrderedWith[U:! type, T:! Core.OrderedWith(U)](x: T, y: U) { - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: OrderedWith(less_returns_void, less_returns_void); OrderedWith(less_non_const, less_non_const); diff --git a/toolchain/driver/testdata/stdin.carbon b/toolchain/driver/testdata/stdin.carbon index 7bfaf0d25988..5b559ac3671c 100644 --- a/toolchain/driver/testdata/stdin.carbon +++ b/toolchain/driver/testdata/stdin.carbon @@ -32,6 +32,7 @@ // CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: clang_decls: {} +// CHECK:STDOUT: clang_decl_signatures: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/lower/testdata/interop/cpp/constructor.carbon b/toolchain/lower/testdata/interop/cpp/constructor.carbon index a9d69a563635..5e6addf70679 100644 --- a/toolchain/lower/testdata/interop/cpp/constructor.carbon +++ b/toolchain/lower/testdata/interop/cpp/constructor.carbon @@ -181,12 +181,12 @@ fn Four() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc7_26.1.temp = alloca [8 x i8], align 1, !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_26.1.temp), !dbg !14 -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %.loc7_26.1.temp), !dbg !14 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc7_26.1.temp), !dbg !14 // CHECK:STDOUT: ret void, !dbg !15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16 @@ -200,12 +200,12 @@ fn Four() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc11_19.2.temp = alloca [8 x i8], align 1, !dbg !20 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc11_19.2.temp), !dbg !20 -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple(ptr %.loc11_19.2.temp), !dbg !20 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr %.loc11_19.2.temp), !dbg !20 // CHECK:STDOUT: ret void, !dbg !21 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16 @@ -286,7 +286,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16 @@ -298,7 +298,7 @@ fn Four() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret([8 x i8]) %return) #2 !dbg !19 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !24 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !24 // CHECK:STDOUT: ret void, !dbg !24 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -386,18 +386,18 @@ fn Four() { // CHECK:STDOUT: %.loc12_65.1.temp = alloca [4 x i8], align 1, !dbg !16 // CHECK:STDOUT: %_.var.loc13 = alloca [4 x i8], align 1, !dbg !17 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_65.1.temp), !dbg !14 -// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %.loc8_65.1.temp), !dbg !14 +// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %.loc8_65.1.temp), !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc9), !dbg !15 // CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.22b4681b019423d7"(ptr %_.var.loc9), !dbg !15 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_65.1.temp), !dbg !16 -// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %.loc12_65.1.temp), !dbg !16 +// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %.loc12_65.1.temp), !dbg !16 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc13), !dbg !17 // CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.1a27c303748a2360"(ptr %_.var.loc13), !dbg !17 // CHECK:STDOUT: ret void, !dbg !18 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !19 @@ -409,12 +409,12 @@ fn Four() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.2e5fb550c65543cf.Core:ImplicitlyDefaultedDefault.Cpp"(ptr sret([4 x i8]) %return) #2 !dbg !22 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %return), !dbg !27 +// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %return), !dbg !27 // CHECK:STDOUT: ret void, !dbg !27 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !28 @@ -426,7 +426,7 @@ fn Four() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.cad83ce9b7db87bf.Core:ExplicitlyDefaultedDefault.Cpp"(ptr sret([4 x i8]) %return) #2 !dbg !30 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %return), !dbg !31 +// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %return), !dbg !31 // CHECK:STDOUT: ret void, !dbg !31 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -534,12 +534,12 @@ fn Four() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc7_10.1.temp = alloca [4 x i8], align 1, !dbg !17 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_10.1.temp), !dbg !17 -// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk(ptr %c, ptr %return), !dbg !17 +// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr %c, ptr %return), !dbg !17 // CHECK:STDOUT: ret void, !dbg !18 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN4CopyC1ERKS_.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -554,7 +554,7 @@ fn Four() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Copy.692da64e78c7deec.Core:Copy.Cpp"(ptr sret([4 x i8]) %return, ptr %self) #2 !dbg !22 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk(ptr %self, ptr %return), !dbg !26 +// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr %self, ptr %return), !dbg !26 // CHECK:STDOUT: ret void, !dbg !26 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -633,12 +633,12 @@ fn Four() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc7_44.1.temp = alloca [8 x i8], align 1, !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_44.1.temp), !dbg !14 -// CHECK:STDOUT: call void @_ZN7DerivedC1Ev.carbon_thunk(ptr %.loc7_44.1.temp), !dbg !14 +// CHECK:STDOUT: call void @_ZN7DerivedC1Ev.carbon_thunk.(ptr %.loc7_44.1.temp), !dbg !14 // CHECK:STDOUT: ret void, !dbg !15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN7DerivedC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN7DerivedC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16 @@ -712,14 +712,14 @@ fn Four() { // CHECK:STDOUT: %.loc7_26.1.temp = alloca [1 x i8], align 1, !dbg !14 // CHECK:STDOUT: %.loc8_19.2.temp = alloca [1 x i8], align 1, !dbg !15 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_26.1.temp), !dbg !14 -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %.loc7_26.1.temp), !dbg !14 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc7_26.1.temp), !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_19.2.temp), !dbg !15 -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple(ptr %.loc8_19.2.temp), !dbg !15 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr %.loc8_19.2.temp), !dbg !15 // CHECK:STDOUT: ret void, !dbg !16 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 @@ -729,7 +729,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 @@ -745,16 +745,16 @@ fn Four() { // CHECK:STDOUT: %.loc13_18.1.temp = alloca [1 x i8], align 1, !dbg !22 // CHECK:STDOUT: %.loc14_21.2.temp = alloca [1 x i8], align 1, !dbg !23 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_27.1.temp), !dbg !21 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 1, ptr %.loc12_27.1.temp), !dbg !21 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk._(i32 1, ptr %.loc12_27.1.temp), !dbg !21 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc13_18.1.temp), !dbg !22 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 2, ptr %.loc13_18.1.temp), !dbg !22 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk._(i32 2, ptr %.loc13_18.1.temp), !dbg !22 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_21.2.temp), !dbg !23 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple(i32 3, ptr %.loc14_21.2.temp), !dbg !23 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple._(i32 3, ptr %.loc14_21.2.temp), !dbg !23 // CHECK:STDOUT: ret void, !dbg !24 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk(i32 noundef %0, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk._(i32 noundef %0, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -767,7 +767,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk_tuple(i32 noundef %0, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk_tuple._(i32 noundef %0, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -785,14 +785,14 @@ fn Four() { // CHECK:STDOUT: %.loc18_30.1.temp = alloca [1 x i8], align 1, !dbg !26 // CHECK:STDOUT: %.loc19_23.2.temp = alloca [1 x i8], align 1, !dbg !27 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_30.1.temp), !dbg !26 -// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk(i32 1, i32 2, ptr %.loc18_30.1.temp), !dbg !26 +// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk.__(i32 1, i32 2, ptr %.loc18_30.1.temp), !dbg !26 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_23.2.temp), !dbg !27 -// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple(i32 3, i32 4, ptr %.loc19_23.2.temp), !dbg !27 +// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple.__(i32 3, i32 4, ptr %.loc19_23.2.temp), !dbg !27 // CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk.__(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -808,7 +808,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk_tuple(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk_tuple.__(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -829,14 +829,14 @@ fn Four() { // CHECK:STDOUT: %.loc23_33.1.temp = alloca [1 x i8], align 1, !dbg !30 // CHECK:STDOUT: %.loc24_26.2.temp = alloca [1 x i8], align 1, !dbg !31 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_33.1.temp), !dbg !30 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk3(i32 1, i32 2, i32 3, ptr %.loc23_33.1.temp), !dbg !30 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk.___(i32 1, i32 2, i32 3, ptr %.loc23_33.1.temp), !dbg !30 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_26.2.temp), !dbg !31 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 4, i32 5, i32 6, ptr %.loc24_26.2.temp), !dbg !31 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple.___(i32 4, i32 5, i32 6, ptr %.loc24_26.2.temp), !dbg !31 // CHECK:STDOUT: ret void, !dbg !32 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk3(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk.___(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -855,7 +855,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple.___(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -879,14 +879,14 @@ fn Four() { // CHECK:STDOUT: %.loc28_36.1.temp = alloca [1 x i8], align 1, !dbg !34 // CHECK:STDOUT: %.loc29_29.2.temp = alloca [1 x i8], align 1, !dbg !35 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc28_36.1.temp), !dbg !34 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk(i32 1, i32 2, i32 3, i32 4, ptr %.loc28_36.1.temp), !dbg !34 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk.____(i32 1, i32 2, i32 3, i32 4, ptr %.loc28_36.1.temp), !dbg !34 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc29_29.2.temp), !dbg !35 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 5, i32 6, i32 7, i32 8, ptr %.loc29_29.2.temp), !dbg !35 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple.____(i32 5, i32 6, i32 7, i32 8, ptr %.loc29_29.2.temp), !dbg !35 // CHECK:STDOUT: ret void, !dbg !36 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk.____(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -908,7 +908,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple.____(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca i32, align 4 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -983,7 +983,7 @@ fn Four() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @_ZN1CC1Ei.carbon_thunk, { 1, 0 } +// CHECK:STDOUT: uselistorder ptr @_ZN1CC1Ei.carbon_thunk._, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } diff --git a/toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon b/toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon new file mode 100644 index 000000000000..1c47445c2885 --- /dev/null +++ b/toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon @@ -0,0 +1,504 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon +// EXTRA-ARGS: --clang-arg=-fno-exceptions +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon + +// --- copyable.carbon +library "[[@TEST_NAME]]"; + +import Cpp; +inline Cpp ''' +struct Copyable { + Copyable(const Copyable&); + Copyable& operator=(const Copyable&); + ~Copyable(); +}; +Copyable make(); +void pass(Copyable); +'''; + +var c: Cpp.Copyable = Cpp.make(); + +fn PassGlobal() { + Cpp.pass(c); +} + +fn PassTemporary() { + Cpp.pass(Cpp.make()); +} + +fn PassValue(c: Cpp.Copyable) { + Cpp.pass(c); +} + +fn PassRef(ref c: Cpp.Copyable) { + Cpp.pass(c); +} + +// --- copy_or_move.carbon +library "[[@TEST_NAME]]"; + +import Cpp; +inline Cpp ''' +struct CopyOrMove { + CopyOrMove(const CopyOrMove&); + CopyOrMove& operator=(const CopyOrMove&); + CopyOrMove(CopyOrMove&&); + CopyOrMove& operator=(CopyOrMove&&); + ~CopyOrMove(); +}; +CopyOrMove make(); +void pass(CopyOrMove); +'''; + +var c: Cpp.CopyOrMove = Cpp.make(); + +fn PassGlobal() { + Cpp.pass(c); +} + +fn PassTemporary() { + Cpp.pass(Cpp.make()); +} + +fn PassValue(c: Cpp.CopyOrMove) { + Cpp.pass(c); +} + +fn PassRef(ref c: Cpp.CopyOrMove) { + Cpp.pass(c); +} + +// --- move_only.carbon +library "[[@TEST_NAME]]"; + +import Cpp; +inline Cpp ''' +namespace std { +template T&& move(T& t) { return static_cast(t); } +} + +struct MoveOnly { + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&); + MoveOnly& operator=(MoveOnly&&); + ~MoveOnly(); +}; +MoveOnly make(); +void pass(MoveOnly); +'''; + +var c: Cpp.MoveOnly = Cpp.make(); + +fn PassGlobalByMove() { + // TODO: This should be accepted. + // Cpp.pass(Cpp.std.move(ref c)); +} + +fn PassTemporary() { + Cpp.pass(Cpp.make()); +} + +// CHECK:STDOUT: ; ModuleID = 'copyable.carbon' +// CHECK:STDOUT: source_filename = "copyable.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: %struct.Copyable = type { i8 } +// CHECK:STDOUT: +// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer +// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }] +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %return.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.Copyable) align 1 %0) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassGlobal.Main() #1 !dbg !14 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr @_Cc.Main), !dbg !17 +// CHECK:STDOUT: ret void, !dbg !18 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4pass8Copyable.carbon_thunk._(ptr noundef %0) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: %agg.tmp = alloca %struct.Copyable, align 1 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_ZN8CopyableC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1) +// CHECK:STDOUT: call void @_Z4pass8Copyable(ptr noundef %agg.tmp) +// CHECK:STDOUT: call void @_ZN8CopyableD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !19 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.loc21_21.1.temp = alloca [1 x i8], align 1, !dbg !20 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc21_21.1.temp), !dbg !20 +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %.loc21_21.1.temp), !dbg !20 +// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %.loc21_21.1.temp), !dbg !21 +// CHECK:STDOUT: call void @_ZN8CopyableD1Ev(ptr %.loc21_21.1.temp), !dbg !20 +// CHECK:STDOUT: ret void, !dbg !22 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: declare void @_ZN8CopyableD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassValue.Main(ptr %c) #1 !dbg !23 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %c), !dbg !29 +// CHECK:STDOUT: ret void, !dbg !30 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassRef.Main(ptr %c) #1 !dbg !31 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %c), !dbg !34 +// CHECK:STDOUT: ret void, !dbg !35 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !36 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !37 +// CHECK:STDOUT: ret void, !dbg !38 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.Copyable) align 1) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4pass8Copyable(ptr noundef) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN8CopyableC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { nounwind } +// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} +// CHECK:STDOUT: !llvm.dbg.cu = !{!5} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!7} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !6 = !DIFile(filename: "copyable.carbon", directory: "") +// CHECK:STDOUT: !7 = !{!8, !8, i64 0} +// CHECK:STDOUT: !8 = !{!"int", !9, i64 0} +// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0} +// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !11 = !{!12, !12, i64 0} +// CHECK:STDOUT: !12 = !{!"p1 _ZTS8Copyable", !13, i64 0} +// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0} +// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobal", linkageName: "_CPassGlobal.Main", scope: null, file: !6, line: 16, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !15 = !DISubroutineType(types: !16) +// CHECK:STDOUT: !16 = !{null} +// CHECK:STDOUT: !17 = !DILocation(line: 17, column: 3, scope: !14) +// CHECK:STDOUT: !18 = !DILocation(line: 16, column: 1, scope: !14) +// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 20, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !20 = !DILocation(line: 21, column: 12, scope: !19) +// CHECK:STDOUT: !21 = !DILocation(line: 21, column: 3, scope: !19) +// CHECK:STDOUT: !22 = !DILocation(line: 20, column: 1, scope: !19) +// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "PassValue", linkageName: "_CPassValue.Main", scope: null, file: !6, line: 24, type: !24, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !27) +// CHECK:STDOUT: !24 = !DISubroutineType(types: !25) +// CHECK:STDOUT: !25 = !{null, !26} +// CHECK:STDOUT: !26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !27 = !{!28} +// CHECK:STDOUT: !28 = !DILocalVariable(arg: 1, scope: !23, type: !26) +// CHECK:STDOUT: !29 = !DILocation(line: 25, column: 3, scope: !23) +// CHECK:STDOUT: !30 = !DILocation(line: 24, column: 1, scope: !23) +// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "PassRef", linkageName: "_CPassRef.Main", scope: null, file: !6, line: 28, type: !24, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !32) +// CHECK:STDOUT: !32 = !{!33} +// CHECK:STDOUT: !33 = !DILocalVariable(arg: 1, scope: !31, type: !26) +// CHECK:STDOUT: !34 = !DILocation(line: 29, column: 3, scope: !31) +// CHECK:STDOUT: !35 = !DILocation(line: 28, column: 1, scope: !31) +// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !37 = !DILocation(line: 14, column: 23, scope: !36) +// CHECK:STDOUT: !38 = !DILocation(line: 0, scope: !36) +// CHECK:STDOUT: ; ModuleID = 'copy_or_move.carbon' +// CHECK:STDOUT: source_filename = "copy_or_move.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: %struct.CopyOrMove = type { i8 } +// CHECK:STDOUT: +// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer +// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }] +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %return.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.CopyOrMove) align 1 %0) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassGlobal.Main() #1 !dbg !14 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr @_Cc.Main), !dbg !17 +// CHECK:STDOUT: ret void, !dbg !18 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4pass10CopyOrMove.carbon_thunk._(ptr noundef %0) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: %agg.tmp = alloca %struct.CopyOrMove, align 1 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_ZN10CopyOrMoveC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1) +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove(ptr noundef %agg.tmp) +// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !19 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !20 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !20 +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %_.var), !dbg !21 +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk.v(ptr %_.var), !dbg !22 +// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr %_.var), !dbg !20 +// CHECK:STDOUT: ret void, !dbg !23 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4pass10CopyOrMove.carbon_thunk.v(ptr noundef %0) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: %agg.tmp = alloca %struct.CopyOrMove, align 1 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_ZN10CopyOrMoveC1EOS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1) +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove(ptr noundef %agg.tmp) +// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: declare void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassValue.Main(ptr %c) #1 !dbg !24 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr %c), !dbg !30 +// CHECK:STDOUT: ret void, !dbg !31 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassRef.Main(ptr %c) #1 !dbg !32 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr %c), !dbg !35 +// CHECK:STDOUT: ret void, !dbg !36 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !37 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !38 +// CHECK:STDOUT: ret void, !dbg !39 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.CopyOrMove) align 1) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4pass10CopyOrMove(ptr noundef) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN10CopyOrMoveC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN10CopyOrMoveC1EOS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 +// CHECK:STDOUT: +// CHECK:STDOUT: ; uselistorder directives +// CHECK:STDOUT: uselistorder ptr @_ZN10CopyOrMoveD1Ev, { 1, 2, 0 } +// CHECK:STDOUT: uselistorder ptr @_Z4pass10CopyOrMove, { 1, 0 } +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { nounwind } +// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} +// CHECK:STDOUT: !llvm.dbg.cu = !{!5} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!7} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !6 = !DIFile(filename: "copy_or_move.carbon", directory: "") +// CHECK:STDOUT: !7 = !{!8, !8, i64 0} +// CHECK:STDOUT: !8 = !{!"int", !9, i64 0} +// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0} +// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !11 = !{!12, !12, i64 0} +// CHECK:STDOUT: !12 = !{!"p1 _ZTS10CopyOrMove", !13, i64 0} +// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0} +// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobal", linkageName: "_CPassGlobal.Main", scope: null, file: !6, line: 18, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !15 = !DISubroutineType(types: !16) +// CHECK:STDOUT: !16 = !{null} +// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 3, scope: !14) +// CHECK:STDOUT: !18 = !DILocation(line: 18, column: 1, scope: !14) +// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 22, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !20 = !DILocation(line: 13, column: 21, scope: !19) +// CHECK:STDOUT: !21 = !DILocation(line: 23, column: 12, scope: !19) +// CHECK:STDOUT: !22 = !DILocation(line: 23, column: 3, scope: !19) +// CHECK:STDOUT: !23 = !DILocation(line: 22, column: 1, scope: !19) +// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "PassValue", linkageName: "_CPassValue.Main", scope: null, file: !6, line: 26, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !28) +// CHECK:STDOUT: !25 = !DISubroutineType(types: !26) +// CHECK:STDOUT: !26 = !{null, !27} +// CHECK:STDOUT: !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !28 = !{!29} +// CHECK:STDOUT: !29 = !DILocalVariable(arg: 1, scope: !24, type: !27) +// CHECK:STDOUT: !30 = !DILocation(line: 27, column: 3, scope: !24) +// CHECK:STDOUT: !31 = !DILocation(line: 26, column: 1, scope: !24) +// CHECK:STDOUT: !32 = distinct !DISubprogram(name: "PassRef", linkageName: "_CPassRef.Main", scope: null, file: !6, line: 30, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !33) +// CHECK:STDOUT: !33 = !{!34} +// CHECK:STDOUT: !34 = !DILocalVariable(arg: 1, scope: !32, type: !27) +// CHECK:STDOUT: !35 = !DILocation(line: 31, column: 3, scope: !32) +// CHECK:STDOUT: !36 = !DILocation(line: 30, column: 1, scope: !32) +// CHECK:STDOUT: !37 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !38 = !DILocation(line: 16, column: 25, scope: !37) +// CHECK:STDOUT: !39 = !DILocation(line: 0, scope: !37) +// CHECK:STDOUT: ; ModuleID = 'move_only.carbon' +// CHECK:STDOUT: source_filename = "move_only.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: %struct.MoveOnly = type { i8 } +// CHECK:STDOUT: +// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer +// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }] +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %return.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.MoveOnly) align 1 %0) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassGlobalByMove.Main() #1 !dbg !14 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: ret void, !dbg !17 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !18 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !19 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !19 +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %_.var), !dbg !20 +// CHECK:STDOUT: call void @_Z4pass8MoveOnly.carbon_thunk.v(ptr %_.var), !dbg !21 +// CHECK:STDOUT: call void @_ZN8MoveOnlyD1Ev(ptr %_.var), !dbg !19 +// CHECK:STDOUT: ret void, !dbg !22 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_Z4pass8MoveOnly.carbon_thunk.v(ptr noundef %0) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: %agg.tmp = alloca %struct.MoveOnly, align 1 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: call void @_ZN8MoveOnlyC1EOS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1) +// CHECK:STDOUT: call void @_Z4pass8MoveOnly(ptr noundef %agg.tmp) +// CHECK:STDOUT: call void @_ZN8MoveOnlyD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: declare void @_ZN8MoveOnlyD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !23 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !24 +// CHECK:STDOUT: ret void, !dbg !25 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.MoveOnly) align 1) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4pass8MoveOnly(ptr noundef) #4 +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN8MoveOnlyC1EOS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4 +// CHECK:STDOUT: +// CHECK:STDOUT: ; uselistorder directives +// CHECK:STDOUT: uselistorder ptr @_ZN8MoveOnlyD1Ev, { 1, 0 } +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { nounwind } +// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} +// CHECK:STDOUT: !llvm.dbg.cu = !{!5} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!7} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !6 = !DIFile(filename: "move_only.carbon", directory: "") +// CHECK:STDOUT: !7 = !{!8, !8, i64 0} +// CHECK:STDOUT: !8 = !{!"int", !9, i64 0} +// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0} +// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !11 = !{!12, !12, i64 0} +// CHECK:STDOUT: !12 = !{!"p1 _ZTS8MoveOnly", !13, i64 0} +// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0} +// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobalByMove", linkageName: "_CPassGlobalByMove.Main", scope: null, file: !6, line: 22, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !15 = !DISubroutineType(types: !16) +// CHECK:STDOUT: !16 = !{null} +// CHECK:STDOUT: !17 = !DILocation(line: 22, column: 1, scope: !14) +// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 27, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !19 = !DILocation(line: 17, column: 19, scope: !18) +// CHECK:STDOUT: !20 = !DILocation(line: 28, column: 12, scope: !18) +// CHECK:STDOUT: !21 = !DILocation(line: 28, column: 3, scope: !18) +// CHECK:STDOUT: !22 = !DILocation(line: 27, column: 1, scope: !18) +// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !24 = !DILocation(line: 20, column: 23, scope: !23) +// CHECK:STDOUT: !25 = !DILocation(line: 0, scope: !23) diff --git a/toolchain/lower/testdata/interop/cpp/extern_c.carbon b/toolchain/lower/testdata/interop/cpp/extern_c.carbon index 2480c2ca3de4..5d398ee19039 100644 --- a/toolchain/lower/testdata/interop/cpp/extern_c.carbon +++ b/toolchain/lower/testdata/interop/cpp/extern_c.carbon @@ -227,12 +227,12 @@ fn MyF() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CMyF.Main(ptr sret({}) %return, ptr %a, ptr %b) #0 !dbg !11 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Zpl1XS_.carbon_thunk(ptr %a, ptr %b, ptr %return), !dbg !18 +// CHECK:STDOUT: call void @_Zpl1XS_.carbon_thunk.__(ptr %a, ptr %b, ptr %return), !dbg !18 // CHECK:STDOUT: ret void, !dbg !19 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zpl1XS_.carbon_thunk(ptr noundef %0, ptr noundef %1, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zpl1XS_.carbon_thunk.__(ptr noundef %0, ptr noundef %1, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %.addr1 = alloca ptr, align 8 diff --git a/toolchain/lower/testdata/interop/cpp/function_decl.carbon b/toolchain/lower/testdata/interop/cpp/function_decl.carbon index 8d2301d3de7c..6cfa765313c2 100644 --- a/toolchain/lower/testdata/interop/cpp/function_decl.carbon +++ b/toolchain/lower/testdata/interop/cpp/function_decl.carbon @@ -385,13 +385,13 @@ fn MyF() -> i32 { // CHECK:STDOUT: define i32 @_CMyF.Main() #0 !dbg !11 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %value.var = alloca i32, align 4, !dbg !15 -// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk0(), !dbg !16 -// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk1(i32 3), !dbg !17 +// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk.(), !dbg !16 +// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk._(i32 3), !dbg !17 // CHECK:STDOUT: call void @_Z13NoReturnValueii(i32 3, i32 4), !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %value.var), !dbg !15 -// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc11 = call i32 @_Z17SimpleReturnValueii.carbon_thunk0(), !dbg !19 +// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc11 = call i32 @_Z17SimpleReturnValueii.carbon_thunk.(), !dbg !19 // CHECK:STDOUT: store i32 %SimpleReturnValue__carbon_thunk.call.loc11, ptr %value.var, align 4, !dbg !15 -// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc12 = call i32 @_Z17SimpleReturnValueii.carbon_thunk1(i32 3), !dbg !20 +// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc12 = call i32 @_Z17SimpleReturnValueii.carbon_thunk._(i32 3), !dbg !20 // CHECK:STDOUT: store i32 %SimpleReturnValue__carbon_thunk.call.loc12, ptr %value.var, align 4, !dbg !21 // CHECK:STDOUT: %SimpleReturnValue.call = call i32 @_Z17SimpleReturnValueii(i32 3, i32 4), !dbg !22 // CHECK:STDOUT: store i32 %SimpleReturnValue.call, ptr %value.var, align 4, !dbg !23 @@ -401,14 +401,14 @@ fn MyF() -> i32 { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: call void @_Z13NoReturnValueii(i32 noundef 1, i32 noundef 2) // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk1(i32 noundef %a) #1 { +// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk._(i32 noundef %a) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %a.addr = alloca i32, align 4 // CHECK:STDOUT: store i32 %a, ptr %a.addr, align 4, !tbaa !7 @@ -420,14 +420,14 @@ fn MyF() -> i32 { // CHECK:STDOUT: declare void @_Z13NoReturnValueii(i32 noundef, i32 noundef) #2 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %call = call noundef i32 @_Z17SimpleReturnValueii(i32 noundef 1, i32 noundef 2) // CHECK:STDOUT: ret i32 %call // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk1(i32 noundef %a) #1 { +// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk._(i32 noundef %a) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %a.addr = alloca i32, align 4 // CHECK:STDOUT: store i32 %a, ptr %a.addr, align 4, !tbaa !7 diff --git a/toolchain/lower/testdata/interop/cpp/method.carbon b/toolchain/lower/testdata/interop/cpp/method.carbon index 007daf64e52c..994427704d4a 100644 --- a/toolchain/lower/testdata/interop/cpp/method.carbon +++ b/toolchain/lower/testdata/interop/cpp/method.carbon @@ -86,7 +86,7 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define i32 @_CUseVal.Main(ptr %a) #0 !dbg !11 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %by_val__carbon_thunk.call = call i32 @_ZNK1A6by_valEv.carbon_thunk(ptr %a), !dbg !18 +// CHECK:STDOUT: %by_val__carbon_thunk.call = call i32 @_ZNK1A6by_valEv.carbon_thunk._(ptr %a), !dbg !18 // CHECK:STDOUT: ret i32 %by_val__carbon_thunk.call, !dbg !19 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -95,7 +95,7 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: declare void @_ZN1A5virt1Ev(ptr noundef nonnull align 8 dereferenceable(12)) unnamed_addr #1 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef i32 @_ZNK1A6by_valEv.carbon_thunk(ptr noundef nonnull align 8 dereferenceable(12) %this) #2 { +// CHECK:STDOUT: define internal noundef i32 @_ZNK1A6by_valEv.carbon_thunk._(ptr noundef nonnull align 8 dereferenceable(12) %this) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !20 @@ -284,16 +284,16 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: %.loc7_14.3.temp = alloca i8, align 1, !dbg !17 // CHECK:STDOUT: %.loc8_14.3.temp = alloca i8, align 1, !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_14.3.temp), !dbg !17 -// CHECK:STDOUT: call void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk(ptr %n, ptr @int_1.30e), !dbg !19 +// CHECK:STDOUT: call void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk.__(ptr %n, ptr @int_1.30e), !dbg !19 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_14.3.temp), !dbg !18 -// CHECK:STDOUT: call void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk(ptr %n, ptr @int_1.30e), !dbg !20 +// CHECK:STDOUT: call void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk.__(ptr %n, ptr @int_1.30e), !dbg !20 // CHECK:STDOUT: call void @"_COp.43bece552030817c:core.Destroy.Core"(ptr @int_1.30e), !dbg !18 // CHECK:STDOUT: call void @"_COp.43bece552030817c:core.Destroy.Core"(ptr @int_1.30e), !dbg !17 // CHECK:STDOUT: ret void, !dbg !21 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr noundef %c) #1 { +// CHECK:STDOUT: define internal void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk.__(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr noundef %c) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: %c.addr = alloca ptr, align 8 @@ -307,7 +307,7 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk(ptr noundef %0, ptr noundef %c) #1 { +// CHECK:STDOUT: define internal void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk.__(ptr noundef %0, ptr noundef %c) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %c.addr = alloca ptr, align 8 diff --git a/toolchain/lower/testdata/interop/cpp/nullptr.carbon b/toolchain/lower/testdata/interop/cpp/nullptr.carbon index ea7a93b7394a..c5df966c4794 100644 --- a/toolchain/lower/testdata/interop/cpp/nullptr.carbon +++ b/toolchain/lower/testdata/interop/cpp/nullptr.carbon @@ -67,7 +67,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) { // CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !15 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_22.1.temp), !dbg !15 // CHECK:STDOUT: store ptr %Cpp.nullptr_t.as.Copy.impl.Op.call, ptr %.loc14_22.1.temp, align 8, !dbg !15 -// CHECK:STDOUT: call void @_Z11TakeNullptrDn.carbon_thunk(ptr %.loc14_22.1.temp), !dbg !17 +// CHECK:STDOUT: call void @_Z11TakeNullptrDn.carbon_thunk._(ptr %.loc14_22.1.temp), !dbg !17 // CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc14_22.1.temp), !dbg !15 // CHECK:STDOUT: call void @"_COp.e34c165b4a1e692a:core.Destroy.Core"(ptr %.loc12_18.2.temp), !dbg !14 // CHECK:STDOUT: ret void, !dbg !18 @@ -76,7 +76,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) { // CHECK:STDOUT: declare void @_Z7TakePtrPi(ptr noundef) #1 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11TakeNullptrDn.carbon_thunk(ptr noundef %n) #2 { +// CHECK:STDOUT: define internal void @_Z11TakeNullptrDn.carbon_thunk._(ptr noundef %n) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %n.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %n, ptr %n.addr, align 8, !tbaa !19 @@ -130,7 +130,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !48 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !48 -// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %a.var), !dbg !49 +// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk.(ptr %a.var), !dbg !49 // CHECK:STDOUT: %.loc28_10 = load ptr, ptr %a.var, align 8, !dbg !50 // CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.a5972e826b98ae3c.Core.b88d1103f417c6d4"(ptr %.loc28_10), !dbg !51 // CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %a.var), !dbg !48 @@ -138,7 +138,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13ReturnNullptrv.carbon_thunk(ptr noundef %return) #2 { +// CHECK:STDOUT: define internal void @_Z13ReturnNullptrv.carbon_thunk.(ptr noundef %return) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !19 @@ -153,7 +153,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc32_28.1.temp = alloca ptr, align 8, !dbg !55 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc32_28.1.temp), !dbg !55 -// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %.loc32_28.1.temp), !dbg !55 +// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk.(ptr %.loc32_28.1.temp), !dbg !55 // CHECK:STDOUT: %.loc32_28.4 = load ptr, ptr %.loc32_28.1.temp, align 8, !dbg !55 // CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.a5972e826b98ae3c.Core.b88d1103f417c6d4"(ptr %.loc32_28.4), !dbg !56 // CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc32_28.1.temp), !dbg !55 diff --git a/toolchain/lower/testdata/interop/cpp/operators.carbon b/toolchain/lower/testdata/interop/cpp/operators.carbon index e839e38cf840..b00db6aacf14 100644 --- a/toolchain/lower/testdata/interop/cpp/operators.carbon +++ b/toolchain/lower/testdata/interop/cpp/operators.carbon @@ -93,7 +93,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zeq1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zeq1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -119,7 +119,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zne1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zne1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -149,7 +149,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !34 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !34 -// CHECK:STDOUT: call void @_Zeq1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !34 +// CHECK:STDOUT: call void @_Zeq1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !34 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !34 // CHECK:STDOUT: ret i1 %0, !dbg !34 // CHECK:STDOUT: } @@ -159,7 +159,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !39 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !39 -// CHECK:STDOUT: call void @_Zne1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !39 +// CHECK:STDOUT: call void @_Zne1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !39 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !39 // CHECK:STDOUT: ret i1 %0, !dbg !39 // CHECK:STDOUT: } @@ -304,7 +304,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zlt1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zlt1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -330,7 +330,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zle1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zle1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -356,7 +356,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zgt1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zgt1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -382,7 +382,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Zge1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Zge1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 @@ -412,7 +412,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !34 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !34 -// CHECK:STDOUT: call void @_Zlt1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !34 +// CHECK:STDOUT: call void @_Zlt1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !34 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !34 // CHECK:STDOUT: ret i1 %0, !dbg !34 // CHECK:STDOUT: } @@ -422,7 +422,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !39 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !39 -// CHECK:STDOUT: call void @_Zle1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !39 +// CHECK:STDOUT: call void @_Zle1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !39 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !39 // CHECK:STDOUT: ret i1 %0, !dbg !39 // CHECK:STDOUT: } @@ -432,7 +432,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !44 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !44 -// CHECK:STDOUT: call void @_Zgt1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !44 +// CHECK:STDOUT: call void @_Zgt1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !44 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !44 // CHECK:STDOUT: ret i1 %0, !dbg !44 // CHECK:STDOUT: } @@ -442,7 +442,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !49 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !49 -// CHECK:STDOUT: call void @_Zge1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !49 +// CHECK:STDOUT: call void @_Zge1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !49 // CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !49 // CHECK:STDOUT: ret i1 %0, !dbg !49 // CHECK:STDOUT: } diff --git a/toolchain/lower/testdata/interop/cpp/parameters.carbon b/toolchain/lower/testdata/interop/cpp/parameters.carbon index ed79da3dddf8..02649c4aa022 100644 --- a/toolchain/lower/testdata/interop/cpp/parameters.carbon +++ b/toolchain/lower/testdata/interop/cpp/parameters.carbon @@ -129,10 +129,10 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: %.loc9_24.3.temp = alloca i16, align 2, !dbg !17 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_19.3.temp), !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_22.3.temp), !dbg !15 -// CHECK:STDOUT: call void @_Z11pass_signedasil.carbon_thunk(ptr @int_1.30e, ptr @int_2.305, i32 3, i64 4), !dbg !18 +// CHECK:STDOUT: call void @_Z11pass_signedasil.carbon_thunk.____(ptr @int_1.30e, ptr @int_2.305, i32 3, i64 4), !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_21.3.temp), !dbg !16 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_24.3.temp), !dbg !17 -// CHECK:STDOUT: call void @_Z13pass_unsignedhtjm.carbon_thunk(ptr @int_1.e80, ptr @int_2.fb2, i32 3, i64 4), !dbg !19 +// CHECK:STDOUT: call void @_Z13pass_unsignedhtjm.carbon_thunk.____(ptr @int_1.e80, ptr @int_2.fb2, i32 3, i64 4), !dbg !19 // CHECK:STDOUT: call void @"_COp.ecaf8c3e76291eee:core.Destroy.Core"(ptr @int_2.fb2), !dbg !17 // CHECK:STDOUT: call void @"_COp.3de38e83520d6bec:core.Destroy.Core"(ptr @int_1.e80), !dbg !16 // CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr @int_2.305), !dbg !15 @@ -141,7 +141,7 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11pass_signedasil.carbon_thunk(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 { +// CHECK:STDOUT: define internal void @_Z11pass_signedasil.carbon_thunk.____(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %.addr1 = alloca ptr, align 8 @@ -162,7 +162,7 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13pass_unsignedhtjm.carbon_thunk(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 { +// CHECK:STDOUT: define internal void @_Z13pass_unsignedhtjm.carbon_thunk.____(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %.addr1 = alloca ptr, align 8 @@ -217,19 +217,19 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: %.loc20_28.3.temp = alloca i16, align 2, !dbg !69 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc17_18.1.temp), !dbg !66 // CHECK:STDOUT: store i16 %a, ptr %.loc17_18.1.temp, align 2, !dbg !66 -// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc17_18.1.temp), !dbg !70 +// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc17_18.1.temp), !dbg !70 // CHECK:STDOUT: %.loc18_18.2 = load i16, ptr %b, align 2, !dbg !67 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_18.3.temp), !dbg !67 // CHECK:STDOUT: store i16 %.loc18_18.2, ptr %.loc18_18.3.temp, align 2, !dbg !67 -// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc18_18.3.temp), !dbg !71 +// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc18_18.3.temp), !dbg !71 // CHECK:STDOUT: %.loc19_18.1 = load i16, ptr @_Cc.Main, align 2, !dbg !68 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_18.2.temp), !dbg !68 // CHECK:STDOUT: store i16 %.loc19_18.1, ptr %.loc19_18.2.temp, align 2, !dbg !68 -// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc19_18.2.temp), !dbg !72 +// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc19_18.2.temp), !dbg !72 // CHECK:STDOUT: %MakeShort.call = call i16 @_CMakeShort.Main(), !dbg !69 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_28.3.temp), !dbg !69 // CHECK:STDOUT: store i16 %MakeShort.call, ptr %.loc20_28.3.temp, align 2, !dbg !69 -// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc20_28.3.temp), !dbg !73 +// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc20_28.3.temp), !dbg !73 // CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc20_28.3.temp), !dbg !69 // CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc19_18.2.temp), !dbg !68 // CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc18_18.3.temp), !dbg !67 @@ -238,7 +238,7 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z10pass_shorts.carbon_thunk(ptr noundef %0) #1 { +// CHECK:STDOUT: define internal void @_Z10pass_shorts.carbon_thunk._(ptr noundef %0) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !24 @@ -265,7 +265,7 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: declare void @_Z10pass_shorts(i16 noundef signext) #3 // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @_Z10pass_shorts.carbon_thunk, { 3, 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @_Z10pass_shorts.carbon_thunk._, { 3, 2, 1, 0 } // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 7, 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } @@ -374,12 +374,12 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: store i32 2, ptr %.loc9_4.b, align 4, !dbg !16 // CHECK:STDOUT: %.loc10_4.c = getelementptr inbounds nuw [12 x i8], ptr %x.var, i32 0, i32 8, !dbg !17 // CHECK:STDOUT: store i32 3, ptr %.loc10_4.c, align 4, !dbg !17 -// CHECK:STDOUT: call void @_Z11pass_struct1X.carbon_thunk(ptr %x.var), !dbg !18 +// CHECK:STDOUT: call void @_Z11pass_struct1X.carbon_thunk._(ptr %x.var), !dbg !18 // CHECK:STDOUT: ret void, !dbg !19 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN1XC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1XC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !20 @@ -390,12 +390,12 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.17a84649916546b3.Core:X.Cpp"(ptr sret([12 x i8]) %return) #2 !dbg !23 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN1XC1Ev.carbon_thunk(ptr %return), !dbg !28 +// CHECK:STDOUT: call void @_ZN1XC1Ev.carbon_thunk.(ptr %return), !dbg !28 // CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11pass_struct1X.carbon_thunk(ptr noundef %0) #3 { +// CHECK:STDOUT: define internal void @_Z11pass_struct1X.carbon_thunk._(ptr noundef %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %struct.X, align 4 @@ -493,12 +493,12 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: store i32 2, ptr %.loc9_4.b, align 4, !dbg !16 // CHECK:STDOUT: %.loc10_4.c = getelementptr inbounds nuw [12 x i8], ptr %y.var, i32 0, i32 8, !dbg !17 // CHECK:STDOUT: store i32 3, ptr %.loc10_4.c, align 4, !dbg !17 -// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %y.var), !dbg !18 +// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %y.var), !dbg !18 // CHECK:STDOUT: ret void, !dbg !19 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11pass_struct1Y.carbon_thunk(ptr noundef %0) #1 { +// CHECK:STDOUT: define internal void @_Z11pass_struct1Y.carbon_thunk._(ptr noundef %0) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.Y, align 4 @@ -517,14 +517,14 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: %.loc17_24.1.temp = alloca [12 x i8], align 1, !dbg !24 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc17_24.1.temp), !dbg !24 // CHECK:STDOUT: call void @_CMake.Main(ptr %.loc17_24.1.temp), !dbg !24 -// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %.loc17_24.1.temp), !dbg !25 +// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %.loc17_24.1.temp), !dbg !25 // CHECK:STDOUT: ret void, !dbg !26 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CPassValueExpr.Main(ptr %y) #0 !dbg !27 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %y), !dbg !33 +// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %y), !dbg !33 // CHECK:STDOUT: ret void, !dbg !34 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/pointer.carbon b/toolchain/lower/testdata/interop/cpp/pointer.carbon index 3b340a725505..eab466cb2aa5 100644 --- a/toolchain/lower/testdata/interop/cpp/pointer.carbon +++ b/toolchain/lower/testdata/interop/cpp/pointer.carbon @@ -128,12 +128,12 @@ fn Convert() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CPassPtrWithThunk.Main(ptr %p) #0 !dbg !24 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr %p), !dbg !27 +// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr %p), !dbg !27 // CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr noundef %0) #2 { +// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr noundef %0) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !29 @@ -145,12 +145,12 @@ fn Convert() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define ptr @_CReturnPtrWithThunk.Main() #0 !dbg !32 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk0(), !dbg !33 +// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk.(), !dbg !33 // CHECK:STDOUT: ret ptr %ReturnPtrWithThunk__carbon_thunk.call, !dbg !34 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk0() #2 { +// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk.() #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %call = call noundef ptr @_Z18ReturnPtrWithThunki(i32 noundef 0) // CHECK:STDOUT: ret ptr %call @@ -264,13 +264,13 @@ fn Convert() { // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc35_24.2.temp), !dbg !44 // CHECK:STDOUT: store ptr %U.as_type.as.ImplicitAs.impl.Convert.call, ptr %.loc35_24.2.temp, align 8, !dbg !44 // CHECK:STDOUT: %.loc35_24.4 = load ptr, ptr %.loc35_24.2.temp, align 8, !dbg !44 -// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr %.loc35_24.4), !dbg !45 +// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr %.loc35_24.4), !dbg !45 // CHECK:STDOUT: call void @"_COp.f6ed00b54444c4a3:core.Destroy.Core"(ptr %.loc35_24.2.temp), !dbg !44 // CHECK:STDOUT: ret void, !dbg !46 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr noundef %0) #2 { +// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr noundef %0) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !47 @@ -282,12 +282,12 @@ fn Convert() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define ptr @_CReturnPtrWithThunk.Main() #0 !dbg !50 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk0(), !dbg !51 +// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk.(), !dbg !51 // CHECK:STDOUT: ret ptr %ReturnPtrWithThunk__carbon_thunk.call, !dbg !52 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk0() #2 { +// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk.() #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %call = call noundef ptr @_Z18ReturnPtrWithThunki(i32 noundef 0) // CHECK:STDOUT: ret ptr %call diff --git a/toolchain/lower/testdata/interop/cpp/reference.carbon b/toolchain/lower/testdata/interop/cpp/reference.carbon index 393bb2f6e0ea..7cb67c4ca083 100644 --- a/toolchain/lower/testdata/interop/cpp/reference.carbon +++ b/toolchain/lower/testdata/interop/cpp/reference.carbon @@ -148,18 +148,18 @@ fn GetRefs() { // CHECK:STDOUT: call void @_Z8TakeCRefR1C(ptr %c.var), !dbg !19 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.1), !dbg !15 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %_.var.1, ptr align 1 @C.val.loc19_20, i64 0, i1 false), !dbg !15 -// CHECK:STDOUT: call void @_Z9TakeCRRefO1C.carbon_thunk(ptr %_.var.1), !dbg !20 -// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C.carbon_thunk(ptr %c.var), !dbg !21 +// CHECK:STDOUT: call void @_Z9TakeCRRefO1C.carbon_thunk.v(ptr %_.var.1), !dbg !20 +// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C.carbon_thunk._(ptr %c.var), !dbg !21 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !16 // CHECK:STDOUT: store i32 poison, ptr %n.var, align 4, !dbg !16 // CHECK:STDOUT: call void @_Z10TakeIntRefRi(ptr %n.var), !dbg !22 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.2), !dbg !17 // CHECK:STDOUT: store i32 42, ptr %_.var.2, align 4, !dbg !17 -// CHECK:STDOUT: call void @_Z11TakeIntRRefOi.carbon_thunk(ptr %_.var.2), !dbg !23 +// CHECK:STDOUT: call void @_Z11TakeIntRRefOi.carbon_thunk.v(ptr %_.var.2), !dbg !23 // CHECK:STDOUT: %.loc25_23.1 = load i32, ptr %n.var, align 4, !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc25_23.2.temp), !dbg !18 // CHECK:STDOUT: store i32 %.loc25_23.1, ptr %.loc25_23.2.temp, align 4, !dbg !18 -// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi.carbon_thunk(ptr %.loc25_23.2.temp), !dbg !24 +// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi.carbon_thunk._(ptr %.loc25_23.2.temp), !dbg !24 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %.loc25_23.2.temp), !dbg !18 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %_.var.2), !dbg !17 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %n.var), !dbg !16 @@ -167,7 +167,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !26 @@ -178,14 +178,14 @@ fn GetRefs() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret({}) %return) #2 !dbg !29 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !33 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !33 // CHECK:STDOUT: ret void, !dbg !33 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: declare void @_Z8TakeCRefR1C(ptr noundef nonnull align 1 dereferenceable(1)) #3 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z9TakeCRRefO1C.carbon_thunk(ptr noundef %0) #4 { +// CHECK:STDOUT: define internal void @_Z9TakeCRRefO1C.carbon_thunk.v(ptr noundef %0) #4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !26 @@ -195,7 +195,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C.carbon_thunk(ptr noundef %0) #4 { +// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C.carbon_thunk._(ptr noundef %0) #4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !26 @@ -207,7 +207,7 @@ fn GetRefs() { // CHECK:STDOUT: declare void @_Z10TakeIntRefRi(ptr noundef nonnull align 4 dereferenceable(4)) #3 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi.carbon_thunk(ptr noundef %0) #4 { +// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi.carbon_thunk.v(ptr noundef %0) #4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !34 @@ -217,7 +217,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi.carbon_thunk(ptr noundef %0) #4 { +// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi.carbon_thunk._(ptr noundef %0) #4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !34 @@ -335,20 +335,20 @@ fn GetRefs() { // CHECK:STDOUT: %.loc26_23.2.temp = alloca i32, align 4, !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !14 // CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.93349b0fe912a29b"(ptr %c.var), !dbg !14 -// CHECK:STDOUT: call void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk1(ptr %c.var), !dbg !19 +// CHECK:STDOUT: call void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk.r(ptr %c.var), !dbg !19 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_18.2.temp), !dbg !15 -// CHECK:STDOUT: call void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk1(ptr @C.val.loc20_20.3), !dbg !20 -// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk1(ptr %c.var), !dbg !21 +// CHECK:STDOUT: call void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk._(ptr @C.val.loc20_20.3), !dbg !20 +// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk._(ptr %c.var), !dbg !21 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !16 // CHECK:STDOUT: store i32 poison, ptr %n.var, align 4, !dbg !16 -// CHECK:STDOUT: call void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk1(ptr %n.var), !dbg !22 +// CHECK:STDOUT: call void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk.r(ptr %n.var), !dbg !22 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !17 // CHECK:STDOUT: store i32 42, ptr %_.var, align 4, !dbg !17 -// CHECK:STDOUT: call void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk1(ptr %_.var), !dbg !23 +// CHECK:STDOUT: call void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk.v(ptr %_.var), !dbg !23 // CHECK:STDOUT: %.loc26_23.1 = load i32, ptr %n.var, align 4, !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc26_23.2.temp), !dbg !18 // CHECK:STDOUT: store i32 %.loc26_23.1, ptr %.loc26_23.2.temp, align 4, !dbg !18 -// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk1(ptr %.loc26_23.2.temp), !dbg !24 +// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk._(ptr %.loc26_23.2.temp), !dbg !24 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %.loc26_23.2.temp), !dbg !18 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %_.var), !dbg !17 // CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %n.var), !dbg !16 @@ -356,7 +356,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable -// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !26 @@ -367,12 +367,12 @@ fn GetRefs() { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret({}) %return) #2 !dbg !29 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !33 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !33 // CHECK:STDOUT: ret void, !dbg !33 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk1(ptr noundef nonnull align 1 dereferenceable(1) %0) #3 { +// CHECK:STDOUT: define internal void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk.r(ptr noundef nonnull align 1 dereferenceable(1) %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -383,7 +383,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk1(ptr noundef %0) #3 { +// CHECK:STDOUT: define internal void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk._(ptr noundef %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -394,7 +394,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk1(ptr noundef %0) #3 { +// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk._(ptr noundef %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -405,7 +405,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk1(ptr noundef nonnull align 4 dereferenceable(4) %0) #3 { +// CHECK:STDOUT: define internal void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk.r(ptr noundef nonnull align 4 dereferenceable(4) %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -416,7 +416,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk1(ptr noundef %0) #3 { +// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk.v(ptr noundef %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -427,7 +427,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk1(ptr noundef %0) #3 { +// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk._(ptr noundef %0) #3 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 @@ -595,17 +595,17 @@ fn GetRefs() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CGetRefs.Main() #0 !dbg !11 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0(), !dbg !14 -// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0(), !dbg !15 -// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0(), !dbg !16 -// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0(), !dbg !17 -// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0(), !dbg !18 -// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0(), !dbg !19 +// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk.(), !dbg !14 +// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk.(), !dbg !15 +// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk.(), !dbg !16 +// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk.(), !dbg !17 +// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk.(), !dbg !18 +// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk.(), !dbg !19 // CHECK:STDOUT: ret void, !dbg !20 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk() @@ -613,7 +613,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk() @@ -621,7 +621,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk() @@ -629,7 +629,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk() @@ -637,7 +637,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk() @@ -645,7 +645,7 @@ fn GetRefs() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0() #1 { +// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk.() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1 // CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk() diff --git a/toolchain/lower/testdata/interop/cpp/return.carbon b/toolchain/lower/testdata/interop/cpp/return.carbon index 69d8f449ed34..5a0204c7c7c9 100644 --- a/toolchain/lower/testdata/interop/cpp/return.carbon +++ b/toolchain/lower/testdata/interop/cpp/return.carbon @@ -122,13 +122,13 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc6_40.1.temp = alloca i8, align 1, !dbg !15 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_40.1.temp), !dbg !15 -// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %.loc6_40.1.temp), !dbg !15 +// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %.loc6_40.1.temp), !dbg !15 // CHECK:STDOUT: %0 = load i8, ptr %.loc6_40.1.temp, align 1, !dbg !16 // CHECK:STDOUT: ret i8 %0, !dbg !16 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z8ReturnU8v.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z8ReturnU8v.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 @@ -143,13 +143,13 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc7_43.1.temp = alloca i16, align 2, !dbg !25 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_43.1.temp), !dbg !25 -// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %.loc7_43.1.temp), !dbg !25 +// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %.loc7_43.1.temp), !dbg !25 // CHECK:STDOUT: %0 = load i16, ptr %.loc7_43.1.temp, align 2, !dbg !26 // CHECK:STDOUT: ret i16 %0, !dbg !26 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z9ReturnU16v.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z9ReturnU16v.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !27 @@ -182,13 +182,13 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc11_40.1.temp = alloca i8, align 1, !dbg !47 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc11_40.1.temp), !dbg !47 -// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %.loc11_40.1.temp), !dbg !47 +// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %.loc11_40.1.temp), !dbg !47 // CHECK:STDOUT: %0 = load i8, ptr %.loc11_40.1.temp, align 1, !dbg !48 // CHECK:STDOUT: ret i8 %0, !dbg !48 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z8ReturnI8v.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z8ReturnI8v.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 @@ -203,13 +203,13 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc12_43.1.temp = alloca i16, align 2, !dbg !53 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_43.1.temp), !dbg !53 -// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %.loc12_43.1.temp), !dbg !53 +// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %.loc12_43.1.temp), !dbg !53 // CHECK:STDOUT: %0 = load i16, ptr %.loc12_43.1.temp, align 2, !dbg !54 // CHECK:STDOUT: ret i16 %0, !dbg !54 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z9ReturnI16v.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z9ReturnI16v.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !27 @@ -247,18 +247,18 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: %.loc24_32.1.temp = alloca i8, align 1, !dbg !72 // CHECK:STDOUT: %.loc25_35.1.temp = alloca i16, align 2, !dbg !73 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_32.1.temp), !dbg !70 -// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %.loc19_32.1.temp), !dbg !70 +// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %.loc19_32.1.temp), !dbg !70 // CHECK:STDOUT: %.loc19_32.4 = load i8, ptr %.loc19_32.1.temp, align 1, !dbg !70 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_35.1.temp), !dbg !71 -// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %.loc20_35.1.temp), !dbg !71 +// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %.loc20_35.1.temp), !dbg !71 // CHECK:STDOUT: %.loc20_35.4 = load i16, ptr %.loc20_35.1.temp, align 2, !dbg !71 // CHECK:STDOUT: %ReturnU32.call = call i32 @_Z9ReturnU32v(), !dbg !74 // CHECK:STDOUT: %ReturnU64.call = call i64 @_Z9ReturnU64v(), !dbg !75 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_32.1.temp), !dbg !72 -// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %.loc24_32.1.temp), !dbg !72 +// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %.loc24_32.1.temp), !dbg !72 // CHECK:STDOUT: %.loc24_32.4 = load i8, ptr %.loc24_32.1.temp, align 1, !dbg !72 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc25_35.1.temp), !dbg !73 -// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %.loc25_35.1.temp), !dbg !73 +// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %.loc25_35.1.temp), !dbg !73 // CHECK:STDOUT: %.loc25_35.4 = load i16, ptr %.loc25_35.1.temp, align 2, !dbg !73 // CHECK:STDOUT: %ReturnI32.call = call i32 @_Z9ReturnI32v(), !dbg !76 // CHECK:STDOUT: %ReturnI64.call = call i64 @_Z9ReturnI64v(), !dbg !77 @@ -306,9 +306,9 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: %my_i32.var = alloca i32, align 4, !dbg !111 // CHECK:STDOUT: %my_i64.var = alloca i64, align 8, !dbg !112 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u8.var), !dbg !105 -// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %my_u8.var), !dbg !113 +// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %my_u8.var), !dbg !113 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u16.var), !dbg !106 -// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %my_u16.var), !dbg !114 +// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %my_u16.var), !dbg !114 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u32.var), !dbg !107 // CHECK:STDOUT: %ReturnU32.call = call i32 @_Z9ReturnU32v(), !dbg !115 // CHECK:STDOUT: store i32 %ReturnU32.call, ptr %my_u32.var, align 4, !dbg !107 @@ -316,9 +316,9 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: %ReturnU64.call = call i64 @_Z9ReturnU64v(), !dbg !116 // CHECK:STDOUT: store i64 %ReturnU64.call, ptr %my_u64.var, align 8, !dbg !108 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i8.var), !dbg !109 -// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %my_i8.var), !dbg !117 +// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %my_i8.var), !dbg !117 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i16.var), !dbg !110 -// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %my_i16.var), !dbg !118 +// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %my_i16.var), !dbg !118 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i32.var), !dbg !111 // CHECK:STDOUT: %ReturnI32.call = call i32 @_Z9ReturnI32v(), !dbg !119 // CHECK:STDOUT: store i32 %ReturnI32.call, ptr %my_i32.var, align 4, !dbg !111 @@ -557,12 +557,12 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CGetX.Main(ptr sret([16 x i8]) %return) #0 !dbg !11 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %return), !dbg !15 +// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %return), !dbg !15 // CHECK:STDOUT: ret void, !dbg !16 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z4Makev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z4Makev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 @@ -576,7 +576,7 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc9_27.1.temp = alloca [16 x i8], align 1, !dbg !23 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_27.1.temp), !dbg !23 -// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %.loc9_27.1.temp), !dbg !23 +// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %.loc9_27.1.temp), !dbg !23 // CHECK:STDOUT: call void @_ZN1XD1Ev(ptr %.loc9_27.1.temp), !dbg !23 // CHECK:STDOUT: ret void, !dbg !24 // CHECK:STDOUT: } @@ -589,7 +589,7 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: entry: // CHECK:STDOUT: %_.var = alloca [16 x i8], align 1, !dbg !26 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !26 -// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %_.var), !dbg !27 +// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %_.var), !dbg !27 // CHECK:STDOUT: call void @_ZN1XD1Ev(ptr %_.var), !dbg !26 // CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } @@ -652,12 +652,12 @@ fn Call(x: Cpp.D) -> Cpp.C { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CCall.Main(ptr sret({}) %return, ptr %x) #0 !dbg !11 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Z1f1D.carbon_thunk(ptr %x, ptr %return), !dbg !17 +// CHECK:STDOUT: call void @_Z1f1D.carbon_thunk._(ptr %x, ptr %return), !dbg !17 // CHECK:STDOUT: ret void, !dbg !18 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z1f1D.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_Z1f1D.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 diff --git a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon index 859c43f9606c..828f2cab777d 100644 --- a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon +++ b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon @@ -178,7 +178,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: store ptr @array.loc13_50.15, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !34 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.end = getelementptr inbounds nuw [16 x i8], ptr %.loc18_36.2.temp, i32 0, i32 8, !dbg !34 // CHECK:STDOUT: store ptr getelementptr inbounds ([3 x i32], ptr @array.loc13_50.15, i32 1), ptr %initializer_list.initializer_list.call.init_list.end, align 8, !dbg !34 -// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33 +// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33 // CHECK:STDOUT: call void @_CWithinLifetime.Main(), !dbg !35 // CHECK:STDOUT: call void @"_COp.bfd302cd235977c4:core.Destroy.Core"(ptr @array), !dbg !34 // CHECK:STDOUT: call void @_ZN11vector_likeD2Ev(ptr %_.var), !dbg !33 @@ -186,7 +186,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr noundef %list, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr noundef %list, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %list.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -221,11 +221,11 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !46 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !47 // CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !47 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !47 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.18.array.index), !dbg !47 // CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !47 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !47 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.16.array.index), !dbg !47 // CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !47 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !47 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.15.array.index), !dbg !47 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !46 // CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !46 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.end = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 8, !dbg !46 @@ -237,7 +237,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !50 @@ -291,7 +291,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple, { 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple., { 2, 1, 0 } // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } @@ -427,7 +427,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: store ptr @array.loc13_50.15, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !34 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.size = getelementptr inbounds nuw [16 x i8], ptr %.loc18_36.2.temp, i32 0, i32 8, !dbg !34 // CHECK:STDOUT: store i64 3, ptr %initializer_list.initializer_list.call.init_list.size, align 8, !dbg !34 -// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33 +// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33 // CHECK:STDOUT: call void @_CWithinLifetime.Main(), !dbg !35 // CHECK:STDOUT: call void @"_COp.bfd302cd235977c4:core.Destroy.Core"(ptr @array), !dbg !34 // CHECK:STDOUT: call void @_ZN11vector_likeD2Ev(ptr %_.var), !dbg !33 @@ -435,7 +435,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr noundef %list, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr noundef %list, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %list.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -470,11 +470,11 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !48 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !49 // CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !49 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !49 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.18.array.index), !dbg !49 // CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !49 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !49 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.16.array.index), !dbg !49 // CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !49 -// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !49 +// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.15.array.index), !dbg !49 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !48 // CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !48 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.size = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 8, !dbg !48 @@ -485,7 +485,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !52 @@ -539,7 +539,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple, { 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple., { 2, 1, 0 } // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } diff --git a/toolchain/lower/testdata/interop/cpp/template.carbon b/toolchain/lower/testdata/interop/cpp/template.carbon index 0c0c2e569373..da13de41b9ad 100644 --- a/toolchain/lower/testdata/interop/cpp/template.carbon +++ b/toolchain/lower/testdata/interop/cpp/template.carbon @@ -126,12 +126,12 @@ fn Call3() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CPassClass.Main(ptr sret({}) %return, ptr %a) #0 !dbg !24 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_Z8identityI5ClassET_S1_.carbon_thunk(ptr %a, ptr %return), !dbg !30 +// CHECK:STDOUT: call void @_Z8identityI5ClassET_S1_.carbon_thunk._(ptr %a, ptr %return), !dbg !30 // CHECK:STDOUT: ret void, !dbg !31 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z8identityI5ClassET_S1_.carbon_thunk(ptr noundef %x, ptr noundef %return) #2 { +// CHECK:STDOUT: define internal void @_Z8identityI5ClassET_S1_.carbon_thunk._(ptr noundef %x, ptr noundef %return) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -271,12 +271,12 @@ fn Call3() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc12_12.2.temp = alloca {}, align 8, !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_12.2.temp), !dbg !14 -// CHECK:STDOUT: call void @_Z3fooIJEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3), !dbg !15 +// CHECK:STDOUT: call void @_Z3fooIJEEv1XDpT_.carbon_thunk._(ptr @X.val.loc12_14.3), !dbg !15 // CHECK:STDOUT: ret void, !dbg !16 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z3fooIJEEv1XDpT_.carbon_thunk(ptr noundef %0) #1 { +// CHECK:STDOUT: define internal void @_Z3fooIJEEv1XDpT_.carbon_thunk._(ptr noundef %0) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.X, align 1 @@ -291,12 +291,12 @@ fn Call3() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc18_12.2.temp = alloca {}, align 8, !dbg !21 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_12.2.temp), !dbg !21 -// CHECK:STDOUT: call void @_Z3fooIJiEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3, i32 2), !dbg !22 +// CHECK:STDOUT: call void @_Z3fooIJiEEv1XDpT_.carbon_thunk.__(ptr @X.val.loc12_14.3, i32 2), !dbg !22 // CHECK:STDOUT: ret void, !dbg !23 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z3fooIJiEEv1XDpT_.carbon_thunk(ptr noundef %0, i32 noundef %1) #1 { +// CHECK:STDOUT: define internal void @_Z3fooIJiEEv1XDpT_.carbon_thunk.__(ptr noundef %0, i32 noundef %1) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 @@ -314,12 +314,12 @@ fn Call3() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc24_12.2.temp = alloca {}, align 8, !dbg !25 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_12.2.temp), !dbg !25 -// CHECK:STDOUT: call void @_Z3fooIJiiEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3, i32 2, i32 3), !dbg !26 +// CHECK:STDOUT: call void @_Z3fooIJiiEEv1XDpT_.carbon_thunk.___(ptr @X.val.loc12_14.3, i32 2, i32 3), !dbg !26 // CHECK:STDOUT: ret void, !dbg !27 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_Z3fooIJiiEEv1XDpT_.carbon_thunk(ptr noundef %0, i32 noundef %1, i32 noundef %2) #1 { +// CHECK:STDOUT: define internal void @_Z3fooIJiiEEv1XDpT_.carbon_thunk.___(ptr noundef %0, i32 noundef %1, i32 noundef %2) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %.addr1 = alloca i32, align 4 diff --git a/toolchain/lower/testdata/interop/cpp/thunks.carbon b/toolchain/lower/testdata/interop/cpp/thunks.carbon index 6c5b25772758..51e7327f5d2d 100644 --- a/toolchain/lower/testdata/interop/cpp/thunks.carbon +++ b/toolchain/lower/testdata/interop/cpp/thunks.carbon @@ -43,12 +43,12 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: %.loc9_34.1.temp = alloca [1 x i8], align 1, !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n2.var), !dbg !17 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_34.1.temp), !dbg !18 -// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr %n, ptr %n2.var), !dbg !18 +// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr %n, ptr %n2.var), !dbg !18 // CHECK:STDOUT: ret void, !dbg !19 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 @@ -63,7 +63,7 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind // CHECK:STDOUT: define void @"_COp:thunk:Copy.fdeb6dbda014bd1f.Core:NeedThunk.Cpp"(ptr sret([1 x i8]) %return, ptr %self) #2 !dbg !23 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr %self, ptr %return), !dbg !29 +// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr %self, ptr %return), !dbg !29 // CHECK:STDOUT: ret void, !dbg !29 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/virtual_base.carbon b/toolchain/lower/testdata/interop/cpp/virtual_base.carbon index 71eb3bed3f48..8543a080f5cc 100644 --- a/toolchain/lower/testdata/interop/cpp/virtual_base.carbon +++ b/toolchain/lower/testdata/interop/cpp/virtual_base.carbon @@ -113,12 +113,12 @@ fn AccessD(d: Cpp.D) -> i32 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %_.var = alloca [40 x i8], align 1, !dbg !14 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !14 -// CHECK:STDOUT: call void @_ZN1DC1Ev.carbon_thunk(ptr %_.var), !dbg !15 +// CHECK:STDOUT: call void @_ZN1DC1Ev.carbon_thunk.(ptr %_.var), !dbg !15 // CHECK:STDOUT: ret void, !dbg !16 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal void @_ZN1DC1Ev.carbon_thunk(ptr noundef %return) #1 { +// CHECK:STDOUT: define internal void @_ZN1DC1Ev.carbon_thunk.(ptr noundef %return) #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17 diff --git a/toolchain/sem_ir/clang_decl.cpp b/toolchain/sem_ir/clang_decl.cpp index dcdf591a2643..8752e0740d57 100644 --- a/toolchain/sem_ir/clang_decl.cpp +++ b/toolchain/sem_ir/clang_decl.cpp @@ -11,6 +11,50 @@ namespace Carbon::SemIR { +auto ClangDeclSignature::Print(llvm::raw_ostream& out) const -> void { + out << "{kind: "; + switch (kind) { + case Normal: + out << "normal"; + break; + case TuplePattern: + out << "tuple"; + break; + } + out << ", num_params: " << num_params; + + auto print_mode = [&](PassingMode mode) { + switch (mode) { + case PassingMode::ByValue: + out << "value"; + break; + case PassingMode::ByVar: + out << "var"; + break; + case PassingMode::ByRef: + out << "ref"; + break; + } + }; + + if (!passing_modes.empty() && llvm::any_of(passing_modes, [](auto mode) { + return mode != PassingMode::ByVar; + })) { + out << ", modes: ["; + llvm::ListSeparator sep; + for (auto mode : passing_modes) { + out << sep; + print_mode(mode); + } + out << "]"; + } + if (self_passing_mode != PassingMode::ByRef) { + out << ", self_mode: "; + print_mode(self_passing_mode); + } + out << "}"; +} + auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void { RawStringOstream decl_stream; auto policy = decl->getASTContext().getPrintingPolicy(); @@ -21,20 +65,11 @@ auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void { decl->print(decl_stream, policy); } - if (signature.num_params != -1) { - out << "{decl: \"" << FormatEscaped(decl_stream.TakeStr()) << "\", kind: "; - switch (signature.kind) { - case ClangDeclKey::Signature::Normal: - out << "normal"; - break; - case ClangDeclKey::Signature::TuplePattern: - out << "tuple"; - break; - } - out << ", num_params: " << signature.num_params << "}"; - } else { - out << "\"" << FormatEscaped(decl_stream.TakeStr()) << "\""; + out << "{decl: \"" << FormatEscaped(decl_stream.TakeStr()) << "\""; + if (signature_id != ClangDeclSignatureId::None) { + out << ", clang_decl_signature_id: " << signature_id; } + out << "}"; } auto ClangDecl::Print(llvm::raw_ostream& out) const -> void { diff --git a/toolchain/sem_ir/clang_decl.h b/toolchain/sem_ir/clang_decl.h index 4a3a99ec9ff1..d9920ba47a74 100644 --- a/toolchain/sem_ir/clang_decl.h +++ b/toolchain/sem_ir/clang_decl.h @@ -15,6 +15,95 @@ namespace Carbon::SemIR { +// Information about how to form the Carbon function signature from the Clang +// function declaration. +struct ClangDeclSignature : public Printable { + // A passing mode for a parameter in a C++ function signature. + enum class PassingMode : int8_t { + // This parameter is passed by Carbon value. This is used for a C++ + // non-reference parameter that would be copied at the call site, and for a + // C++ const reference parameter (either lvalue or rvalue reference). + ByValue, + // This parameter is passed as a Carbon var parameter. This is used for a + // C++ non-reference parameter that would be moved or constructed in-place + // at the call site, or for a C++ non-const rvalue reference parameter. + ByVar, + // This parameter is passed as a Carbon ref parameter. This is used for a + // C++ non-const lvalue reference parameter. + ByRef, + }; + + enum Kind : int8_t { + // A normal function signature: each C++ parameter maps into a Carbon + // parameter. + Normal, + // A function signature taking a tuple pattern that contains the C++ + // parameters. This is used when importing a constructor that is used for + // list initialization from a Carbon tuple. + TuplePattern, + }; + + // The kind of function signature being imported. + Kind kind = Normal; + + // The number of parameters to import. This can be less than the number of + // parameters in the Clang declaration if the Clang declaration has default + // arguments. Excludes the (implicit or explicit) object parameter, if there + // is one. + // TODO: Remove in favor of `passing_modes`. + int32_t num_params = -1; + + // The passing mode for the (implicit or explicit) object parameter, if there + // is one. Otherwise PassingMode::ByRef. + PassingMode self_passing_mode = PassingMode::ByRef; + + // The passing mode for each parameter. Excludes the (implicit or explicit) + // object parameter, if there is one. This must be the same size as + // `num_params`. + // TODO: Generalize this to be parameter info, not just passing mode. + llvm::SmallVector passing_modes; + + // Convenience function to make a fixed signature. + static auto Make( + std::initializer_list modes, + Kind kind = Normal, PassingMode self_passing_mode = PassingMode::ByRef) + -> ClangDeclSignature { + ClangDeclSignature signature; + signature.kind = kind; + signature.num_params = static_cast(modes.size()); + signature.self_passing_mode = self_passing_mode; + signature.passing_modes.assign(modes.begin(), modes.end()); + return signature; + } + + // Returns the passing mode for the i-th parameter. + auto GetPassingMode(int32_t i) const -> PassingMode { + return i < static_cast(passing_modes.size()) ? passing_modes[i] + : PassingMode::ByVar; + } + + auto Print(llvm::raw_ostream& out) const -> void; + + auto operator==(const ClangDeclSignature& rhs) const -> bool { + return kind == rhs.kind && num_params == rhs.num_params && + passing_modes == rhs.passing_modes && + self_passing_mode == rhs.self_passing_mode; + } + + // Hashing for ClangDeclSignature. + friend auto CarbonHashValue(const ClangDeclSignature& value, uint64_t seed) + -> HashCode { + HashCode code = + HashValue(std::tuple{value.kind, value.num_params, + static_cast(value.self_passing_mode)}, + seed); + for (auto mode : value.passing_modes) { + code = HashValue(static_cast(mode), static_cast(code)); + } + return code; + } +}; + // A key describing a Clang declaration that can be looked up in the value // store. This is a `clang::Decl*` pointing to a canonical declaration, plus any // other information that affects the mapping into Carbon. Currently this @@ -24,29 +113,6 @@ namespace Carbon::SemIR { // A canonical declaration pointer is used so that we can perform direct address // comparisons and hash this structure based on its contents. struct ClangDeclKey : public Printable { - // Information about how to form the Carbon function signature from the Clang - // function declaration. - struct Signature { - enum Kind : int8_t { - // A normal function signature: each C++ parameter maps into a Carbon - // parameter. - Normal, - // A function signature taking a tuple pattern that contains the C++ - // parameters. This is used when importing a constructor that is used for - // list initialization from a Carbon tuple. - TuplePattern, - }; - // The kind of function signature being imported. - Kind kind = Normal; - // The number of parameters to import. This can be less than the number of - // parameters in the Clang declaration if the Clang declaration has default - // arguments. Excludes the implicit object parameter, if there is one. - int32_t num_params = -1; - - friend auto operator==(const Signature& lhs, const Signature& rhs) - -> bool = default; - }; - // For declaration classes that are unrelated to FunctionDecl, no parameter // count is expected. template @@ -54,35 +120,33 @@ struct ClangDeclKey : public Printable { !std::derived_from && !std::derived_from) explicit ClangDeclKey(DeclT* decl) - : ClangDeclKey(decl, Signature{}, UncheckedTag()) {} + : ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag()) {} // For declaration classes that are derived from FunctionDecl, a parameter // count is required. - static auto ForFunctionDecl(clang::FunctionDecl* decl, Signature signature) + static auto ForFunctionDecl(clang::FunctionDecl* decl, + ClangDeclSignatureId signature_id) -> ClangDeclKey { - return ClangDeclKey(decl, signature, UncheckedTag()); + return ClangDeclKey(decl, signature_id, UncheckedTag()); } // Factory function for clang declaration that is dynamically known to not be // a function declaration. static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey { CARBON_CHECK(!isa(decl)); - return ClangDeclKey(decl, Signature{}, UncheckedTag()); + return ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag()); } auto Print(llvm::raw_ostream& out) const -> void; auto operator==(const ClangDeclKey& rhs) const -> bool { - return decl == rhs.decl && signature == rhs.signature; + return decl == rhs.decl && signature_id == rhs.signature_id; } // Hashing for ClangDecl. See common/hashing.h. friend auto CarbonHashValue(const ClangDeclKey& value, uint64_t seed) -> HashCode { - // Manual hashing support is required because `Signature` has padding. - return HashValue(std::tuple{value.decl, value.signature.num_params, - value.signature.kind}, - seed); + return HashValue(std::tuple{value.decl, value.signature_id}, seed); } // The Clang declaration pointing to the Clang AST. @@ -90,16 +154,17 @@ struct ClangDeclKey : public Printable { // `clang::LazyDeclPtr`. clang::Decl* decl; - // The parameters to import for a function declaration. Otherwise a - // default-constructed value. - Signature signature; + // The parameters to import for a function declaration. Otherwise + // ClangDeclSignatureId::None. + ClangDeclSignatureId signature_id; private: struct UncheckedTag { explicit UncheckedTag() = default; }; - ClangDeclKey(clang::Decl* decl, Signature signature, UncheckedTag /*_*/) - : decl(decl->getCanonicalDecl()), signature(signature) {} + ClangDeclKey(clang::Decl* decl, ClangDeclSignatureId signature_id, + UncheckedTag /*_*/) + : decl(decl->getCanonicalDecl()), signature_id(signature_id) {} }; // A Clang declaration mapped to a Carbon instruction. @@ -151,6 +216,11 @@ class ClangDeclStore { Map inst_id_to_clang_decl_id_; }; +// A ClangDeclSignature mapped to an ID. +using ClangDeclSignatureStore = + CanonicalValueStore, ClangDeclSignature>; + } // namespace Carbon::SemIR #endif // CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_ diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index aa6b89ab0548..47460acd1d98 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -56,6 +56,7 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id, // `ImportIRId::{ApiForImpl,Cpp}`. import_irs_(check_ir_id, 2), clang_decls_(check_ir_id), + clang_decl_signatures_(check_ir_id), // The `+1` prevents adding a tag to the global `NameSpace::PackageInstId` // instruction. It's not a "singleton" instruction, but it's a unique // instruction id that comes right after the singletons. @@ -143,42 +144,43 @@ auto File::OutputYaml(bool include_singletons) const -> Yaml::OutputMapping { return Yaml::OutputMapping([this, include_singletons]( Yaml::OutputMapping::Map map) { map.Add("filename", filename_); - map.Add("sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { - map.Add("names", names().OutputYaml()); - map.Add("import_irs", import_irs_.OutputYaml()); - map.Add("import_ir_insts", import_ir_insts_.OutputYaml()); - map.Add("clang_decls", clang_decls_.OutputYaml()); - map.Add("name_scopes", name_scopes_.OutputYaml()); - map.Add("entity_names", entity_names_.OutputYaml()); - map.Add("cpp_global_vars", cpp_global_vars_.OutputYaml()); - map.Add("functions", functions_.OutputYaml()); - map.Add("classes", classes_.OutputYaml()); - map.Add("interfaces", interfaces_.OutputYaml()); - map.Add("associated_constants", - associated_constants_.OutputYaml()); - map.Add("impls", impls_.OutputYaml()); - map.Add("generics", generics_.OutputYaml()); - map.Add("specifics", specifics_.OutputYaml()); - map.Add("specific_interfaces", specific_interfaces_.OutputYaml()); - map.Add("struct_type_fields", struct_type_fields_.OutputYaml()); - map.Add("types", types_.OutputYaml()); - map.Add("facet_types", facet_types_.OutputYaml()); - map.Add("insts", - Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { - for (auto [id, inst] : insts_.enumerate()) { - inst.CacheBundleDebugKinds(bundles_); - if (!include_singletons && IsSingletonInstId(id)) { - continue; - } - map.Add(PrintToString(id), Yaml::OutputScalar(inst)); - } - })); - map.Add("bundles", bundles_.OutputYaml()); - map.Add("constant_values", - constant_values_.OutputYaml(include_singletons)); - map.Add("inst_blocks", inst_blocks_.OutputYaml()); - map.Add("value_stores", value_stores_->OutputYaml()); - })); + map.Add( + "sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + map.Add("names", names().OutputYaml()); + map.Add("import_irs", import_irs_.OutputYaml()); + map.Add("import_ir_insts", import_ir_insts_.OutputYaml()); + map.Add("clang_decls", clang_decls_.OutputYaml()); + map.Add("clang_decl_signatures", clang_decl_signatures_.OutputYaml()); + map.Add("name_scopes", name_scopes_.OutputYaml()); + map.Add("entity_names", entity_names_.OutputYaml()); + map.Add("cpp_global_vars", cpp_global_vars_.OutputYaml()); + map.Add("functions", functions_.OutputYaml()); + map.Add("classes", classes_.OutputYaml()); + map.Add("interfaces", interfaces_.OutputYaml()); + map.Add("associated_constants", associated_constants_.OutputYaml()); + map.Add("impls", impls_.OutputYaml()); + map.Add("generics", generics_.OutputYaml()); + map.Add("specifics", specifics_.OutputYaml()); + map.Add("specific_interfaces", specific_interfaces_.OutputYaml()); + map.Add("struct_type_fields", struct_type_fields_.OutputYaml()); + map.Add("types", types_.OutputYaml()); + map.Add("facet_types", facet_types_.OutputYaml()); + map.Add("insts", + Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { + for (auto [id, inst] : insts_.enumerate()) { + inst.CacheBundleDebugKinds(bundles_); + if (!include_singletons && IsSingletonInstId(id)) { + continue; + } + map.Add(PrintToString(id), Yaml::OutputScalar(inst)); + } + })); + map.Add("bundles", bundles_.OutputYaml()); + map.Add("constant_values", + constant_values_.OutputYaml(include_singletons)); + map.Add("inst_blocks", inst_blocks_.OutputYaml()); + map.Add("value_stores", value_stores_->OutputYaml()); + })); }); } @@ -200,6 +202,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const mem_usage.Collect(MemUsage::ConcatLabel(label, "import_ir_insts_"), import_ir_insts_); mem_usage.Collect(MemUsage::ConcatLabel(label, "clang_decls_"), clang_decls_); + mem_usage.Collect(MemUsage::ConcatLabel(label, "clang_decl_signatures_"), + clang_decl_signatures_); mem_usage.Collect(MemUsage::ConcatLabel(label, "struct_type_fields_"), struct_type_fields_); mem_usage.Collect(MemUsage::ConcatLabel(label, "insts_"), insts_); diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index 81541b3b0960..d14ac487d83b 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -238,6 +238,12 @@ class File : public Printable { auto set_cpp_file(std::unique_ptr cpp_file) -> void; auto clang_decls() -> ClangDeclStore& { return clang_decls_; } auto clang_decls() const -> const ClangDeclStore& { return clang_decls_; } + auto clang_decl_signatures() -> ClangDeclSignatureStore& { + return clang_decl_signatures_; + } + auto clang_decl_signatures() const -> const ClangDeclSignatureStore& { + return clang_decl_signatures_; + } auto names() const -> NameStoreWrapper { return NameStoreWrapper(&identifiers()); } @@ -393,6 +399,9 @@ class File : public Printable { // not add multiple entries with the same `decl` and different `inst_id`. ClangDeclStore clang_decls_ = ClangDeclStore(check_ir_id()); + // Storage for function signatures used in C++ interop. + ClangDeclSignatureStore clang_decl_signatures_; + // All instructions. The first entries will always be the singleton // instructions. InstStore insts_; diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 81b5307e3d06..3b8bc7c8e55a 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -493,6 +493,13 @@ struct ClangDeclId : public IdBase { using IdBase::IdBase; }; +// The ID of a `ClangDeclSignature`. +struct ClangDeclSignatureId : public IdBase { + static constexpr llvm::StringLiteral Label = "clang_decl_signature_id"; + + using IdBase::IdBase; +}; + // A boolean value. struct BoolValue : public IdBase { // Not used by `Print`, but for `IdKind`. diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index a2842e3ea009..f777848edd83 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -61,6 +61,7 @@ TEST(SemIRTest, Yaml) { Pair("import_irs", Yaml::Mapping(SizeIs(2))), Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))), Pair("clang_decls", Yaml::Mapping(SizeIs(0))), + Pair("clang_decl_signatures", Yaml::Mapping(SizeIs(0))), Pair("name_scopes", Yaml::Mapping(SizeIs(1))), Pair("entity_names", Yaml::Mapping(SizeIs(1))), Pair("cpp_global_vars", Yaml::Mapping(SizeIs(0))),