Skip to content

Commit 889a33a

Browse files
committed
WIP: Implement unwinding
1 parent 0a54f24 commit 889a33a

File tree

13 files changed

+383
-91
lines changed

13 files changed

+383
-91
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ default = ["master"]
2222
master = ["gccjit/master"]
2323

2424
[dependencies]
25-
gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
25+
#gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
2626

2727
# Local copy.
28-
#gccjit = { path = "../gccjit.rs" }
28+
gccjit = { path = "../gccjit.rs" }
2929

3030
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
3131
target-lexicon = "0.10.0"

Readme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ To print a debug representation of a tree:
162162
debug_tree(expr);
163163
```
164164

165+
(defined in print-tree.h)
166+
167+
To print a debug reprensentation of a gimple struct:
168+
169+
```c
170+
debug_gimple_stmt(gimple_struct)
171+
```
172+
165173
To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
166174
167175
### How to use a custom-build rustc

build_sysroot/build_sysroot.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true
1616
rm -r sysroot/ 2>/dev/null || true
1717

1818
# Build libs
19-
export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked -Cpanic=abort"
19+
export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked"
2020
if [[ "$1" == "--release" ]]; then
2121
sysroot_channel='release'
2222
RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release

config.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
3838
fi
3939
fi
4040

41-
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"
41+
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"
4242

4343
# FIXME(antoyo): remove once the atomic shim is gone
4444
if [[ `uname` == 'Darwin' ]]; then

src/asm.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
352352
inputs.push(AsmInOperand {
353353
constraint: "X".into(),
354354
rust_idx,
355-
val: self.cx.rvalue_as_function(get_fn(self.cx, instance))
356-
.get_address(None),
355+
val: get_fn(self.cx, instance, false).get_address(None),
357356
});
358357
}
359358

@@ -739,7 +738,7 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
739738
}
740739

741740
GlobalAsmOperandRef::SymFn { instance } => {
742-
let function = self.rvalue_as_function(get_fn(self, instance));
741+
let function = get_fn(self, instance, false);
743742
self.add_used_function(function);
744743
// TODO(@Amanieu): Additional mangling is needed on
745744
// some targets to add a leading underscore (Mach-O)

src/base.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_
8787
// Instantiate monomorphizations without filling out definitions yet...
8888
//let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
8989
let context = Context::default();
90+
91+
context.add_command_line_option("-fexceptions");
92+
context.add_driver_option("-fexceptions");
93+
94+
/*context.add_command_line_option("-fasynchronous-unwind-tables");
95+
context.add_driver_option("-fasynchronous-unwind-tables");
96+
97+
context.add_command_line_option("-funwind-tables");
98+
context.add_driver_option("-funwind-tables");*/
99+
90100
// TODO(antoyo): only set on x86 platforms.
91101
context.add_command_line_option("-masm=intel");
92102
// TODO(antoyo): only add the following cli argument if the feature is supported.
@@ -147,6 +157,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_
147157
}
148158

149159
// TODO(bjorn3): Remove once unwinding is properly implemented
160+
// TODO: remove.
150161
context.set_allow_unreachable_blocks(true);
151162

152163
{

src/builder.rs

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use gccjit::{
1313
RValue,
1414
ToRValue,
1515
Type,
16-
UnaryOp,
16+
UnaryOp, FunctionType,
1717
};
1818
use rustc_codegen_ssa::MemFlags;
1919
use rustc_codegen_ssa::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
@@ -372,10 +372,11 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
372372
}
373373
}
374374

375-
impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
375+
impl<'a, 'gcc, 'tcx> Deref for Builder<'a, 'gcc, 'tcx> {
376376
type Target = CodegenCx<'gcc, 'tcx>;
377377

378-
fn deref(&self) -> &Self::Target {
378+
fn deref<'b>(&'b self) -> &'a Self::Target
379+
{
379380
self.cx
380381
}
381382
}
@@ -393,7 +394,7 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
393394
}
394395

395396
impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
396-
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
397+
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
397398
Builder::with_cx(cx, block)
398399
}
399400

@@ -450,8 +451,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
450451
self.block.end_with_switch(None, value, default_block, &gcc_cases);
451452
}
452453

454+
#[cfg(feature="master")]
455+
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
456+
let try_block = self.current_func().new_block("try");
457+
458+
let current_block = self.block.clone();
459+
self.block = try_block;
460+
let call = self.call(typ, func, args, None); // TODO: use funclet here?
461+
self.block = current_block;
462+
463+
let return_value = self.current_func()
464+
.new_local(None, call.get_type(), "invokeResult");
465+
466+
try_block.add_assignment(None, return_value, call);
467+
468+
try_block.end_with_jump(None, then);
469+
470+
self.block.add_try_catch(None, try_block, catch);
471+
472+
self.block.end_with_jump(None, then);
473+
474+
// NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
475+
// state need to be updated.
476+
// FIXME: not sure it's actually needed.
477+
self.switch_to_block(then);
478+
479+
return_value.to_rvalue()
480+
}
481+
482+
#[cfg(not(feature="master"))]
453483
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
454-
// TODO(bjorn3): Properly implement unwinding.
455484
let call_site = self.call(typ, func, args, None);
456485
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
457486
self.llbb().end_with_conditional(None, condition, then, catch);
@@ -1160,23 +1189,56 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
11601189
aggregate_value
11611190
}
11621191

1163-
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
1164-
// TODO(antoyo)
1165-
}
1166-
1167-
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
1168-
let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
1169-
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
1192+
fn set_personality_fn(&mut self, personality: RValue<'gcc>) {
1193+
let personality = self.rvalue_as_function(personality); // FIXME: why calling
1194+
//rvalue_as_function doesn't work?
1195+
//let personality = unsafe { std::mem::transmute(personality) };
1196+
#[cfg(feature="master")]
1197+
self.current_func().set_personality_function(personality);
1198+
// FIXME: rustc manages to generate the symbol DW.ref.rust_eh_personality multiple times
1199+
// for the same asm file, which causes an assembler error.
1200+
}
1201+
1202+
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, pers_fn: RValue<'gcc>) -> RValue<'gcc> {
1203+
self.set_personality_fn(pers_fn);
1204+
1205+
// FIXME: we're probably not creating a real cleanup pad here.
1206+
// FIXME: FIXME: FIXME: It seems to be the actual problem:
1207+
// libunwind finds a catch, so returns _URC_HANDLER_FOUND instead of _URC_CONTINUE_UNWIND.
1208+
// TODO: can we generate a goto from the finally to the cleanup landing pad?
1209+
// TODO: TODO: TODO: add this block to a cleanup_blocks variable and generate a try/finally instead if
1210+
// the catch block for it is a cleanup block.
1211+
//
1212+
// TODO: look at TRY_CATCH_IS_CLEANUP, CLEANUP_POINT_EXPR, WITH_CLEANUP_EXPR, CLEANUP_EH_ONLY.
1213+
let eh_pointer_builtin = self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
1214+
let zero = self.cx.context.new_rvalue_zero(self.int_type);
1215+
let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
1216+
1217+
let field1_type = self.u8_type.make_pointer();
1218+
let field1 = self.context.new_field(None, field1_type, "landing_pad_field_1");
1219+
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_2");
11701220
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
1171-
self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
1172-
.to_rvalue()
1173-
// TODO(antoyo): Properly implement unwinding.
1174-
// the above is just to make the compilation work as it seems
1175-
// rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
1176-
}
1177-
1178-
fn resume(&mut self, _exn: RValue<'gcc>) {
1179-
// TODO(bjorn3): Properly implement unwinding.
1221+
let value = self.current_func().new_local(None, struct_type.as_type(), "landing_pad");
1222+
let ptr = self.cx.context.new_cast(None, ptr, field1_type);
1223+
self.block.add_assignment(None, value.access_field(None, field1), ptr);
1224+
self.block.add_assignment(None, value.access_field(None, field2), zero); // TODO: set the proper value here (the type of exception?).
1225+
1226+
// Resume.
1227+
let param = self.context.new_parameter(None, ptr.get_type(), "exn");
1228+
// TODO: should we call __builtin_unwind_resume instead?
1229+
// FIXME: should probably not called resume because it could be executed (I believe) in
1230+
// normal (no exception) cases
1231+
let unwind_resume = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[param], "_Unwind_Resume", false);
1232+
self.block.add_eval(None, self.context.new_call(None, unwind_resume, &[ptr]));
1233+
1234+
value.to_rvalue()
1235+
}
1236+
1237+
fn resume(&mut self, exn: RValue<'gcc>) {
1238+
let param = self.context.new_parameter(None, exn.get_type(), "exn");
1239+
// TODO: should we call __builtin_unwind_resume instead?
1240+
let unwind_resume = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[param], "_Unwind_Resume", false);
1241+
self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn]));
11801242
self.unreachable();
11811243
}
11821244

src/callee.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#[cfg(feature="master")]
22
use gccjit::{FnAttribute, Visibility};
3-
use gccjit::{FunctionType, RValue};
3+
use gccjit::{FunctionType, RValue, Function};
44
use rustc_codegen_ssa::traits::BaseTypeMethods;
55
use rustc_middle::ty::{self, Instance, TypeVisitable};
66
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
@@ -16,22 +16,31 @@ use crate::context::CodegenCx;
1616
///
1717
/// - `cx`: the crate context
1818
/// - `instance`: the instance to be instantiated
19-
pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> RValue<'gcc> {
19+
pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>, dont_cache: bool) -> Function<'gcc> {
2020
let tcx = cx.tcx();
2121

2222
assert!(!instance.substs.needs_infer());
2323
assert!(!instance.substs.has_escaping_bound_vars());
2424

25+
let sym = tcx.symbol_name(instance).name;
26+
2527
if let Some(&func) = cx.function_instances.borrow().get(&instance) {
28+
if sym == "rust_eh_personality" {
29+
println!("Cached");
30+
}
2631
return func;
2732
}
2833

29-
let sym = tcx.symbol_name(instance).name;
34+
if sym == "rust_eh_personality" {
35+
println!("Not cached");
36+
}
3037

3138
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
3239

3340
let func =
3441
if let Some(func) = cx.get_declared_value(&sym) {
42+
unreachable!();
43+
/*
3544
// Create a fn pointer with the new signature.
3645
let ptrty = fn_abi.ptr_to_gcc_type(cx);
3746
@@ -64,11 +73,14 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
6473
}
6574
else {
6675
func
67-
}
76+
}*/
6877
}
6978
else {
7079
cx.linkage.set(FunctionType::Extern);
71-
let func = cx.declare_fn(&sym, &fn_abi);
80+
/*if sym == "rust_eh_personality" {
81+
panic!();
82+
}*/
83+
let func = cx.declare_fn(&sym, &fn_abi, dont_cache);
7284

7385
attributes::from_fn_attrs(cx, func, instance);
7486

@@ -163,11 +175,15 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
163175
}
164176
}
165177

166-
// FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
167-
unsafe { std::mem::transmute(func) }
178+
func
168179
};
169180

170-
cx.function_instances.borrow_mut().insert(instance, func);
181+
//if !dont_cache {
182+
if sym == "rust_eh_personality" {
183+
println!("Caching here");
184+
}
185+
cx.function_instances.borrow_mut().insert(instance, func);
186+
//}
171187

172188
func
173189
}

0 commit comments

Comments
 (0)