diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index f66975d2ac..186b008cf7 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -294,6 +294,12 @@ pub fn types() -> MutMap { ), ); + // div : Int, Int -> Int + add_type( + Symbol::INT_DIV_UNSAFE, + SolvedType::Func(vec![int_type(), int_type()], Box::new(int_type())), + ); + // mod : Int, Int -> Result Int [ DivByZero ]* add_type( Symbol::INT_MOD, diff --git a/compiler/builtins/src/unique.rs b/compiler/builtins/src/unique.rs index 0a0671b0cf..ca6ac0fce9 100644 --- a/compiler/builtins/src/unique.rs +++ b/compiler/builtins/src/unique.rs @@ -348,9 +348,23 @@ pub fn types() -> MutMap { // lowest : Int add_type(Symbol::INT_LOWEST, int_type(UVAR1)); - // div or (//) : Int, Int -> Int + // div or (//) : Int, Int -> Result Int [ DivByZero ]* + let div_by_zero = SolvedType::TagUnion( + vec![(TagName::Global("DivByZero".into()), vec![])], + Box::new(SolvedType::Wildcard), + ); + add_type( Symbol::INT_DIV, + unique_function( + vec![int_type(UVAR1), int_type(UVAR2)], + result_type(UVAR3, int_type(UVAR4), lift(UVAR5, div_by_zero)), + ), + ); + + // div or (//) : Int, Int -> Int + add_type( + Symbol::INT_DIV_UNSAFE, unique_function(vec![int_type(UVAR1), int_type(UVAR2)], int_type(UVAR3)), ); diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 8a9eafe24c..005fde49f0 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1226,6 +1226,17 @@ fn call_with_args<'a, 'ctx, 'env>( Symbol::FLOAT_ROUND => call_intrinsic(LLVM_LROUND_I64_F64, env, args), Symbol::LIST_SET => list_set(parent, args, env, InPlace::Clone), Symbol::LIST_SET_IN_PLACE => list_set(parent, args, env, InPlace::InPlace), + Symbol::INT_DIV_UNSAFE => { + debug_assert!(args.len() == 2); + + let int_val = env.builder.build_int_signed_div( + args[0].0.into_int_value(), + args[1].0.into_int_value(), + "div_i64", + ); + + BasicValueEnum::IntValue(int_val) + } _ => { let fn_val = env .module diff --git a/compiler/gen/tests/gen_builtins.rs b/compiler/gen/tests/gen_builtins.rs index 13611cde02..d6a78876a8 100644 --- a/compiler/gen/tests/gen_builtins.rs +++ b/compiler/gen/tests/gen_builtins.rs @@ -159,6 +159,19 @@ mod gen_builtins { ); } + #[test] + fn gen_div_i64() { + assert_evals_to!( + indoc!( + r#" + Int.divUnsafe 1000 100 + "# + ), + 10, + i64 + ); + } + #[test] fn gen_order_of_arithmetic_ops() { assert_evals_to!( diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 34abb0569e..5cdf2c7bfe 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -599,6 +599,7 @@ define_builtins! { 9 INT_EQ_I64: "#eqi64" // Equality on 64-bit integers, the standard in Roc 10 INT_EQ_I1: "#eqi1" // Equality on boolean (theoretically i1) values 11 INT_EQ_I8: "#eqi8" // Equality on byte (theoretically i8) values + 12 INT_DIV_UNSAFE: "divUnsafe" // TODO remove once we can code gen Result } 3 FLOAT: "Float" => { 0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias diff --git a/compiler/solve/tests/test_uniq_solve.rs b/compiler/solve/tests/test_uniq_solve.rs index 5eff143efe..717c518b4d 100644 --- a/compiler/solve/tests/test_uniq_solve.rs +++ b/compiler/solve/tests/test_uniq_solve.rs @@ -1944,7 +1944,7 @@ mod test_uniq_solve { Int.highest // Int.highest "# ), - "Attr * Int", + "Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*))", ); } @@ -1956,7 +1956,7 @@ mod test_uniq_solve { 3 // 4 "# ), - "Attr * Int", + "Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*))", ); } @@ -1968,7 +1968,7 @@ mod test_uniq_solve { 3 // Int.highest "# ), - "Attr * Int", + "Attr * (Result (Attr * Int) (Attr * [ DivByZero ]*))", ); } @@ -2097,8 +2097,8 @@ mod test_uniq_solve { reverse "# ), - // "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr b c)))", - "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr a c)))", + "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr b c)))", + // "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr a c)))", ); }