diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 899ae21eb7b9..b6de302f1077 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -513,7 +513,8 @@ auto CheckParseTrees( continue; } inputs.push_back({.check_ir_id = unit_info.unit->sem_ir->check_ir_id(), - .filename = unit_info.unit->sem_ir->filename()}); + .filename = unit_info.unit->sem_ir->filename(), + .is_lowered = unit_info.unit->is_lowered}); } // TODO: Remove dependence on properties of the first unit here. if (auto cpp_domain = InitializeCppDomain( @@ -534,7 +535,8 @@ auto CheckParseTrees( if (auto cpp_domain = InitializeCppDomain( unit_info.err_tracker, {{.check_ir_id = unit_info.unit->sem_ir->check_ir_id(), - .filename = unit_info.unit->sem_ir->filename()}}, + .filename = unit_info.unit->sem_ir->filename(), + .is_lowered = unit_info.unit->is_lowered}}, fs, unit_info.unit->llvm_context, clang_invocation)) { cpp_domains.push_back(std::move(cpp_domain)); unit_info.cpp_domain = cpp_domains.back().get(); diff --git a/toolchain/check/check.h b/toolchain/check/check.h index 927c57c831b4..21a460fbbf6f 100644 --- a/toolchain/check/check.h +++ b/toolchain/check/check.h @@ -28,6 +28,7 @@ struct Unit { // The unit's SemIR, provided as empty and filled in by CheckParseTrees. SemIR::File* sem_ir; llvm::LLVMContext* llvm_context; + bool is_lowered; // The total number of files. int total_ir_count; }; diff --git a/toolchain/check/cpp/domain.h b/toolchain/check/cpp/domain.h index 1b586f7e4565..a2fd38b2f6bc 100644 --- a/toolchain/check/cpp/domain.h +++ b/toolchain/check/cpp/domain.h @@ -26,8 +26,13 @@ namespace Carbon::Check { // An input Carbon file and its CheckIRId for C++ domain code generation. struct CppInputFile { + // The ID used to identify this file within SemIR. SemIR::CheckIRId check_ir_id; + // The Carbon source filename for this input. llvm::StringRef filename; + // Whether this input IR will be lowered. If not, we don't need to build a + // Clang CodeGenerator for it. + bool is_lowered; }; // A C++ compilation domain, including a live Clang instance that can be used to diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index e46a03b2eb00..8f02c78a3dad 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -743,6 +743,10 @@ class GenerateASTAction : public clang::ASTFrontendAction { // a single object file, for a faster `carbon build` mode. std::vector> consumers; for (const auto& input : inputs_) { + if (!input.is_lowered) { + code_generators_.push_back(nullptr); + continue; + } // TODO: Filter what goes into each code generator. If there are strong // external C++ definitions in a Carbon file (for example, in inline C++ // code), they should be emitted only in that one file. diff --git a/toolchain/driver/compile_driver.cpp b/toolchain/driver/compile_driver.cpp index a5f1d3ce3981..881f3d334b4b 100644 --- a/toolchain/driver/compile_driver.cpp +++ b/toolchain/driver/compile_driver.cpp @@ -154,6 +154,7 @@ auto CompilationUnit::GetCheckUnit() -> Check::Unit { .timings = timings_ ? &*timings_ : nullptr, .sem_ir = &*sem_ir_, .llvm_context = llvm_context_, + .is_lowered = is_lowered(), .total_ir_count = total_ir_count_}; } @@ -175,6 +176,8 @@ auto CompilationUnit::PostCheck() -> void { } auto CompilationUnit::RunLower() -> void { + CARBON_CHECK(is_lowered(), "Should not lower this compilation unit"); + LogCall("Lower::LowerToLLVM", "lower", [&] { Lower::LowerToLLVMOptions options; options.llvm_verifier_stream = @@ -364,27 +367,10 @@ auto CompilationUnit::RunCodeGenHelper() -> bool { } } } else { - llvm::SmallString<256> output_filename = llvm::StringRef(output_filename_); - if (output_filename.empty()) { - if (!source_->is_regular_file()) { - // Don't invent file names like `-.o` or `/dev/stdin.o`. - // TODO: Consider rephrasing the diagnostic to use the file as the - // `Emit` location. - CARBON_DIAGNOSTIC(CompileInputNotRegularFile, Error, - "output file name must be specified for input `{0}` " - "that is not a regular file", - std::string); - driver_env_->emitter.Emit(CompileInputNotRegularFile, input_filename_); - return false; - } - output_filename = input_filename_; - llvm::sys::path::replace_extension(output_filename, - options_->asm_output ? ".s" : ".o"); - } - CARBON_VLOG("Writing output to: {0}\n", output_filename); + CARBON_VLOG("Writing output to: {0}\n", output_filename_); std::error_code ec; - llvm::raw_fd_ostream output_file(output_filename, ec, + llvm::raw_fd_ostream output_file(output_filename_, ec, llvm::sys::fs::OF_None); if (ec) { // TODO: Consider rephrasing the diagnostic to use the file as the `Emit` @@ -392,8 +378,8 @@ auto CompilationUnit::RunCodeGenHelper() -> bool { CARBON_DIAGNOSTIC(CompileOutputFileOpenError, Error, "could not open output file `{0}`: {1}", std::string, std::string); - driver_env_->emitter.Emit(CompileOutputFileOpenError, - output_filename.str().str(), ec.message()); + driver_env_->emitter.Emit(CompileOutputFileOpenError, output_filename_, + ec.message()); return false; } if (options_->asm_output) { @@ -647,6 +633,10 @@ auto CompileDriver::Compile(DriverEnv& driver_env) -> DriverResult { // Lower and optimize. for (const auto& unit : units_) { + if (!unit->is_lowered()) { + continue; + } + unit->RunLower(); if (options_->phase != CompileOptions::Phase::Lower) { @@ -662,28 +652,9 @@ auto CompileDriver::Compile(DriverEnv& driver_env) -> DriverResult { CARBON_CHECK(options_->phase == CompileOptions::Phase::CodeGen, "CodeGen should be the last stage"); - bool output_last_input_only = options_->output_last_input_only; - if (!output_last_input_only && units_.size() > 1 && - !options_->output_filename.empty() && options_->output_filename != "-") { - // TODO: Command line structure should change to make this implicit - // (passing non-compiling inputs differently), and the warning should be - // removed. - CARBON_DIAGNOSTIC( - CompileMultipleInputsWithOutput, Warning, - "only outputting {0} to {1}, skipping output of {2} input " - "file{2:s}; pass `--output-last-input-only` to silence this warning", - std::string, std::string, Diagnostics::IntAsSelect); - driver_env.emitter.Emit(CompileMultipleInputsWithOutput, - units_.back()->input_filename().str(), - options_->output_filename.str(), units_.size() - 1); - output_last_input_only = true; - } - // Codegen. - if (output_last_input_only) { - units_.back()->RunCodeGen(); - } else { - for (const auto& unit : units_) { + for (const auto& unit : units_) { + if (unit->is_lowered()) { unit->RunCodeGen(); } } diff --git a/toolchain/driver/compile_driver.h b/toolchain/driver/compile_driver.h index f421775683db..cdb1d163b5d6 100644 --- a/toolchain/driver/compile_driver.h +++ b/toolchain/driver/compile_driver.h @@ -20,7 +20,10 @@ class MultiUnitCache; // Ties together information for a file being compiled. class CompilationUnit { public: - // `driver_env`, `options`, `consumer`, and `target` must be non-null. + // `driver_env`, `options`, `consumer`, and `target` must be non-null. If + // `output_filename` is empty, no output will be generated for this file. This + // is used for inputs that are only used as dependencies of the current + // compilation. explicit CompilationUnit(SemIR::CheckIRId check_ir_id, int total_ir_count, DriverEnv* driver_env, const CompileOptions* options, Diagnostics::Consumer* consumer, @@ -67,6 +70,7 @@ class CompilationUnit { auto input_filename() -> llvm::StringRef { return input_filename_; } auto output_filename() -> llvm::StringRef { return output_filename_; } + auto is_lowered() -> bool { return !output_filename_.empty(); } auto has_include_in_dumps() -> bool { return tokens_ && tokens_->has_include_in_dumps(); } @@ -236,8 +240,7 @@ class CompileDriver { explicit CompileDriver(CompileOptions* options); // Configure the toolchain to compile all input files and dependencies. - // The `map_input` function maps an input file name to an output static - // object name. + // The `map_input` function maps an input file name to an output file name. // Returns `false` on configuration error. [[nodiscard]] auto Initialize( DriverEnv& driver_env, diff --git a/toolchain/driver/compile_options.cpp b/toolchain/driver/compile_options.cpp index 0507e2e13629..fc57f6e510d7 100644 --- a/toolchain/driver/compile_options.cpp +++ b/toolchain/driver/compile_options.cpp @@ -374,17 +374,6 @@ Excludes files with the given prefix from dumps. )""", }, [&](auto& arg_b) { arg_b.Append(&exclude_dump_file_prefixes); }); - b.AddFlag( - { - .name = "output-last-input-only", - .help = R"""( -Only write output for the last input file, ignoring all others. - -TODO: This is a temporary workaround and should be removed once separate -compilation is better implemented. -)""", - }, - [&](auto& arg_b) { arg_b.Set(&output_last_input_only); }); b.AddStringOption( { .name = "sem-ir-crash-dump", diff --git a/toolchain/driver/compile_options.h b/toolchain/driver/compile_options.h index b874f8fb5b03..a85ce0520404 100644 --- a/toolchain/driver/compile_options.h +++ b/toolchain/driver/compile_options.h @@ -115,7 +115,6 @@ struct CompileOptions { Parse::ParseOptions::DumpFormat parse_dump_format; bool builtin_sem_ir = false; bool prelude_import = true; - bool output_last_input_only = false; bool include_carbon_core = true; llvm::SmallVector exclude_dump_file_prefixes; diff --git a/toolchain/driver/compile_subcommand.cpp b/toolchain/driver/compile_subcommand.cpp index f2c65ebcc166..6a913da62db2 100644 --- a/toolchain/driver/compile_subcommand.cpp +++ b/toolchain/driver/compile_subcommand.cpp @@ -4,6 +4,10 @@ #include "toolchain/driver/compile_subcommand.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Path.h" +#include "toolchain/diagnostics/emitter.h" +#include "toolchain/diagnostics/format_providers.h" #include "toolchain/driver/compile_driver.h" namespace Carbon { @@ -35,12 +39,84 @@ auto CompileSubcommand::Run(DriverEnv& driver_env) -> DriverResult { return {.success = false}; } + // If we're lowering and have an output file name, we can only support a + // single input filename. + // TODO: Produce an error in this case rather than skipping all files but the + // last, and remove the `--output-last-input-only` flag. + if (options_.compile_options.phase >= CompileOptions::Phase::Lower && + options_.compile_options.input_filenames.size() > 1 && + !options_.output_last_input_only && + !options_.compile_options.output_filename.empty() && + options_.compile_options.output_filename != "-") { + CARBON_DIAGNOSTIC( + CompileMultipleInputsWithOutput, Warning, + "only outputting {0} to {1}, skipping output of {2} input " + "file{2:s}; pass `--output-last-input-only` to silence this " + "warning", + std::string, std::string, Diagnostics::IntAsSelect); + driver_env.emitter.Emit( + CompileMultipleInputsWithOutput, + options_.compile_options.input_filenames.back().str(), + options_.compile_options.output_filename.str(), + options_.compile_options.input_filenames.size() - 1); + } + + llvm::StringSet<> input_filenames(llvm::from_range, + options_.compile_options.input_filenames); + auto compile_driver = CompileDriver(&options_.compile_options); - if (!compile_driver.Initialize( - driver_env, [&](llvm::StringRef) -> std::string { - return options_.compile_options.output_filename.str(); - })) { + bool init_success = true; + auto get_output_filename = + [&](llvm::StringRef input_filename) -> std::string { + // We only generate output for inputs specified on the command line, + // not for inputs discovered through imports. + if (!input_filenames.contains(input_filename)) { + return ""; + } + + // If the output filename is "-", that's used for all inputs. + if (options_.compile_options.output_filename == "-") { + return "-"; + } + + // If single output filename was specified, it's used for the final + // input filename only. + if (!options_.compile_options.output_filename.empty()) { + if (input_filename == options_.compile_options.input_filenames.back()) { + return options_.compile_options.output_filename.str(); + } + return ""; + } + + // Otherwise, generate an output filename for each explicitly-specified + // input file. + bool is_regular_file = true; + if (input_filename == "-") { + // TODO: If we would produce textual output, using "-" as the default + // output filename here would be reasonable and useful. + is_regular_file = false; + } else if (auto status = driver_env.fs->status(input_filename); + status && status->isOther()) { + is_regular_file = false; + } + if (!is_regular_file) { + CARBON_DIAGNOSTIC(CompileInputNotRegularFile, Error, + "output file name must be specified for input " + "`{0}` that is not a regular file", + std::string); + driver_env.emitter.Emit(CompileInputNotRegularFile, input_filename.str()); + init_success = false; + return ""; + } + llvm::SmallString<256> output_filename = input_filename; + llvm::sys::path::replace_extension( + output_filename, options_.compile_options.asm_output ? ".s" : ".o"); + return output_filename.str().str(); + }; + + if (!compile_driver.Initialize(driver_env, get_output_filename) || + !init_success) { return {.success = false}; } diff --git a/toolchain/driver/compile_subcommand.h b/toolchain/driver/compile_subcommand.h index 47a64ba13353..8aa57568484d 100644 --- a/toolchain/driver/compile_subcommand.h +++ b/toolchain/driver/compile_subcommand.h @@ -16,10 +16,22 @@ namespace Carbon { struct CompileSubcommandOptions { auto Build(CommandLine::CommandBuilder& b) -> void { compile_options.BuildForCompileSubcommand(b, &codegen_options); + b.AddFlag( + { + .name = "output-last-input-only", + .help = R"""( +Only write output for the last input file, ignoring all others. + +TODO: This is a temporary workaround and should be removed once separate +compilation is better implemented. +)""", + }, + [&](auto& arg_b) { arg_b.Set(&output_last_input_only); }); } CodegenOptions codegen_options; CompileOptions compile_options; + bool output_last_input_only = false; }; // Implements the compile subcommand of the driver. diff --git a/toolchain/driver/testdata/stdin.carbon b/toolchain/driver/testdata/stdin.carbon index 27df3370f956..e53f7f351ab3 100644 --- a/toolchain/driver/testdata/stdin.carbon +++ b/toolchain/driver/testdata/stdin.carbon @@ -6,7 +6,7 @@ // dump flags. // TODO: Align lex/parse with check/lower. // -// ARGS: compile - --phase=lower --no-prelude-import --target=x86_64-linux-gnu --dump-tokens --dump-parse-tree --parse-dump-format=yaml-postorder --dump-sem-ir --dump-raw-sem-ir --dump-llvm-ir +// ARGS: compile - --output=- --phase=lower --no-prelude-import --target=x86_64-linux-gnu --dump-tokens --dump-parse-tree --parse-dump-format=yaml-postorder --dump-sem-ir --dump-raw-sem-ir --dump-llvm-ir // // AUTOUPDATE // TIP: To test this file alone, run: diff --git a/toolchain/lower/testdata/function/generic/call_different_specific.carbon b/toolchain/lower/testdata/function/generic/call_different_specific.carbon index dc454daec477..b96f762c0ad5 100644 --- a/toolchain/lower/testdata/function/generic/call_different_specific.carbon +++ b/toolchain/lower/testdata/function/generic/call_different_specific.carbon @@ -48,7 +48,7 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; ModuleID = 'call_different_specific.carbon' // CHECK:STDOUT: source_filename = "call_different_specific.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: %type.58 = type {} +// CHECK:STDOUT: %type.0 = type {} // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CM.Main(ptr %ptr_i32, ptr %ptr_f64) #0 !dbg !4 { @@ -73,7 +73,7 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define linkonce_odr void @_CF.Main.58016a73bff04416(ptr %x) #0 !dbg !27 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %A.call = call %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 zeroinitializer), !dbg !30 +// CHECK:STDOUT: %A.call = call %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 zeroinitializer), !dbg !30 // CHECK:STDOUT: call void @_CB.Main.58016a73bff04416(ptr %x), !dbg !31 // CHECK:STDOUT: ret void, !dbg !32 // CHECK:STDOUT: } @@ -81,15 +81,15 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define linkonce_odr void @_CF.Main.fa1f0912a5bbe922(ptr %x) #0 !dbg !33 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %A.call = call %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 zeroinitializer), !dbg !36 +// CHECK:STDOUT: %A.call = call %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 zeroinitializer), !dbg !36 // CHECK:STDOUT: call void @_CB.Main.fa1f0912a5bbe922(ptr %x), !dbg !37 // CHECK:STDOUT: ret void, !dbg !38 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define linkonce_odr %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 %x) #0 !dbg !39 { +// CHECK:STDOUT: define linkonce_odr %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 %x) #0 !dbg !39 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret %type.58 %x, !dbg !44 +// CHECK:STDOUT: ret %type.0 %x, !dbg !44 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind diff --git a/toolchain/lower/testdata/interop/cpp/operators.carbon b/toolchain/lower/testdata/interop/cpp/operators.carbon index 610f3dad578a..b199ae8608d4 100644 --- a/toolchain/lower/testdata/interop/cpp/operators.carbon +++ b/toolchain/lower/testdata/interop/cpp/operators.carbon @@ -290,7 +290,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // 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.A.62 = type { i32 } +// CHECK:STDOUT: %struct.A.4 = type { i32 } // CHECK:STDOUT: // CHECK:STDOUT: $_Zlt1AS_ = comdat any // CHECK:STDOUT: @@ -313,8 +313,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -323,9 +323,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -339,8 +339,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -349,9 +349,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zle1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -365,8 +365,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -375,9 +375,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zgt1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -391,8 +391,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -401,9 +401,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zge1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -467,15 +467,15 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zlt1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 -// CHECK:STDOUT: %value = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %value = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %value, align 4, !tbaa !61 -// CHECK:STDOUT: %value2 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %value2 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %value2, align 4, !tbaa !61 // CHECK:STDOUT: %cmp = icmp slt i32 %0, %1 // CHECK:STDOUT: ret i1 %cmp @@ -487,19 +487,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zle1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: %lnot = xor i1 %call, true @@ -509,19 +509,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zgt1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: ret i1 %call @@ -530,19 +530,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zge1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: %lnot = xor i1 %call, true diff --git a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon index dd0d76773517..009c76fd8b01 100644 --- a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon +++ b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon @@ -368,7 +368,7 @@ fn InitNontrivialDtor() { // 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: %"class.std::initializer_list.64" = type { ptr, i64 } +// CHECK:STDOUT: %"class.std::initializer_list.6" = type { ptr, i64 } // CHECK:STDOUT: // CHECK:STDOUT: $_ZN11vector_likeD2Ev = comdat any // CHECK:STDOUT: @@ -442,7 +442,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %list.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %"class.std::initializer_list.64", align 8 +// CHECK:STDOUT: %agg.tmp = alloca %"class.std::initializer_list.6", align 8 // CHECK:STDOUT: store ptr %list, ptr %list.addr, align 8, !tbaa !38 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !41 // CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !41 @@ -521,7 +521,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN11vector_likeC2ESt16initializer_listIiE(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr %list.coerce0, i64 %list.coerce1) unnamed_addr #2 comdat align 2 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %list = alloca %"class.std::initializer_list.64", align 8 +// CHECK:STDOUT: %list = alloca %"class.std::initializer_list.6", align 8 // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: %0 = getelementptr inbounds nuw { ptr, i64 }, ptr %list, i32 0, i32 0 // CHECK:STDOUT: store ptr %list.coerce0, ptr %0, align 8