1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-04 06:23:13 +03:00
juvix/tests/runtime/positive/test015.c
Łukasz Czajka 4dcbb002fe
Add an if instruction to JuvixReg (#2855)
* Closes #2829
* Adds a transformation which converts `br` to `if` when the variable
branched on was assigned in the previous instruction. The transformation
itself doesn't check liveness and doesn't remove the assignment. Dead
code elimination should be run afterwards to remove the assignment.
* For Cairo, it only makes sense to convert `br` to `if` for equality
comparisons against zero. The assignment before `br` will always become
dead after converting `br` to `if`, because we convert to SSA before.
2024-06-26 19:08:33 +02:00

266 lines
8.2 KiB
C

/* Branching, matching and recursion on lists */
#include <juvix/api.h>
#define CONSTRS_NUM (BUILTIN_UIDS_NUM + 2)
static constr_info_t juvix_constr_info_array[CONSTRS_NUM] = {
BUILTIN_UIDS_INFO, {"nil", 0, APP_FIXITY}, {"cons", 0, APP_FIXITY}};
#define UID_NIL FIRST_USER_UID
#define UID_CONS (FIRST_USER_UID + 1)
#define CONSTR_NIL MAKE_HEADER(UID_NIL, 0)
int main() {
DECL_REG_ARG(0);
DECL_REG_ARG(1);
JUVIX_PROLOGUE(3);
juvix_constrs_num = CONSTRS_NUM;
juvix_constr_info = juvix_constr_info_array;
CALL(0, juvix_function_main, juvix_label_0);
goto juvix_program_end;
JUVIX_FUNCTION_NS(juvix_function_hd);
{
juvix_result = CONSTR_ARG(ARG(0), 0);
RETURN_NS;
}
JUVIX_FUNCTION_NS(juvix_function_tl);
{
juvix_result = CONSTR_ARG(ARG(0), 1);
RETURN_NS;
}
JUVIX_FUNCTION_NS(juvix_function_null);
{
switch (ARG(0)) {
case CONSTR_NIL:
juvix_result = BOOL_TRUE;
break;
default: // cons
juvix_result = BOOL_FALSE;
break;
}
RETURN_NS;
}
JUVIX_FUNCTION(juvix_function_map, 3);
{
switch (ARG(1)) {
case CONSTR_NIL:
juvix_result = CONSTR_NIL;
RETURN;
default: {
DECL_TMP(0);
DECL_TMP(1);
TMP(0) = ARG(0);
TMP(1) = ARG(1);
STACK_PUSH(TMP(0));
STACK_PUSH(TMP(1));
ARG(0) = TMP(0);
ARG(1) = CONSTR_ARG(TMP(1), 1);
CALL(0, juvix_function_map, juvix_label_1);
STACK_POP(TMP(1));
STACK_POP(TMP(0));
STACK_PUSH(juvix_result);
ASSIGN_CARGS(TMP(0), {
CARG(juvix_closure_nargs) = CONSTR_ARG(TMP(1), 0);
});
CALL_CLOSURE(TMP(0), juvix_label_2);
STACK_POP(TMP(0));
TMP(1) = juvix_result;
PREALLOC(
3,
{
STACK_PUSH(TMP(0));
STACK_PUSH(TMP(1));
},
{
STACK_POP(TMP(1));
STACK_POP(TMP(0));
});
ALLOC_CONSTR_BOXED(juvix_result, UID_CONS, 2);
CONSTR_ARG(juvix_result, 0) = TMP(1);
CONSTR_ARG(juvix_result, 1) = TMP(0);
RETURN;
}
}
}
JUVIX_FUNCTION(juvix_function_map_1, 3);
{
STACK_PUSH(ARG(0));
STACK_PUSH(ARG(1));
ARG(0) = ARG(1);
CALL(0, juvix_function_null, juvix_label_3);
STACK_POP(ARG(1));
STACK_POP(ARG(0));
JUVIX_BRANCH(
juvix_result, { juvix_result = CONSTR_NIL; },
{
DECL_TMP(0);
DECL_TMP(1);
STACK_PUSH(ARG(0));
ARG(0) = ARG(1);
CALL(0, juvix_function_tl, juvix_label_4);
ARG(0) = STACK_TOP;
STACK_PUSH(ARG(1));
ARG(1) = juvix_result;
CALL(0, juvix_function_map_1, juvix_label_5);
STACK_POP(TMP(1));
STACK_POP(TMP(0));
STACK_PUSH(TMP(0));
STACK_PUSH(juvix_result);
ARG(0) = TMP(1);
CALL(0, juvix_function_hd, juvix_label_6);
STACK_POP(TMP(1)); // TMP(1) = map tail
STACK_POP(TMP(0)); // TMP(0) = function
STACK_PUSH(TMP(1));
ASSIGN_CARGS(TMP(0),
{ CARG(juvix_closure_nargs) = juvix_result; });
CALL_CLOSURE(TMP(0), juvix_label_7);
STACK_POP(TMP(1));
PREALLOC(3, { STACK_PUSH(TMP(1)); }, { STACK_POP(TMP(1)); });
ALLOC_CONSTR_BOXED(TMP(0), UID_CONS, 2);
CONSTR_ARG(TMP(0), 0) = juvix_result;
CONSTR_ARG(TMP(0), 1) = TMP(1);
juvix_result = TMP(0);
});
RETURN;
}
juvix_closure_add_one:
ARG(0) = CARG(0);
JUVIX_FUNCTION_NS(juvix_function_add_one);
{
JUVIX_INT_ADD(juvix_result, ARG(0), make_smallint(1));
RETURN_NS;
}
JUVIX_FUNCTION(juvix_function_gen, 2);
{
DECL_TMP(0);
JUVIX_VAL_EQ(TMP(0), ARG(0), make_smallint(0));
JUVIX_BRANCH(
TMP(0),
{
juvix_result = CONSTR_NIL;
RETURN;
},
{
JUVIX_INT_SUB(TMP(0), ARG(0), make_smallint(1));
STACK_PUSH(ARG(0));
ARG(0) = TMP(0);
CALL(0, juvix_function_gen, juvix_label_gen_1);
STACK_POP(ARG(0));
PREALLOC(3, { STACK_PUSH(ARG(0)); }, { STACK_POP(ARG(0)); });
ALLOC_CONSTR_BOXED(TMP(0), UID_CONS, 2);
CONSTR_ARG(TMP(0), 0) = ARG(0);
CONSTR_ARG(TMP(0), 1) = juvix_result;
juvix_result = TMP(0);
RETURN;
});
}
JUVIX_FUNCTION(juvix_function_sum, 2);
{
switch (ARG(0)) {
case CONSTR_NIL:
juvix_result = make_smallint(0);
RETURN;
default: {
DECL_TMP(0);
DECL_TMP(1);
TMP(0) = CONSTR_ARG(ARG(0), 0);
STACK_PUSH(TMP(0));
ARG(0) = CONSTR_ARG(ARG(0), 1);
CALL(0, juvix_function_sum, juvix_label_sum_1);
STACK_POP(TMP(0));
JUVIX_INT_ADD(TMP(1), TMP(0), juvix_result);
juvix_result = TMP(1);
RETURN;
}
}
}
JUVIX_FUNCTION(juvix_function_length, 1);
{
switch (ARG(0)) {
case CONSTR_NIL:
juvix_result = make_smallint(0);
RETURN;
default: {
DECL_TMP(0);
ARG(0) = CONSTR_ARG(ARG(0), 1);
CALL(0, juvix_function_length, juvix_label_length_1);
JUVIX_INT_ADD(TMP(0), juvix_result, make_smallint(1));
juvix_result = TMP(0);
RETURN;
}
}
}
JUVIX_FUNCTION_NS(juvix_function_length_tail);
{
switch (ARG(0)) {
case CONSTR_NIL:
juvix_result = ARG(1);
RETURN_NS;
default: {
ARG(0) = CONSTR_ARG(ARG(0), 1);
JUVIX_INT_ADD(ARG(1), ARG(1), make_smallint(1));
TAIL_CALL_NS(0, juvix_function_length_tail);
}
}
}
JUVIX_FUNCTION(juvix_function_main, MAX_STACK_DELTA);
{
DECL_TMP(0); // cons 0 (cons 1 nil)
DECL_TMP(1); // cons 1 nil
DECL_TMP(2); // calloc add_one 0
ALLOC_CONSTR_BOXED(TMP(1), UID_CONS, 2);
CONSTR_ARG(TMP(1), 0) = make_smallint(1);
CONSTR_ARG(TMP(1), 1) = CONSTR_NIL;
ALLOC_CONSTR_BOXED(TMP(0), UID_CONS, 2);
CONSTR_ARG(TMP(0), 0) = make_smallint(0);
CONSTR_ARG(TMP(0), 1) = TMP(1);
ALLOC_CLOSURE(TMP(2), 0, LABEL_ADDR(juvix_closure_add_one), 0, 1);
ARG(0) = TMP(2);
ARG(1) = TMP(0);
CALL(0, juvix_function_map, juvix_label_8);
JUVIX_TRACE(juvix_result);
ARG(0) = TMP(2);
ARG(1) = TMP(0);
CALL(0, juvix_function_map_1, juvix_label_9);
JUVIX_TRACE(juvix_result);
ARG(0) = make_smallint(10000);
CALL(0, juvix_function_gen, juvix_label_10);
ARG(0) = TMP(2);
ARG(1) = juvix_result;
CALL(0, juvix_function_map, juvix_label_11);
ARG(0) = juvix_result;
CALL(0, juvix_function_sum, juvix_label_12);
JUVIX_TRACE(juvix_result);
ARG(0) = make_smallint(1000000);
CALL(0, juvix_function_gen, juvix_label_13);
STACK_PUSH(juvix_result);
ARG(0) = TMP(2);
ARG(1) = juvix_result;
CALL(0, juvix_function_map, juvix_label_14);
ARG(0) = juvix_result;
CALL(0, juvix_function_length, juvix_label_15);
JUVIX_TRACE(juvix_result);
STACK_POP(ARG(0));
ARG(1) = make_smallint(0);
TAIL_CALL(0, juvix_function_length_tail);
}
JUVIX_EPILOGUE;
return 0;
}