Merge pull request #244 from rust-lang/feature/unwinding
Implement unwinding
This commit is contained in:
commit
6c5a70de20
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -19,9 +19,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- { gcc: "libgccjit.so", extra: "", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", extra: "", artifacts_branch: "master-without-128bit-integers" }
|
||||
- { gcc: "libgccjit12.so", extra: "--no-default-features", artifacts_branch: "gcc12" }
|
||||
- { gcc: "libgccjit.so", extra: "", env_extra: "", artifacts_branch: "master" }
|
||||
- { gcc: "libgccjit_without_int128.so", extra: "", env_extra: "", artifacts_branch: "master-without-128bit-integers" }
|
||||
- { gcc: "libgccjit12.so", extra: "--no-default-features", env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests'", artifacts_branch: "gcc12" }
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
@ -120,8 +120,8 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
./prepare_build.sh
|
||||
./build.sh ${{ matrix.libgccjit_version.extra }}
|
||||
cargo test ${{ matrix.libgccjit_version.extra }}
|
||||
${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }}
|
||||
${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
|
||||
./clean_all.sh
|
||||
|
||||
- name: Prepare dependencies
|
||||
@ -143,7 +143,7 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
|
||||
${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
|
||||
|
||||
duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -41,7 +41,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#f30cc2bd330f4fda3d625f305bdfd7e523e2d8f8"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#1e6ecc67fe73ac995e511516eacf4fe3aec8974e"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
@ -49,7 +49,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#f30cc2bd330f4fda3d625f305bdfd7e523e2d8f8"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#1e6ecc67fe73ac995e511516eacf4fe3aec8974e"
|
||||
dependencies = [
|
||||
"libc 0.1.12",
|
||||
]
|
||||
|
18
Readme.md
18
Readme.md
@ -162,8 +162,26 @@ To print a debug representation of a tree:
|
||||
debug_tree(expr);
|
||||
```
|
||||
|
||||
(defined in print-tree.h)
|
||||
|
||||
To print a debug reprensentation of a gimple struct:
|
||||
|
||||
```c
|
||||
debug_gimple_stmt(gimple_struct)
|
||||
```
|
||||
|
||||
To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
|
||||
|
||||
To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`, TODO
|
||||
|
||||
Maybe by calling the following at the beginning of gdb:
|
||||
|
||||
```
|
||||
set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc
|
||||
```
|
||||
|
||||
TODO: but that's not what I remember I was doing.
|
||||
|
||||
### How to use a custom-build rustc
|
||||
|
||||
* Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
|
||||
|
@ -16,7 +16,7 @@ rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true
|
||||
rm -r sysroot/ 2>/dev/null || true
|
||||
|
||||
# Build libs
|
||||
export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked -Cpanic=abort"
|
||||
export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked"
|
||||
if [[ "$1" == "--release" ]]; then
|
||||
sysroot_channel='release'
|
||||
RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
|
||||
|
@ -38,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Cpanic=abort -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot"
|
||||
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
|
||||
|
||||
# FIXME(antoyo): remove once the atomic shim is gone
|
||||
if [[ `uname` == 'Darwin' ]]; then
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(start, box_syntax, core_intrinsics, alloc_error_handler)]
|
||||
#![feature(start, box_syntax, core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
@ -26,6 +26,16 @@ fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
fn eh_personality() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn _Unwind_Resume() {
|
||||
core::intrinsics::unreachable();
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let world: Box<&str> = box "Hello World!\0";
|
||||
|
@ -41,3 +41,29 @@ src/test/ui/sse2.rs
|
||||
src/test/ui/statics/issue-91050-1.rs
|
||||
src/test/ui/statics/issue-91050-2.rs
|
||||
src/test/ui/target-feature/missing-plusminus.rs
|
||||
src/test/ui/asm/x86_64/may_unwind.rs
|
||||
src/test/ui/backtrace.rs
|
||||
src/test/ui/catch-unwind-bang.rs
|
||||
src/test/ui/cfg/cfg-panic-abort.rs
|
||||
src/test/ui/drop/dynamic-drop-async.rs
|
||||
src/test/ui/drop/repeat-drop.rs
|
||||
src/test/ui/fmt/format-args-capture.rs
|
||||
src/test/ui/generator/panic-drops-resume.rs
|
||||
src/test/ui/generator/panic-drops.rs
|
||||
src/test/ui/generator/panic-safe.rs
|
||||
src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
|
||||
src/test/ui/issues/issue-14875.rs
|
||||
src/test/ui/issues/issue-29948.rs
|
||||
src/test/ui/issues/issue-43853.rs
|
||||
src/test/ui/iterators/iter-sum-overflow-debug.rs
|
||||
src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
|
||||
src/test/ui/mir/mir_calls_to_shims.rs
|
||||
src/test/ui/mir/mir_drop_order.rs
|
||||
src/test/ui/mir/mir_let_chains_drop_order.rs
|
||||
src/test/ui/oom_unwind.rs
|
||||
src/test/ui/panic-runtime/abort-link-to-unwinding-crates.rs
|
||||
src/test/ui/panic-runtime/abort.rs
|
||||
src/test/ui/panic-runtime/link-to-abort.rs
|
||||
src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
|
||||
src/test/ui/rfcs/rfc1857-drop-order.rs
|
||||
src/test/ui/unwind-no-uwtable.rs
|
||||
|
@ -22,3 +22,12 @@ src/test/ui/simd/intrinsic/inlining-issue67557.rs
|
||||
src/test/ui/simd/monomorphize-shuffle-index.rs
|
||||
src/test/ui/simd/shuffle.rs
|
||||
src/test/ui/simd/simd-bitmask.rs
|
||||
src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
|
||||
src/test/ui/drop/dynamic-drop.rs
|
||||
src/test/ui/generator/resume-after-return.rs
|
||||
src/test/ui/iterators/iter-step-overflow-debug.rs
|
||||
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
|
||||
src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
|
||||
src/test/ui/panic-while-printing.rs
|
||||
src/test/ui/privacy/reachable-unnameable-items.rs
|
||||
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
|
||||
|
@ -352,8 +352,7 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
|
||||
inputs.push(AsmInOperand {
|
||||
constraint: "X".into(),
|
||||
rust_idx,
|
||||
val: self.cx.rvalue_as_function(get_fn(self.cx, instance))
|
||||
.get_address(None),
|
||||
val: get_fn(self.cx, instance).get_address(None),
|
||||
});
|
||||
}
|
||||
|
||||
@ -739,7 +738,7 @@ fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[Gl
|
||||
}
|
||||
|
||||
GlobalAsmOperandRef::SymFn { instance } => {
|
||||
let function = self.rvalue_as_function(get_fn(self, instance));
|
||||
let function = get_fn(self, instance);
|
||||
self.add_used_function(function);
|
||||
// TODO(@Amanieu): Additional mangling is needed on
|
||||
// some targets to add a leading underscore (Mach-O)
|
||||
|
@ -87,6 +87,10 @@ fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol
|
||||
// Instantiate monomorphizations without filling out definitions yet...
|
||||
//let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
|
||||
let context = Context::default();
|
||||
|
||||
context.add_command_line_option("-fexceptions");
|
||||
context.add_driver_option("-fexceptions");
|
||||
|
||||
// TODO(antoyo): only set on x86 platforms.
|
||||
context.add_command_line_option("-masm=intel");
|
||||
// TODO(antoyo): only add the following cli argument if the feature is supported.
|
||||
@ -146,7 +150,7 @@ fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol
|
||||
context.set_keep_intermediates(true);
|
||||
}
|
||||
|
||||
// TODO(bjorn3): Remove once unwinding is properly implemented
|
||||
// NOTE: The codegen generates unrechable blocks.
|
||||
context.set_allow_unreachable_blocks(true);
|
||||
|
||||
{
|
||||
|
@ -372,10 +372,11 @@ fn handle_fn_abi_err(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
|
||||
impl<'a, 'gcc, 'tcx> Deref for Builder<'a, 'gcc, 'tcx> {
|
||||
type Target = CodegenCx<'gcc, 'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
fn deref<'b>(&'b self) -> &'a Self::Target
|
||||
{
|
||||
self.cx
|
||||
}
|
||||
}
|
||||
@ -393,7 +394,7 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
|
||||
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
|
||||
Builder::with_cx(cx, block)
|
||||
}
|
||||
|
||||
@ -450,8 +451,36 @@ fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: imp
|
||||
self.block.end_with_switch(None, value, default_block, &gcc_cases);
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
let try_block = self.current_func().new_block("try");
|
||||
|
||||
let current_block = self.block.clone();
|
||||
self.block = try_block;
|
||||
let call = self.call(typ, func, args, None); // TODO(antoyo): use funclet here?
|
||||
self.block = current_block;
|
||||
|
||||
let return_value = self.current_func()
|
||||
.new_local(None, call.get_type(), "invokeResult");
|
||||
|
||||
try_block.add_assignment(None, return_value, call);
|
||||
|
||||
try_block.end_with_jump(None, then);
|
||||
|
||||
if self.cleanup_blocks.borrow().contains(&catch) {
|
||||
self.block.add_try_finally(None, try_block, catch);
|
||||
}
|
||||
else {
|
||||
self.block.add_try_catch(None, try_block, catch);
|
||||
}
|
||||
|
||||
self.block.end_with_jump(None, then);
|
||||
|
||||
return_value.to_rvalue()
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
|
||||
// TODO(bjorn3): Properly implement unwinding.
|
||||
let call_site = self.call(typ, func, args, None);
|
||||
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
|
||||
self.llbb().end_with_conditional(None, condition, then, catch);
|
||||
@ -1161,22 +1190,61 @@ fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, i
|
||||
}
|
||||
|
||||
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
|
||||
// TODO(antoyo)
|
||||
#[cfg(feature="master")]
|
||||
{
|
||||
let personality = self.rvalue_as_function(_personality);
|
||||
self.current_func().set_personality_function(personality);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, pers_fn: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.set_personality_fn(pers_fn);
|
||||
|
||||
// NOTE: insert the current block in a variable so that a later call to invoke knows to
|
||||
// generate a try/finally instead of a try/catch for this block.
|
||||
self.cleanup_blocks.borrow_mut().insert(self.block);
|
||||
|
||||
let eh_pointer_builtin = self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
|
||||
let zero = self.cx.context.new_rvalue_zero(self.int_type);
|
||||
let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
|
||||
|
||||
let field1_type = self.u8_type.make_pointer();
|
||||
let field1 = self.context.new_field(None, field1_type, "landing_pad_field_1");
|
||||
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_2");
|
||||
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
|
||||
let value = self.current_func().new_local(None, struct_type.as_type(), "landing_pad");
|
||||
let ptr = self.cx.context.new_cast(None, ptr, field1_type);
|
||||
self.block.add_assignment(None, value.access_field(None, field1), ptr);
|
||||
self.block.add_assignment(None, value.access_field(None, field2), zero); // TODO: set the proper value here (the type of exception?).
|
||||
|
||||
value.to_rvalue()
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
|
||||
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
|
||||
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
|
||||
self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
|
||||
.to_rvalue()
|
||||
// TODO(antoyo): Properly implement unwinding.
|
||||
// the above is just to make the compilation work as it seems
|
||||
// rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn resume(&mut self, exn: RValue<'gcc>) {
|
||||
// TODO: check if this is normal that we need to dereference the value.
|
||||
// NOTE: the type is wrong, so in order to get a pointer for parameter, cast it to a
|
||||
// pointer of pointer that is later dereferenced.
|
||||
let exn_type = exn.get_type().make_pointer();
|
||||
let exn = self.context.new_cast(None, exn, exn_type);
|
||||
let exn = exn.dereference(None).to_rvalue();
|
||||
let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
|
||||
self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn]));
|
||||
self.unreachable();
|
||||
}
|
||||
|
||||
#[cfg(not(feature="master"))]
|
||||
fn resume(&mut self, _exn: RValue<'gcc>) {
|
||||
// TODO(bjorn3): Properly implement unwinding.
|
||||
self.unreachable();
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
#[cfg(feature="master")]
|
||||
use gccjit::{FnAttribute, Visibility};
|
||||
use gccjit::{FunctionType, RValue};
|
||||
use rustc_codegen_ssa::traits::BaseTypeMethods;
|
||||
use gccjit::{FunctionType, Function};
|
||||
use rustc_middle::ty::{self, Instance, TypeVisitable};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::attributes;
|
||||
use crate::context::CodegenCx;
|
||||
|
||||
@ -16,22 +14,26 @@
|
||||
///
|
||||
/// - `cx`: the crate context
|
||||
/// - `instance`: the instance to be instantiated
|
||||
pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> {
|
||||
let tcx = cx.tcx();
|
||||
|
||||
assert!(!instance.substs.needs_infer());
|
||||
assert!(!instance.substs.has_escaping_bound_vars());
|
||||
|
||||
let sym = tcx.symbol_name(instance).name;
|
||||
|
||||
if let Some(&func) = cx.function_instances.borrow().get(&instance) {
|
||||
return func;
|
||||
}
|
||||
|
||||
let sym = tcx.symbol_name(instance).name;
|
||||
|
||||
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
|
||||
let func =
|
||||
if let Some(func) = cx.get_declared_value(&sym) {
|
||||
if let Some(_func) = cx.get_declared_value(&sym) {
|
||||
// FIXME: we never reach this because get_declared_value only returns global variables
|
||||
// and here we try to get a function.
|
||||
unreachable!();
|
||||
/*
|
||||
// Create a fn pointer with the new signature.
|
||||
let ptrty = fn_abi.ptr_to_gcc_type(cx);
|
||||
|
||||
@ -64,7 +66,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
||||
}
|
||||
else {
|
||||
func
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else {
|
||||
cx.linkage.set(FunctionType::Extern);
|
||||
@ -163,8 +165,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
|
||||
unsafe { std::mem::transmute(func) }
|
||||
func
|
||||
};
|
||||
|
||||
cx.function_instances.borrow_mut().insert(instance, func);
|
||||
|
@ -4,6 +4,7 @@
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BackendTypes,
|
||||
BaseTypeMethods,
|
||||
MiscMethods,
|
||||
};
|
||||
use rustc_data_structures::base_n;
|
||||
@ -11,7 +12,7 @@
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::mir::mono::CodegenUnit;
|
||||
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
|
||||
use rustc_middle::ty::layout::{FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||
@ -82,7 +83,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
||||
/// Cache instances of monomorphic and polymorphic items
|
||||
pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>,
|
||||
/// Cache function instances of monomorphic and polymorphic items
|
||||
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>,
|
||||
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
|
||||
/// Cache generated vtables
|
||||
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
|
||||
|
||||
@ -109,6 +110,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
||||
local_gen_sym_counter: Cell<usize>,
|
||||
|
||||
eh_personality: Cell<Option<RValue<'gcc>>>,
|
||||
pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
|
||||
|
||||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||
|
||||
@ -118,6 +120,8 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
||||
/// they can be dereferenced later.
|
||||
/// FIXME(antoyo): fix the rustc API to avoid having this hack.
|
||||
pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>,
|
||||
|
||||
pub cleanup_blocks: RefCell<FxHashSet<Block<'gcc>>>,
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
@ -245,15 +249,18 @@ pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
struct_types: Default::default(),
|
||||
local_gen_sym_counter: Cell::new(0),
|
||||
eh_personality: Cell::new(None),
|
||||
rust_try_fn: Cell::new(None),
|
||||
pointee_infos: Default::default(),
|
||||
structs_as_pointer: Default::default(),
|
||||
cleanup_blocks: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
|
||||
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
|
||||
// FIXME: seems like self.functions get overwritten for rust_eh_personality.
|
||||
debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
|
||||
"{:?} ({:?}) is not a function", value, value.get_type());
|
||||
"{:?} is not a function", function);
|
||||
function
|
||||
}
|
||||
|
||||
@ -326,8 +333,8 @@ fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRe
|
||||
|
||||
fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
let func = get_fn(self, instance);
|
||||
*self.current_func.borrow_mut() = Some(self.rvalue_as_function(func));
|
||||
func
|
||||
*self.current_func.borrow_mut() = Some(func);
|
||||
unsafe { std::mem::transmute(func) }
|
||||
}
|
||||
|
||||
fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
@ -338,8 +345,7 @@ fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
|
||||
self.intrinsics.borrow()[func_name].clone()
|
||||
}
|
||||
else {
|
||||
let func = get_fn(self, instance);
|
||||
self.rvalue_as_function(func)
|
||||
get_fn(self, instance)
|
||||
};
|
||||
let ptr = func.get_address(None);
|
||||
|
||||
@ -377,31 +383,40 @@ fn eh_personality(&self) -> RValue<'gcc> {
|
||||
return llpersonality;
|
||||
}
|
||||
let tcx = self.tcx;
|
||||
let llfn = match tcx.lang_items().eh_personality() {
|
||||
Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr(
|
||||
let func =
|
||||
match tcx.lang_items().eh_personality() {
|
||||
Some(def_id) if !wants_msvc_seh(self.sess()) => {
|
||||
let instance =
|
||||
ty::Instance::resolve(
|
||||
tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
tcx.intern_substs(&[]),
|
||||
)
|
||||
.unwrap().unwrap(),
|
||||
),
|
||||
.unwrap().unwrap();
|
||||
|
||||
let symbol_name = tcx.symbol_name(instance).name;
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(FunctionType::Extern);
|
||||
let func = self.declare_fn(symbol_name, &fn_abi);
|
||||
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
|
||||
func
|
||||
},
|
||||
_ => {
|
||||
let _name = if wants_msvc_seh(self.sess()) {
|
||||
let name =
|
||||
if wants_msvc_seh(self.sess()) {
|
||||
"__CxxFrameHandler3"
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
"rust_eh_personality"
|
||||
};
|
||||
//let func = self.declare_func(name, self.type_i32(), &[], true);
|
||||
// FIXME(antoyo): this hack should not be needed. That will probably be removed when
|
||||
// unwinding support is added.
|
||||
self.context.new_rvalue_from_int(self.int_type, 0)
|
||||
let func = self.declare_func(name, self.type_i32(), &[], true);
|
||||
unsafe { std::mem::transmute(func) }
|
||||
}
|
||||
};
|
||||
// TODO(antoyo): apply target cpu attributes.
|
||||
self.eh_personality.set(Some(llfn));
|
||||
llfn
|
||||
self.eh_personality.set(Some(func));
|
||||
func
|
||||
}
|
||||
|
||||
fn sess(&self) -> &Session {
|
||||
|
@ -38,12 +38,10 @@ pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: G
|
||||
global
|
||||
}
|
||||
|
||||
/*pub fn declare_func(&self, name: &str, return_type: Type<'gcc>, params: &[Type<'gcc>], variadic: bool) -> RValue<'gcc> {
|
||||
self.linkage.set(FunctionType::Exported);
|
||||
let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic);
|
||||
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
|
||||
unsafe { std::mem::transmute(func) }
|
||||
}*/
|
||||
pub fn declare_func(&self, name: &str, return_type: Type<'gcc>, params: &[Type<'gcc>], variadic: bool) -> Function<'gcc> {
|
||||
self.linkage.set(FunctionType::Extern);
|
||||
declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic)
|
||||
}
|
||||
|
||||
pub fn declare_global(&self, name: &str, ty: Type<'gcc>, global_kind: GlobalKind, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
|
||||
let global = self.context.new_global(None, global_kind, ty, name);
|
||||
|
@ -705,9 +705,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
||||
"llvm.x86.aesni.aesenclast.512" => "__builtin_ia32_vaesenclast_v64qi",
|
||||
"llvm.x86.aesni.aesdec.512" => "__builtin_ia32_vaesdec_v64qi",
|
||||
"llvm.x86.aesni.aesdeclast.512" => "__builtin_ia32_vaesdeclast_v64qi",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8hi",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16hi",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32hi",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf",
|
||||
"llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf",
|
||||
"llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf",
|
||||
"llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf",
|
||||
"llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf",
|
||||
|
@ -1,6 +1,9 @@
|
||||
pub mod llvm;
|
||||
mod simd;
|
||||
|
||||
#[cfg(feature="master")]
|
||||
use std::iter;
|
||||
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
@ -8,15 +11,23 @@
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
|
||||
#[cfg(feature="master")]
|
||||
use rustc_codegen_ssa::traits::{DerivedTypeMethods, MiscMethods};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature="master")]
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_span::{Span, Symbol, symbol::kw, sym};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
#[cfg(feature="master")]
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::abi::GccType;
|
||||
#[cfg(feature="master")]
|
||||
use crate::abi::FnAbiGccExt;
|
||||
use crate::builder::Builder;
|
||||
use crate::common::{SignType, TypeReflection};
|
||||
use crate::context::CodegenCx;
|
||||
@ -1115,10 +1126,8 @@ fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
|
||||
// NOTE: the `|| true` here is to use the panic=abort strategy with panic=unwind too
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort || true {
|
||||
// TODO(bjorn3): Properly implement unwinding and remove the `|| true` once this is done.
|
||||
fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(bx: &'b mut Builder<'a, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
bx.call(bx.type_void(), try_func, &[data], None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
// we can never unwind.
|
||||
@ -1129,6 +1138,143 @@ fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<
|
||||
unimplemented!();
|
||||
}
|
||||
else {
|
||||
#[cfg(feature="master")]
|
||||
codegen_gnu_try(bx, try_func, data, _catch_func, dest);
|
||||
#[cfg(not(feature="master"))]
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
// Definition of the standard `try` function for Rust using the GNU-like model
|
||||
// of exceptions (e.g., the normal semantics of LLVM's `landingpad` and `invoke`
|
||||
// instructions).
|
||||
//
|
||||
// This codegen is a little surprising because we always call a shim
|
||||
// function instead of inlining the call to `invoke` manually here. This is done
|
||||
// because in LLVM we're only allowed to have one personality per function
|
||||
// definition. The call to the `try` intrinsic is being inlined into the
|
||||
// function calling it, and that function may already have other personality
|
||||
// functions in play. By calling a shim we're guaranteed that our shim will have
|
||||
// the right personality function.
|
||||
#[cfg(feature="master")]
|
||||
fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>, data: RValue<'gcc>, catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
|
||||
//use std::ops::Deref;
|
||||
//let cx: &CodegenCx<'gcc, '_> = bx.deref();
|
||||
let cx: &CodegenCx<'gcc, '_> = bx.cx;
|
||||
let (llty, func) = get_rust_try_fn(cx, &mut |mut bx| {
|
||||
// Codegens the shims described above:
|
||||
//
|
||||
// bx:
|
||||
// invoke %try_func(%data) normal %normal unwind %catch
|
||||
//
|
||||
// normal:
|
||||
// ret 0
|
||||
//
|
||||
// catch:
|
||||
// (%ptr, _) = landingpad
|
||||
// call %catch_func(%data, %ptr)
|
||||
// ret 1
|
||||
let then = bx.append_sibling_block("then");
|
||||
let catch = bx.append_sibling_block("catch");
|
||||
|
||||
let func = bx.current_func();
|
||||
let try_func = func.get_param(0).to_rvalue();
|
||||
let data = func.get_param(1).to_rvalue();
|
||||
let catch_func = func.get_param(2).to_rvalue();
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
|
||||
let current_block = bx.block.clone();
|
||||
|
||||
bx.switch_to_block(then);
|
||||
bx.ret(bx.const_i32(0));
|
||||
|
||||
// Type indicator for the exception being thrown.
|
||||
//
|
||||
// The value is a pointer to the exception object
|
||||
// being thrown.
|
||||
bx.switch_to_block(catch);
|
||||
bx.set_personality_fn(bx.eh_personality());
|
||||
|
||||
let eh_pointer_builtin = bx.cx.context.get_target_builtin_function("__builtin_eh_pointer");
|
||||
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
|
||||
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
bx.call(catch_ty, catch_func, &[data, ptr], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
|
||||
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
|
||||
// generate a try/catch.
|
||||
// FIXME: add a check in the libgccjit API to prevent this.
|
||||
bx.switch_to_block(current_block);
|
||||
bx.invoke(try_func_ty, try_func, &[data], then, catch, None);
|
||||
});
|
||||
|
||||
let func = unsafe { std::mem::transmute(func) };
|
||||
|
||||
// Note that no invoke is used here because by definition this function
|
||||
// can't panic (that's what it's catching).
|
||||
let ret = bx.call(llty, func, &[try_func, data, catch_func], None);
|
||||
let i32_align = bx.tcx().data_layout.i32_align.abi;
|
||||
bx.store(ret, dest, i32_align);
|
||||
}
|
||||
|
||||
|
||||
// Helper function used to get a handle to the `__rust_try` function used to
|
||||
// catch exceptions.
|
||||
//
|
||||
// This function is only generated once and is then cached.
|
||||
#[cfg(feature="master")]
|
||||
fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
|
||||
if let Some(llfn) = cx.rust_try_fn.get() {
|
||||
return llfn;
|
||||
}
|
||||
|
||||
// Define the type up front for the signature of the rust_try function.
|
||||
let tcx = cx.tcx;
|
||||
let i8p = tcx.mk_mut_ptr(tcx.types.i8);
|
||||
// `unsafe fn(*mut i8) -> ()`
|
||||
let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
iter::once(i8p),
|
||||
tcx.mk_unit(),
|
||||
false,
|
||||
rustc_hir::Unsafety::Unsafe,
|
||||
Abi::Rust,
|
||||
)));
|
||||
// `unsafe fn(*mut i8, *mut i8) -> ()`
|
||||
let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[i8p, i8p].iter().cloned(),
|
||||
tcx.mk_unit(),
|
||||
false,
|
||||
rustc_hir::Unsafety::Unsafe,
|
||||
Abi::Rust,
|
||||
)));
|
||||
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
|
||||
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
|
||||
[try_fn_ty, i8p, catch_fn_ty].iter(),
|
||||
&tcx.types.i32,
|
||||
false,
|
||||
rustc_hir::Unsafety::Unsafe,
|
||||
Abi::Rust,
|
||||
));
|
||||
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
|
||||
cx.rust_try_fn.set(Some(rust_try));
|
||||
rust_try
|
||||
}
|
||||
|
||||
// Helper function to give a Block to a closure to codegen a shim function.
|
||||
// This is currently primarily used for the `try` intrinsic functions above.
|
||||
#[cfg(feature="master")]
|
||||
fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
|
||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||
let (typ, _, _, _) = fn_abi.gcc_type(cx);
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
cx.linkage.set(FunctionType::Internal);
|
||||
let func = cx.declare_fn(name, fn_abi);
|
||||
let func_val = unsafe { std::mem::transmute(func) };
|
||||
cx.set_frame_pointer_type(func_val);
|
||||
cx.apply_target_cpu_attr(func_val);
|
||||
let block = Builder::append_block(cx, func_val, "entry-block");
|
||||
let bx = Builder::build(cx, block);
|
||||
codegen(bx);
|
||||
(typ, func)
|
||||
}
|
||||
|
@ -59,5 +59,8 @@ fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: V
|
||||
// TODO(antoyo): call set_link_section() to allow initializing argc/argv.
|
||||
// TODO(antoyo): set unique comdat.
|
||||
// TODO(antoyo): use inline attribute from there in linkage.set() above.
|
||||
|
||||
self.functions.borrow_mut().insert(symbol_name.to_string(), decl);
|
||||
self.function_instances.borrow_mut().insert(instance, unsafe { std::mem::transmute(decl) });
|
||||
}
|
||||
}
|
||||
|
10
test.sh
10
test.sh
@ -191,11 +191,11 @@ function std_tests() {
|
||||
$RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE
|
||||
|
||||
echo "[AOT] subslice-patterns-const-eval"
|
||||
$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
||||
|
||||
echo "[AOT] track-caller-attribute"
|
||||
$RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
||||
$RUSTC example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
|
||||
$RUN_WRAPPER ./target/out/track-caller-attribute
|
||||
|
||||
echo "[BUILD] mod_bench"
|
||||
@ -338,9 +338,9 @@ function test_rustc() {
|
||||
|
||||
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
|
||||
|
||||
rm -r src/test/ui/{abi*,extern/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
|
||||
rm -r src/test/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
|
||||
rm src/test/ui/mir/mir_heavy_promoted.rs # this tests is oom-killed in the CI.
|
||||
for test in $(rg --files-with-matches "catch_unwind|should_panic|thread|lto" src/test/ui); do
|
||||
for test in $(rg --files-with-matches "thread|lto" src/test/ui); do
|
||||
rm $test
|
||||
done
|
||||
git checkout src/test/ui/lto/auxiliary/dylib.rs
|
||||
@ -348,7 +348,7 @@ function test_rustc() {
|
||||
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
|
||||
git checkout src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
|
||||
|
||||
RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
|
||||
RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot"
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
# No argument supplied to the function. Doing nothing.
|
||||
|
@ -46,11 +46,15 @@ pub fn main_inner(profile: Profile) {
|
||||
&format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir),
|
||||
"--sysroot", &format!("{}/build_sysroot/sysroot/", current_dir),
|
||||
"-Zno-parallel-llvm",
|
||||
"-C", "panic=abort",
|
||||
"-C", "link-arg=-lc",
|
||||
"-o", exe.to_str().expect("to_str"),
|
||||
path.to_str().expect("to_str"),
|
||||
]);
|
||||
if let Some(flags) = option_env!("TEST_FLAGS") {
|
||||
for flag in flags.split_whitespace() {
|
||||
compiler.arg(&flag);
|
||||
}
|
||||
}
|
||||
match profile {
|
||||
Profile::Debug => {}
|
||||
Profile::Release => {
|
||||
|
@ -3,22 +3,14 @@
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
|
||||
|
||||
#![no_std]
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
#![feature(bench_black_box, const_black_box)]
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
use core::hint::black_box;
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
||||
macro_rules! check {
|
||||
($ty:ty, $expr:expr) => {
|
||||
@ -335,6 +327,4 @@ macro_rules! check_ops32 {
|
||||
const VAL5: T = 73236519889708027473620326106273939584_i128;
|
||||
check_ops128!();
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user