Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ bazel_dep(name = "zstd", version = "1.5.7.bcr.1", repo_name = "llvm_zstd")
# We pin to specific upstream commits and try to track top-of-tree reasonably
# closely rather than pinning to a specific release.
# HEAD as of 2026-02-12.
llvm_project_version = "b20d7d0278059735bb8eb538ac51e13b58895c1a"
llvm_project_version = "6811a83c81500ee373adfc0d9978ff9625a4cf1c"

# Load a repository for the raw llvm-project, pre-overlay.
http_archive(
name = "llvm-raw",
build_file_content = "# empty",
integrity = "sha256-sRZjS3KippWoaVcr1mWtJ1kFZ+jrjb/KoNkzh+N8HOM=",
integrity = "sha256-vo6s56nm08V/ffBlouba7xYb1m5IW3U/0ZBh42T90ak=",
patch_args = ["-p1"],
patches = [
"@carbon//bazel/llvm_project:0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch",
Expand Down
1 change: 0 additions & 1 deletion third_party/llvm/clang_cc1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ auto RunClangCC1(const InstallPaths& installation,
// engine. If we've already hit an error, we can exit early once that's done.
diag_buffer.FlushDiagnostics(clang_instance->getDiagnostics());
if (!success) {
clang_instance->getDiagnosticClient().finish();
return EXIT_FAILURE;
}

Expand Down
183 changes: 93 additions & 90 deletions toolchain/driver/clang_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,101 +340,104 @@ auto ClangRunner::RunInternal(
CARBON_VLOG(" '{0}'\n", cstr_arg);
}

// Create the diagnostic options and parse arguments controlling them out of
// our arguments.
std::unique_ptr<clang::DiagnosticOptions> diagnostic_options =
clang::CreateAndPopulateDiagOpts(cstr_args);

// TODO: We don't yet support serializing diagnostics the way the actual
// `clang` command line does. Unclear if we need to or not, but it would need
// a bit more logic here to set up chained consumers.
clang::TextDiagnosticPrinter diagnostic_client(llvm::errs(),
*diagnostic_options);

// Note that the `DiagnosticsEngine` takes ownership (via a ref count) of the
// DiagnosticIDs, unlike the other parameters.
clang::DiagnosticsEngine diagnostics(clang::DiagnosticIDs::create(),
*diagnostic_options, &diagnostic_client,
/*ShouldOwnClient=*/false);
clang::ProcessWarningOptions(diagnostics, *diagnostic_options, *fs_);

// Note that we configure the driver's *default* target here, not the expected
// target as that will be parsed out of the command line below.
clang::driver::Driver driver(clang_path_.native(),
llvm::sys::getDefaultTargetTriple(), diagnostics,
"clang LLVM compiler", fs_);

llvm::Triple target_triple(target);

// We need to set an SDK system root on macOS by default. Setting it here
// allows a custom sysroot to still be specified on the command line.
//
// TODO: A different system root should be used for iOS, watchOS, tvOS.
// Currently, we're only targeting macOS support though.
if (target_triple.isMacOSX()) {
// This is the default CLT system root, shown by `xcrun --show-sdk-path`.
// We hard code it here to avoid the overhead of subprocessing to `xcrun` on
// each Clang invocation, but this may need to be updated to search or
// reflect macOS versions if this changes in the future.
driver.SysRoot = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk";
}
llvm::SmallVector<std::pair<int, const clang::driver::Command*>>
failing_commands;
int result = -1;
{
// Create the diagnostic options and parse arguments controlling them out of
// our arguments.
std::unique_ptr<clang::DiagnosticOptions> diagnostic_options =
clang::CreateAndPopulateDiagOpts(cstr_args);

// TODO: We don't yet support serializing diagnostics the way the actual
// `clang` command line does. Unclear if we need to or not, but it would
// need a bit more logic here to set up chained consumers.
clang::TextDiagnosticPrinter diagnostic_client(llvm::errs(),
*diagnostic_options);

// Note that the `DiagnosticsEngine` takes ownership (via a ref count) of
// the DiagnosticIDs, unlike the other parameters.
clang::DiagnosticsEngine diagnostics(
clang::DiagnosticIDs::create(), *diagnostic_options, &diagnostic_client,
/*ShouldOwnClient=*/false);
clang::ProcessWarningOptions(diagnostics, *diagnostic_options, *fs_);

// Note that we configure the driver's *default* target here, not the
// expected target as that will be parsed out of the command line below.
clang::driver::Driver driver(clang_path_.native(),
llvm::sys::getDefaultTargetTriple(),
diagnostics, "clang LLVM compiler", fs_);

llvm::Triple target_triple(target);

// We need to set an SDK system root on macOS by default. Setting it here
// allows a custom sysroot to still be specified on the command line.
//
// TODO: A different system root should be used for iOS, watchOS, tvOS.
// Currently, we're only targeting macOS support though.
if (target_triple.isMacOSX()) {
// This is the default CLT system root, shown by `xcrun --show-sdk-path`.
// We hard code it here to avoid the overhead of subprocessing to `xcrun`
// on each Clang invocation, but this may need to be updated to search or
// reflect macOS versions if this changes in the future.
driver.SysRoot = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk";
}

// If we have a target-specific resource directory, set it as the default
// here, otherwise use the installation's resource directory.
driver.ResourceDir = target_resource_dir_path
? target_resource_dir_path->str()
: installation_->clang_resource_path().native();

// Configure the install directory to find other tools and data files.
//
// We directly override the detected directory as we use a synthetic path
// above. This makes it appear that our binary was in the installed binaries
// directory, and allows finding tools relative to it.
driver.Dir = installation_->llvm_install_bin();
CARBON_VLOG("Setting bin directory to: {0}\n", driver.Dir);

// When there's only one command being run, this will run it in-process.
// However, a `clang` invocation may cause multiple `cc1` invocations, which
// still subprocess. See `InProcess` comment at:
// https://github.com/llvm/llvm-project/blob/86ce8e4504c06ecc3cc42f002ad4eb05cac10925/clang/lib/Driver/Job.cpp#L411-L413
//
// Note the subprocessing will effectively call `clang -cc1`, which turns into
// `carbon-busybox clang -cc1`, which results in an equivalent `clang_main`
// call.
//
// Also note that we only do `-disable-free` filtering in the in-process
// execution here, as subprocesses leaking memory won't impact this process.
auto cc1_main = [this, enable_leaking](
llvm::SmallVectorImpl<const char*>& cc1_args) -> int {
return RunClangCC1(*installation_, fs_, cc1_args, enable_leaking);
};
driver.CC1Main = cc1_main;

std::unique_ptr<clang::driver::Compilation> compilation(
driver.BuildCompilation(cstr_args));
CARBON_CHECK(compilation, "Should always successfully allocate!");
if (compilation->containsError()) {
// These should have been diagnosed by the driver.
return false;
}
// If we have a target-specific resource directory, set it as the default
// here, otherwise use the installation's resource directory.
driver.ResourceDir = target_resource_dir_path
? target_resource_dir_path->str()
: installation_->clang_resource_path().native();

// Configure the install directory to find other tools and data files.
//
// We directly override the detected directory as we use a synthetic path
// above. This makes it appear that our binary was in the installed binaries
// directory, and allows finding tools relative to it.
driver.Dir = installation_->llvm_install_bin();
CARBON_VLOG("Setting bin directory to: {0}\n", driver.Dir);

// When there's only one command being run, this will run it in-process.
// However, a `clang` invocation may cause multiple `cc1` invocations, which
// still subprocess. See `InProcess` comment at:
// https://github.com/llvm/llvm-project/blob/86ce8e4504c06ecc3cc42f002ad4eb05cac10925/clang/lib/Driver/Job.cpp#L411-L413
//
// Note the subprocessing will effectively call `clang -cc1`, which turns
// into `carbon-busybox clang -cc1`, which results in an equivalent
// `clang_main` call.
//
// Also note that we only do `-disable-free` filtering in the in-process
// execution here, as subprocesses leaking memory won't impact this process.
auto cc1_main = [this, enable_leaking](
llvm::SmallVectorImpl<const char*>& cc1_args) -> int {
return RunClangCC1(*installation_, fs_, cc1_args, enable_leaking);
};
driver.CC1Main = cc1_main;

std::unique_ptr<clang::driver::Compilation> compilation(
driver.BuildCompilation(cstr_args));
CARBON_CHECK(compilation, "Should always successfully allocate!");
if (compilation->containsError()) {
// These should have been diagnosed by the driver.
return false;
}

// Make sure our target detection matches Clang's. Sadly, we can't just reuse
// Clang's as it is available too late.
// TODO: Use nice diagnostics here rather than a check failure.
CARBON_CHECK(llvm::Triple(target) == llvm::Triple(driver.getTargetTriple()),
"Mismatch between the expected target '{0}' and the one "
"computed by Clang '{1}'",
target, driver.getTargetTriple());
// Make sure our target detection matches Clang's. Sadly, we can't just
// reuse Clang's as it is available too late.
// TODO: Use nice diagnostics here rather than a check failure.
CARBON_CHECK(llvm::Triple(target) == llvm::Triple(driver.getTargetTriple()),
"Mismatch between the expected target '{0}' and the one "
"computed by Clang '{1}'",
target, driver.getTargetTriple());

CARBON_VLOG("Running Clang driver...\n");
CARBON_VLOG("Running Clang driver...\n");

llvm::SmallVector<std::pair<int, const clang::driver::Command*>>
failing_commands;
int result = driver.ExecuteCompilation(*compilation, failing_commands);
result = driver.ExecuteCompilation(*compilation, failing_commands);

// Finish diagnosing any failures before we verbosely log the source of those
// failures.
diagnostic_client.finish();
// Let diagnostics fall out of scope and be destroyed. This finishes
// diagnosing any failures before we verbosely log the source of those
// failures.
Comment on lines +437 to +439
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional (happy for it here, or in a follow-up, or I can send a follow-up):

Given that upstream is now baking more assumptions in about the scope here, I would be inclined to extract this block into a helper function? That would let it return the integer and failing commands, and also hold a comment about the fact that the compilation is fundamentally stateful. WDYT?

}

CARBON_VLOG("Execution result code: {0}\n", result);
for (const auto& [command_result, failing_command] : failing_commands) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,34 @@ fn Call() -> i32 {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: noinline nounwind optnone
// CHECK:STDOUT: define i32 @_CCall.Main() #2 !dbg !12 {
// CHECK:STDOUT: define i32 @_CCall.Main() #2 !dbg !11 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %g.call = call i32 @_Z1gv(), !dbg !16
// CHECK:STDOUT: ret i32 %g.call, !dbg !17
// CHECK:STDOUT: %g.call = call i32 @_Z1gv(), !dbg !15
// CHECK:STDOUT: ret i32 %g.call, !dbg !16
// CHECK:STDOUT: }
// 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 #1 = { 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 #2 = { noinline nounwind optnone }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
// CHECK:STDOUT: !llvm.dbg.cu = !{!6}
// CHECK:STDOUT: !llvm.errno.tbaa = !{!8}
// 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 1, !"wchar_size", i32 4}
// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 2}
// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2}
// CHECK:STDOUT: !5 = !{i32 7, !"uwtable", i32 2}
// CHECK:STDOUT: !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !7, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !7 = !DIFile(filename: "foo.carbon", directory: "")
// CHECK:STDOUT: !8 = !{!9, !9, i64 0}
// CHECK:STDOUT: !9 = !{!"int", !10, i64 0}
// CHECK:STDOUT: !10 = !{!"omnipotent char", !11, i64 0}
// CHECK:STDOUT: !11 = !{!"Simple C++ TBAA"}
// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "Call", linkageName: "_CCall.Main", scope: null, file: !7, line: 12, type: !13, spFlags: DISPFlagDefinition, unit: !6)
// CHECK:STDOUT: !13 = !DISubroutineType(types: !14)
// CHECK:STDOUT: !14 = !{!15}
// CHECK:STDOUT: !15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK:STDOUT: !16 = !DILocation(line: 13, column: 10, scope: !12)
// CHECK:STDOUT: !17 = !DILocation(line: 13, column: 3, scope: !12)
// 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: "foo.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 = distinct !DISubprogram(name: "Call", linkageName: "_CCall.Main", scope: null, file: !6, line: 12, type: !12, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !12 = !DISubroutineType(types: !13)
// CHECK:STDOUT: !13 = !{!14}
// CHECK:STDOUT: !14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK:STDOUT: !15 = !DILocation(line: 13, column: 10, scope: !11)
// CHECK:STDOUT: !16 = !DILocation(line: 13, column: 3, scope: !11)
Loading
Loading