diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index b8df6bf28b26..c62b4bd1b0a2 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -355,6 +355,9 @@ class CarbonExternalASTSource : public clang::ExternalASTSource { auto MapInstIdToClangDeclOrType(LookupResult lookup) -> std::variant; + auto GetOrExportFunctionToCpp(SemIR::InstId target_inst_id, + SemIR::FunctionId function_id) + -> clang::FunctionDecl*; // Get a current best-effort location for the current position within C++ // processing. auto GetCurrentCppLocId() -> SemIR::LocId { @@ -426,15 +429,8 @@ auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup) return nullptr; } - const SemIR::Function& function = - context_->functions().Get(callee_function->function_id); - if (function.clang_decl_id.has_value()) { - return cast( - context_->clang_decls().Get(function.clang_decl_id).key.decl); - } - - return ExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), - callee_function->function_id); + return GetOrExportFunctionToCpp(target_inst_id, + callee_function->function_id); } case CARBON_KIND(SemIR::FieldDecl field_decl): { return ExportFieldToCpp(*context_, target_inst_id, field_decl); @@ -444,6 +440,19 @@ auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup) } } +auto CarbonExternalASTSource::GetOrExportFunctionToCpp( + SemIR::InstId target_inst_id, SemIR::FunctionId function_id) + -> clang::FunctionDecl* { + const SemIR::Function& function = context_->functions().Get(function_id); + if (function.clang_decl_id.has_value()) { + return cast( + context_->clang_decls().Get(function.clang_decl_id).key.decl); + } + + return ExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), + function_id); +} + auto CarbonExternalASTSource::BuildCarbonNamespace() -> void { static const llvm::StringLiteral carbon_namespace_name = "Carbon"; auto& ast_context = context_->ast_context(); @@ -653,6 +662,33 @@ auto CarbonExternalASTSource::CompleteType(clang::TagDecl* tag_decl) -> void { class_decl->addDecl(ExportDestructorToCpp(*context_, class_info, class_decl)); // TODO: Import any special member functions that affect class properties. + + if (class_info.vtable_decl_id.has_value()) { + auto vtable_inst_block = context_->inst_blocks().Get( + context_->vtables() + .Get(context_->insts() + .GetAs(class_info.vtable_decl_id) + .vtable_id) + .virtual_functions_id); + for (auto vtable_entry_id : vtable_inst_block) { + if (!vtable_entry_id.has_value()) { + continue; + } + + auto callee_function = + GetCalleeAsFunction(context_->sem_ir(), vtable_entry_id); + const SemIR::Function& function = + context_->functions().Get(callee_function.function_id); + + // If this is a member of a base class, nothing to do here. + if (function.parent_scope_id != class_info.scope_id) { + continue; + } + auto* method_decl = cast(GetOrExportFunctionToCpp( + vtable_entry_id, callee_function.function_id)); + context_->clang_sema().AddOverriddenMethods(class_decl, method_decl); + } + } class_decl->completeDefinition(); } diff --git a/toolchain/check/testdata/interop/cpp/class/export/base.carbon b/toolchain/check/testdata/interop/cpp/class/export/base.carbon index 2e6b4b48ed01..d28a56cf51ee 100644 --- a/toolchain/check/testdata/interop/cpp/class/export/base.carbon +++ b/toolchain/check/testdata/interop/cpp/class/export/base.carbon @@ -133,6 +133,16 @@ import Cpp; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: abstract class Abstract { + // CHECK:STDERR: fail_todo_abstract_nonvirtual_dtor_but_virtual_fns.carbon:[[@LINE+10]]:3: error: initialization of abstract type `Abstract` [AbstractTypeInInit] + // CHECK:STDERR: abstract fn F[self: Self](); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_abstract_nonvirtual_dtor_but_virtual_fns.carbon:[[@LINE-4]]:1: note: class was declared abstract here [ClassAbstractHere] + // CHECK:STDERR: abstract class Abstract { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_abstract_nonvirtual_dtor_but_virtual_fns.carbon:[[@LINE+4]]:17: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: abstract fn F[self: Self](); + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: abstract fn F[self: Self](); } diff --git a/toolchain/lower/testdata/interop/cpp/class/import/dynamic.carbon b/toolchain/lower/testdata/interop/cpp/class/import/dynamic.carbon index 0cb07add47a2..2b2bca3db762 100644 --- a/toolchain/lower/testdata/interop/cpp/class/import/dynamic.carbon +++ b/toolchain/lower/testdata/interop/cpp/class/import/dynamic.carbon @@ -19,31 +19,26 @@ import Cpp; inline Cpp ''' struct FurtherBase { - virtual auto further_base_func() -> int { - return 11; - } + virtual auto further_base_func() -> void; }; struct Base: FurtherBase { int i; - virtual auto func() -> int { - return 7; - } + virtual auto func() & -> void; }; -auto Use(Base& b) -> int { - return b.func(); +__attribute__((optnone)) auto Use(Base& b) { } '''; base class Derived { extend base: Cpp.Base; - // TODO: `other_func` should appear in the vtable (it currently - // doesn't because the CXXRecordDecl we export has no CXXMethodDecl - // children - those need to be added, and in the right order) - virtual fn other_func[unused self: Self]() -> i32 { - return 3; + // TODO: `other_func` should appear in the vtable (it currently doesn't + // maybe because the CXXMethodDecl isn't marked as virtual) + virtual fn other_func[unused self: Self]() { + } + override fn func[unused ref self: Self]() { } } @@ -56,9 +51,9 @@ void WorkaroundToEmitCtorAndVtable() { // TODO: Carbon lowering should emit initialization that refers to the // Clang-lowered vtable. -auto DoThing() -> int { +auto DoThing() -> void { Carbon::Derived d; - return Use(d); + Use(d); } '''; @@ -76,10 +71,6 @@ auto DoThing() -> int { // CHECK:STDOUT: // CHECK:STDOUT: $_ZN6Carbon7DerivedD2Ev = comdat any // CHECK:STDOUT: -// CHECK:STDOUT: $_ZN11FurtherBase17further_base_funcEv = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZN4Base4funcEv = comdat any -// CHECK:STDOUT: // CHECK:STDOUT: $_ZN4BaseC2Ev = comdat any // CHECK:STDOUT: // CHECK:STDOUT: $_ZN11FurtherBaseC2Ev = comdat any @@ -90,51 +81,31 @@ auto DoThing() -> int { // CHECK:STDOUT: // CHECK:STDOUT: $_ZTSN6Carbon7DerivedE = comdat any // CHECK:STDOUT: -// CHECK:STDOUT: $_ZTI4Base = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZTS4Base = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZTI11FurtherBase = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZTS11FurtherBase = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZTV4Base = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: $_ZTV11FurtherBase = comdat any -// CHECK:STDOUT: -// CHECK:STDOUT: @_ZTVN6Carbon7DerivedE = linkonce_odr dso_local unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN6Carbon7DerivedE, ptr @_ZN11FurtherBase17further_base_funcEv, ptr @_ZN4Base4funcEv] }, comdat, align 8 +// CHECK:STDOUT: @_ZTVN6Carbon7DerivedE = linkonce_odr dso_local unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN6Carbon7DerivedE, ptr @_ZN11FurtherBase17further_base_funcEv, ptr @_ZNR6Carbon7Derived4funcEv] }, comdat, align 8 // CHECK:STDOUT: @_ZTIN6Carbon7DerivedE = linkonce_odr dso_local constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr @_ZTSN6Carbon7DerivedE, ptr @_ZTI4Base }, comdat, align 8 // CHECK:STDOUT: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global [0 x ptr] // CHECK:STDOUT: @_ZTSN6Carbon7DerivedE = linkonce_odr dso_local constant [18 x i8] c"N6Carbon7DerivedE\00", comdat, align 1 -// CHECK:STDOUT: @_ZTI4Base = linkonce_odr dso_local constant { ptr, ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr @_ZTS4Base, ptr @_ZTI11FurtherBase }, comdat, align 8 -// CHECK:STDOUT: @_ZTS4Base = linkonce_odr dso_local constant [6 x i8] c"4Base\00", comdat, align 1 -// CHECK:STDOUT: @_ZTI11FurtherBase = linkonce_odr dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS11FurtherBase }, comdat, align 8 -// CHECK:STDOUT: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] -// CHECK:STDOUT: @_ZTS11FurtherBase = linkonce_odr dso_local constant [14 x i8] c"11FurtherBase\00", comdat, align 1 -// CHECK:STDOUT: @_ZTV4Base = linkonce_odr dso_local unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI4Base, ptr @_ZN11FurtherBase17further_base_funcEv, ptr @_ZN4Base4funcEv] }, comdat, align 8 -// CHECK:STDOUT: @_ZTV11FurtherBase = linkonce_odr dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI11FurtherBase, ptr @_ZN11FurtherBase17further_base_funcEv] }, comdat, align 8 +// CHECK:STDOUT: @_ZTI4Base = external constant ptr +// CHECK:STDOUT: @_ZTV4Base = available_externally unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI4Base, ptr @_ZN11FurtherBase17further_base_funcEv, ptr @_ZNR4Base4funcEv] }, align 8 +// CHECK:STDOUT: @_ZTV11FurtherBase = available_externally unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI11FurtherBase, ptr @_ZN11FurtherBase17further_base_funcEv] }, align 8 +// CHECK:STDOUT: @_ZTI11FurtherBase = external constant ptr // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef i32 @_Z3UseR4Base(ptr noundef nonnull align 8 dereferenceable(12) %b) #0 { +// CHECK:STDOUT: ; Function Attrs: mustprogress noinline nounwind optnone uwtable +// CHECK:STDOUT: define dso_local void @_Z3UseR4Base(ptr noundef nonnull align 8 dereferenceable(12) %b) #0 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %b.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %b, ptr %b.addr, align 8, !tbaa !11 -// CHECK:STDOUT: %0 = load ptr, ptr %b.addr, align 8, !tbaa !11, !nonnull !14, !align !15 -// CHECK:STDOUT: %vtable = load ptr, ptr %0, align 8, !tbaa !16 -// CHECK:STDOUT: %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1 -// CHECK:STDOUT: %1 = load ptr, ptr %vfn, align 8 -// CHECK:STDOUT: %call = call noundef i32 %1(ptr noundef nonnull align 8 dereferenceable(12) %0) -// CHECK:STDOUT: ret i32 %call +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define dso_local void @_Z29WorkaroundToEmitCtorAndVtablev() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %d = alloca %"class.Carbon::Derived", align 8 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %d) #4 -// CHECK:STDOUT: call void @_ZN6Carbon7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %d) #4 -// CHECK:STDOUT: call void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %d) #4 -// CHECK:STDOUT: call void @llvm.lifetime.end.p0(ptr %d) #4 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %d) #5 +// CHECK:STDOUT: call void @_ZN6Carbon7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %d) #5 +// CHECK:STDOUT: call void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %d) #5 +// CHECK:STDOUT: call void @llvm.lifetime.end.p0(ptr %d) #5 // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: @@ -145,9 +116,9 @@ auto DoThing() -> int { // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN6Carbon7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !18 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !14 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 -// CHECK:STDOUT: call void @_ZN4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this1) #4 +// CHECK:STDOUT: call void @_ZN4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this1) #5 // CHECK:STDOUT: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTVN6Carbon7DerivedE, i32 0, i32 0, i32 2), ptr %this1, align 8, !tbaa !16 // CHECK:STDOUT: ret void // CHECK:STDOUT: } @@ -156,7 +127,7 @@ auto DoThing() -> int { // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !18 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !14 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 // CHECK:STDOUT: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTVN6Carbon7DerivedE, i32 0, i32 0, i32 2), ptr %this1, align 8, !tbaa !16 // CHECK:STDOUT: call void @"_C__destroy_thunk:thunk.Derived.Main"(ptr noundef nonnull align 8 dereferenceable(12) %this1) @@ -166,123 +137,120 @@ auto DoThing() -> int { // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.end.p0(ptr captures(none)) #2 // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: mustprogress uwtable -// CHECK:STDOUT: define dso_local noundef i32 @_Z7DoThingv() #0 personality ptr @__gxx_personality_v0 { +// CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable +// CHECK:STDOUT: define dso_local void @_Z7DoThingv() #1 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %d = alloca %"class.Carbon::Derived", align 8 -// CHECK:STDOUT: %exn.slot = alloca ptr, align 8 -// CHECK:STDOUT: %ehselector.slot = alloca i32, align 4 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %d) #4 -// CHECK:STDOUT: call void @_ZN6Carbon7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %d) #4 -// CHECK:STDOUT: %call = invoke noundef i32 @_Z3UseR4Base(ptr noundef nonnull align 8 dereferenceable(12) %d) -// CHECK:STDOUT: to label %invoke.cont unwind label %lpad -// CHECK:STDOUT: -// CHECK:STDOUT: invoke.cont: ; preds = %entry -// CHECK:STDOUT: call void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %d) #4 -// CHECK:STDOUT: call void @llvm.lifetime.end.p0(ptr %d) #4 -// CHECK:STDOUT: ret i32 %call -// CHECK:STDOUT: -// CHECK:STDOUT: lpad: ; preds = %entry -// CHECK:STDOUT: %0 = landingpad { ptr, i32 } -// CHECK:STDOUT: cleanup -// CHECK:STDOUT: %1 = extractvalue { ptr, i32 } %0, 0 -// CHECK:STDOUT: store ptr %1, ptr %exn.slot, align 8 -// CHECK:STDOUT: %2 = extractvalue { ptr, i32 } %0, 1 -// CHECK:STDOUT: store i32 %2, ptr %ehselector.slot, align 4 -// CHECK:STDOUT: call void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %d) #4 -// CHECK:STDOUT: call void @llvm.lifetime.end.p0(ptr %d) #4 -// CHECK:STDOUT: br label %eh.resume -// CHECK:STDOUT: -// CHECK:STDOUT: eh.resume: ; preds = %lpad -// CHECK:STDOUT: %exn = load ptr, ptr %exn.slot, align 8 -// CHECK:STDOUT: %sel = load i32, ptr %ehselector.slot, align 4 -// CHECK:STDOUT: %lpad.val = insertvalue { ptr, i32 } poison, ptr %exn, 0 -// CHECK:STDOUT: %lpad.val1 = insertvalue { ptr, i32 } %lpad.val, i32 %sel, 1 -// CHECK:STDOUT: resume { ptr, i32 } %lpad.val1 -// CHECK:STDOUT: -// CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr %d, { 0, 2, 1, 3, 4, 5, 6 } +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %d) #5 +// CHECK:STDOUT: call void @_ZN6Carbon7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %d) #5 +// CHECK:STDOUT: call void @_Z3UseR4Base(ptr noundef nonnull align 8 dereferenceable(12) %d) +// CHECK:STDOUT: call void @_ZN6Carbon7DerivedD2Ev(ptr noundef nonnull align 8 dead_on_return(12) dereferenceable(12) %d) #5 +// CHECK:STDOUT: call void @llvm.lifetime.end.p0(ptr %d) #5 +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare i32 @__gxx_personality_v0(...) +// CHECK:STDOUT: declare void @_ZN11FurtherBase17further_base_funcEv(ptr noundef nonnull align 8 dereferenceable(8)) unnamed_addr #4 // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable -// CHECK:STDOUT: define linkonce_odr dso_local noundef i32 @_ZN11FurtherBase17further_base_funcEv(ptr noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #1 comdat align 2 { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !20 -// CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 -// CHECK:STDOUT: ret i32 11 -// CHECK:STDOUT: } +// CHECK:STDOUT: declare void @_ZNR4Base4funcEv(ptr noundef nonnull align 8 dereferenceable(12)) unnamed_addr #4 // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable -// CHECK:STDOUT: define linkonce_odr dso_local noundef i32 @_ZN4Base4funcEv(ptr noundef nonnull align 8 dereferenceable(12) %this) unnamed_addr #1 comdat align 2 { +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_Cother_func.Derived.Main(ptr %self) #5 !dbg !18 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !11 -// CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 -// CHECK:STDOUT: ret i32 7 +// CHECK:STDOUT: ret void, !dbg !24 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define i32 @_Cother_func.Derived.Main(ptr %self) #4 !dbg !22 { +// CHECK:STDOUT: define void @_Cfunc.Derived.Main(ptr %self) #5 !dbg !25 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret i32 3, !dbg !29 +// CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind -// CHECK:STDOUT: define void @"_C__destroy_thunk:thunk.Derived.Main"(ptr %self) #5 !dbg !30 { +// CHECK:STDOUT: define void @"_C__destroy_thunk:thunk.Derived.Main"(ptr %self) #6 !dbg !29 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @"_COp.12e0d0434542305a:core.Destroy.Core"(ptr %self), !dbg !35 -// CHECK:STDOUT: ret void, !dbg !35 +// CHECK:STDOUT: call void @"_COp.12e0d0434542305a:core.Destroy.Core"(ptr %self), !dbg !32 +// CHECK:STDOUT: ret void, !dbg !32 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_COp.bfe31446004e2b71:core.Destroy.Core"(ptr %self) #4 !dbg !36 { +// CHECK:STDOUT: define weak_odr void @"_COp.bfe31446004e2b71:core.Destroy.Core"(ptr %self) #5 !dbg !33 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret void, !dbg !39 +// CHECK:STDOUT: ret void, !dbg !36 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_COp.12e0d0434542305a:core.Destroy.Core"(ptr %self) #4 !dbg !40 { +// CHECK:STDOUT: define weak_odr void @"_COp.12e0d0434542305a:core.Destroy.Core"(ptr %self) #5 !dbg !37 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret void, !dbg !43 +// CHECK:STDOUT: ret void, !dbg !40 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_Cfunc__carbon_thunk.Derived.Main(ptr %self) #5 !dbg !41 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %Derived.func.call.vtable = load ptr, ptr %self, align 8, !dbg !44 +// CHECK:STDOUT: %Derived.func.call = call ptr @llvm.load.relative.i32(ptr %Derived.func.call.vtable, i32 4), !dbg !44 +// CHECK:STDOUT: call void %Derived.func.call(ptr %self), !dbg !44 +// CHECK:STDOUT: ret void, !dbg !44 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_Cother_func__carbon_thunk.Derived.Main(ptr %self) #5 !dbg !45 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %Derived.other_func.call.vtable = load ptr, ptr %self, align 8, !dbg !48 +// CHECK:STDOUT: %Derived.other_func.call = call ptr @llvm.load.relative.i32(ptr %Derived.other_func.call.vtable, i32 8), !dbg !48 +// CHECK:STDOUT: call void %Derived.other_func.call(ptr %self), !dbg !48 +// CHECK:STDOUT: ret void, !dbg !48 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read) +// CHECK:STDOUT: declare ptr @llvm.load.relative.i32(ptr, i32) #7 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: inlinehint mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !11 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 -// CHECK:STDOUT: call void @_ZN11FurtherBaseC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this1) #4 +// CHECK:STDOUT: call void @_ZN11FurtherBaseC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this1) #5 // CHECK:STDOUT: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV4Base, i32 0, i32 0, i32 2), ptr %this1, align 8, !tbaa !16 // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable +// CHECK:STDOUT: define internal void @_ZNR6Carbon7Derived4funcEv(ptr noundef nonnull align 8 dereferenceable(12) %this) unnamed_addr #8 align 2 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %this.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !14 +// CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 +// CHECK:STDOUT: call void @_Cfunc__carbon_thunk.Derived.Main(ptr noundef nonnull align 8 dereferenceable(12) %this1) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: inlinehint mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN11FurtherBaseC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !20 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !49 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 // CHECK:STDOUT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV11FurtherBase, i32 0, i32 0, i32 2), ptr %this1, align 8, !tbaa !16 // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN6Carbon7DerivedC2Ev, { 1, 0 } -// CHECK:STDOUT: uselistorder ptr @_ZN6Carbon7DerivedD2Ev, { 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @_ZN6Carbon7DerivedD2Ev, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN11FurtherBase17further_base_funcEv, { 2, 1, 0 } -// CHECK:STDOUT: uselistorder ptr @_ZN4Base4funcEv, { 1, 0 } +// CHECK:STDOUT: uselistorder ptr @llvm.load.relative.i32, { 1, 0 } // CHECK:STDOUT: -// CHECK:STDOUT: attributes #0 = { mustprogress 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 #0 = { mustprogress noinline nounwind optnone 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 = { 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 #2 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #3 = { inlinehint 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 #4 = { nounwind } -// CHECK:STDOUT: attributes #5 = { alwaysinline nounwind } +// 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: attributes #5 = { nounwind } +// CHECK:STDOUT: attributes #6 = { alwaysinline nounwind } +// CHECK:STDOUT: attributes #7 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } +// CHECK:STDOUT: attributes #8 = { 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: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -302,33 +270,40 @@ auto DoThing() -> int { // CHECK:STDOUT: !11 = !{!12, !12, i64 0} // CHECK:STDOUT: !12 = !{!"p1 _ZTS4Base", !13, i64 0} // CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0} -// CHECK:STDOUT: !14 = !{} -// CHECK:STDOUT: !15 = !{i64 8} +// CHECK:STDOUT: !14 = !{!15, !15, i64 0} +// CHECK:STDOUT: !15 = !{!"p1 _ZTSN6Carbon7DerivedE", !13, i64 0} // CHECK:STDOUT: !16 = !{!17, !17, i64 0} // CHECK:STDOUT: !17 = !{!"vtable pointer", !10, i64 0} -// CHECK:STDOUT: !18 = !{!19, !19, i64 0} -// CHECK:STDOUT: !19 = !{!"p1 _ZTSN6Carbon7DerivedE", !13, i64 0} -// CHECK:STDOUT: !20 = !{!21, !21, i64 0} -// CHECK:STDOUT: !21 = !{!"p1 _ZTS11FurtherBase", !13, i64 0} -// CHECK:STDOUT: !22 = distinct !DISubprogram(name: "other_func", linkageName: "_Cother_func.Derived.Main", scope: null, file: !6, line: 32, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !27) -// CHECK:STDOUT: !23 = !DISubroutineType(types: !24) -// CHECK:STDOUT: !24 = !{!25, !26} -// CHECK:STDOUT: !25 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -// CHECK:STDOUT: !26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) -// CHECK:STDOUT: !27 = !{!28} -// CHECK:STDOUT: !28 = !DILocalVariable(arg: 1, scope: !22, type: !26) -// CHECK:STDOUT: !29 = !DILocation(line: 33, column: 5, scope: !22) -// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "__destroy_thunk", linkageName: "_C__destroy_thunk:thunk.Derived.Main", scope: null, file: !6, line: 27, type: !31, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !33) -// CHECK:STDOUT: !31 = !DISubroutineType(types: !32) -// CHECK:STDOUT: !32 = !{null, !26} -// CHECK:STDOUT: !33 = !{!34} -// CHECK:STDOUT: !34 = !DILocalVariable(arg: 1, scope: !30, type: !26) -// CHECK:STDOUT: !35 = !DILocation(line: 27, column: 1, scope: !30) -// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "Op", linkageName: "_COp.bfe31446004e2b71:core.Destroy.Core", scope: null, file: !6, line: 27, type: !31, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !37) -// CHECK:STDOUT: !37 = !{!38} -// CHECK:STDOUT: !38 = !DILocalVariable(arg: 1, scope: !36, type: !26) -// CHECK:STDOUT: !39 = !DILocation(line: 27, column: 1, scope: !36) -// CHECK:STDOUT: !40 = distinct !DISubprogram(name: "Op", linkageName: "_COp.12e0d0434542305a:core.Destroy.Core", scope: null, file: !6, line: 27, type: !31, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !41) -// CHECK:STDOUT: !41 = !{!42} -// CHECK:STDOUT: !42 = !DILocalVariable(arg: 1, scope: !40, type: !26) -// CHECK:STDOUT: !43 = !DILocation(line: 27, column: 1, scope: !40) +// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "other_func", linkageName: "_Cother_func.Derived.Main", scope: null, file: !6, line: 26, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !22) +// CHECK:STDOUT: !19 = !DISubroutineType(types: !20) +// CHECK:STDOUT: !20 = !{null, !21} +// CHECK:STDOUT: !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !22 = !{!23} +// CHECK:STDOUT: !23 = !DILocalVariable(arg: 1, scope: !18, type: !21) +// CHECK:STDOUT: !24 = !DILocation(line: 26, column: 3, scope: !18) +// CHECK:STDOUT: !25 = distinct !DISubprogram(name: "func", linkageName: "_Cfunc.Derived.Main", scope: null, file: !6, line: 28, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !26) +// CHECK:STDOUT: !26 = !{!27} +// CHECK:STDOUT: !27 = !DILocalVariable(arg: 1, scope: !25, type: !21) +// CHECK:STDOUT: !28 = !DILocation(line: 28, column: 3, scope: !25) +// CHECK:STDOUT: !29 = distinct !DISubprogram(name: "__destroy_thunk", linkageName: "_C__destroy_thunk:thunk.Derived.Main", scope: null, file: !6, line: 22, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !30) +// CHECK:STDOUT: !30 = !{!31} +// CHECK:STDOUT: !31 = !DILocalVariable(arg: 1, scope: !29, type: !21) +// CHECK:STDOUT: !32 = !DILocation(line: 22, column: 1, scope: !29) +// CHECK:STDOUT: !33 = distinct !DISubprogram(name: "Op", linkageName: "_COp.bfe31446004e2b71:core.Destroy.Core", scope: null, file: !6, line: 22, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !34) +// CHECK:STDOUT: !34 = !{!35} +// CHECK:STDOUT: !35 = !DILocalVariable(arg: 1, scope: !33, type: !21) +// CHECK:STDOUT: !36 = !DILocation(line: 22, column: 1, scope: !33) +// CHECK:STDOUT: !37 = distinct !DISubprogram(name: "Op", linkageName: "_COp.12e0d0434542305a:core.Destroy.Core", scope: null, file: !6, line: 22, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !38) +// CHECK:STDOUT: !38 = !{!39} +// CHECK:STDOUT: !39 = !DILocalVariable(arg: 1, scope: !37, type: !21) +// CHECK:STDOUT: !40 = !DILocation(line: 22, column: 1, scope: !37) +// CHECK:STDOUT: !41 = distinct !DISubprogram(name: "func__carbon_thunk", linkageName: "_Cfunc__carbon_thunk.Derived.Main", scope: null, file: !6, line: 28, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !42) +// CHECK:STDOUT: !42 = !{!43} +// CHECK:STDOUT: !43 = !DILocalVariable(arg: 1, scope: !41, type: !21) +// CHECK:STDOUT: !44 = !DILocation(line: 28, column: 3, scope: !41) +// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "other_func__carbon_thunk", linkageName: "_Cother_func__carbon_thunk.Derived.Main", scope: null, file: !6, line: 26, type: !19, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !46) +// CHECK:STDOUT: !46 = !{!47} +// CHECK:STDOUT: !47 = !DILocalVariable(arg: 1, scope: !45, type: !21) +// CHECK:STDOUT: !48 = !DILocation(line: 26, column: 3, scope: !45) +// CHECK:STDOUT: !49 = !{!50, !50, i64 0} +// CHECK:STDOUT: !50 = !{!"p1 _ZTS11FurtherBase", !13, i64 0} diff --git a/toolchain/lower/testdata/interop/cpp/class/virtual_fn.carbon b/toolchain/lower/testdata/interop/cpp/class/virtual_fn.carbon index 34d400277f03..45e51c92607a 100644 --- a/toolchain/lower/testdata/interop/cpp/class/virtual_fn.carbon +++ b/toolchain/lower/testdata/interop/cpp/class/virtual_fn.carbon @@ -95,7 +95,7 @@ void delete_new_Base() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %p = alloca ptr, align 8 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %p) #8 -// CHECK:STDOUT: %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 8) #10 +// CHECK:STDOUT: %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 8) #11 // CHECK:STDOUT: call void @_ZN6Carbon5FinalC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %call) #8 // CHECK:STDOUT: store ptr %call, ptr %p, align 8, !tbaa !11 // CHECK:STDOUT: %0 = load ptr, ptr %p, align 8, !tbaa !11 @@ -104,7 +104,7 @@ void delete_new_Base() { // CHECK:STDOUT: // CHECK:STDOUT: delete.notnull: ; preds = %entry // CHECK:STDOUT: call void @_ZN6Carbon5FinalD2Ev(ptr noundef nonnull align 8 dead_on_return(8) dereferenceable(8) %0) #8 -// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %0, i64 noundef 8) #11 +// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %0, i64 noundef 8) #12 // CHECK:STDOUT: br label %delete.end // CHECK:STDOUT: // CHECK:STDOUT: delete.end: ; preds = %delete.notnull, %entry @@ -151,7 +151,7 @@ void delete_new_Base() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %p = alloca ptr, align 8 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %p) #8 -// CHECK:STDOUT: %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 8) #10 +// CHECK:STDOUT: %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 8) #11 // CHECK:STDOUT: call void @_ZN6Carbon4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %call) #8 // CHECK:STDOUT: store ptr %call, ptr %p, align 8, !tbaa !16 // CHECK:STDOUT: %0 = load ptr, ptr %p, align 8, !tbaa !16 @@ -220,19 +220,40 @@ void delete_new_Base() { // CHECK:STDOUT: ret void, !dbg !36 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind -// CHECK:STDOUT: define void @"_C__destroy_thunk:thunk.Base.Main"(ptr %self) #6 !dbg !37 { +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF__carbon_thunk.Final.Main(ptr %self) #8 !dbg !37 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: call void @"_COp.96a711151205ee34:core.Destroy.Core"(ptr %self), !dbg !40 +// CHECK:STDOUT: %Final.F.call.vtable = load ptr, ptr %self, align 8, !dbg !40 +// CHECK:STDOUT: %Final.F.call = call ptr @llvm.load.relative.i32(ptr %Final.F.call.vtable, i32 8), !dbg !40 +// CHECK:STDOUT: call void %Final.F.call(ptr %self), !dbg !40 // CHECK:STDOUT: ret void, !dbg !40 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_COp.96a711151205ee34:core.Destroy.Core"(ptr %self) #8 !dbg !41 { +// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind +// CHECK:STDOUT: define void @"_C__destroy_thunk:thunk.Base.Main"(ptr %self) #6 !dbg !41 { // CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @"_COp.96a711151205ee34:core.Destroy.Core"(ptr %self), !dbg !44 // CHECK:STDOUT: ret void, !dbg !44 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define weak_odr void @"_COp.96a711151205ee34:core.Destroy.Core"(ptr %self) #8 !dbg !45 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: ret void, !dbg !48 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF__carbon_thunk.Base.Main(ptr %self) #8 !dbg !49 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %Base.F.call.vtable = load ptr, ptr %self, align 8, !dbg !52 +// CHECK:STDOUT: %Base.F.call = call ptr @llvm.load.relative.i32(ptr %Base.F.call.vtable, i32 8), !dbg !52 +// CHECK:STDOUT: call void %Base.F.call(ptr %self), !dbg !52 +// CHECK:STDOUT: ret void, !dbg !52 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read) +// CHECK:STDOUT: declare ptr @llvm.load.relative.i32(ptr, i32) #9 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: inlinehint mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: @@ -250,11 +271,11 @@ void delete_new_Base() { // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !11 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 // CHECK:STDOUT: call void @_ZN6Carbon5FinalD2Ev(ptr noundef nonnull align 8 dead_on_return(8) dereferenceable(8) %this1) #8 -// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %this1, i64 noundef 8) #11 +// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %this1, i64 noundef 8) #12 // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_ZNK1A1FEv(ptr noundef nonnull align 8 dereferenceable(8)) unnamed_addr #9 +// CHECK:STDOUT: declare void @_ZNK1A1FEv(ptr noundef nonnull align 8 dereferenceable(8)) unnamed_addr #10 // CHECK:STDOUT: // CHECK:STDOUT: declare void @__cxa_pure_virtual() unnamed_addr // CHECK:STDOUT: @@ -280,12 +301,13 @@ void delete_new_Base() { // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !16 // CHECK:STDOUT: %this1 = load ptr, ptr %this.addr, align 8 // CHECK:STDOUT: call void @_ZN6Carbon4BaseD2Ev(ptr noundef nonnull align 8 dead_on_return(8) dereferenceable(8) %this1) #8 -// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %this1, i64 noundef 8) #11 +// CHECK:STDOUT: call void @_ZdlPvm(ptr noundef %this1, i64 noundef 8) #12 // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @_ZN6Carbon5FinalD2Ev, { 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @llvm.load.relative.i32, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN1AC2Ev, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZNK1A1FEv, { 2, 1, 0 } // CHECK:STDOUT: uselistorder ptr @__cxa_pure_virtual, { 1, 0 } @@ -300,9 +322,10 @@ void delete_new_Base() { // CHECK:STDOUT: attributes #6 = { alwaysinline nounwind } // CHECK:STDOUT: attributes #7 = { 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 #8 = { nounwind } -// CHECK:STDOUT: attributes #9 = { "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 #10 = { builtin allocsize(0) } -// CHECK:STDOUT: attributes #11 = { builtin nounwind } +// CHECK:STDOUT: attributes #9 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } +// CHECK:STDOUT: attributes #10 = { "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 #11 = { builtin allocsize(0) } +// CHECK:STDOUT: attributes #12 = { builtin nounwind } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -345,11 +368,19 @@ void delete_new_Base() { // CHECK:STDOUT: !34 = !{!35} // CHECK:STDOUT: !35 = !DILocalVariable(arg: 1, scope: !33, type: !25) // CHECK:STDOUT: !36 = !DILocation(line: 12, column: 1, scope: !33) -// CHECK:STDOUT: !37 = distinct !DISubprogram(name: "__destroy_thunk", linkageName: "_C__destroy_thunk:thunk.Base.Main", scope: null, file: !6, line: 17, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !38) +// CHECK:STDOUT: !37 = distinct !DISubprogram(name: "F__carbon_thunk", linkageName: "_CF__carbon_thunk.Final.Main", scope: null, file: !6, line: 14, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !38) // CHECK:STDOUT: !38 = !{!39} // CHECK:STDOUT: !39 = !DILocalVariable(arg: 1, scope: !37, type: !25) -// CHECK:STDOUT: !40 = !DILocation(line: 17, column: 1, scope: !37) -// CHECK:STDOUT: !41 = distinct !DISubprogram(name: "Op", linkageName: "_COp.96a711151205ee34:core.Destroy.Core", scope: null, file: !6, line: 17, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !42) +// CHECK:STDOUT: !40 = !DILocation(line: 14, column: 3, scope: !37) +// CHECK:STDOUT: !41 = distinct !DISubprogram(name: "__destroy_thunk", linkageName: "_C__destroy_thunk:thunk.Base.Main", scope: null, file: !6, line: 17, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !42) // CHECK:STDOUT: !42 = !{!43} // CHECK:STDOUT: !43 = !DILocalVariable(arg: 1, scope: !41, type: !25) // CHECK:STDOUT: !44 = !DILocation(line: 17, column: 1, scope: !41) +// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "Op", linkageName: "_COp.96a711151205ee34:core.Destroy.Core", scope: null, file: !6, line: 17, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !46) +// CHECK:STDOUT: !46 = !{!47} +// CHECK:STDOUT: !47 = !DILocalVariable(arg: 1, scope: !45, type: !25) +// CHECK:STDOUT: !48 = !DILocation(line: 17, column: 1, scope: !45) +// CHECK:STDOUT: !49 = distinct !DISubprogram(name: "F__carbon_thunk", linkageName: "_CF__carbon_thunk.Base.Main", scope: null, file: !6, line: 19, type: !23, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !50) +// CHECK:STDOUT: !50 = !{!51} +// CHECK:STDOUT: !51 = !DILocalVariable(arg: 1, scope: !49, type: !25) +// CHECK:STDOUT: !52 = !DILocation(line: 19, column: 3, scope: !49)