Skip to content

Commit 1fb9821

Browse files
authored
Merge pull request rust-lang#131 from bjorn3/fix_non_singleton_builder
Fix miscompilation when cg_ssa is using multiple builders at the same time
2 parents ddbbded + 9d09842 commit 1fb9821

File tree

5 files changed

+49
-93
lines changed

5 files changed

+49
-93
lines changed

src/builder.rs

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ impl EnumClone for AtomicOrdering {
8080

8181
pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
8282
pub cx: &'a CodegenCx<'gcc, 'tcx>,
83-
pub block: Option<Block<'gcc>>,
83+
pub block: Block<'gcc>,
8484
stack_var_count: Cell<usize>,
8585
}
8686

8787
impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
88-
fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>) -> Self {
88+
fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
8989
Builder {
9090
cx,
91-
block: None,
91+
block,
9292
stack_var_count: Cell::new(0),
9393
}
9494
}
@@ -114,10 +114,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
114114
let after_block = func.new_block("after_while");
115115
self.llbb().end_with_jump(None, while_block);
116116

117-
// NOTE: since jumps were added and compare_exchange doesn't expect this, the current blocks in the
117+
// NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the
118118
// state need to be updated.
119-
self.block = Some(while_block);
120-
*self.cx.current_block.borrow_mut() = Some(while_block);
119+
self.switch_to_block(while_block);
121120

122121
let comparison_operator =
123122
match operation {
@@ -132,10 +131,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
132131

133132
while_block.end_with_conditional(None, cond, while_block, after_block);
134133

135-
// NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
134+
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
136135
// state need to be updated.
137-
self.block = Some(after_block);
138-
*self.cx.current_block.borrow_mut() = Some(after_block);
136+
self.switch_to_block(after_block);
139137

140138
return_value.to_rvalue()
141139
}
@@ -245,7 +243,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
245243
}
246244

247245
pub fn current_func(&self) -> Function<'gcc> {
248-
self.block.expect("block").get_function()
246+
self.block.get_function()
249247
}
250248

251249
fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
@@ -256,17 +254,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
256254
// gccjit requires to use the result of functions, even when it's not used.
257255
// That's why we assign the result to a local or call add_eval().
258256
let return_type = func.get_return_type();
259-
let current_block = self.current_block.borrow().expect("block");
260257
let void_type = self.context.new_type::<()>();
261-
let current_func = current_block.get_function();
258+
let current_func = self.block.get_function();
262259
if return_type != void_type {
263260
unsafe { RETURN_VALUE_COUNT += 1 };
264261
let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
265-
current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
262+
self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
266263
result.to_rvalue()
267264
}
268265
else {
269-
current_block.add_eval(None, self.cx.context.new_call(None, func, &args));
266+
self.block.add_eval(None, self.cx.context.new_call(None, func, &args));
270267
// Return dummy value when not having return value.
271268
self.context.new_rvalue_from_long(self.isize_type, 0)
272269
}
@@ -279,9 +276,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
279276
// That's why we assign the result to a local or call add_eval().
280277
let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
281278
let mut return_type = gcc_func.get_return_type();
282-
let current_block = self.current_block.borrow().expect("block");
283279
let void_type = self.context.new_type::<()>();
284-
let current_func = current_block.get_function();
280+
let current_func = self.block.get_function();
285281

286282
// FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
287283
if gcc_func.get_param_count() == 0 && format!("{:?}", func_ptr) == "__builtin_ia32_pmovmskb128" {
@@ -291,20 +287,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
291287
if return_type != void_type {
292288
unsafe { RETURN_VALUE_COUNT += 1 };
293289
let result = current_func.new_local(None, return_type, &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
294-
current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
290+
self.block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
295291
result.to_rvalue()
296292
}
297293
else {
298294
if gcc_func.get_param_count() == 0 {
299295
// FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
300-
current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
296+
self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
301297
}
302298
else {
303-
current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
299+
self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
304300
}
305301
// Return dummy value when not having return value.
306302
let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed");
307-
current_block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
303+
self.block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
308304
result.to_rvalue()
309305
}
310306
}
@@ -313,12 +309,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
313309
// gccjit requires to use the result of functions, even when it's not used.
314310
// That's why we assign the result to a local.
315311
let return_type = self.context.new_type::<bool>();
316-
let current_block = self.current_block.borrow().expect("block");
317-
let current_func = current_block.get_function();
312+
let current_func = self.block.get_function();
318313
// TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects.
319314
unsafe { RETURN_VALUE_COUNT += 1 };
320315
let result = current_func.new_local(None, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
321-
current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
316+
self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
322317
result.to_rvalue()
323318
}
324319
}
@@ -384,14 +379,11 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
384379

