From 3badb7d8b82683a9932d3d3c6cf9039e64b6b461 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 9 May 2024 09:23:40 +0200 Subject: [PATCH 1/4] try array cast --- crates/concrete_codegen_mlir/src/codegen.rs | 49 +++++++++++++++++++-- crates/concrete_ir/src/lib.rs | 4 ++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/crates/concrete_codegen_mlir/src/codegen.rs b/crates/concrete_codegen_mlir/src/codegen.rs index 2dd5fb8..3527b0c 100644 --- a/crates/concrete_codegen_mlir/src/codegen.rs +++ b/crates/concrete_codegen_mlir/src/codegen.rs @@ -511,7 +511,7 @@ fn compile_rvalue<'c: 'b, 'b>( let target_ty = target_ty.clone(); let target_mlir_ty = compile_type(ctx.module_ctx, &target_ty); let (value, current_ty) = compile_load_operand(ctx, block, op, locals)?; - let is_signed = target_ty.kind.is_signed(); + let is_signed = current_ty.kind.is_signed(); if target_ty.kind.is_ptr_like() { // int to ptr @@ -525,8 +525,51 @@ fn compile_rvalue<'c: 'b, 'b>( .into(); (value, target_ty.clone()) } else if current_ty.kind.is_ptr_like() { - // ptr to ptr: noop (value, target_ty.clone()) + } else if current_ty.kind.is_array() { + let k1 = block + .append_operation(arith::constant( + ctx.context(), + IntegerAttribute::new(IntegerType::new(ctx.context(), 64).into(), 1) + .into(), + location, + )) + .result(0)? + .into(); + let ptr = block + .append_operation( + ods::llvm::alloca( + ctx.context(), + pointer(ctx.context(), 0), + k1, + TypeAttribute::new(compile_type(ctx.module_ctx, ¤t_ty)), + location, + ) + .into(), + ) + .result(0)? + .into(); + block.append_operation( + ods::llvm::store(ctx.context(), value, ptr, location).into(), + ); + let ptr = block.append_operation( + { + let mut op = ods::llvm::getelementptr( + ctx.context(), + pointer(ctx.context(), 0), + ptr, + &[], + DenseI32ArrayAttribute::new(ctx.context(), &[0]), + TypeAttribute::new(compile_type(ctx.module_ctx, ¤t_ty)), + location, + ); + op.set_inbounds(Attribute::unit(ctx.context())); + op + } + .into(), + ).result(0)?.into(); + + (ptr, target_ty.clone()) } else { unreachable!("cast from {:?} to ptr", current_ty.kind) } @@ -1370,7 +1413,7 @@ fn compile_type<'c>(ctx: ModuleCodegenCtx<'c>, ty: &Ty) -> Type<'c> { match &ty.kind { concrete_ir::TyKind::Unit => Type::none(ctx.ctx.mlir_context), concrete_ir::TyKind::Bool => IntegerType::new(ctx.ctx.mlir_context, 1).into(), - concrete_ir::TyKind::Char => IntegerType::new(ctx.ctx.mlir_context, 32).into(), + concrete_ir::TyKind::Char => IntegerType::new(ctx.ctx.mlir_context, 8).into(), concrete_ir::TyKind::Int(int_ty) => match int_ty { concrete_ir::IntTy::I8 => IntegerType::new(ctx.ctx.mlir_context, 8).into(), concrete_ir::IntTy::I16 => IntegerType::new(ctx.ctx.mlir_context, 16).into(), diff --git a/crates/concrete_ir/src/lib.rs b/crates/concrete_ir/src/lib.rs index 464a532..cade4bb 100644 --- a/crates/concrete_ir/src/lib.rs +++ b/crates/concrete_ir/src/lib.rs @@ -325,6 +325,10 @@ impl TyKind { matches!(self, TyKind::Ptr(_, _) | TyKind::Ref(_, _)) } + pub fn is_array(&self) -> bool { + matches!(self, TyKind::Array(_, _)) + } + pub fn is_int(&self) -> bool { matches!(self, TyKind::Int(_) | TyKind::Uint(_)) } From 1986a810a76448b64039cfb1174e4272d8a95c86 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 9 May 2024 10:01:32 +0200 Subject: [PATCH 2/4] fix chars --- crates/concrete_codegen_mlir/src/codegen.rs | 158 ++++++++++++-------- crates/concrete_ir/src/lib.rs | 3 +- crates/concrete_ir/src/lowering.rs | 2 +- examples/hello_world_array.con | 10 ++ 4 files changed, 108 insertions(+), 65 deletions(-) create mode 100644 examples/hello_world_array.con diff --git a/crates/concrete_codegen_mlir/src/codegen.rs b/crates/concrete_codegen_mlir/src/codegen.rs index 3527b0c..82861cf 100644 --- a/crates/concrete_codegen_mlir/src/codegen.rs +++ b/crates/concrete_codegen_mlir/src/codegen.rs @@ -552,22 +552,6 @@ fn compile_rvalue<'c: 'b, 'b>( block.append_operation( ods::llvm::store(ctx.context(), value, ptr, location).into(), ); - let ptr = block.append_operation( - { - let mut op = ods::llvm::getelementptr( - ctx.context(), - pointer(ctx.context(), 0), - ptr, - &[], - DenseI32ArrayAttribute::new(ctx.context(), &[0]), - TypeAttribute::new(compile_type(ctx.module_ctx, ¤t_ty)), - location, - ); - op.set_inbounds(Attribute::unit(ctx.context())); - op - } - .into(), - ).result(0)?.into(); (ptr, target_ty.clone()) } else { @@ -1093,11 +1077,6 @@ fn compile_store_place<'c: 'b, 'b>( } } PlaceElem::Index(local) => { - local_ty = match local_ty.kind { - TyKind::Array(inner, _) => *inner, - _ => unreachable!(), - }; - let place = Place { local: *local, projection: vec![], @@ -1106,34 +1085,58 @@ fn compile_store_place<'c: 'b, 'b>( let (index, _) = compile_load_place(ctx, block, &place, locals)?; ptr = block - .append_operation(llvm::get_element_ptr_dynamic( - ctx.context(), - ptr, - &[index], - compile_type(ctx.module_ctx, &local_ty), - pointer(ctx.context(), 0), - Location::unknown(ctx.context()), - )) + .append_operation( + { + let mut op = ods::llvm::getelementptr( + ctx.context(), + pointer(ctx.context(), 0), + ptr, + &[index], + DenseI32ArrayAttribute::new(ctx.context(), &[0, i32::MIN]), + TypeAttribute::new(compile_type(ctx.module_ctx, &local_ty)), + Location::unknown(ctx.context()), + ); + op.set_inbounds(Attribute::unit(ctx.context())); + op + } + .into(), + ) .result(0)? .into(); - } - PlaceElem::ConstantIndex(index) => { + local_ty = match local_ty.kind { TyKind::Array(inner, _) => *inner, _ => unreachable!(), }; - + } + PlaceElem::ConstantIndex(index) => { ptr = block - .append_operation(llvm::get_element_ptr( - ctx.context(), - ptr, - DenseI32ArrayAttribute::new(ctx.context(), &[(*index).try_into().unwrap()]), - compile_type(ctx.module_ctx, &local_ty), - pointer(ctx.context(), 0), - Location::unknown(ctx.context()), - )) + .append_operation( + { + let mut op = ods::llvm::getelementptr( + ctx.context(), + pointer(ctx.context(), 0), + ptr, + &[], + DenseI32ArrayAttribute::new( + ctx.context(), + &[0, (*index).try_into().unwrap()], + ), + TypeAttribute::new(compile_type(ctx.module_ctx, &local_ty)), + Location::unknown(ctx.context()), + ); + op.set_inbounds(Attribute::unit(ctx.context())); + op + } + .into(), + ) .result(0)? .into(); + + local_ty = match local_ty.kind { + TyKind::Array(inner, _) => *inner, + _ => unreachable!(), + }; } } } @@ -1206,11 +1209,6 @@ fn compile_load_place<'c: 'b, 'b>( } } PlaceElem::Index(local) => { - local_ty = match local_ty.kind { - TyKind::Array(inner, _) => *inner, - _ => unreachable!(), - }; - let place = Place { local: *local, projection: Default::default(), @@ -1219,33 +1217,58 @@ fn compile_load_place<'c: 'b, 'b>( let (index, _) = compile_load_place(ctx, block, &place, locals)?; ptr = block - .append_operation(llvm::get_element_ptr_dynamic( - ctx.context(), - ptr, - &[index], - compile_type(ctx.module_ctx, &local_ty), - pointer(ctx.context(), 0), - Location::unknown(ctx.context()), - )) + .append_operation( + { + let mut op = ods::llvm::getelementptr( + ctx.context(), + pointer(ctx.context(), 0), + ptr, + &[index], + DenseI32ArrayAttribute::new(ctx.context(), &[0, i32::MIN]), + TypeAttribute::new(compile_type(ctx.module_ctx, &local_ty)), + Location::unknown(ctx.context()), + ); + op.set_inbounds(Attribute::unit(ctx.context())); + op + } + .into(), + ) .result(0)? .into(); - } - PlaceElem::ConstantIndex(index) => { + local_ty = match local_ty.kind { TyKind::Array(inner, _) => *inner, _ => unreachable!(), }; + } + PlaceElem::ConstantIndex(index) => { ptr = block - .append_operation(llvm::get_element_ptr( - ctx.context(), - ptr, - DenseI32ArrayAttribute::new(ctx.context(), &[(*index).try_into().unwrap()]), - compile_type(ctx.module_ctx, &local_ty), - pointer(ctx.context(), 0), - Location::unknown(ctx.context()), - )) + .append_operation( + { + let mut op = ods::llvm::getelementptr( + ctx.context(), + pointer(ctx.context(), 0), + ptr, + &[], + DenseI32ArrayAttribute::new( + ctx.context(), + &[0, (*index).try_into().unwrap()], + ), + TypeAttribute::new(compile_type(ctx.module_ctx, &local_ty)), + Location::unknown(ctx.context()), + ); + op.set_inbounds(Attribute::unit(ctx.context())); + op + } + .into(), + ) .result(0)? .into(); + + local_ty = match local_ty.kind { + TyKind::Array(inner, _) => *inner, + _ => unreachable!(), + }; } } } @@ -1276,6 +1299,7 @@ fn value_tree_to_int(value: &ValueTree) -> Option { concrete_ir::ConstValue::I64(value) => Some(*value), concrete_ir::ConstValue::I128(value) => Some((*value) as i64), concrete_ir::ConstValue::U8(value) => Some((*value) as i64), + concrete_ir::ConstValue::Char(value) => Some((*value) as i64), concrete_ir::ConstValue::U16(value) => Some((*value) as i64), concrete_ir::ConstValue::U32(value) => Some((*value) as i64), concrete_ir::ConstValue::U64(value) => Some((*value) as i64), @@ -1343,6 +1367,14 @@ fn compile_value_tree<'c: 'b, 'b>( )) .result(0)? .into(), + concrete_ir::ConstValue::Char(value) => block + .append_operation(arith::constant( + ctx.context(), + Attribute::parse(ctx.context(), &format!("{} : i8", value)).unwrap(), + Location::unknown(ctx.context()), + )) + .result(0)? + .into(), concrete_ir::ConstValue::U8(value) => block .append_operation(arith::constant( ctx.context(), diff --git a/crates/concrete_ir/src/lib.rs b/crates/concrete_ir/src/lib.rs index cade4bb..54af5a7 100644 --- a/crates/concrete_ir/src/lib.rs +++ b/crates/concrete_ir/src/lib.rs @@ -440,7 +440,7 @@ impl TyKind { match self { TyKind::Unit => unreachable!(), TyKind::Bool => ValueTree::Leaf(ConstValue::Bool(false)), - TyKind::Char => todo!(), + TyKind::Char => ValueTree::Leaf(ConstValue::Char(0)), TyKind::Int(ty) => match ty { IntTy::I8 => ValueTree::Leaf(ConstValue::I8(0)), IntTy::I16 => ValueTree::Leaf(ConstValue::I16(0)), @@ -571,6 +571,7 @@ pub enum UnOp { #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub enum ConstValue { Bool(bool), + Char(u8), I8(i8), I16(i16), I32(i32), diff --git a/crates/concrete_ir/src/lowering.rs b/crates/concrete_ir/src/lowering.rs index dd2104c..3829408 100644 --- a/crates/concrete_ir/src/lowering.rs +++ b/crates/concrete_ir/src/lowering.rs @@ -1381,7 +1381,7 @@ fn lower_value_expr( span: Some(*const_span), kind: TyKind::Char, }, - data: ConstKind::Value(ValueTree::Leaf(ConstValue::U32((*value) as u32))), + data: ConstKind::Value(ValueTree::Leaf(ConstValue::Char((*value) as u8))), })), Ty { span: Some(*const_span), diff --git a/examples/hello_world_array.con b/examples/hello_world_array.con new file mode 100644 index 0000000..1e06b76 --- /dev/null +++ b/examples/hello_world_array.con @@ -0,0 +1,10 @@ +mod Main { + pub extern fn puts(data: *mut char) -> i32; + + pub fn main() -> i32 { + let x: [char; 13] = ['h','e','l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0']; + let z: *mut char = x as *mut char; + puts(z); + return 0; + } +} From 859afb78874017293d33d51b3036b6d7647f829d Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 9 May 2024 10:06:02 +0200 Subject: [PATCH 3/4] add test --- crates/concrete_driver/tests/examples.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/concrete_driver/tests/examples.rs b/crates/concrete_driver/tests/examples.rs index 1377b7f..4215fef 100644 --- a/crates/concrete_driver/tests/examples.rs +++ b/crates/concrete_driver/tests/examples.rs @@ -41,6 +41,7 @@ fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) { } #[test_case(include_str!("../../../examples/hello_world_hacky.con"), "hello_world_hacky", false, "Hello World\n" ; "hello_world_hacky.con")] +#[test_case(include_str!("../../../examples/hello_world_array.con"), "hello_world_array", false, "hello world!\n" ; "hello_world_array.con")] fn example_tests_with_output(source: &str, name: &str, is_library: bool, result: &str) { assert_eq!( result, From a84992072ecc4155438bc62cba34c6ef8d9f5d71 Mon Sep 17 00:00:00 2001 From: Edgar Date: Fri, 10 May 2024 15:10:40 +0100 Subject: [PATCH 4/4] docs --- crates/concrete_codegen_mlir/src/codegen.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/concrete_codegen_mlir/src/codegen.rs b/crates/concrete_codegen_mlir/src/codegen.rs index 82861cf..1fb511c 100644 --- a/crates/concrete_codegen_mlir/src/codegen.rs +++ b/crates/concrete_codegen_mlir/src/codegen.rs @@ -527,6 +527,8 @@ fn compile_rvalue<'c: 'b, 'b>( } else if current_ty.kind.is_ptr_like() { (value, target_ty.clone()) } else if current_ty.kind.is_array() { + // Cast from fixed size array to pointer. + // We need to create a alloca and store the array there, because we have it by-value. let k1 = block .append_operation(arith::constant( ctx.context(), @@ -553,6 +555,8 @@ fn compile_rvalue<'c: 'b, 'b>( ods::llvm::store(ctx.context(), value, ptr, location).into(), ); + // Return the alloca ptr, making this "the cast". + (ptr, target_ty.clone()) } else { unreachable!("cast from {:?} to ptr", current_ty.kind)