From 729ecd94c28fa43c60055acf55b5bfac83c6f26b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 3 Oct 2020 16:35:58 -0400 Subject: [PATCH 1/3] Use new reflection API --- Cargo.lock | 2 -- Cargo.toml | 3 ++- src/builder.rs | 17 +++++------- src/common.rs | 68 +++++++++++++----------------------------------- src/context.rs | 2 -- src/intrinsic.rs | 23 +++------------- src/type_.rs | 37 +++----------------------- 7 files changed, 34 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd36fc6f1f1..e4b9d48cb1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,6 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs?branch=feature/rustc#74dc7b3095a215d9fba3f6b54cc47ebf1a82d1e8" dependencies = [ "gccjit_sys", ] @@ -38,7 +37,6 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs?branch=feature/rustc#74dc7b3095a215d9fba3f6b54cc47ebf1a82d1e8" dependencies = [ "libc 0.1.12", ] diff --git a/Cargo.toml b/Cargo.toml index 13dc3815d82..a0bfe0ecc05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ harness = false [dependencies] #gccjit = "1.0.0" -gccjit = { git = "https://github.com/antoyo/gccjit.rs", branch = "feature/rustc" } +#gccjit = { git = "https://github.com/antoyo/gccjit.rs", branch = "feature/rustc" } +gccjit = { path = "/home/bouanto/Ordinateur/Programmation/Rust/Projets/gccjit.rs" } target-lexicon = "0.10.0" diff --git a/src/builder.rs b/src/builder.rs index f704505a987..1b3ecdbd84a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -599,7 +599,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { let operation = - if a.get_type().is_bool(&self.cx) { + if a.get_type().is_bool() { UnaryOp::LogicalNegate } else { @@ -756,11 +756,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> { let aligned_type = ty.get_aligned(align.bytes()); let type_fields = self.fields.borrow().get(&ty).cloned(); - // TODO: remove these conditiosn when libgccjit has a reflection API. - if self.array_types.borrow().contains(&ty) { - self.array_types.borrow_mut().insert(aligned_type); - } - else if self.vector_types.borrow().contains_key(&ty) { + // TODO: remove these conditions when libgccjit has a reflection API. + if self.vector_types.borrow().contains_key(&ty) { let value = self.vector_types.borrow().get(&ty).expect("vector type").clone(); self.vector_types.borrow_mut().insert(aligned_type, value); } @@ -1033,7 +1030,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let value = ptr.dereference(None).to_rvalue(); let value_type = value.get_type(); - if self.array_types.borrow().contains(&value_type) { + if value_type.is_array() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, value, index); element.get_address(None) @@ -1247,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { assert_eq!(idx as usize as u64, idx); let value_type = aggregate_value.get_type(); - if self.array_types.borrow().contains(&value_type) { + if value_type.is_array() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, aggregate_value, index); element.get_address(None) @@ -1271,7 +1268,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let value_type = aggregate_value.get_type(); let lvalue = - if self.array_types.borrow().contains(&value_type) { + if value_type.is_array() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); self.context.new_array_access(None, aggregate_value, index) } @@ -1469,7 +1466,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { // FIXME: this does not zero-extend. - if value.get_type().is_bool(&self.cx) && dest_typ.is_i8(&self.cx) { + if value.get_type().is_bool() && dest_typ.is_i8(&self.cx) { // FIXME: hack because base::from_immediate converts i1 to i8. // Fix the code in codegen_ssa::base::from_immediate. return value; diff --git a/src/common.rs b/src/common.rs index 87683a5f279..41b7709c0b9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -96,10 +96,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> } pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool { - // TODO: fix when having proper type reflection. - // TODO: put all pointer types in a HashSet and check if it's there instead of relying on - // string comparison. - format!("{:?}", typ).ends_with('*') + typ.get_pointee().is_some() } impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { @@ -303,8 +300,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { pub trait SignType<'gcc, 'tcx> { fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; - - fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; } impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { @@ -315,31 +310,9 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { self.is_u8(cx) || self.is_u16(cx) || self.is_u32(cx) || self.is_u64(cx) || self.is_u128(cx) } - - fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { - if self.is_i8(cx) { - cx.u8_type - } - else if self.is_i16(cx) { - cx.u16_type - } - else if self.is_i32(cx) { - cx.u32_type - } - else if self.is_i64(cx) { - cx.u64_type - } - else if self.is_i128(cx) { - cx.u128_type - } - else { - *self - } - } } pub trait TypeReflection<'gcc, 'tcx> { - fn is_bool(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; @@ -361,77 +334,72 @@ pub trait TypeReflection<'gcc, 'tcx> { fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; } -// TODO: remove all this when libgccjit has a reflection API. impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { - fn is_bool(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.bool_type)) - } - fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u8_type)) + self.get_original() == cx.u8_type } fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u16_type)) + self.get_original() == cx.u16_type } fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.uint_type)) + self.get_original() == cx.uint_type } fn is_ulong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - !self.is_ulonglong(cx) && format!("{:?}", self).starts_with(&format!("{:?}", cx.ulong_type)) + self.get_original() == cx.ulong_type } fn is_ulonglong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.ulonglong_type)) + self.get_original() == cx.ulonglong_type } fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.i8_type)) + self.get_original() == cx.i8_type } fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u8_type)) + self.get_original() == cx.u8_type } fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.i16_type)) + self.get_original() == cx.i16_type } fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u16_type)) + self.get_original() == cx.u16_type } fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.i32_type)) + self.get_original() == cx.i32_type } fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u32_type)) + self.get_original() == cx.u32_type } fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.i64_type)) + self.get_original() == cx.i64_type } fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u64_type)) + self.get_original() == cx.u64_type } fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.i128_type)) + self.get_original() == cx.i128_type } fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.u128_type)) + self.get_original() == cx.u128_type } fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.context.new_type::())) + self.get_original() == cx.context.new_type::() } fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - format!("{:?}", self).starts_with(&format!("{:?}", cx.context.new_type::())) + self.get_original() == cx.context.new_type::() } } diff --git a/src/context.rs b/src/context.rs index 2ff23847a63..e87457b9a6e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -85,7 +85,6 @@ pub struct CodegenCx<'gcc, 'tcx> { pub tcx: TyCtxt<'tcx>, pub fields: RefCell, Vec>>>, - pub array_types: RefCell>>, pub vector_types: RefCell, (u64, Type<'gcc>)>>, pub struct_types: RefCell>, Type<'gcc>>>, @@ -216,7 +215,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { types: Default::default(), tcx, fields: Default::default(), - array_types: Default::default(), vector_types: Default::default(), struct_types: Default::default(), types_with_fields_to_set: Default::default(), diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 001e871f308..ba0aecdf464 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -1246,24 +1246,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn int_width(&self, typ: Type<'gcc>) -> i64 { - if typ.is_i8(&self.cx) || typ.is_u8(&self.cx) { - 8 - } - else if typ.is_i16(&self.cx) || typ.is_u16(&self.cx) { - 16 - } - else if typ.is_i32(&self.cx) || typ.is_u32(&self.cx) { - 32 - } - else if typ.is_i64(&self.cx) || typ.is_u64(&self.cx) { - 64 - } - else if typ.is_i128(&self.cx) || typ.is_u128(&self.cx) { - 128 - } - else { - unimplemented!(); - } + typ.get_size() as i64 * 8 } fn overflow_intrinsic_call(&mut self, intrinsic: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>, result: &PlaceRef<'tcx, RValue<'gcc>>) { @@ -1350,7 +1333,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let then_block = func.new_block("then"); - let unsigned_type = result_type.to_unsigned(&self.cx); + let unsigned_type = self.context.new_int_type(width as i32 / 8, false); let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, self.context.new_rvalue_from_int(unsigned_type, 0) @@ -1412,7 +1395,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let then_block = func.new_block("then"); let after_block = func.new_block("after"); - let unsigned_type = result_type.to_unsigned(&self.cx); + let unsigned_type = self.context.new_int_type(width as i32 / 8, false); let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, self.context.new_rvalue_from_int(unsigned_type, 0) diff --git a/src/type_.rs b/src/type_.rs index 6ed268ef18b..ebe29779a06 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -132,23 +132,13 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { - // TODO: find a better way to compare types without taking alignment into account. - if typ.is_i8(self) || typ.is_u8(self) || - typ.is_i16(self) || typ.is_u16(self) || - typ.is_i32(self) || typ.is_u32(self) || - typ.is_i64(self) || typ.is_u64(self) || - typ.is_i128(self) || typ.is_u128(self) - { + if typ.is_int() { TypeKind::Integer } - // TODO: find a better way to do that. - else if format!("{:?}", typ).contains("__attribute__ ((vector_size") { + else if typ.is_vector() { TypeKind::Vector } else { - if format!("{:?}", typ).contains("vector_size") { - panic!("missed vector type"); - } // TODO TypeKind::Void } @@ -195,24 +185,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn int_width(&self, typ: Type<'gcc>) -> u64 { - if typ.is_i8(self) || typ.is_u8(self) { - 8 - } - else if typ.is_i16(self) || typ.is_u16(self) { - 16 - } - else if typ.is_i32(self) || typ.is_u32(self) { - 32 - } - else if typ.is_i64(self) || typ.is_u64(self) { - 64 - } - else if typ.is_i128(self) || typ.is_u128(self) { - 128 - } - else { - panic!("Cannot get width of int type {:?}", typ); - } + typ.get_size() as u64 * 8 } fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { @@ -253,9 +226,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> { - let array_type = self.context.new_array_type(None, ty, len as i32); - self.array_types.borrow_mut().insert(array_type); - array_type + self.context.new_array_type(None, ty, len as i32) } } From 0443c3a1875885879f0533e0c6b6b39341fc7049 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 6 Oct 2020 09:00:21 -0400 Subject: [PATCH 2/3] Use more of the new reflection API --- gcc_path | 2 +- src/abi.rs | 4 ---- src/builder.rs | 18 +++++------------- src/common.rs | 34 +++++++++++++++++----------------- src/context.rs | 8 +------- src/intrinsic.rs | 2 +- src/type_.rs | 27 +++++++++++++++++++-------- src/type_of.rs | 4 ---- 8 files changed, 44 insertions(+), 55 deletions(-) diff --git a/gcc_path b/gcc_path index 85e26eb02d4..b3696e3cf88 100644 --- a/gcc_path +++ b/gcc_path @@ -1 +1 @@ -/tmp/gcc-build/build/gcc +/home/bouanto/Ordinateur/Programmation/Projets/gcc-build/build/gcc diff --git a/src/abi.rs b/src/abi.rs index 8334c717961..0059111c2c1 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -162,10 +162,6 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { let (return_type, params, variadic) = self.gcc_type(cx); let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic); - cx.function_type_param_return_value.borrow_mut().insert(pointer_type, FuncSig { - params, - return_type, - }); pointer_type } diff --git a/src/builder.rs b/src/builder.rs index 1b3ecdbd84a..ad2341ca9f0 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -154,12 +154,9 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { let mut all_args_match = true; let mut param_types = vec![]; - let func_types = self.cx.function_type_param_return_value.borrow(); - let ptr: *mut usize = unsafe { std::mem::transmute(func.get_type()) }; - let func_sig = func_types.get(&func.get_type()) - .unwrap_or_else(|| panic!("No function_type_param_return_value for {:?}", func.get_type())); - for (index, arg) in args.iter().enumerate().take(func_sig.params.len()) { - let param = func_sig.params[index]; + let gcc_func: Function<'gcc> = self.cx.rvalue_as_function(func); + for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) { + let param = gcc_func.get_param(index as i32).to_rvalue().get_type(); if param != arg.get_type() { all_args_match = false; } @@ -265,9 +262,8 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). - let return_type = self.function_type_param_return_value.borrow().get(&func.get_type()) - .map(|func_sig| func_sig.return_type) - .unwrap_or_else(|| panic!("No return type for {:?}", func)); + let gcc_func: Function<'gcc> = self.cx.rvalue_as_function(func); + let return_type = gcc_func.get_return_type(); let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); let current_func = current_block.get_function(); @@ -764,10 +760,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { else if let Some(fields) = type_fields { self.fields.borrow_mut().insert(aligned_type, fields); } - else if self.function_type_param_return_value.borrow().contains_key(&ty) { - let func_sig = self.function_type_param_return_value.borrow().get(&ty).expect("function sig").clone(); - self.function_type_param_return_value.borrow_mut().insert(aligned_type, func_sig); - } // TODO: It might be better to return a LValue, but fixing the rustc API is non-trivial. self.current_func().new_local(None, aligned_type, "stack_var").get_address(None) diff --git a/src/common.rs b/src/common.rs index 41b7709c0b9..1c7976963ae 100644 --- a/src/common.rs +++ b/src/common.rs @@ -336,70 +336,70 @@ pub trait TypeReflection<'gcc, 'tcx> { impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u8_type + self.unqualified() == cx.u8_type } fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u16_type + self.unqualified() == cx.u16_type } fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.uint_type + self.unqualified() == cx.uint_type } fn is_ulong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.ulong_type + self.unqualified() == cx.ulong_type } fn is_ulonglong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.ulonglong_type + self.unqualified() == cx.ulonglong_type } fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.i8_type + self.unqualified() == cx.i8_type } fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u8_type + self.unqualified() == cx.u8_type } fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.i16_type + self.unqualified() == cx.i16_type } fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u16_type + self.unqualified() == cx.u16_type } fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.i32_type + self.unqualified() == cx.i32_type } fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u32_type + self.unqualified() == cx.u32_type } fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.i64_type + self.unqualified() == cx.i64_type } fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u64_type + self.unqualified() == cx.u64_type } fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.i128_type + self.unqualified() == cx.i128_type } fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.u128_type + self.unqualified() == cx.u128_type } fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.context.new_type::() + self.unqualified() == cx.context.new_type::() } fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.get_original() == cx.context.new_type::() + self.unqualified() == cx.context.new_type::() } } diff --git a/src/context.rs b/src/context.rs index e87457b9a6e..1e65f9ccbe6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -49,7 +49,6 @@ pub struct CodegenCx<'gcc, 'tcx> { // TODO: First set it to a dummy block to avoid using Option? pub current_block: RefCell>>, pub current_func: RefCell>>, - pub function_type_param_return_value: RefCell, FuncSig<'gcc>>>, pub normal_function_addresses: RefCell>>, /// The function where globals are initialized. @@ -177,7 +176,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { context, current_block: RefCell::new(None), current_func: RefCell::new(None), - function_type_param_return_value: Default::default(), normal_function_addresses: Default::default(), functions: RefCell::new(functions), global_init_func, @@ -238,7 +236,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(), - "{:?} is not a function", value); + "{:?} ({:?}) is not a function", value, value.get_type()); function } @@ -291,10 +289,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let pointer_type = ptr.get_type(); self.normal_function_addresses.borrow_mut().insert(ptr); - self.function_type_param_return_value.borrow_mut().insert(pointer_type, FuncSig { - params, - return_type, - }); ptr } diff --git a/src/intrinsic.rs b/src/intrinsic.rs index ba0aecdf464..956b82cab34 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -1246,7 +1246,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn int_width(&self, typ: Type<'gcc>) -> i64 { - typ.get_size() as i64 * 8 + self.cx.int_width(typ) as i64 } fn overflow_intrinsic_call(&mut self, intrinsic: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>, result: &PlaceRef<'tcx, RValue<'gcc>>) { diff --git a/src/type_.rs b/src/type_.rs index ebe29779a06..fb20c0b258a 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -105,13 +105,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { - let pointer_type = self.context.new_function_pointer_type(None, return_type, params, false); - // TODO: check if necessary. - /*self.function_type_param_return_value.borrow_mut().insert(pointer_type, crate::context::FuncSig { - params: params.to_vec(), - return_type, - });*/ - pointer_type + self.context.new_function_pointer_type(None, return_type, params, false) } fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { @@ -185,7 +179,24 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn int_width(&self, typ: Type<'gcc>) -> u64 { - typ.get_size() as u64 * 8 + if typ.is_i8(self) || typ.is_u8(self) { + 8 + } + else if typ.is_i16(self) || typ.is_u16(self) { + 16 + } + else if typ.is_i32(self) || typ.is_u32(self) { + 32 + } + else if typ.is_i64(self) || typ.is_u64(self) { + 64 + } + else if typ.is_i128(self) || typ.is_u128(self) { + 128 + } + else { + panic!("Cannot get width of int type {:?}", typ); + } } fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { diff --git a/src/type_of.rs b/src/type_of.rs index 7a722197eda..598222758a3 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -177,10 +177,6 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // TODO: don't compute the params and return value twice. let (return_type, params, _) = fn_abi.gcc_type(cx); let fn_ptr_type = cx.fn_ptr_backend_type(&fn_abi); - cx.function_type_param_return_value.borrow_mut().insert(fn_ptr_type, FuncSig { - params, - return_type, - }); fn_ptr_type }, _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), From 5ae525292064aeec518f5b3cf45d177a9b52039d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 18 Oct 2020 12:30:43 -0400 Subject: [PATCH 3/3] Use new reflection API --- Cargo.toml | 3 +- gcc-test-backend/Cargo.lock | 25 ---------------- gcc-test-backend/Cargo.toml | 2 +- gcc-test-backend/src/main.rs | 5 ++-- gcc_path | 2 +- src/base.rs | 2 +- src/builder.rs | 58 ++++++++++++++++-------------------- src/common.rs | 7 +++-- src/context.rs | 4 --- src/type_.rs | 10 ++----- src/type_of.rs | 4 +-- 11 files changed, 40 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0bfe0ecc05..13dc3815d82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,7 @@ harness = false [dependencies] #gccjit = "1.0.0" -#gccjit = { git = "https://github.com/antoyo/gccjit.rs", branch = "feature/rustc" } -gccjit = { path = "/home/bouanto/Ordinateur/Programmation/Rust/Projets/gccjit.rs" } +gccjit = { git = "https://github.com/antoyo/gccjit.rs", branch = "feature/rustc" } target-lexicon = "0.10.0" diff --git a/gcc-test-backend/Cargo.lock b/gcc-test-backend/Cargo.lock index 2d7fcb5f075..02169d0f27c 100644 --- a/gcc-test-backend/Cargo.lock +++ b/gcc-test-backend/Cargo.lock @@ -1,30 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "deflate" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" -dependencies = [ - "adler32", - "byteorder", -] - [[package]] name = "test-rust" version = "0.1.0" -dependencies = [ - "deflate", -] diff --git a/gcc-test-backend/Cargo.toml b/gcc-test-backend/Cargo.toml index 8c3f39c794f..7cbbd446c35 100644 --- a/gcc-test-backend/Cargo.toml +++ b/gcc-test-backend/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] #depth1 = { path = "depth1" } #mini_core = { path = "mini_core" } -deflate = "0.7.19" +#deflate = "0.7.19" [profile.dev] panic = "abort" diff --git a/gcc-test-backend/src/main.rs b/gcc-test-backend/src/main.rs index eb5d8b643b6..0d7dd7fe01e 100644 --- a/gcc-test-backend/src/main.rs +++ b/gcc-test-backend/src/main.rs @@ -128,13 +128,14 @@ fn main() { println!("{}", leaves.capacity());*/ + println!("Hello, world!"); - let mut leaves: Vec = Vec::with_capacity(286); + /*let mut leaves: Vec = Vec::with_capacity(286); let frequencies/*: &[i32]*/ = &[526, 124, 128, 125, 107, 92, 84, 75, 88, 53, 63, 43, 54, 68, 56, 60, 38, 53, 37, 23, 36, 32, 21, 25, 20, 21, 27, 26, 16, 15, 20, 24, 22, 14, 12, 19, 19, 10, 15, 11, 13, 4, 15, 7, 6, 10, 10, 2, 1, 3, 3, 2, 2, 3, 2, 1, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 3, 0, 1, 2, 3, 0, 2, 1, 4, 0, 1, 1, 1, 2, 2, 2, 3, 1, 1, 0, 0, 3, 0, 1, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 2, 1, 0, 2, 0, 0, 1, 0, 2, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 2, 0, 0, 1, 1, 0, 2, 0, 1, 1, 0, 0, 1, 2, 0, 2, 1, 1, 2, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 2, 0, 0, 0, 2, 1, 2, 0, 2, 0, 0, 1, 0, 0, 0, 2, 1, 0, 0, 1, 0, 0, 2, 0, 2, 0, 4, 6, 3, 4, 8, 7, 2, 7, 6, 8, 5, 8, 8, 17, 11, 16, 10, 8, 7, 13, 9, 14, 18, 12, 10, 19, 12, 11, 17, 15, 13, 17, 14, 17, 23, 31, 44, 27, 25, 30, 18, 17, 20, 25, 72, 52, 55, 69, 87, 75, 1, 7754, 5054, 3016, 2120, 1790, 1263, 606, 602, 958, 783, 481, 333, 510, 392, 211, 177, 169, 89, 58, 70, 110, 56, 37, 52, 63, 38, 48, 13, 1373]; let len = 10; unsafe { println!("&{:?}[10] = {:?}", frequencies.as_ptr(), frequencies.as_ptr().add(len)); - } + }*/ /*leaves.extend(frequencies.iter().enumerate().filter_map( |(n, f)| if *f > 0 { Some(Node { diff --git a/gcc_path b/gcc_path index b3696e3cf88..85e26eb02d4 100644 --- a/gcc_path +++ b/gcc_path @@ -1 +1 @@ -/home/bouanto/Ordinateur/Programmation/Projets/gcc-build/build/gcc +/tmp/gcc-build/build/gcc diff --git a/src/base.rs b/src/base.rs index 193b579ed57..4d70a3e99b3 100644 --- a/src/base.rs +++ b/src/base.rs @@ -73,7 +73,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); let context = Context::default(); //context.set_dump_code_on_compile(true); - //context.set_dump_initial_gimple(true); + context.set_dump_initial_gimple(true); context.set_debug_info(true); //context.set_dump_everything(true); //context.set_keep_intermediates(true); diff --git a/src/builder.rs b/src/builder.rs index ad2341ca9f0..691aa5e6088 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -131,7 +131,7 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { Cow::Owned(casted_args) } - fn check_ptr_call<'b>(&mut self, typ: &str, func: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { + fn check_ptr_call<'b>(&mut self, typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { //let mut fn_ty = self.cx.val_ty(func); // Strip off pointers /*while self.cx.type_kind(fn_ty) == TypeKind::Pointer { @@ -154,9 +154,9 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { let mut all_args_match = true; let mut param_types = vec![]; - let gcc_func: Function<'gcc> = self.cx.rvalue_as_function(func); + let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) { - let param = gcc_func.get_param(index as i32).to_rvalue().get_type(); + let param = gcc_func.get_param_type(index); if param != arg.get_type() { all_args_match = false; } @@ -253,16 +253,16 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { } } - fn function_ptr_call(&mut self, mut func: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> { + fn function_ptr_call(&mut self, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> { //debug!("func ptr call {:?} with args ({:?})", func, args); - let args = self.check_ptr_call("call", func, args); + let args = self.check_ptr_call("call", func_ptr, args); //let bundle = funclet.map(|funclet| funclet.bundle()); //let bundle = bundle.as_ref().map(|b| &*b.raw); // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). - let gcc_func: Function<'gcc> = self.cx.rvalue_as_function(func); + let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); let return_type = gcc_func.get_return_type(); let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); @@ -271,11 +271,11 @@ impl<'gcc, 'tcx> Builder<'_, 'gcc, 'tcx> { if return_type != void_type { unsafe { RETURN_VALUE_COUNT += 1 }; let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); - current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func, &args)); + current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); result.to_rvalue() } else { - current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func, &args)); + current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); // Return dummy value when not having return value. self.context.new_rvalue_from_long(self.isize_type, 0) } @@ -751,16 +751,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> { let aligned_type = ty.get_aligned(align.bytes()); - let type_fields = self.fields.borrow().get(&ty).cloned(); - // TODO: remove these conditions when libgccjit has a reflection API. - if self.vector_types.borrow().contains_key(&ty) { - let value = self.vector_types.borrow().get(&ty).expect("vector type").clone(); - self.vector_types.borrow_mut().insert(aligned_type, value); - } - else if let Some(fields) = type_fields { - self.fields.borrow_mut().insert(aligned_type, fields); - } - // TODO: It might be better to return a LValue, but fixing the rustc API is non-trivial. self.current_func().new_local(None, aligned_type, "stack_var").get_address(None) } @@ -1027,7 +1017,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let element = self.context.new_array_access(None, value, index); element.get_address(None) } - else if let Some(&(count, element_type)) = self.vector_types.borrow().get(&value_type) { + else if let Some(vector_type) = value_type.is_vector() { + let count = vector_type.get_num_units(); + let element_type = vector_type.get_element_type(); let indexes = vec![self.context.new_rvalue_from_long(element_type, i64::try_from(idx).expect("i64::try_from")); count as usize]; let indexes = self.context.new_rvalue_from_vector(None, value_type, &indexes); let variable = self.current_func.borrow().expect("func") @@ -1036,11 +1028,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { .add_assignment(None, variable, value + indexes); variable.get_address(None) } + else if let Some(struct_type) = value_type.is_struct() { + ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) + } else { - let fields = self.fields.borrow(); - let fields = &fields.get(&value_type) - .unwrap_or_else(|| panic!("Structure {:?} ({:?}) not in fields", value, value.get_type())); - ptr.dereference_field(None, fields[idx as usize]).get_address(None) + panic!("Unexpected type {:?}", value_type); } } @@ -1241,14 +1233,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let element = self.context.new_array_access(None, aggregate_value, index); element.get_address(None) } - else if let Some(&(count, element_type)) = self.vector_types.borrow().get(&value_type) { + else if value_type.is_vector().is_some() { panic!(); } + else if let Some(struct_type) = value_type.is_struct() { + aggregate_value.access_field(None, struct_type.get_field(idx as i32)).to_rvalue() + } else { - let fields = self.fields.borrow(); - let fields = &fields.get(&value_type) - .unwrap_or_else(|| panic!("Structure {:?} not in fields", aggregate_value.get_type())); - aggregate_value.access_field(None, fields[idx as usize]).to_rvalue() + panic!("Unexpected type {:?}", value_type); } /*assert_eq!(idx as c_uint as u64, idx); unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED) }*/ @@ -1264,14 +1256,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); self.context.new_array_access(None, aggregate_value, index) } - else if let Some(&(count, element_type)) = self.vector_types.borrow().get(&value_type) { + else if value_type.is_vector().is_some() { panic!(); } + else if let Some(struct_type) = value_type.is_struct() { + aggregate_value.access_field(None, struct_type.get_field(idx as i32)) + } else { - let fields = self.fields.borrow(); - let fields = &fields.get(&value_type) - .unwrap_or_else(|| panic!("Structure {:?} not in fields", aggregate_value.get_type())); - aggregate_value.access_field(None, fields[idx as usize]) + panic!("Unexpected type {:?}", value_type); }; self.llbb().add_assignment(None, lvalue, value); diff --git a/src/common.rs b/src/common.rs index 1c7976963ae..496eec631ec 100644 --- a/src/common.rs +++ b/src/common.rs @@ -187,9 +187,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let name = fields.iter().map(|typ| format!("{:?}", typ)).collect::>().join("_"); let typ = self.type_struct(&fields, packed); let structure = self.global_init_func.new_local(None, typ, &name); - let fields = &self.fields.borrow()[&typ]; - for (value, field) in values.iter().zip(fields.iter()) { - let field_lvalue = structure.access_field(None, *field); + let struct_type = typ.is_struct().expect("struct type"); + for (index, value) in values.iter().enumerate() { + let field = struct_type.get_field(index as i32); + let field_lvalue = structure.access_field(None, field); self.global_init_block.add_assignment(None, field_lvalue, *value); } self.lvalue_to_rvalue(structure) diff --git a/src/context.rs b/src/context.rs index 1e65f9ccbe6..b17848493ec 100644 --- a/src/context.rs +++ b/src/context.rs @@ -83,8 +83,6 @@ pub struct CodegenCx<'gcc, 'tcx> { pub types: RefCell, Option), Type<'gcc>>>, pub tcx: TyCtxt<'tcx>, - pub fields: RefCell, Vec>>>, - pub vector_types: RefCell, (u64, Type<'gcc>)>>, pub struct_types: RefCell>, Type<'gcc>>>, pub types_with_fields_to_set: RefCell, (Struct<'gcc>, TyAndLayout<'tcx>)>>, @@ -212,8 +210,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { scalar_types: Default::default(), types: Default::default(), tcx, - fields: Default::default(), - vector_types: Default::default(), struct_types: Default::default(), types_with_fields_to_set: Default::default(), local_gen_sym_counter: Cell::new(0), diff --git a/src/type_.rs b/src/type_.rs index fb20c0b258a..99122329aa9 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -120,16 +120,15 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let name = types.iter().map(|typ| format!("{:?}", typ)).collect::>().join("_"); //let typ = self.context.new_struct_type(None, format!("struct{}", name), &fields).as_type(); let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); - self.fields.borrow_mut().insert(typ, fields); self.struct_types.borrow_mut().insert(types, typ); typ } fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { - if typ.is_int() { + if typ.is_integral() { TypeKind::Integer } - else if typ.is_vector() { + else if typ.is_vector().is_some() { TypeKind::Vector } else { @@ -219,7 +218,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { .map(|field| self.context.new_field(None, *field, "field")) .collect(); typ.set_fields(None, &fields); - self.fields.borrow_mut().insert(typ.as_type(), fields); } fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { @@ -227,9 +225,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let fields: Vec<_> = fields.iter() .map(|field| self.context.new_field(None, *field, "field")) .collect(); - let typ = self.context.new_struct_type(None, "unnamedStruct", &fields).as_type(); - self.fields.borrow_mut().insert(typ, fields); - typ + return self.context.new_struct_type(None, "unnamedStruct", &fields).as_type(); } pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { diff --git a/src/type_of.rs b/src/type_of.rs index 598222758a3..4c6ca401833 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -44,9 +44,7 @@ pub fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLa Abi::Scalar(_) => bug!("handled elsewhere"), Abi::Vector { ref element, count } => { let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO); - let vector_type = cx.context.new_vector_type(element, count); - cx.vector_types.borrow_mut().insert(vector_type, (count, element)); - return vector_type + return cx.context.new_vector_type(element, count); }, Abi::ScalarPair(..) => { return cx.type_struct(