385380
impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
386381
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
387-
let mut bx = Builder::with_cx(cx);
388-
*cx.current_block.borrow_mut() = Some(block);
389-
bx.block = Some(block);
390-
bx
382+
Builder::with_cx(cx, block)
391383
}
392384

393385
fn llbb(&self) -> Block<'gcc> {
394-
self.block.expect("block")
386+
self.block
395387
}
396388

397389
fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
@@ -405,8 +397,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
405397
}
406398

407399
fn switch_to_block(&mut self, block: Self::BasicBlock) {
408-
*self.cx.current_block.borrow_mut() = Some(block);
409-
self.block = Some(block);
400+
self.block = block;
410401
}
411402

412403
fn ret_void(&mut self) {
@@ -441,7 +432,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
441432
let on_val = self.const_uint_big(typ, on_val);
442433
gcc_cases.push(self.context.new_case(on_val, on_val, dest));
443434
}
444-
self.block.expect("block").end_with_switch(None, value, default_block, &gcc_cases);
435+
self.block.end_with_switch(None, value, default_block, &gcc_cases);
445436
}
446437

447438
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,17 +445,16 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
454445

455446
fn unreachable(&mut self) {
456447
let func = self.context.get_builtin_function("__builtin_unreachable");
457-
let block = self.block.expect("block");
458-
block.add_eval(None, self.context.new_call(None, func, &[]));
459-
let return_type = block.get_function().get_return_type();
448+
self.block.add_eval(None, self.context.new_call(None, func, &[]));
449+
let return_type = self.block.get_function().get_return_type();
460450
let void_type = self.context.new_type::<()>();
461451
if return_type == void_type {
462-
block.end_with_void_return(None)
452+
self.block.end_with_void_return(None)
463453
}
464454
else {
465455
let return_value = self.current_func()
466456
.new_local(None, return_type, "unreachableReturn");
467-
block.end_with_return(None, return_value)
457+
self.block.end_with_return(None, return_value)
468458
}
469459
}
470460

@@ -911,11 +901,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
911901
}
912902

913903
fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
914-
self.cx.ptrtoint(self.block.expect("block"), value, dest_ty)
904+
let usize_value = self.cx.const_bitcast(value, self.cx.type_isize());
905+
self.intcast(usize_value, dest_ty, false)
915906
}
916907

917908
fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
918-
self.cx.inttoptr(self.block.expect("block"), value, dest_ty)
909+
let usize_value = self.intcast(value, self.cx.type_isize(), false);
910+
self.cx.const_bitcast(usize_value, dest_ty)
919911
}
920912

921913
fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -967,9 +959,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
967959
let dst = self.pointercast(dst, self.type_i8p());
968960
let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
969961
let memcpy = self.context.get_builtin_function("memcpy");
970-
let block = self.block.expect("block");
971962
// TODO(antoyo): handle aligns and is_volatile.
972-
block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
963+
self.block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
973964
}
974965

975966
fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
@@ -986,20 +977,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
986977
let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
987978

988979
let memmove = self.context.get_builtin_function("memmove");
989-
let block = self.block.expect("block");
990980
// TODO(antoyo): handle is_volatile.
991-
block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
981+
self.block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
992982
}
993983

994984
fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) {
995985
let _is_volatile = flags.contains(MemFlags::VOLATILE);
996986
let ptr = self.pointercast(ptr, self.type_i8p());
997987
let memset = self.context.get_builtin_function("memset");
998-
let block = self.block.expect("block");
999988
// TODO(antoyo): handle align and is_volatile.
1000989
let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type);
1001990
let size = self.intcast(size, self.type_size_t(), false);
1002-
block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
991+
self.block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
1003992
}
1004993

1005994
fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> {
@@ -1019,10 +1008,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
10191008
else_block.add_assignment(None, variable, else_val);
10201009
else_block.end_with_jump(None, after_block);
10211010

1022-
// NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
1011+
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
10231012
// state need to be updated.
1024-
self.block = Some(after_block);
1025-
*self.cx.current_block.borrow_mut() = Some(after_block);
1013+
self.switch_to_block(after_block);
10261014

10271015
variable.to_rvalue()
10281016
}

