mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
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
This commit is contained in:
committed by
Christoffer Lerno
parent
bfde58b9a5
commit
4d4bbbdebc
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@@ -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: |
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// #target: x64-mingw
|
||||
module test;
|
||||
|
||||
extern fn void printf(char*, ...);
|
||||
|
||||
324
test/test_suite/macros/macro_nested_labels.c3t
Normal file
324
test/test_suite/macros/macro_nested_labels.c3t
Normal file
@@ -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
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// #target: x64-darwin
|
||||
module test;
|
||||
|
||||
extern fn void printf(char*, ...);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
func1 a = 1; // #error: declaration before the variable
|
||||
func1 a = 1; // #error: A type name was expected
|
||||
|
||||
fn void func1() {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user