diff --git a/skull/llvm/flow.c b/skull/llvm/flow.c index 00c67241..9c07589d 100644 --- a/skull/llvm/flow.c +++ b/skull/llvm/flow.c @@ -28,8 +28,9 @@ bool node_to_llvm_ir(AstNode *); Builds an return statement from `node`. */ void llvm_make_return(AstNode *node) { - if (node->token->next->token_type == TOKEN_IDENTIFIER) { - SCOPE_FIND_VAR(found_var, node->token->next, var_name); + const Token *const token_val = node->token->next; + if (token_val->token_type == TOKEN_IDENTIFIER) { + SCOPE_FIND_VAR(found_var, token_val, var_name); free(var_name); if (CURRENT_FUNC == MAIN_FUNC && found_var->type != &TYPE_INT) { @@ -37,10 +38,14 @@ void llvm_make_return(AstNode *node) { } LLVMBuildRet(BUILDER, llvm_var_get_value(found_var)); + return; } - else { - LLVMBuildRet(BUILDER, LLVM_INT(eval_integer(node->token->next))); + + if (CURRENT_FUNC == MAIN_FUNC && token_val->token_type != TOKEN_INT_CONST) { + PANIC("returning non-int value \"%s\" from main\n", { .tok = token_val }); } + + LLVMBuildRet(BUILDER, llvm_parse_token(token_val)); } LLVMValueRef llvm_make_cond(AstNode *); diff --git a/skull/parse/ast/node.c b/skull/parse/ast/node.c index 46fb71fb..c70697b1 100644 --- a/skull/parse/ast/node.c +++ b/skull/parse/ast/node.c @@ -308,7 +308,7 @@ AstNode *make_ast_tree_(Token *token, unsigned indent_lvl, Token **token_last) { if (token->token_type == TOKEN_KW_RETURN && token->next && ( token->next->token_type == TOKEN_IDENTIFIER || - token->next->token_type == TOKEN_INT_CONST) + is_const_literal(token->next)) ) { token = token->next; push_ast_node(token, &last, AST_NODE_RETURN, &node); diff --git a/test/sh/error/_non_int_return.sk.out b/test/sh/error/_non_int_return.sk.out new file mode 100644 index 00000000..2f862d9a --- /dev/null +++ b/test/sh/error/_non_int_return.sk.out @@ -0,0 +1 @@ +Compilation error: returning non-int value "1.0" from main diff --git a/test/sh/error/non_int_return.sk b/test/sh/error/non_int_return.sk new file mode 100644 index 00000000..fe312f22 --- /dev/null +++ b/test/sh/error/non_int_return.sk @@ -0,0 +1 @@ +return 1.0 \ No newline at end of file diff --git a/test/sh/function/_non_int_return.sk.ll b/test/sh/function/_non_int_return.sk.ll index ae15fd2c..50d0f171 100644 --- a/test/sh/function/_non_int_return.sk.ll +++ b/test/sh/function/_non_int_return.sk.ll @@ -7,6 +7,14 @@ entry: } define private double @func() { +entry: + %ret = alloca double + store double 3.140000e+00, double* %ret + %0 = load double, double* %ret + ret double %0 +} + +define private double @func2() { entry: ret double 3.140000e+00 } diff --git a/test/sh/function/non_int_return.sk b/test/sh/function/non_int_return.sk index a70eb936..56eaaa77 100644 --- a/test/sh/function/non_int_return.sk +++ b/test/sh/function/non_int_return.sk @@ -1,4 +1,8 @@ func() float { - ret := 3.14 + mut ret := 3.14 return ret } + +func2() float { + return 3.14 +} diff --git a/test/sh/main.sh b/test/sh/main.sh index 3074e189..2ebf0845 100755 --- a/test/sh/main.sh +++ b/test/sh/main.sh @@ -200,6 +200,7 @@ test_error "unexpected_code_block.sk" test_error "unreachable_return.sk" test_error "invalid_identifier.sk" test_error "main_reserved.sk" +test_error "non_int_return.sk" touch test/sh/error/read_protected.sk chmod 200 test/sh/error/read_protected.sk