Skip to content
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
8 changes: 4 additions & 4 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@ dependencies = [

[[package]]
name = "gccjit"
version = "4.1.0"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859af1dd2815fd0f8ca97f5917a595f18c415692b07e58993a6ad34ff13204d5"
checksum = "0d4c19a75fd8c674bbcd459fc8235ff38f8e5219c07fc3b022556fd28d16c909"
dependencies = [
"gccjit_sys",
]

[[package]]
name = "gccjit_sys"
version = "2.0.0"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab6a00a243aba2a45442bfd72b28d871137d4dac094f13de7f48cf9705112ffe"
checksum = "54c3a46c818a4b7d6c8d572ed0f3513a091dcf8e8dbafbb58381c6062eaef942"
dependencies = [
"libc",
]
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ default = ["master"]
[dependencies]
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
tempfile = "3.20"
gccjit = { version = "4.1.0", features = ["dlopen"] }
gccjit = { version = "5.0.0", features = ["dlopen"] }
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] }

# Local copy.
#gccjit = { path = "../gccjit.rs", features = ["dlopen"] }
# gccjit = { path = "../gccjit.rs", features = ["dlopen"] }

[dev-dependencies]
boml = "0.3.1"
Expand Down
2 changes: 1 addition & 1 deletion libgccjit.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
dfbee712e611693596ffec1de22177089c537491
3498409672c805d51b46faaa4a14f8682de8e1bf
5 changes: 5 additions & 0 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ pub fn compile_codegen_unit(
// ... and now that we have everything pre-defined, fill out those definitions.
for &(mono_item, item_data) in &mono_items {
mono_item.define::<Builder<'_, '_, '_>>(&mut cx, cgu_name.as_str(), item_data);

// Now that this function's blocks all exist, fill in the cleanup
// regions reconstructed from MIR while lowering its `invoke`s.
#[cfg(feature = "master")]
cx.populate_cleanup_regions();
}

// If this codegen unit contains the main function, also create the
Expand Down
54 changes: 29 additions & 25 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
use crate::abi::FnAbiGccExt;
use crate::common::{SignType, TypeReflection, type_is_pointer};
use crate::context::CodegenCx;
#[cfg(feature = "master")]
use crate::context::PendingCleanup;
use crate::intrinsic::llvm;
use crate::type_of::LayoutGccExt;

Expand Down Expand Up @@ -652,23 +654,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
_funclet: Option<&Funclet>,
instance: Option<Instance<'tcx>>,
) -> RValue<'gcc> {
let try_block = self.current_func().new_block("try");
let current_func = self.current_func();
let try_region = current_func.new_region(self.location);
let try_block = try_region.new_block("try");

let current_block = self.block;
self.block = try_block;
let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here?
self.block = current_block;

let return_value = self.new_temp(self.current_func(), self.location, call.get_type());
let return_value = self.new_temp(current_func, self.location, call.get_type());

try_block.add_assignment(self.location, return_value, call);

try_block.end_with_jump(self.location, then);

if self.cleanup_blocks.borrow().contains(&catch) {
self.block.add_try_finally(self.location, try_block, catch);
if self.cx.landing_pads.borrow().contains(&catch) {
let cleanup_region = current_func.new_region(self.location);
self.block.add_cleanup(self.location, try_region, cleanup_region);
self.cx
.pending_cleanups
.borrow_mut()
.push(PendingCleanup { region: cleanup_region, landing_pad: catch });
} else {
self.block.add_try_catch(self.location, try_block, catch);
let catch_region = current_func.new_region(self.location);
for clone in gccjit::clone_blocks(&[catch]) {
catch_region.add_block(clone);
}
self.block.add_try_catch(self.location, try_region, catch_region);
}

self.block.end_with_jump(self.location, then);
Expand Down Expand Up @@ -706,6 +719,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
if return_type == void_type {
self.block.end_with_void_return(self.location)
} else {
let abort = self.context.get_builtin_function("abort");
self.block.add_eval(self.location, self.context.new_call(self.location, abort, &[]));
let return_value = self.new_temp(self.current_func(), self.location, return_type);
self.block.end_with_return(self.location, return_value)
}
Expand Down Expand Up @@ -1636,18 +1651,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {

// 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(self.location, eh_pointer_builtin, &[zero]);

let value1_type = self.u8_type.make_pointer();
let ptr = self.cx.context.new_cast(self.location, ptr, value1_type);
let value1 = ptr;
let value2 = zero; // FIXME(antoyo): set the proper value here (the type of exception?).
self.cx.landing_pads.borrow_mut().insert(self.block);

// A cleanup resumes by falling through: it never inspects the exception
// object.
let value1 = self.context.new_null(self.u8_type.make_pointer());
let value2 = self.context.new_rvalue_zero(self.i32_type);
(value1, value2)
}

Expand All @@ -1661,18 +1670,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}

fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) {
// FIXME(antoyo): generate the correct landing pad
self.cleanup_landing_pad(pers_fn);
self.set_personality_fn(pers_fn);
}

#[cfg(feature = "master")]
fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
let exn_type = exn0.get_type();
let exn = self.context.new_cast(self.location, exn0, exn_type);
let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
self.llbb()
.add_eval(self.location, self.context.new_call(self.location, unwind_resume, &[exn]));
self.unreachable();
fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
// End the cleanup by falling off the end of its region body.
self.block.end_with_fallthrough(self.location);
}

#[cfg(not(feature = "master"))]
Expand Down
48 changes: 46 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::cell::{Cell, RefCell};
use std::collections::HashMap;

#[cfg(feature = "master")]
use gccjit::Region;
use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type};
use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_codegen_ssa::base::wants_msvc_seh;
Expand Down Expand Up @@ -28,6 +30,12 @@ use crate::callee::get_fn;
use crate::common::SignType;
use crate::type_::StructTypeKey;

#[cfg(feature = "master")]
pub struct PendingCleanup<'gcc> {
pub region: Region<'gcc>,
pub landing_pad: Block<'gcc>,
}

#[cfg_attr(not(feature = "master"), expect(dead_code))]
pub struct CodegenCx<'gcc, 'tcx> {
/// A cache of converted ConstAllocs
Expand Down Expand Up @@ -128,8 +136,14 @@ pub struct CodegenCx<'gcc, 'tcx> {

pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,

/// Blocks that are cleanup landing pads, so `invoke` can tell an unwind
/// edge into a cleanup from a catch/terminate.
#[cfg(feature = "master")]
pub cleanup_blocks: RefCell<FxHashSet<Block<'gcc>>>,
pub landing_pads: RefCell<FxHashSet<Block<'gcc>>>,
/// Cleanup regions to be filled in once the function is fully codegened
/// (done in `populate_cleanup_regions`).
#[cfg(feature = "master")]
pub pending_cleanups: RefCell<Vec<PendingCleanup<'gcc>>>,
/// The alignment of a u128/i128 type.
// We cache this, since it is needed for alignment checks during loads.
pub int128_align: Align,
Expand Down Expand Up @@ -307,13 +321,43 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
rust_try_fn: Cell::new(None),
pointee_infos: Default::default(),
#[cfg(feature = "master")]
cleanup_blocks: Default::default(),
landing_pads: Default::default(),
#[cfg(feature = "master")]
pending_cleanups: Default::default(),
};
// FIXME(antoyo): instead of doing this, add SsizeT to libgccjit.
cx.isize_type = usize_type.to_signed(&cx);
cx
}

/// Fill in the member blocks of every pending cleanup region.
///
/// Clone all blocks reachable from a cleanup block into the cleanup region.
#[cfg(feature = "master")]
pub fn populate_cleanup_regions(&self) {
let pending = std::mem::take(&mut *self.pending_cleanups.borrow_mut());

for cleanup in pending {
// The landing pad is the region's entry, so it must come first.
let mut blocks = vec![];
let mut visited = FxHashSet::default();
let mut stack = vec![cleanup.landing_pad];
while let Some(block) = stack.pop() {
if !visited.insert(block) {
continue;
}
blocks.push(block);
stack.extend(block.get_successors());
}

for clone in gccjit::clone_blocks(&blocks) {
cleanup.region.add_block(clone);
}
}

self.landing_pads.borrow_mut().clear();
}

pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
debug_assert!(
Expand Down
20 changes: 16 additions & 4 deletions src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::{Span, Symbol, sym};
use rustc_target::callconv::{ArgAbi, PassMode};

Expand Down Expand Up @@ -646,10 +647,21 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}

