Add missing cast and change some bitcasts to casts to avoid a gimple verification failure (#100)

This commit is contained in:
antoyo 2021-10-11 10:56:08 -04:00 committed by GitHub
parent cd4810de42
commit 669359530e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 23 deletions

View File

@ -111,6 +111,8 @@ Or add a breakpoint to `add_error` in gdb and print the line number using:
p loc->m_line p loc->m_line
``` ```
To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
### How to use a custom-build rustc ### How to use a custom-build rustc
* Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).

View File

@ -1,4 +1,4 @@
use std::fs; use std::{env, fs};
use gccjit::OutputKind; use gccjit::OutputKind;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
@ -42,17 +42,17 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
let _timer = cgcx let _timer = cgcx
.prof .prof
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
match &*module.name { if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") {
"std_example.7rcbfp3g-cgu.15" => { println!("Module {}", module.name);
println!("Dumping reproducer {}", module.name); }
let _ = fs::create_dir("/tmp/reproducers"); if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) {
// FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by println!("Dumping reproducer {}", module.name);
// transmuting an rvalue to an lvalue. let _ = fs::create_dir("/tmp/reproducers");
// Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); // transmuting an rvalue to an lvalue.
println!("Dumped reproducer {}", module.name); // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue
}, context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
_ => (), println!("Dumped reproducer {}", module.name);
} }
context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
} }

View File

@ -525,7 +525,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let value = let value =
if result_type.is_signed(self.cx) { if result_type.is_signed(self.cx) {
self.context.new_bitcast(None, value, typ) self.context.new_cast(None, value, typ)
} }
else { else {
value value
@ -689,7 +689,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}, },
}; };
self.context.new_bitcast(None, result, result_type) self.context.new_cast(None, result, result_type)
} }
fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
@ -740,6 +740,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low);
let not_low_and_not_high = not_low & not_high; let not_low_and_not_high = not_low & not_high;
let index = not_high + not_low_and_not_high; let index = not_high + not_low_and_not_high;
// NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
// gcc.
// TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
// compilation stage.
let index = self.context.new_cast(None, index, self.i32_type);
let res = self.context.new_array_access(None, result, index); let res = self.context.new_array_access(None, result, index);
@ -763,7 +768,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let arg = let arg =
if result_type.is_signed(self.cx) { if result_type.is_signed(self.cx) {
let new_type = result_type.to_unsigned(self.cx); let new_type = result_type.to_unsigned(self.cx);
self.context.new_bitcast(None, arg, new_type) self.context.new_cast(None, arg, new_type)
} }
else { else {
arg arg
@ -815,10 +820,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high);
let not_low_and_not_high = not_low & not_high; let not_low_and_not_high = not_low & not_high;
let index = not_low + not_low_and_not_high; let index = not_low + not_low_and_not_high;
// NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
// gcc.
// TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
// compilation stage.
let index = self.context.new_cast(None, index, self.i32_type);
let res = self.context.new_array_access(None, result, index); let res = self.context.new_array_access(None, result, index);
return self.context.new_bitcast(None, res, result_type); return self.context.new_cast(None, res, result_type);
} }
else { else {
unimplemented!("count_trailing_zeroes for {:?}", arg_type); unimplemented!("count_trailing_zeroes for {:?}", arg_type);
@ -832,7 +842,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
arg arg
}; };
let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); let res = self.context.new_call(None, count_trailing_zeroes, &[arg]);
self.context.new_bitcast(None, res, result_type) self.context.new_cast(None, res, result_type)
} }
fn int_width(&self, typ: Type<'gcc>) -> i64 { fn int_width(&self, typ: Type<'gcc>) -> i64 {
@ -846,7 +856,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let value = let value =
if result_type.is_signed(self.cx) { if result_type.is_signed(self.cx) {
self.context.new_bitcast(None, value, value_type) self.context.new_cast(None, value, value_type)
} }
else { else {
value value
@ -862,7 +872,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let low = self.context.new_cast(None, value, self.cx.ulonglong_type); let low = self.context.new_cast(None, value, self.cx.ulonglong_type);
let low = self.context.new_call(None, popcount, &[low]); let low = self.context.new_call(None, popcount, &[low]);
let res = high + low; let res = high + low;
return self.context.new_bitcast(None, res, result_type); return self.context.new_cast(None, res, result_type);
} }
// First step. // First step.
@ -887,7 +897,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let value = left + right; let value = left + right;
if value_type.is_u8(&self.cx) { if value_type.is_u8(&self.cx) {
return self.context.new_bitcast(None, value, result_type); return self.context.new_cast(None, value, result_type);
} }
// Fourth step. // Fourth step.
@ -898,7 +908,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let value = left + right; let value = left + right;
if value_type.is_u16(&self.cx) { if value_type.is_u16(&self.cx) {
return self.context.new_bitcast(None, value, result_type); return self.context.new_cast(None, value, result_type);
} }
// Fifth step. // Fifth step.
@ -909,7 +919,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let value = left + right; let value = left + right;
if value_type.is_u32(&self.cx) { if value_type.is_u32(&self.cx) {
return self.context.new_bitcast(None, value, result_type); return self.context.new_cast(None, value, result_type);
} }
// Sixth step. // Sixth step.
@ -919,7 +929,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let right = shifted & mask; let right = shifted & mask;
let value = left + right; let value = left + right;
self.context.new_bitcast(None, value, result_type) self.context.new_cast(None, value, result_type)
} }
// Algorithm from: https://blog.regehr.org/archives/1063 // Algorithm from: https://blog.regehr.org/archives/1063