From 4d4bbbdebc691d120e2af478a2b1385c67cb551e Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 18 Nov 2021 10:59:49 +0100 Subject: [PATCH] Parses attribute defines. Removal of incremental array parsing. Labels in macros should now work correctly. Volatile and attribute are no longer keywords. Checked a few todos. On test failure, return -1 --- .github/workflows/main.yml | 6 +- src/compiler/ast.c | 3 - src/compiler/codegen_general.c | 2 +- src/compiler/compiler.c | 1 - src/compiler/compiler_internal.h | 10 +- src/compiler/context.c | 3 - src/compiler/copying.c | 33 +- src/compiler/enums.h | 8 +- src/compiler/llvm_codegen_expr.c | 2 + src/compiler/llvm_codegen_stmt.c | 2 - src/compiler/parse_global.c | 104 +++--- src/compiler/parse_stmt.c | 15 +- src/compiler/sema_casts.c | 65 +--- src/compiler/sema_decls.c | 5 +- src/compiler/sema_expr.c | 7 +- src/compiler/sema_stmts.c | 10 - src/compiler/sema_types.c | 4 +- src/compiler/tokens.c | 4 - src/utils/file_utils.c | 62 ++-- src/utils/whereami.c | 3 +- src/utils/whereami.h | 2 +- test/src/tester.py | 3 + .../functions/test_regression_mingw.c3t | 8 +- .../initializer_lists/ranges_to_dynamic.c3t | 1 + .../test_suite/macros/macro_nested_labels.c3t | 324 ++++++++++++++++++ test/test_suite/slices/slice_assign.c3t | 1 + test/test_suite/types/various.c3 | 2 +- 27 files changed, 486 insertions(+), 204 deletions(-) create mode 100644 test/test_suite/macros/macro_nested_labels.c3t diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 10eba74e9..5233d05d9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,7 +33,7 @@ jobs: - name: Build testproject run: | cd resources/testproject - ../../build/c3c build + ../../build/c3c build --debug-log - name: run compiler tests run: | @@ -65,7 +65,7 @@ jobs: - name: Build testproject run: | cd resources/testproject - ../../build/c3c build + ../../build/c3c build --debug-log - name: run compiler tests run: | @@ -93,7 +93,7 @@ jobs: - name: Build testproject run: | cd resources/testproject - ../../build/c3c build + ../../build/c3c build --debug-log - name: run compiler tests run: | diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 1defb78c3..136df2892 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -49,8 +49,6 @@ const char *decl_to_name(Decl *decl) return "compile time if"; case DECL_CT_SWITCH: return "compile time switch"; - case DECL_ARRAY_VALUE: - UNREACHABLE; case DECL_IMPORT: return "import"; case DECL_LABEL: @@ -165,7 +163,6 @@ Decl *decl_new_with_type(TokenId name, DeclKind decl_type, Visibility visibility case DECL_VAR: case DECL_ENUM_CONSTANT: case DECL_ERRVALUE: - case DECL_ARRAY_VALUE: case DECL_IMPORT: case DECL_MACRO: case DECL_GENERIC: diff --git a/src/compiler/codegen_general.c b/src/compiler/codegen_general.c index b6154f304..43d393586 100644 --- a/src/compiler/codegen_general.c +++ b/src/compiler/codegen_general.c @@ -325,7 +325,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements) AlignSize type_alloca_alignment(Type *type) { - if (platform_target.abi == ABI_X64) + if (platform_target.abi == ABI_X64 || platform_target.abi == ABI_WIN64) { type = type_lowering(type); if (type->type_kind == TYPE_ARRAY && type_size(type) >= 16) return 16; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 84677fd05..34c1d536c 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -156,7 +156,6 @@ static void register_generic_decls(Module *module, Decl **decls) switch (decl->decl_kind) { case DECL_POISONED: - case DECL_ARRAY_VALUE: case DECL_ENUM_CONSTANT: case DECL_ERRVALUE: case DECL_IMPORT: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 99207e9db..f6368eb31 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -524,6 +524,7 @@ typedef enum DEFINE_TYPE_GENERIC, DEFINE_IDENT_ALIAS, DEFINE_IDENT_GENERIC, + DEFINE_ATTRIBUTE, } DefineType; typedef struct @@ -531,6 +532,11 @@ typedef struct DefineType define_kind: 5; union { + struct + { + Decl **params; + Attr **attrs; + } attributes; struct { union @@ -625,7 +631,6 @@ typedef struct Decl_ CtCaseDecl ct_case_decl; Ast *ct_assert_decl; Decl** ct_else_decl; - Expr *incr_array_decl; }; } Decl; @@ -1174,7 +1179,6 @@ typedef struct bool is_volatile : 1; bool is_inline : 1; bool is_goto : 1; - AsmParams *params; Expr *body; } AstAsmStmt; @@ -1368,7 +1372,6 @@ typedef struct Context_ Decl **methods; Decl **macro_methods; Decl **vars; - Decl **incr_array; Decl **ct_ifs; Decl **ct_asserts; Decl *active_function_for_analysis; @@ -1393,7 +1396,6 @@ typedef struct Context_ Ast **returns_cache; }; Type *rtype; - int in_volatile_section; MacroScope macro_scope; struct { STable external_symbols; diff --git a/src/compiler/context.c b/src/compiler/context.c index 7d0b36655..fd51268c5 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -196,9 +196,6 @@ void context_register_global_decl(Context *context, Decl *decl) vec_add(context->enums, decl); decl_set_external_name(decl); break; - case DECL_ARRAY_VALUE: - vec_add(context->incr_array, decl); - return; case DECL_ERRVALUE: case DECL_ENUM_CONSTANT: case DECL_IMPORT: diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 7f7674154..9a9b755f9 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -13,7 +13,7 @@ Expr **copy_expr_list(Expr **expr_list) static inline Decl *decl_copy_label_from_macro(Decl *to_copy, Ast *ast) { if (!to_copy) return NULL; - to_copy = decl_copy_local_from_macro(to_copy); + to_copy = copy_decl(to_copy); to_copy->label.parent = astid(ast); return to_copy; } @@ -241,12 +241,14 @@ Ast *copy_ast(Ast *source) case AST_POISONED: return ast; case AST_ASM_STMT: - TODO + MACRO_COPY_EXPR(ast->asm_stmt.body); + return ast; case AST_ASSERT_STMT: MACRO_COPY_EXPR(ast->ct_assert_stmt.expr); MACRO_COPY_EXPR(ast->ct_assert_stmt.message); return ast; case AST_BREAK_STMT: + case AST_CONTINUE_STMT: return ast; case AST_CASE_STMT: MACRO_COPY_AST(ast->case_stmt.body); @@ -258,8 +260,6 @@ Ast *copy_ast(Ast *source) case AST_CT_COMPOUND_STMT: MACRO_COPY_AST_LIST(ast->ct_compound_stmt); return ast; - case AST_CONTINUE_STMT: - TODO case AST_CT_ASSERT: MACRO_COPY_EXPR(ast->ct_assert_stmt.message); MACRO_COPY_EXPR(ast->ct_assert_stmt.expr); @@ -327,8 +327,15 @@ Ast *copy_ast(Ast *source) MACRO_COPY_AST(ast->if_stmt.then_body); return ast; case AST_NEXT_STMT: - MACRO_COPY_EXPR(ast->next_stmt.switch_expr); - TODO + if (ast->next_stmt.is_type) + { + MACRO_COPY_TYPE(ast->next_stmt.type_info); + } + else + { + MACRO_COPY_EXPR(ast->next_stmt.target); + } + return ast; case AST_NOP_STMT: return ast; case AST_RETURN_STMT: @@ -345,9 +352,6 @@ Ast *copy_ast(Ast *source) return ast; case AST_UNREACHABLE_STMT: return ast; - case AST_VOLATILE_STMT: - TODO - return ast; case AST_WHILE_STMT: copy_flow(ast); MACRO_COPY_EXPR(ast->while_stmt.cond); @@ -409,7 +413,6 @@ TypeInfo *copy_type_info(TypeInfo *source) copy->array.len = copy_expr(source->array.len); copy->array.base = copy_type_info(source->array.base); return copy; - case TYPE_INFO_INC_ARRAY: case TYPE_INFO_INFERRED_ARRAY: case TYPE_INFO_SUBARRAY: assert(source->resolve_status == RESOLVE_NOT_DONE); @@ -498,8 +501,8 @@ Decl *copy_decl(Decl *decl) } break; case DECL_LABEL: - TODO - break; + // Note that the ast id should be patched by the parent. + return copy; case DECL_ENUM_CONSTANT: MACRO_COPY_EXPR(copy->enum_constant.expr); MACRO_COPY_EXPR_LIST(copy->enum_constant.args); @@ -543,8 +546,6 @@ Decl *copy_decl(Decl *decl) break; case DECL_IMPORT: break; - case DECL_ARRAY_VALUE: - TODO case DECL_GENERIC: case DECL_MACRO: MACRO_COPY_TYPE(decl->macro_decl.type_parent); @@ -565,6 +566,10 @@ Decl *copy_decl(Decl *decl) break; case DEFINE_IDENT_ALIAS: break; + case DEFINE_ATTRIBUTE: + decl->define_decl.attributes.attrs = copy_attributes(decl->define_decl.attributes.attrs); + MACRO_COPY_DECL_LIST(decl->define_decl.attributes.params); + break; } break; } diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 7967592d9..099c903de 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -75,7 +75,6 @@ typedef enum AST_SWITCH_STMT, AST_NEXT_STMT, AST_UNREACHABLE_STMT, - AST_VOLATILE_STMT, AST_WHILE_STMT, AST_SCOPED_STMT, } AstKind; @@ -120,6 +119,7 @@ typedef enum CAST_STST, CAST_PTRANY, CAST_ANYPTR, + CAST_VECARR, } CastKind; @@ -127,7 +127,6 @@ typedef enum { DECL_POISONED = 0, DECL_ATTRIBUTE, - DECL_ARRAY_VALUE, DECL_BITSTRUCT, DECL_CT_CASE, DECL_CT_ELIF, @@ -152,7 +151,7 @@ typedef enum DECL_VAR, } DeclKind; -#define NON_TYPE_DECLS DECL_ARRAY_VALUE: case DECL_IMPORT: case DECL_MACRO: \ +#define NON_TYPE_DECLS DECL_IMPORT: case DECL_MACRO: \ case DECL_CT_IF: case DECL_CT_ELSE: case DECL_CT_ELIF: \ case DECL_CT_SWITCH: case DECL_CT_CASE: case DECL_ATTRIBUTE: case DECL_LABEL: \ case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_GENERIC @@ -285,7 +284,6 @@ typedef enum TYPE_INFO_EXPRESSION, TYPE_INFO_ARRAY, TYPE_INFO_VECTOR, - TYPE_INFO_INC_ARRAY, TYPE_INFO_INFERRED_ARRAY, TYPE_INFO_SUBARRAY, TYPE_INFO_POINTER, @@ -422,7 +420,6 @@ typedef enum TOKEN_AS, TOKEN_ASSERT, TOKEN_ASM, - TOKEN_ATTRIBUTE, TOKEN_BITSTRUCT, TOKEN_BREAK, TOKEN_CASE, @@ -461,7 +458,6 @@ typedef enum TOKEN_UNION, TOKEN_VAR, // Reserved TOKEN_VIRTUAL, - TOKEN_VOLATILE, TOKEN_WHILE, TOKEN_CT_ALIGNOF, // $alignof diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 8ce882e55..8564d50c8 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1129,6 +1129,8 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_ // This is a no op. assert(type_lowering(to_type) == type_lowering(from_type)); break; + case CAST_VECARR: + TODO case CAST_EUER: TODO // gencontext_emit_value_bitcast(c, value->value, to_type, from_type); case CAST_ERBOOL: diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index fee8a5d75..e99311f14 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1355,8 +1355,6 @@ void llvm_emit_stmt(GenContext *c, Ast *ast) case AST_UNREACHABLE_STMT: gencontext_emit_unreachable_stmt(c, ast); break; - case AST_VOLATILE_STMT: - TODO } } diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index dfe810527..d97ababdb 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -77,7 +77,6 @@ void recover_top_level(Context *context) case TOKEN_EXTERN: case TOKEN_ENUM: case TOKEN_GENERIC: - case TOKEN_ATTRIBUTE: case TOKEN_DEFINE: case TOKEN_ERRTYPE: return; @@ -620,7 +619,6 @@ static inline TypeInfo *parse_base_type(Context *context) * array_type_index * : '[' constant_expression ']' * | '[' ']' - * | '[' '+' ']' * | '[' '*' ']' * ; * @@ -632,14 +630,6 @@ static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type) assert(type_info_ok(type)); advance_and_verify(context, TOKEN_LBRACKET); - if (try_consume(context, TOKEN_PLUS)) - { - CONSUME_OR(TOKEN_RBRACKET, poisoned_type_info); - TypeInfo *incr_array = type_info_new(TYPE_INFO_INC_ARRAY, type->span); - incr_array->array.base = type; - RANGE_EXTEND_PREV(incr_array); - return incr_array; - } if (try_consume(context, TOKEN_STAR)) { CONSUME_OR(TOKEN_RBRACKET, poisoned_type_info); @@ -886,26 +876,6 @@ static inline bool is_function_start(Context *context) } -static inline Decl *parse_incremental_array(Context *context) -{ - Token name = context->tok; - advance_and_verify(context, TOKEN_IDENT); - - if (!try_consume(context, TOKEN_PLUS_ASSIGN)) - { - SEMA_TOKEN_ERROR(name, "Did you miss a declaration before the variable name?"); - return poisoned_decl; - } - Decl *decl = decl_new(DECL_ARRAY_VALUE, name.id, VISIBLE_LOCAL); - ASSIGN_EXPR_ELSE(decl->incr_array_decl, parse_initializer(context), poisoned_decl); - TRY_CONSUME_EOS_OR(poisoned_decl); - return decl; -} - - - - - bool parse_next_is_decl(Context *context) { TokenType next_tok = context->next_tok.type; @@ -1691,11 +1661,67 @@ static inline Decl *parse_define_ident(Context *context, Visibility visibility) TRY_CONSUME_EOS_OR(poisoned_decl); return decl; } + +/** + * define_attribute ::= 'define' '@' IDENT '(' parameter_list ')' ('=' (void | attribute_list))? + */ +static inline Decl *parse_define_attribute(Context *context, Visibility visibility) +{ + // 1. Store the beginning of the define. + TokenId start = context->tok.id; + advance_and_verify(context, TOKEN_DEFINE); + + advance_and_verify(context, TOKEN_AT); + + TokenType alias_type = context->tok.type; + if (alias_type != TOKEN_TYPE_IDENT) + { + if (token_is_some_ident(alias_type) || token_is_keyword(alias_type)) + { + SEMA_TOKEN_ERROR(context->tok, "A user defined attribute must start with an uppercase character, followed by at least one lower case."); + return false; + } + SEMA_TOKEN_ERROR(context->tok, "The attribute name was expected here."); + return false; + } + Decl *decl = decl_new(DECL_DEFINE, context->tok.id, visibility); + advance_and_verify(context, TOKEN_TYPE_IDENT); + + Decl **parameters = NULL; + if (try_consume(context, TOKEN_LPAREN)) + { + if (!parse_parameters(context, visibility, ¶meters)) return false; + CONSUME_OR(TOKEN_RPAREN, poisoned_decl); + } + + Attr **attributes = NULL; + if (try_consume(context, TOKEN_EQ)) + { + if (try_consume(context, TOKEN_VOID)) + { + if (!parse_attributes(context, &attributes)) return false; + } + } + + decl->define_decl.define_kind = DEFINE_ATTRIBUTE; + decl->define_decl.attributes.attrs = attributes; + decl->define_decl.attributes.params = parameters; + // 3. Set up the define. + decl->span.loc = start; + RANGE_EXTEND_PREV(decl); + return decl; +} + /** * define_decl ::= DEFINE define_type_body | */ static inline Decl *parse_define(Context *context, Visibility visibility) { + if (context->next_tok.type == TOKEN_AT) + { + // define @foo = @inline, @noreturn + return parse_define_attribute(context, visibility); + } if (context->next_tok.type == TOKEN_TYPE_IDENT) { return parse_define_type(context, visibility); @@ -2258,9 +2284,6 @@ Decl *parse_top_level_statement(Context *context) ASSIGN_DECL_ELSE(decl, parse_define(context, visibility), poisoned_decl); break; } - case TOKEN_ATTRIBUTE: - TODO - break; case TOKEN_FUNC: case TOKEN_FN: { @@ -2335,20 +2358,7 @@ Decl *parse_top_level_statement(Context *context) break; } case TOKEN_IDENT: - if (context->next_tok.type == TOKEN_SCOPE) - { - ASSIGN_DECL_ELSE(decl, parse_global_declaration(context, visibility), poisoned_decl); - break; - } - if (!check_no_visibility_before(context, visibility)) return poisoned_decl; - ASSIGN_DECL_ELSE(decl, parse_incremental_array(context), poisoned_decl); - if (docs) - { - SEMA_ERROR(docs, - "Unexpected doc comment before incremental array, did you mean to use a regular comment?"); - return poisoned_decl; - } - break; + return parse_global_declaration(context, visibility); case TOKEN_EOF: SEMA_TOKID_ERROR(context->prev_tok, "Expected a top level declaration"); return poisoned_decl; diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index ff9da35cc..4ae202d0e 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -58,7 +58,7 @@ static inline Ast* parse_asm_stmt(Context *context) { Ast *ast = AST_NEW_TOKEN(AST_ASM_STMT, context->tok); advance_and_verify(context, TOKEN_ASM); - ast->asm_stmt.is_volatile = try_consume(context, TOKEN_VOLATILE); + // TODO use attributes, like volatile CONSUME_OR(TOKEN_LPAREN, poisoned_ast); ASSIGN_EXPR_ELSE(ast->asm_stmt.body, parse_expr(context), poisoned_ast); ast->asm_stmt.is_volatile = true; @@ -655,16 +655,6 @@ static inline Ast *parse_return(Context *context) -/** - * volatile_stmt - * : VOLATILE compound_stmt - */ -static Ast *parse_volatile_stmt(Context *context) -{ - Ast *ast = AST_NEW_TOKEN(AST_VOLATILE_STMT, context->tok); - ASSIGN_AST_ELSE(ast->volatile_stmt, parse_compound_stmt(context), poisoned_ast); - return ast; -} @@ -862,8 +852,6 @@ Ast *parse_stmt(Context *context) return parse_ct_switch_stmt(context); case TOKEN_CT_FOR: return parse_ct_for_stmt(context); - case TOKEN_VOLATILE: - return parse_volatile_stmt(context); case TOKEN_CT_UNREACHABLE: return parse_unreachable_stmt(context); case TOKEN_STAR: @@ -954,7 +942,6 @@ Ast *parse_stmt(Context *context) case TOKEN_STRUCT: case TOKEN_ERRTYPE: case TOKEN_UNION: - case TOKEN_ATTRIBUTE: case TOKEN_DEFINE: case TOKEN_DOCS_START: case TOKEN_DOCS_END: diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 9c1f38c43..d108ee8d5 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -358,8 +358,6 @@ CastKind cast_to_bool_kind(Type *type) case TYPE_DISTINCT: case TYPE_INFERRED_ARRAY: UNREACHABLE - case TYPE_ANY: - TODO case TYPE_BOOL: return CAST_BOOLBOOL; case TYPE_ANYERR: @@ -388,6 +386,7 @@ CastKind cast_to_bool_kind(Type *type) case TYPE_BITSTRUCT: case TYPE_UNTYPED_LIST: case TYPE_FAILABLE: + case TYPE_ANY: case TYPE_FAILABLE_ANY: return CAST_ERROR; } @@ -510,44 +509,6 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, UNREACHABLE } -static bool may_cast_to_virtual(Type *virtual, Type *from) -{ - assert(from->canonical == from); - - // 1. We need a pointer, we can't cast from a non pointer. - if (from->type_kind != TYPE_POINTER) return false; - - // 2. Virtual* converts to anything, including ints - if (virtual->type_kind == TYPE_ANY) return true; - - // 3. Get the data. - Decl *virtual_decl = virtual->decl; - Decl **methods = virtual_decl->interface_decl.functions; - - // 4. No variables nor members? Then this is essentially a virtual* - if (!vec_size(methods) && !vec_size(virtual_decl->strukt.members)) return true; - - // 5. Look at the pointer. - Type *pointee = from->pointer; - - // 6. Is this an array, if so it doesn't have any functions, - // so we implicitly lower to the first element. - if (pointee->type_kind == TYPE_ARRAY) - { - pointee = pointee->array.base; - } - - // Do this: create a function that returns a matching interface method. - // store this decl. - // Same with looking at members -> store the Decl. - // Later, generating the table we provide the decl backend ref and the offset. - // Note that matching types should take into account the first element. - // Also go recursively into substructs structs - // Note that this resolution cannot be cached completely due to the module import lookup - - TODO; -} - bool type_may_convert_to_anyerr(Type *type) { if (type_is_failable_any(type)) return true; @@ -904,6 +865,8 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_LEN: case EXPR_CATCH: case EXPR_BUILTIN: + case EXPR_TRY_UNWRAP: + case EXPR_TRY_UNWRAP_CHAIN: UNREACHABLE case EXPR_POST_UNARY: return recursive_may_narrow_float(expr->unary_expr.expr, type); @@ -911,10 +874,6 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) return recursive_may_narrow_float(expr->expr_scope.expr, type); case EXPR_TRY: return recursive_may_narrow_float(expr->inner_expr, type); - case EXPR_TRY_UNWRAP: - TODO - case EXPR_TRY_UNWRAP_CHAIN: - TODO case EXPR_UNARY: { switch (expr->unary_expr.operator) @@ -1056,6 +1015,8 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_CT_CALL: case EXPR_NOP: case EXPR_BUILTIN: + case EXPR_TRY_UNWRAP: + case EXPR_TRY_UNWRAP_CHAIN: UNREACHABLE case EXPR_POST_UNARY: return recursive_may_narrow_int(expr->unary_expr.expr, type); @@ -1066,10 +1027,6 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_GROUP: case EXPR_FORCE_UNWRAP: return recursive_may_narrow_int(expr->inner_expr, type); - case EXPR_TRY_UNWRAP: - TODO - case EXPR_TRY_UNWRAP_CHAIN: - TODO case EXPR_UNARY: { switch (expr->unary_expr.operator) @@ -1266,11 +1223,12 @@ static inline bool subarray_to_bool(Expr *expr) return insert_cast(expr, CAST_SABOOL, type_bool); } -static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type, bool from_is_failable) +static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type) { switch (from_type->type_kind) { case TYPE_FAILABLE_ANY: + case TYPE_FAILABLE: UNREACHABLE case TYPE_VOID: UNREACHABLE @@ -1282,8 +1240,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type, boo UNREACHABLE case TYPE_BITSTRUCT: return bitstruct_cast(expr, from_type, to, to_type); - case TYPE_FAILABLE: - TODO case TYPE_BOOL: // Bool may convert into integers and floats but only explicitly. if (type_is_integer(to)) return bool_to_int(expr, to, to_type); @@ -1352,7 +1308,8 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type, boo if (to->type_kind == TYPE_BOOL) return subarray_to_bool(expr); break; case TYPE_VECTOR: - TODO + if (to->type_kind == TYPE_ARRAY) return insert_cast(expr, CAST_VECARR, to); + break; } UNREACHABLE } @@ -1420,7 +1377,9 @@ bool cast(Expr *expr, Type *to_type) } return true; } - if (!cast_inner(expr, from_type, to, to_type, from_is_failable)) return false; + bool result = cast_inner(expr, from_type, to, to_type); + assert(result == true); + Type *result_type = expr->type; if (from_is_failable && !type_is_failable(result_type)) { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 934e620f1..abe50751b 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1587,6 +1587,8 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl) name = define_type->unresolved.name_loc; break; } + case DEFINE_ATTRIBUTE: + TODO default: UNREACHABLE } @@ -1647,6 +1649,8 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl) type->canonical = symbol->type->canonical; return true; } + case DEFINE_ATTRIBUTE: + TODO default: UNREACHABLE } @@ -1733,7 +1737,6 @@ bool sema_analyse_decl(Context *context, Decl *decl) case DECL_POISONED: case DECL_IMPORT: case DECL_ENUM_CONSTANT: - case DECL_ARRAY_VALUE: case DECL_CT_ELSE: case DECL_CT_ELIF: case DECL_LABEL: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index dea2aaa7b..b38f8a270 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -186,6 +186,7 @@ bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) case CAST_STST: case CAST_PTRANY: case CAST_ENUMLOW: + case CAST_VECARR: if (eval_kind == CONSTANT_EVAL_FOLDABLE) return false; return expr_is_constant_eval(expr->cast_expr.expr, eval_kind); case CAST_EUINT: @@ -544,8 +545,6 @@ static inline bool sema_cast_ident_rvalue(Context *context, Expr *expr) case DECL_ERRTYPE: SEMA_ERROR(expr, "Expected errtype name followed by '.' and an error value."); return expr_poison(expr); - case DECL_ARRAY_VALUE: - UNREACHABLE case DECL_IMPORT: case DECL_CT_IF: case DECL_CT_ELSE: @@ -1175,7 +1174,7 @@ static inline bool sema_expand_call_arguments(Context *context, CalledDecl *call if (!variadic) { // 15. We have too many parameters... - SEMA_ERROR(arg, "This argument would would exceed the number of parameters, did you add to many arguments?"); + SEMA_ERROR(arg, "This argument would would exceed the number of parameters, did you add too many arguments?"); return false; } @@ -6314,8 +6313,6 @@ static Type *sema_expr_check_type_exists(Context *context, TypeInfo *type_info) if (!type_ok(type)) return type; return type_get_subarray(type); } - case TYPE_INFO_INC_ARRAY: - TODO case TYPE_INFO_INFERRED_ARRAY: { // If it's an array, make sure we can resolve the length diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index d99ac8e31..3c358e101 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1945,13 +1945,6 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement) -static bool sema_analyse_volatile_stmt(Context *context, Ast *statement) -{ - context->in_volatile_section++; - bool result = sema_analyse_statement(context, statement->volatile_stmt); - context->in_volatile_section--; - return result; -} bool sema_analyse_ct_assert_stmt(Context *context, Ast *statement) { @@ -2154,8 +2147,6 @@ static inline bool sema_analyse_statement_inner(Context *context, Ast *statement return sema_analyse_nextcase_stmt(context, statement); case AST_UNREACHABLE_STMT: return sema_analyse_unreachable_stmt(context); - case AST_VOLATILE_STMT: - return sema_analyse_volatile_stmt(context, statement); case AST_WHILE_STMT: return sema_analyse_while_stmt(context, statement); case AST_CT_SWITCH_STMT: @@ -2235,7 +2226,6 @@ bool sema_analyse_function_body(Context *context, Decl *func) // Clear returns vec_resize(context->returns, 0); context->scope_id = 0; - context->in_volatile_section = 0; context->continue_target = 0; context->next_target = 0; context->next_switch = 0; diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 9c0022d0f..1d1771eca 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -155,17 +155,16 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info) case DECL_FUNC: case DECL_ERRVALUE: case DECL_ENUM_CONSTANT: - case DECL_ARRAY_VALUE: case DECL_IMPORT: case DECL_MACRO: case DECL_GENERIC: case DECL_LABEL: + case DECL_ATTRIBUTE: SEMA_TOKID_ERROR(type_info->unresolved.name_loc, "This is not a type."); return type_info_poison(type_info); case DECL_CT_ELSE: case DECL_CT_IF: case DECL_CT_ELIF: - case DECL_ATTRIBUTE: case DECL_CT_SWITCH: case DECL_CT_CASE: case DECL_CT_ASSERT: @@ -234,7 +233,6 @@ bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info, bool allow switch (type_info->kind) { case TYPE_INFO_POISON: - case TYPE_INFO_INC_ARRAY: UNREACHABLE case TYPE_INFO_IDENTIFIER: if (!sema_resolve_type_identifier(context, type_info)) return false; diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index f2e0a946b..2cfddee35 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -194,8 +194,6 @@ const char *token_type_to_string(TokenType type) return "asm"; case TOKEN_ASSERT: return "assert"; - case TOKEN_ATTRIBUTE: - return "attribute"; case TOKEN_BITSTRUCT: return "bitstruct"; case TOKEN_BREAK: @@ -272,8 +270,6 @@ const char *token_type_to_string(TokenType type) return "union"; case TOKEN_VAR: return "var"; - case TOKEN_VOLATILE: - return "volatile"; case TOKEN_WHILE: return "while"; diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index 98258b251..47cdb6d67 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -174,36 +174,47 @@ char *read_file(const char *path, size_t *return_size) return buffer; } -const char *find_lib_dir(void) +static inline const char *lib_find(const char *exe_path, const char *rel_path) { - - const char *path = find_executable_path(); - - DEBUG_LOG("Detected executable path at %s", path); - struct stat info; char *lib_path = NULL; - - asprintf(&lib_path, "%s../lib/std", path); + asprintf(&lib_path, "%s%sstd", exe_path, rel_path); DEBUG_LOG("Checking %s", lib_path); int err = stat(lib_path, &info); - // Found it at ../lib/std - if (!err && S_ISDIR(info.st_mode)) - { - asprintf(&lib_path, "%s../lib/", path); - return lib_path; - } + // Not a dir or had error? + if (err || !S_ISDIR(info.st_mode)) return NULL; - asprintf(&lib_path, "%slib/std", path); - err = stat(lib_path, &info); + char *check_path = NULL; + asprintf(&check_path, "%s/libc.c3", lib_path); + DEBUG_LOG("Potential lib found, sanity check for libc..."); + err = stat(check_path, &info); + if (err || !S_ISREG(info.st_mode)) return NULL; - // Found it at ./lib/std - if (!err && S_ISDIR(info.st_mode)) + asprintf(&lib_path, "%s%s", exe_path, rel_path); + DEBUG_LOG("Library path found at %s", lib_path); + return lib_path; +} + +const char *find_lib_dir(void) +{ + + char *path = find_executable_path(); + + DEBUG_LOG("Detected executable path at %s", path); + + size_t strlen_path = strlen(path); + // Remove any last path slash + if (strlen_path > 1 && (path[strlen_path - 1] == '/' || path[strlen_path - 1] == '\\')) { - asprintf(&lib_path, "%slib/", path); - return lib_path; + path[strlen_path - 1] = '\0'; } + const char *lib_path; + if ((lib_path = lib_find(path, "/../lib/"))) return lib_path; + if ((lib_path = lib_find(path, "/lib/"))) return lib_path; + if ((lib_path = lib_find(path, "/"))) return lib_path; + if ((lib_path = lib_find(path, "/../"))) return lib_path; + if ((lib_path = lib_find(path, "/../../lib/"))) return lib_path; DEBUG_LOG("Could not find the standard library /lib/std/"); return NULL; @@ -272,14 +283,19 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi if (strncmp(&ent->d_name[namelen - 3], ".c3", 3) != 0) { char *new_path = NULL; - char *format = path_ends_with_slash ? "%s%s/" : "%s/%s/"; + char *format = path_ends_with_slash ? "%s%s" : "%s/%s"; if (!asprintf(&new_path, format, path, ent->d_name)) { error_exit("Failed to allocate path."); } bool is_directory; struct stat st; - is_directory = stat(new_path, &st) == 0 && S_ISDIR(st.st_mode); + if (stat(new_path, &st)) + { + DEBUG_LOG("Failed to stat %s", new_path); + continue; + } + is_directory = S_ISDIR(st.st_mode); if (is_directory && ent->d_name[0] != '.' && recursive) { file_add_wildcard_files(files, new_path, recursive); @@ -287,7 +303,7 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi free(new_path); continue; } - char *format = path_ends_with_slash ? "%s%s" : "%s/s"; + char *format = path_ends_with_slash ? "%s%s" : "%s/%s"; vec_add(*files, strformat(format, path, ent->d_name)); } closedir(dir); diff --git a/src/utils/whereami.c b/src/utils/whereami.c index 69c1be105..634e2fc99 100644 --- a/src/utils/whereami.c +++ b/src/utils/whereami.c @@ -413,9 +413,10 @@ static int get_executable_path_raw(char *out, int capacity, int *dirname_length) #endif -const char *find_executable_path(void) +char *find_executable_path(void) { int len = get_executable_path_raw(NULL, 0, NULL); + if (len < 0) return ""; char *path = malloc(len + 1); get_executable_path_raw(path, len, NULL); path[len] = '\0'; diff --git a/src/utils/whereami.h b/src/utils/whereami.h index a2d9042af..6c19de0f3 100644 --- a/src/utils/whereami.h +++ b/src/utils/whereami.h @@ -4,4 +4,4 @@ // Use of this source code is governed by a LGPLv3.0 // a copy of which can be found in the LICENSE file. -const char *find_executable_path(void); +char *find_executable_path(void); diff --git a/test/src/tester.py b/test/src/tester.py index 30de44857..50ccbf34c 100644 --- a/test/src/tester.py +++ b/test/src/tester.py @@ -304,5 +304,8 @@ def main(): usage() print("Found %d tests: %.1f%% (%d / %d) passed (%d skipped)." % (conf.numtests, 100 * conf.numsuccess / max(1, conf.numtests - conf.numskipped), conf.numsuccess, conf.numtests - conf.numskipped, conf.numskipped)) + if (conf.numsuccess != conf.numtests - conf.numskipped): + exit(-1) + exit(0) main() diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index d41f44b6f..d20b74aa1 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -268,7 +268,7 @@ fn Type getValue(Blob blob) @.str.9 = private constant [10 x i8] c"b was %f\0A\00", align 1 @.str.10 = private constant [17 x i8] c"Mult int was %d\0A\00", align 1 @.str.11 = private constant [20 x i8] c"Mult double was %f\0A\00", align 1 -@.__const.12 = private constant [4 x i32] [i32 1, i32 2, i32 3, i32 3], align 4 +@.__const.12 = private constant [4 x i32] [i32 1, i32 2, i32 3, i32 3], align 16 @.str.13 = private constant [22 x i8] c"1Vararg4unsplatA: %d\0A\00", align 1 @.str.14 = private constant [4 x i8] c"%d\0A\00", align 1 @.__const.15 = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4 @@ -512,7 +512,7 @@ entry: %tempcoerce = alloca i64, align 8 %ddx = alloca %Foo, align 4 %fro = alloca i32, align 4 - %x = alloca [4 x i32], align 4 + %x = alloca [4 x i32], align 16 %vararg = alloca %"int[]", align 8 %indirectarg = alloca %"int[]", align 8 %z = alloca %"int[]", align 8 @@ -522,7 +522,7 @@ entry: %vararg13 = alloca %"int[]", align 8 %indirectarg14 = alloca %"int[]", align 8 %vararg15 = alloca %"int[]", align 8 - %varargslots = alloca [4 x i32], align 4 + %varargslots = alloca [4 x i32], align 16 %indirectarg16 = alloca %"int[]", align 8 %vararg17 = alloca %"int[]", align 8 %varargslots18 = alloca [1 x i32], align 4 @@ -628,7 +628,7 @@ for.exit9: ; preds = %for.cond2 call void @llvm.memset.p0i8.i64(i8* align 4 %37, i8 0, i64 8, i1 false) store i32 3, i32* %fro, align 4 %38 = bitcast [4 x i32]* %x to i8* - call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %38, i8* align 4 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false) + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %38, i8* align 16 bitcast ([4 x i32]* @.__const.12 to i8*), i32 16, i1 false) %39 = load i32, i32* %fro, align 4 %40 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 1 %41 = getelementptr inbounds %"int[]", %"int[]"* %vararg, i32 0, i32 0 diff --git a/test/test_suite/initializer_lists/ranges_to_dynamic.c3t b/test/test_suite/initializer_lists/ranges_to_dynamic.c3t index b253a064e..c59ebc18a 100644 --- a/test/test_suite/initializer_lists/ranges_to_dynamic.c3t +++ b/test/test_suite/initializer_lists/ranges_to_dynamic.c3t @@ -1,3 +1,4 @@ +// #target: x64-mingw module test; extern fn void printf(char*, ...); diff --git a/test/test_suite/macros/macro_nested_labels.c3t b/test/test_suite/macros/macro_nested_labels.c3t new file mode 100644 index 000000000..3639006bc --- /dev/null +++ b/test/test_suite/macros/macro_nested_labels.c3t @@ -0,0 +1,324 @@ +module test; + +extern fn void printf(char *string, ...); + +macro checker(int x, $i) +{ + var $indent = 3 - $i; + for (int i = 0; i < $indent; i++) printf(" "); + printf("Enter %d\n", $i); + while FOO: (x-- > 0) + { + for (int i = 0; i < $indent; i++) printf(" "); + printf("Helo %d\n", x); + $if ($i > 0): + @checker(x, $i - 1); + $endif; + if (x % 2 == 0) break FOO; + } + for (int i = 0; i < $indent; i++) printf(" "); + printf("Exit %d\n", $i); +} + +fn void main() +{ + int ab = 7; + @checker(ab, 3); +} + +/* #expect: test.ll + +define void @main() #0 { +entry: + %ab = alloca i32, align 4 + %x = alloca i32, align 4 + %i = alloca i32, align 4 + %i1 = alloca i32, align 4 + %x8 = alloca i32, align 4 + %i9 = alloca i32, align 4 + %i20 = alloca i32, align 4 + %x27 = alloca i32, align 4 + %i28 = alloca i32, align 4 + %i39 = alloca i32, align 4 + %x46 = alloca i32, align 4 + %i47 = alloca i32, align 4 + %i58 = alloca i32, align 4 + %i65 = alloca i32, align 4 + %i77 = alloca i32, align 4 + %i89 = alloca i32, align 4 + %i101 = alloca i32, align 4 + store i32 7, i32* %ab, align 4 + %0 = load i32, i32* %ab, align 4 + store i32 %0, i32* %x, align 4 + store i32 0, i32* %i, align 4 + br label %for.cond +for.cond: ; preds = %for.inc, %entry + %1 = load i32, i32* %i, align 4 + %lt = icmp slt i32 %1, 0 + br i1 %lt, label %for.body, label %for.exit +for.body: ; preds = %for.cond + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) + br label %for.inc +for.inc: ; preds = %for.body + %2 = load i32, i32* %i, align 4 + %add = add i32 %2, 1 + store i32 %add, i32* %i, align 4 + br label %for.cond +for.exit: ; preds = %for.cond + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i32 0, i32 0), i32 3) + br label %while.begin +while.begin: ; preds = %if.exit99, %for.exit + %3 = load i32, i32* %x, align 4 + %sub = sub i32 %3, 1 + store i32 %sub, i32* %x, align 4 + %gt = icmp sgt i32 %3, 0 + br i1 %gt, label %while.body, label %while.exit100 +while.body: ; preds = %while.begin + store i32 0, i32* %i1, align 4 + br label %for.cond2 +for.cond2: ; preds = %for.inc5, %while.body + %4 = load i32, i32* %i1, align 4 + %lt3 = icmp slt i32 %4, 0 + br i1 %lt3, label %for.body4, label %for.exit7 +for.body4: ; preds = %for.cond2 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.2, i32 0, i32 0)) + br label %for.inc5 +for.inc5: ; preds = %for.body4 + %5 = load i32, i32* %i1, align 4 + %add6 = add i32 %5, 1 + store i32 %add6, i32* %i1, align 4 + br label %for.cond2 +for.exit7: ; preds = %for.cond2 + %6 = load i32, i32* %x, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.3, i32 0, i32 0), i32 %6) + %7 = load i32, i32* %x, align 4 + store i32 %7, i32* %x8, align 4 + store i32 0, i32* %i9, align 4 + br label %for.cond10 +for.cond10: ; preds = %for.inc13, %for.exit7 + %8 = load i32, i32* %i9, align 4 + %lt11 = icmp slt i32 %8, 1 + br i1 %lt11, label %for.body12, label %for.exit15 +for.body12: ; preds = %for.cond10 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.4, i32 0, i32 0)) + br label %for.inc13 +for.inc13: ; preds = %for.body12 + %9 = load i32, i32* %i9, align 4 + %add14 = add i32 %9, 1 + store i32 %add14, i32* %i9, align 4 + br label %for.cond10 +for.exit15: ; preds = %for.cond10 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i32 2) + br label %while.begin16 +while.begin16: ; preds = %if.exit87, %for.exit15 + %10 = load i32, i32* %x8, align 4 + %sub17 = sub i32 %10, 1 + store i32 %sub17, i32* %x8, align 4 + %gt18 = icmp sgt i32 %10, 0 + br i1 %gt18, label %while.body19, label %while.exit88 +while.body19: ; preds = %while.begin16 + store i32 0, i32* %i20, align 4 + br label %for.cond21 +for.cond21: ; preds = %for.inc24, %while.body19 + %11 = load i32, i32* %i20, align 4 + %lt22 = icmp slt i32 %11, 1 + br i1 %lt22, label %for.body23, label %for.exit26 +for.body23: ; preds = %for.cond21 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.6, i32 0, i32 0)) + br label %for.inc24 +for.inc24: ; preds = %for.body23 + %12 = load i32, i32* %i20, align 4 + %add25 = add i32 %12, 1 + store i32 %add25, i32* %i20, align 4 + br label %for.cond21 +for.exit26: ; preds = %for.cond21 + %13 = load i32, i32* %x8, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.7, i32 0, i32 0), i32 %13) + %14 = load i32, i32* %x8, align 4 + store i32 %14, i32* %x27, align 4 + store i32 0, i32* %i28, align 4 + br label %for.cond29 +for.cond29: ; preds = %for.inc32, %for.exit26 + %15 = load i32, i32* %i28, align 4 + %lt30 = icmp slt i32 %15, 2 + br i1 %lt30, label %for.body31, label %for.exit34 +for.body31: ; preds = %for.cond29 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.8, i32 0, i32 0)) + br label %for.inc32 +for.inc32: ; preds = %for.body31 + %16 = load i32, i32* %i28, align 4 + %add33 = add i32 %16, 1 + store i32 %add33, i32* %i28, align 4 + br label %for.cond29 +for.exit34: ; preds = %for.cond29 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i32 1) + br label %while.begin35 +while.begin35: ; preds = %if.exit75, %for.exit34 + %17 = load i32, i32* %x27, align 4 + %sub36 = sub i32 %17, 1 + store i32 %sub36, i32* %x27, align 4 + %gt37 = icmp sgt i32 %17, 0 + br i1 %gt37, label %while.body38, label %while.exit76 +while.body38: ; preds = %while.begin35 + store i32 0, i32* %i39, align 4 + br label %for.cond40 +for.cond40: ; preds = %for.inc43, %while.body38 + %18 = load i32, i32* %i39, align 4 + %lt41 = icmp slt i32 %18, 2 + br i1 %lt41, label %for.body42, label %for.exit45 +for.body42: ; preds = %for.cond40 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.10, i32 0, i32 0)) + br label %for.inc43 +for.inc43: ; preds = %for.body42 + %19 = load i32, i32* %i39, align 4 + %add44 = add i32 %19, 1 + store i32 %add44, i32* %i39, align 4 + br label %for.cond40 +for.exit45: ; preds = %for.cond40 + %20 = load i32, i32* %x27, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.11, i32 0, i32 0), i32 %20) + %21 = load i32, i32* %x27, align 4 + store i32 %21, i32* %x46, align 4 + store i32 0, i32* %i47, align 4 + br label %for.cond48 +for.cond48: ; preds = %for.inc51, %for.exit45 + %22 = load i32, i32* %i47, align 4 + %lt49 = icmp slt i32 %22, 3 + br i1 %lt49, label %for.body50, label %for.exit53 +for.body50: ; preds = %for.cond48 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.12, i32 0, i32 0)) + br label %for.inc51 +for.inc51: ; preds = %for.body50 + %23 = load i32, i32* %i47, align 4 + %add52 = add i32 %23, 1 + store i32 %add52, i32* %i47, align 4 + br label %for.cond48 +for.exit53: ; preds = %for.cond48 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.13, i32 0, i32 0), i32 0) + br label %while.begin54 +while.begin54: ; preds = %if.exit, %for.exit53 + %24 = load i32, i32* %x46, align 4 + %sub55 = sub i32 %24, 1 + store i32 %sub55, i32* %x46, align 4 + %gt56 = icmp sgt i32 %24, 0 + br i1 %gt56, label %while.body57, label %while.exit +while.body57: ; preds = %while.begin54 + store i32 0, i32* %i58, align 4 + br label %for.cond59 +for.cond59: ; preds = %for.inc62, %while.body57 + %25 = load i32, i32* %i58, align 4 + %lt60 = icmp slt i32 %25, 3 + br i1 %lt60, label %for.body61, label %for.exit64 +for.body61: ; preds = %for.cond59 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.14, i32 0, i32 0)) + br label %for.inc62 +for.inc62: ; preds = %for.body61 + %26 = load i32, i32* %i58, align 4 + %add63 = add i32 %26, 1 + store i32 %add63, i32* %i58, align 4 + br label %for.cond59 +for.exit64: ; preds = %for.cond59 + %27 = load i32, i32* %x46, align 4 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.15, i32 0, i32 0), i32 %27) + %28 = load i32, i32* %x46, align 4 + %smod = srem i32 %28, 2 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then, label %if.exit +if.then: ; preds = %for.exit64 + br label %while.exit +if.exit: ; preds = %for.exit64 + br label %while.begin54 +while.exit: ; preds = %if.then, %while.begin54 + store i32 0, i32* %i65, align 4 + br label %for.cond66 +for.cond66: ; preds = %for.inc69, %while.exit + %29 = load i32, i32* %i65, align 4 + %lt67 = icmp slt i32 %29, 3 + br i1 %lt67, label %for.body68, label %for.exit71 +for.body68: ; preds = %for.cond66 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.16, i32 0, i32 0)) + br label %for.inc69 +for.inc69: ; preds = %for.body68 + %30 = load i32, i32* %i65, align 4 + %add70 = add i32 %30, 1 + store i32 %add70, i32* %i65, align 4 + br label %for.cond66 +for.exit71: ; preds = %for.cond66 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.17, i32 0, i32 0), i32 0) + %31 = load i32, i32* %x27, align 4 + %smod72 = srem i32 %31, 2 + %eq73 = icmp eq i32 %smod72, 0 + br i1 %eq73, label %if.then74, label %if.exit75 +if.then74: ; preds = %for.exit71 + br label %while.exit76 +if.exit75: ; preds = %for.exit71 + br label %while.begin35 +while.exit76: ; preds = %if.then74, %while.begin35 + store i32 0, i32* %i77, align 4 + br label %for.cond78 +for.cond78: ; preds = %for.inc81, %while.exit76 + %32 = load i32, i32* %i77, align 4 + %lt79 = icmp slt i32 %32, 2 + br i1 %lt79, label %for.body80, label %for.exit83 +for.body80: ; preds = %for.cond78 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.18, i32 0, i32 0)) + br label %for.inc81 +for.inc81: ; preds = %for.body80 + %33 = load i32, i32* %i77, align 4 + %add82 = add i32 %33, 1 + store i32 %add82, i32* %i77, align 4 + br label %for.cond78 +for.exit83: ; preds = %for.cond78 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.19, i32 0, i32 0), i32 1) + %34 = load i32, i32* %x8, align 4 + %smod84 = srem i32 %34, 2 + %eq85 = icmp eq i32 %smod84, 0 + br i1 %eq85, label %if.then86, label %if.exit87 +if.then86: ; preds = %for.exit83 + br label %while.exit88 +if.exit87: ; preds = %for.exit83 + br label %while.begin16 +while.exit88: ; preds = %if.then86, %while.begin16 + store i32 0, i32* %i89, align 4 + br label %for.cond90 +for.cond90: ; preds = %for.inc93, %while.exit88 + %35 = load i32, i32* %i89, align 4 + %lt91 = icmp slt i32 %35, 1 + br i1 %lt91, label %for.body92, label %for.exit95 +for.body92: ; preds = %for.cond90 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.20, i32 0, i32 0)) + br label %for.inc93 +for.inc93: ; preds = %for.body92 + %36 = load i32, i32* %i89, align 4 + %add94 = add i32 %36, 1 + store i32 %add94, i32* %i89, align 4 + br label %for.cond90 +for.exit95: ; preds = %for.cond90 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.21, i32 0, i32 0), i32 2) + %37 = load i32, i32* %x, align 4 + %smod96 = srem i32 %37, 2 + %eq97 = icmp eq i32 %smod96, 0 + br i1 %eq97, label %if.then98, label %if.exit99 +if.then98: ; preds = %for.exit95 + br label %while.exit100 +if.exit99: ; preds = %for.exit95 + br label %while.begin +while.exit100: ; preds = %if.then98, %while.begin + store i32 0, i32* %i101, align 4 + br label %for.cond102 +for.cond102: ; preds = %for.inc105, %while.exit100 + %38 = load i32, i32* %i101, align 4 + %lt103 = icmp slt i32 %38, 0 + br i1 %lt103, label %for.body104, label %for.exit107 +for.body104: ; preds = %for.cond102 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.22, i32 0, i32 0)) + br label %for.inc105 +for.inc105: ; preds = %for.body104 + %39 = load i32, i32* %i101, align 4 + %add106 = add i32 %39, 1 + store i32 %add106, i32* %i101, align 4 + br label %for.cond102 +for.exit107: ; preds = %for.cond102 + call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.23, i32 0, i32 0), i32 3) + ret void +} diff --git a/test/test_suite/slices/slice_assign.c3t b/test/test_suite/slices/slice_assign.c3t index beb49e923..63fcebfba 100644 --- a/test/test_suite/slices/slice_assign.c3t +++ b/test/test_suite/slices/slice_assign.c3t @@ -1,3 +1,4 @@ +// #target: x64-darwin module test; extern fn void printf(char*, ...); diff --git a/test/test_suite/types/various.c3 b/test/test_suite/types/various.c3 index 19f585b8c..3a93475fc 100644 --- a/test/test_suite/types/various.c3 +++ b/test/test_suite/types/various.c3 @@ -1,4 +1,4 @@ -func1 a = 1; // #error: declaration before the variable +func1 a = 1; // #error: A type name was expected fn void func1() {}