src/common.rs

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use gccjit::LValue;
2-
use gccjit::{Block, RValue, Type, ToRValue};
2+
use gccjit::{RValue, Type, ToRValue};
33
use rustc_codegen_ssa::mir::place::PlaceRef;
44
use rustc_codegen_ssa::traits::{
55
BaseTypeMethods,
@@ -45,27 +45,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
4545
global
4646
// TODO(antoyo): set linkage.
4747
}
48-
49-
pub fn inttoptr(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
50-
let func = block.get_function();
51-
let local = func.new_local(None, value.get_type(), "intLocal");
52-
block.add_assignment(None, local, value);
53-
let value_address = local.get_address(None);
54-
55-
let ptr = self.context.new_cast(None, value_address, dest_ty.make_pointer());
56-
ptr.dereference(None).to_rvalue()
57-
}
58-
59-
pub fn ptrtoint(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
60-
// TODO(antoyo): when libgccjit allow casting from pointer to int, remove this.
61-
let func = block.get_function();
62-
let local = func.new_local(None, value.get_type(), "ptrLocal");
63-
block.add_assignment(None, local, value);
64-
let ptr_address = local.get_address(None);
65-
66-
let ptr = self.context.new_cast(None, ptr_address, dest_ty.make_pointer());
67-
ptr.dereference(None).to_rvalue()
68-
}
6948
}
7049

7150
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
@@ -202,11 +181,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
202181
}
203182

204183
let value = self.const_uint_big(self.type_ix(bitsize), data);
205-
if layout.value == Pointer {
206-
self.inttoptr(self.current_block.borrow().expect("block"), value, ty)
207-
} else {
208-
self.const_bitcast(value, ty)
209-
}
184+
// TODO(bjorn3): assert size is correct
185+
self.const_bitcast(value, ty)
210186
}
211187
Scalar::Ptr(ptr, _size) => {
212188
let (alloc_id, offset) = ptr.into_parts();

src/context.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
3131
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
3232
pub context: &'gcc Context<'gcc>,
3333

34-
// TODO(antoyo): First set it to a dummy block to avoid using Option?
35-
pub current_block: RefCell<Option<Block<'gcc>>>,
34+
// TODO(bjorn3): Can this field be removed?
3635
pub current_func: RefCell<Option<Function<'gcc>>>,
3736
pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>,
3837

@@ -177,7 +176,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
177176
check_overflow,
178177
codegen_unit,
179178
context,
180-
current_block: RefCell::new(None),
181179
current_func: RefCell::new(None),
182180
normal_function_addresses: Default::default(),
183181
functions: RefCell::new(functions),

src/int.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
148148

149149
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
150150
// state need to be updated.
151-
self.block = Some(after_block);
152-
*self.cx.current_block.borrow_mut() = Some(after_block);
151+
self.switch_to_block(after_block);
153152

154153
result.to_rvalue()
155154
}
@@ -494,8 +493,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
494493

495494
// NOTE: since jumps were added in a place rustc does not expect, the current block in the
496495
// state need to be updated.
497-
self.block = Some(after_block);
498-
*self.cx.current_block.borrow_mut() = Some(after_block);
496+
self.switch_to_block(after_block);
499497

500498
result.to_rvalue()
501499
}

src/intrinsic/mod.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
184184
then_block.end_with_jump(None, after_block);
185185

186186
// NOTE: since jumps were added in a place
187-
// count_leading_zeroes() does not expect, the current blocks
187+
// count_leading_zeroes() does not expect, the current block
188188
// in the state need to be updated.
189-
*self.current_block.borrow_mut() = Some(else_block);
190-
self.block = Some(else_block);
189+
self.switch_to_block(else_block);
191190

192191
let zeros =
193192
match name {
@@ -199,9 +198,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
199198
self.llbb().end_with_jump(None, after_block);
200199

201200
// NOTE: since jumps were added in a place rustc does not
202-
// expect, the current blocks in the state need to be updated.
203-
*self.current_block.borrow_mut() = Some(after_block);
204-
self.block = Some(after_block);
201+
// expect, the current block in the state need to be updated.
202+
self.switch_to_block(after_block);
205203

206204
result.to_rvalue()
207205
}
@@ -1002,9 +1000,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
10021000
self.llbb().end_with_conditional(None, overflow, then_block, after_block);
10031001

10041002
// NOTE: since jumps were added in a place rustc does not
1005-
// expect, the current blocks in the state need to be updated.
1006-
*self.current_block.borrow_mut() = Some(after_block);
1007-
self.block = Some(after_block);
1003+
// expect, the current block in the state need to be updated.
1004+
self.switch_to_block(after_block);
10081005

10091006
res.to_rvalue()
10101007
}
@@ -1073,9 +1070,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
10731070
self.llbb().end_with_conditional(None, overflow, then_block, after_block);
10741071

10751072
// NOTE: since jumps were added in a place rustc does not
1076-
// expect, the current blocks in the state need to be updated.
1077-
*self.current_block.borrow_mut() = Some(after_block);
1078-
self.block = Some(after_block);
1073+
// expect, the current block in the state need to be updated.
1074+
self.switch_to_block(after_block);
10791075

10801076
res.to_rvalue()
10811077
}

0 commit comments

Comments
 (0)