391 lines
18 KiB
Diff
391 lines
18 KiB
Diff
This reverts
|
|
https://github.com/rust-lang/rust/commit/659e20fa7524f8fd217476daf5ecbbe366b2ae61
|
|
and
|
|
https://github.com/rust-lang/rust/pull/131829
|
|
|
|
to restore support for -Zprofile (gcov-style coverage) that was removed from
|
|
rustc 1.84.0
|
|
|
|
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
|
|
index a25ce9e5a90..5fb2f7d7e7b 100644
|
|
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
|
|
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
|
|
@@ -269,6 +269,11 @@ fn probestack_attr<'ll, 'tcx>(cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>) -> Option<&
|
|
return None;
|
|
}
|
|
|
|
+ // probestack doesn't play nice either with gcov profiling.
|
|
+ if tcx.sess.opts.unstable_opts.profile {
|
|
+ return None;
|
|
+ }
|
|
+
|
|
let attr_value = match tcx.sess.target.stack_probes {
|
|
StackProbeType::None => return None,
|
|
// Request LLVM to generate the probes inline. If the given LLVM version does not support
|
|
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
|
|
index bcadb6f0de9..691c53f5782 100644
|
|
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
|
|
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
|
|
@@ -762,6 +762,7 @@ fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) {
|
|
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
|
config.instrument_coverage,
|
|
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
|
+ config.instrument_gcov,
|
|
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
|
config.debug_info_for_profiling,
|
|
llvm_selfprofiler,
|
|
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
|
|
index e11ed796887..ee21a6d3644 100644
|
|
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
|
|
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
|
|
@@ -1,7 +1,7 @@
|
|
use std::borrow::Cow;
|
|
use std::fmt::{self, Write};
|
|
use std::hash::{Hash, Hasher};
|
|
-use std::path::PathBuf;
|
|
+use std::path::{Path, PathBuf};
|
|
use std::sync::Arc;
|
|
use std::{iter, ptr};
|
|
|
|
@@ -9,6 +9,7 @@
|
|
use rustc_abi::{Align, Size};
|
|
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
|
|
use rustc_codegen_ssa::traits::*;
|
|
+use rustc_fs_util::path_to_c_string;
|
|
use rustc_hir::def::{CtorKind, DefKind};
|
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
|
use rustc_middle::bug;
|
|
@@ -939,8 +940,33 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
|
debug_name_table_kind,
|
|
);
|
|
|
|
+ if tcx.sess.opts.unstable_opts.profile {
|
|
+ let default_gcda_path = &output_filenames.with_extension("gcda");
|
|
+ let gcda_path =
|
|
+ tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
|
|
+
|
|
+ let gcov_cu_info = [
|
|
+ path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
|
|
+ path_to_mdstring(debug_context.llcontext, gcda_path),
|
|
+ unit_metadata,
|
|
+ ];
|
|
+ let gcov_metadata = llvm::LLVMMDNodeInContext2(
|
|
+ debug_context.llcontext,
|
|
+ gcov_cu_info.as_ptr(),
|
|
+ gcov_cu_info.len(),
|
|
+ );
|
|
+ let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata);
|
|
+
|
|
+ llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val);
|
|
+ }
|
|
+
|
|
return unit_metadata;
|
|
};
|
|
+
|
|
+ fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata {
|
|
+ let path_str = path_to_c_string(path);
|
|
+ unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) }
|
|
+ }
|
|
}
|
|
|
|
/// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.
|
|
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
|
|
index 1c63bbcd171..74f563e7470 100644
|
|
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
|
|
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
|
|
@@ -55,6 +55,7 @@
|
|
|
|
/// A context object for maintaining all state needed by the debuginfo module.
|
|
pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
|
|
+ llcontext: &'ll llvm::Context,
|
|
llmod: &'ll llvm::Module,
|
|
builder: DIBuilderBox<'ll>,
|
|
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
|
|
@@ -70,7 +71,9 @@ pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
|
|
debug!("CodegenUnitDebugContext::new");
|
|
let builder = DIBuilderBox::new(llmod);
|
|
// DIBuilder inherits context from the module, so we'd better use the same one
|
|
+ let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
|
|
CodegenUnitDebugContext {
|
|
+ llcontext,
|
|
llmod,
|
|
builder,
|
|
created_files: Default::default(),
|
|
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
|
|
index a90013801c8..a42d6d9a243 100644
|
|
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
|
|
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
|
|
@@ -876,6 +876,7 @@ pub(crate) fn LLVMModuleCreateWithNameInContext(
|
|
ModuleID: *const c_char,
|
|
C: &Context,
|
|
) -> &Module;
|
|
+ pub(crate) fn LLVMGetModuleContext(M: &Module) -> &Context;
|
|
pub(crate) safe fn LLVMCloneModule(M: &Module) -> &Module;
|
|
|
|
/// Data layout. See Module::getDataLayout.
|
|
@@ -2382,6 +2383,7 @@ pub(crate) fn LLVMRustOptimize<'a>(
|
|
PGOUsePath: *const c_char,
|
|
InstrumentCoverage: bool,
|
|
InstrProfileOutput: *const c_char,
|
|
+ InstrumentGCOV: bool,
|
|
PGOSampleUsePath: *const c_char,
|
|
DebugInfoForProfiling: bool,
|
|
llvm_selfprofiler: *mut c_void,
|
|
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
|
|
index 3e36bd8552b..e64a0110a08 100644
|
|
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
|
|
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
|
|
@@ -84,6 +84,7 @@ pub struct ModuleConfig {
|
|
pub pgo_sample_use: Option<PathBuf>,
|
|
pub debug_info_for_profiling: bool,
|
|
pub instrument_coverage: bool,
|
|
+ pub instrument_gcov: bool,
|
|
|
|
pub sanitizer: SanitizerSet,
|
|
pub sanitizer_recover: SanitizerSet,
|
|
@@ -116,7 +117,12 @@ pub struct ModuleConfig {
|
|
}
|
|
|
|
impl ModuleConfig {
|
|
- fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
|
|
+ fn new(
|
|
+ kind: ModuleKind,
|
|
+ tcx: TyCtxt<'_>,
|
|
+ no_builtins: bool,
|
|
+ is_compiler_builtins: bool,
|
|
+ ) -> ModuleConfig {
|
|
// If it's a regular module, use `$regular`, otherwise use `$other`.
|
|
// `$regular` and `$other` are evaluated lazily.
|
|
macro_rules! if_regular {
|
|
@@ -175,6 +181,13 @@ macro_rules! if_regular {
|
|
pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
|
|
debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
|
|
instrument_coverage: if_regular!(sess.instrument_coverage(), false),
|
|
+ instrument_gcov: if_regular!(
|
|
+ // compiler_builtins overrides the codegen-units settings,
|
|
+ // which is incompatible with -Zprofile which requires that
|
|
+ // only a single codegen unit is used per crate.
|
|
+ sess.opts.unstable_opts.profile && !is_compiler_builtins,
|
|
+ false
|
|
+ ),
|
|
|
|
sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()),
|
|
sanitizer_dataflow_abilist: if_regular!(
|
|
@@ -436,11 +449,14 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
|
|
|
|
let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
|
|
let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
|
|
+ let is_compiler_builtins = attr::contains_name(crate_attrs, sym::compiler_builtins);
|
|
|
|
let crate_info = CrateInfo::new(tcx, target_cpu);
|
|
|
|
- let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
|
|
- let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
|
|
+ let regular_config =
|
|
+ ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins);
|
|
+ let allocator_config =
|
|
+ ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins);
|
|
|
|
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
|
|
let (codegen_worker_send, codegen_worker_receive) = channel();
|
|
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
|
|
index a78b0e8e1ed..b2fefc50806 100644
|
|
--- a/compiler/rustc_interface/src/tests.rs
|
|
+++ b/compiler/rustc_interface/src/tests.rs
|
|
@@ -851,6 +851,8 @@ macro_rules! tracked {
|
|
tracked!(plt, Some(true));
|
|
tracked!(polonius, Polonius::Legacy);
|
|
tracked!(precise_enum_drop_elaboration, false);
|
|
+ tracked!(profile, true);
|
|
+ tracked!(profile_emit, Some(PathBuf::from("abc")));
|
|
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
|
|
tracked!(profiler_runtime, "abc".to_string());
|
|
tracked!(reg_struct_return, true);
|
|
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
|
|
index 733f5fd0df0..664940af30c 100644
|
|
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
|
|
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
|
|
@@ -42,6 +42,7 @@
|
|
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
|
|
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
|
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
|
|
+#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
|
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
|
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
|
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
|
@@ -568,8 +569,9 @@ extern "C" LLVMRustResult LLVMRustOptimize(
|
|
bool PrintBeforeEnzyme, bool PrintAfterEnzyme, bool PrintPasses,
|
|
LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath,
|
|
const char *PGOUsePath, bool InstrumentCoverage,
|
|
- const char *InstrProfileOutput, const char *PGOSampleUsePath,
|
|
- bool DebugInfoForProfiling, void *LlvmSelfProfiler,
|
|
+ const char *InstrProfileOutput, bool InstrumentGCOV,
|
|
+ const char *PGOSampleUsePath, bool DebugInfoForProfiling,
|
|
+ void *LlvmSelfProfiler,
|
|
LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
|
|
LLVMRustSelfProfileAfterPassCallback AfterPassCallback,
|
|
const char *ExtraPasses, size_t ExtraPassesLen, const char *LLVMPlugins,
|
|
@@ -711,6 +713,13 @@ extern "C" LLVMRustResult LLVMRustOptimize(
|
|
});
|
|
}
|
|
|
|
+ if (InstrumentGCOV) {
|
|
+ PipelineStartEPCallbacks.push_back(
|
|
+ [](ModulePassManager &MPM, OptimizationLevel Level) {
|
|
+ MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault()));
|
|
+ });
|
|
+ }
|
|
+
|
|
if (InstrumentCoverage) {
|
|
PipelineStartEPCallbacks.push_back(
|
|
[InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) {
|
|
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
|
|
index 4000f12459a..cf1abd3f8c9 100644
|
|
--- a/compiler/rustc_metadata/src/creader.rs
|
|
+++ b/compiler/rustc_metadata/src/creader.rs
|
|
@@ -1003,7 +1003,7 @@ fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
|
|
|
|
fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) {
|
|
let needs_profiler_runtime =
|
|
- tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled();
|
|
+ tcx.sess.instrument_coverage() || tcx.sess.opts.unstable_opts.profile || tcx.sess.opts.cg.profile_generate.enabled();
|
|
if !needs_profiler_runtime || tcx.sess.opts.unstable_opts.no_profiler_runtime {
|
|
return;
|
|
}
|
|
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
|
|
index f0dc5b9ac48..f6a1c9858e9 100644
|
|
--- a/compiler/rustc_session/src/config.rs
|
|
+++ b/compiler/rustc_session/src/config.rs
|
|
@@ -2474,7 +2474,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
|
let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
|
|
|
|
let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers);
|
|
- let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
|
|
+ let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
|
|
early_dcx,
|
|
&output_types,
|
|
matches,
|
|
@@ -2493,6 +2493,18 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
|
|
|
let assert_incr_state = parse_assert_incr_state(early_dcx, &unstable_opts.assert_incr_state);
|
|
|
|
+ if unstable_opts.profile && incremental.is_some() {
|
|
+ early_dcx.early_fatal("can't instrument with gcov profiling when compiling incrementally");
|
|
+ }
|
|
+ if unstable_opts.profile {
|
|
+ match codegen_units {
|
|
+ Some(1) => {}
|
|
+ None => codegen_units = Some(1),
|
|
+ Some(_) => early_dcx
|
|
+ .early_fatal("can't instrument with gcov profiling with multiple codegen units"),
|
|
+ }
|
|
+ }
|
|
+
|
|
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
|
|
early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive");
|
|
}
|
|
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
|
|
index 96bdcf8beff..a506b494232 100644
|
|
--- a/compiler/rustc_session/src/options.rs
|
|
+++ b/compiler/rustc_session/src/options.rs
|
|
@@ -2591,8 +2591,13 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
|
|
proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,
|
|
parse_proc_macro_execution_strategy, [UNTRACKED],
|
|
"how to run proc-macro code (default: same-thread)"),
|
|
+ profile: bool = (false, parse_bool, [TRACKED],
|
|
+ "insert profiling code (default: no)"),
|
|
profile_closures: bool = (false, parse_no_value, [UNTRACKED],
|
|
"profile size of closures"),
|
|
+ profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
|
+ "file path to emit profiling data at runtime when using 'profile' \
|
|
+ (default based on relative source path)"),
|
|
profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
|
"use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
|
|
profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],
|
|
diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md
|
|
index 57679f82f48..0f88bec2c71 100644
|
|
--- a/src/doc/rustc/src/instrument-coverage.md
|
|
+++ b/src/doc/rustc/src/instrument-coverage.md
|
|
@@ -2,8 +2,12 @@
|
|
|
|
## Introduction
|
|
|
|
-This document describes how to enable and use LLVM instrumentation-based coverage,
|
|
-via the `-C instrument-coverage` compiler flag.
|
|
+The Rust compiler includes two code coverage implementations:
|
|
+
|
|
+- A GCC-compatible, gcov-based coverage implementation, enabled with `-Z profile`, which derives coverage data based on DebugInfo.
|
|
+- A source-based code coverage implementation, enabled with `-C instrument-coverage`, which uses LLVM's native, efficient coverage instrumentation to generate very precise coverage data.
|
|
+
|
|
+This document describes how to enable and use the LLVM instrumentation-based coverage, via the `-C instrument-coverage` compiler flag.
|
|
|
|
## How it works
|
|
|
|
diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md
|
|
new file mode 100644
|
|
index 00000000000..71303bfaff2
|
|
--- /dev/null
|
|
+++ b/src/doc/unstable-book/src/compiler-flags/profile.md
|
|
@@ -0,0 +1,27 @@
|
|
+# `profile`
|
|
+
|
|
+The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
|
|
+
|
|
+------------------------
|
|
+
|
|
+This feature allows the generation of code coverage reports.
|
|
+
|
|
+Set the `-Zprofile` compiler flag in order to enable gcov profiling.
|
|
+
|
|
+For example:
|
|
+```Bash
|
|
+cargo new testgcov --bin
|
|
+cd testgcov
|
|
+export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
|
+export CARGO_INCREMENTAL=0
|
|
+cargo build
|
|
+cargo run
|
|
+```
|
|
+
|
|
+Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
|
|
+You can parse them with [llvm-cov gcov](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/mozilla/grcov).
|
|
+
|
|
+Please note that `RUSTFLAGS` by default applies to everything that cargo builds and runs during a build!
|
|
+When the `--target` flag is explicitly passed to cargo, the `RUSTFLAGS` no longer apply to build scripts and procedural macros.
|
|
+For more fine-grained control consider passing a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to
|
|
+rustc for the specific crates you want to profile.
|
|
diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs
|
|
new file mode 100644
|
|
index 00000000000..58a1b53c040
|
|
--- /dev/null
|
|
+++ b/tests/run-make/profile/rmake.rs
|
|
@@ -0,0 +1,21 @@
|
|
+// This test revolves around the rustc flag -Z profile, which should
|
|
+// generate a .gcno file (initial profiling information) as well
|
|
+// as a .gcda file (branch counters). The path where these are emitted
|
|
+// should also be configurable with -Z profile-emit. This test checks
|
|
+// that the files are produced, and then that the latter flag is respected.
|
|
+// See https://github.com/rust-lang/rust/pull/42433
|
|
+
|
|
+//@ ignore-cross-compile
|
|
+//@ needs-profiler-runtime
|
|
+
|
|
+use run_make_support::{path, run, rustc};
|
|
+
|
|
+fn main() {
|
|
+ rustc().arg("-g").arg("-Zprofile").input("test.rs").run();
|
|
+ run("test");
|
|
+ assert!(path("test.gcno").exists(), "no .gcno file");
|
|
+ assert!(path("test.gcda").exists(), "no .gcda file");
|
|
+ rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run();
|
|
+ run("test");
|
|
+ assert!(path("abc/abc.gcda").exists(), "gcda file not emitted to defined path");
|
|
+}
|
|
diff --git a/tests/run-make/profile/test.rs b/tests/run-make/profile/test.rs
|
|
new file mode 100644
|
|
index 00000000000..f328e4d9d04
|
|
--- /dev/null
|
|
+++ b/tests/run-make/profile/test.rs
|
|
@@ -0,0 +1 @@
|
|
+fn main() {}
|