Skip to content

Commit

Permalink
Merge pull request rust-lang#244 from rust-lang/feature/unwinding
Browse files Browse the repository at this point in the history
Implement unwinding
  • Loading branch information
antoyo authored Jan 11, 2023
2 parents 7c1d21c + 8e77fbf commit 6c5a70d
Show file tree
Hide file tree
Showing 20 changed files with 388 additions and 97 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Expand Down
2 changes: 1 addition & 1 deletion build_sysroot/build_sysroot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion example/alloc_example.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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";
Expand Down
26 changes: 26 additions & 0 deletions failing-ui-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions failing-ui-tests12.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 2 additions & 3 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
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),
});
}

Expand Down Expand Up @@ -739,7 +738,7 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}

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)
Expand Down
6 changes: 5 additions & 1 deletion src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_
// 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.
Expand Down Expand Up @@ -146,7 +150,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_
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);

{
Expand Down
86 changes: 77 additions & 9 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,11 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
}
}

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
}
}
Expand All @@ -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)
}

Expand Down Expand Up @@ -450,8 +451,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
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);
Expand Down Expand Up @@ -1161,22 +1190,61 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}

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();
}

Expand Down
21 changes: 11 additions & 10 deletions src/callee.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -16,22 +14,26 @@ use crate::context::CodegenCx;
///
/// - `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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6c5a70d

Please sign in to comment.