Skip to content

Make dedup guard optional #1215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
9 changes: 8 additions & 1 deletion ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ set -ex
#export RUST_TEST_NOCAPTURE=1
#export RUST_TEST_THREADS=1

RUSTFLAGS="$RUSTFLAGS -D warnings "
export RUSTFLAGS="${RUSTFLAGS} -D warnings -Z merge-functions=disabled "

export STDARCH_DISABLE_DEDUP_GUARD=1

case ${TARGET} in
# On Windows the linker performs identical COMDAT folding (ICF) by default
# in release mode which removes identical COMDAT sections. This interferes
# with our instruction assertions just like LLVM's MergeFunctions pass so
# we disable it.
*-pc-windows-msvc)
export RUSTFLAGS="${RUSTFLAGS} -Clink-args=/OPT:NOICF"
;;
# On 32-bit use a static relocation model which avoids some extra
# instructions when dealing with static data, notably allowing some
Expand Down
57 changes: 36 additions & 21 deletions crates/assert-instr-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ pub fn assert_instr(
// testing for.
let disable_assert_instr = std::env::var("STDARCH_DISABLE_ASSERT_INSTR").is_ok();

// Disable dedup guard. Only works if the LLVM MergeFunctions pass is disabled, e.g.
// with `-Z merge-functions=disabled` in RUSTFLAGS.
let disable_dedup_guard = std::env::var("STDARCH_DISABLE_DEDUP_GUARD").is_ok();

// If instruction tests are disabled avoid emitting this shim at all, just
// return the original item without our attribute.
if !cfg!(optimized) || disable_assert_instr {
Expand Down Expand Up @@ -128,27 +132,38 @@ pub fn assert_instr(
syn::LitStr::new("C", proc_macro2::Span::call_site())
};
let shim_name_str = format!("{}{}", shim_name, assert_name);
let to_test = quote! {

const #shim_name_ptr : *const u8 = #shim_name_str.as_ptr();

#attrs
#[no_mangle]
#[inline(never)]
pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret {
// The compiler in optimized mode by default runs a pass called
// "mergefunc" where it'll merge functions that look identical.
// Turns out some intrinsics produce identical code and they're
// folded together, meaning that one just jumps to another. This
// messes up our inspection of the disassembly of this function and
// we're not a huge fan of that.
//
// To thwart this pass and prevent functions from being merged we
// generate some code that's hopefully very tight in terms of
// codegen but is otherwise unique to prevent code from being
// folded.
::stdarch_test::_DONT_DEDUP = #shim_name_ptr;
#name::<#(#const_vals),*>(#(#input_vals),*)
let to_test = if disable_dedup_guard {
quote! {
#attrs
#[no_mangle]
#[inline(never)]
pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret {
#name::<#(#const_vals),*>(#(#input_vals),*)
}
}
} else {
quote! {

const #shim_name_ptr : *const u8 = #shim_name_str.as_ptr();

#attrs
#[no_mangle]
#[inline(never)]
pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret {
// The compiler in optimized mode by default runs a pass called
// "mergefunc" where it'll merge functions that look identical.
// Turns out some intrinsics produce identical code and they're
// folded together, meaning that one just jumps to another. This
// messes up our inspection of the disassembly of this function and
// we're not a huge fan of that.
//
// To thwart this pass and prevent functions from being merged we
// generate some code that's hopefully very tight in terms of
// codegen but is otherwise unique to prevent code from being
// folded.
::stdarch_test::_DONT_DEDUP = #shim_name_ptr;
#name::<#(#const_vals),*>(#(#input_vals),*)
}
}
};

Expand Down
Loading