Skip to content

Commit

Permalink
Make dedup guard optional (#1215)
Browse files Browse the repository at this point in the history
  • Loading branch information
hkratz authored Sep 20, 2021
1 parent f75b8b7 commit 5fdbc47
Show file tree
Hide file tree
Showing 11 changed files with 647 additions and 620 deletions.
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

0 comments on commit 5fdbc47

Please sign in to comment.