fn assume(&mut self, value: Self::Value) {
// FIXME(antoyo): switch to assume when it exists.
// Or use something like this:
// #define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
self.expect(value, true);
// libgccjit currently has no direct equivalent of LLVM's `llvm.assume`,
// so use the idiom `if (!cond) __builtin_unreachable()`.
// FIXME: this should use IFN_ASSUME when we have internal functions in
// libgccjit.
if self.sess().opts.optimize == OptLevel::No {
return;
}
let then_block = self.append_sibling_block("assume_holds");
let unreachable_block = self.append_sibling_block("assume_violated");
self.block.end_with_conditional(self.location, value, then_block, unreachable_block);

self.switch_to_block(unreachable_block);
self.unreachable();

self.switch_to_block(then_block);
}

fn expect(&mut self, cond: Self::Value, _expected: bool) -> Self::Value {
Expand Down
14 changes: 0 additions & 14 deletions tests/failing-ui-tests.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
tests/ui/asm/may_unwind.rs
tests/ui/asm/x86_64/may_unwind.rs
tests/ui/drop/dynamic-drop-async.rs
tests/ui/intrinsics/panic-uninitialized-zeroed.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
tests/ui/simd/issue-17170.rs
tests/ui/simd/issue-39720.rs
tests/ui/drop/panic-during-drop-14875.rs
tests/ui/drop/move-closure-drop-on-unwind.rs
tests/ui/process/println-with-broken-pipe.rs
tests/ui/lto/thin-lto-inlines2.rs
tests/ui/panic-runtime/lto-abort.rs
tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs
tests/ui/async-await/deep-futures-are-freeze.rs
tests/ui/coroutine/resume-after-return.rs
tests/ui/simd/repr_packed.rs
tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
tests/ui/consts/const_cmp_type_id.rs
Expand All @@ -32,7 +27,6 @@ tests/ui/sanitizer/cfi/sized-associated-ty.rs
tests/ui/sanitizer/cfi/can-reveal-opaques.rs
tests/ui/consts/const-eval/parse_ints.rs
tests/ui/simd/intrinsic/generic-as.rs
tests/ui/runtime/rt-explody-panic-payloads.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
Expand All @@ -49,13 +43,10 @@ tests/ui/simd/simd-bitmask-notpow2.rs
tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
tests/ui/numbers-arithmetic/u128-as-f32.rs
tests/ui/process/nofile-limit.rs
tests/ui/panics/unwind-force-no-unwind-tables.rs
tests/ui/attributes/fn-align-dyn.rs
tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs
tests/ui/statics/const_generics.rs
tests/ui/test-attrs/test-panic-while-printing.rs
tests/ui/thir-print/offset_of.rs
tests/ui/iterators/iter-filter-count-debug-check.rs
tests/ui/eii/default/call_impl.rs
tests/ui/asm/x86_64/global_asm_escape.rs
tests/ui/lto/all-crates.rs
Expand All @@ -71,8 +62,3 @@ tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs
tests/ui/abi/rust-tail-cc.rs
tests/ui/abi/rust-preserve-none-cc.rs
tests/ui/extern/extern-types-field-offset.rs
tests/ui/panics/panic-in-dtor-drops-fields.rs
tests/ui/array-slice-vec/slice-panic-1.rs
tests/ui/array-slice-vec/slice-panic-2.rs
tests/ui/drop/enum-destructor-on-unwind.rs
tests/ui/std/add-spawn-hook-reentrancy-159923.rs
10 changes: 8 additions & 2 deletions tests/lang_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,10 @@ fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) {
"[DEBUG] lang run",
"tests/run",
TestMode::CompileAndRun,
&[],
&[
// FIXME: remove this when the unwind issue is fixed in GCC m68k upstream.
"catch_unwind.rs",
],
);
build_test_runner(
tempdir,
Expand All @@ -309,7 +312,10 @@ fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) {
"[RELEASE] lang run",
"tests/run",
TestMode::CompileAndRun,
&[],
&[
// FIXME: remove this when the unwind issue is fixed in GCC m68k upstream.
"catch_unwind.rs",
],
);
}

Expand Down
25 changes: 25 additions & 0 deletions tests/run/catch_unwind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Compiler:
//
// Run-time:
// status: 0
// stdout: Caught

#![feature(fn_traits, unboxed_closures)]

struct Wrapper<A>(A);

impl<R, F: FnOnce() -> R> FnOnce<()> for Wrapper<F> {
type Output = R;

#[inline]
extern "rust-call" fn call_once(self, _args: ()) -> R {
(self.0)()
}
}

fn main() {
std::panic::set_hook(Box::new(|_| {}));
let result = std::panic::catch_unwind(Wrapper(|| panic!()));
assert!(result.is_err());
println!("Caught");
}
Loading