mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
AST printout removed. Split initializer types. Const list functionality.
This commit is contained in:
committed by
Christoffer Lerno
parent
c76e8e0713
commit
bcda6d71c9
1028
src/compiler/ast.c
1028
src/compiler/ast.c
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,6 @@ void compiler_parse(void)
|
||||
|
||||
global_context_clear_errors();
|
||||
parse_file(file);
|
||||
TODO; //context_print_ast(context, stdout);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -79,18 +79,49 @@ typedef struct BigInt_
|
||||
};
|
||||
} BigInt;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONST_FLOAT,
|
||||
CONST_INTEGER,
|
||||
CONST_BOOL,
|
||||
CONST_ENUM,
|
||||
CONST_ERR,
|
||||
CONST_BYTES,
|
||||
CONST_STRING,
|
||||
CONST_POINTER,
|
||||
CONST_TYPEID,
|
||||
} ConstKind;
|
||||
CONST_INIT_ZERO,
|
||||
CONST_INIT_STRUCT,
|
||||
CONST_INIT_UNION,
|
||||
CONST_INIT_VALUE,
|
||||
CONST_INIT_ARRAY,
|
||||
CONST_INIT_ARRAY_FULL,
|
||||
CONST_INIT_ARRAY_VALUE,
|
||||
} ConstInitType;
|
||||
|
||||
|
||||
typedef struct ConstInitializer_
|
||||
{
|
||||
ConstInitType kind;
|
||||
// Type initialized
|
||||
Type *type;
|
||||
union
|
||||
{
|
||||
struct ConstInitializer_ **init_struct;
|
||||
Expr *init_value;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ *element;
|
||||
MemberIndex index;
|
||||
} init_union;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ **elements;
|
||||
} init_array;
|
||||
struct ConstInitializer_ **init_array_full;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ *element;
|
||||
ArrayIndex index;
|
||||
} init_array_value;
|
||||
};
|
||||
} ConstInitializer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -121,6 +152,7 @@ typedef struct
|
||||
uint64_t len;
|
||||
} bytes;
|
||||
Type *typeid;
|
||||
ConstInitializer *list;
|
||||
};
|
||||
} ExprConst;
|
||||
|
||||
@@ -708,45 +740,6 @@ typedef struct DesignatorElement_
|
||||
ArrayIndex index_end;
|
||||
} DesignatorElement;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONST_INIT_ZERO,
|
||||
CONST_INIT_STRUCT,
|
||||
CONST_INIT_UNION,
|
||||
CONST_INIT_VALUE,
|
||||
CONST_INIT_ARRAY,
|
||||
CONST_INIT_ARRAY_FULL,
|
||||
CONST_INIT_ARRAY_VALUE,
|
||||
} ConstInitType;
|
||||
|
||||
|
||||
typedef struct ConstInitializer_
|
||||
{
|
||||
ConstInitType kind;
|
||||
// Type initialized
|
||||
Type *type;
|
||||
union
|
||||
{
|
||||
struct ConstInitializer_ **init_struct;
|
||||
Expr *init_value;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ *element;
|
||||
MemberIndex index;
|
||||
} init_union;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ **elements;
|
||||
} init_array;
|
||||
struct ConstInitializer_ **init_array_full;
|
||||
struct
|
||||
{
|
||||
struct ConstInitializer_ *element;
|
||||
ArrayIndex index;
|
||||
} init_array_value;
|
||||
};
|
||||
} ConstInitializer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DesignatorElement **path;
|
||||
@@ -839,23 +832,6 @@ typedef struct
|
||||
} ExprMacroBlock;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INITIALIZER_UNKNOWN,
|
||||
INITIALIZER_DESIGNATED,
|
||||
INITIALIZER_NORMAL,
|
||||
INITIALIZER_CONST,
|
||||
} InitializerType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InitializerType init_type;
|
||||
union
|
||||
{
|
||||
Expr** initializer_expr;
|
||||
ConstInitializer *initializer;
|
||||
};
|
||||
} ExprInitializer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -990,10 +966,11 @@ struct Expr_
|
||||
ExprIdentifierRaw hash_ident_expr;
|
||||
TypeInfo *typeid_expr;
|
||||
ExprBodyExpansion body_expansion_expr;
|
||||
ExprInitializer initializer_expr;
|
||||
Decl *expr_enum;
|
||||
ExprCompoundLiteral expr_compound_literal;
|
||||
Expr** expression_list;
|
||||
Expr** initializer_list;
|
||||
Expr** designated_init_list;
|
||||
ExprScope expr_scope;
|
||||
ExprFuncBlock expr_block;
|
||||
ExprMacroBlock macro_block;
|
||||
@@ -1576,8 +1553,9 @@ extern Type *type_char, *type_ushort, *type_uint, *type_ulong, *type_usize;
|
||||
extern Type *type_iptr, *type_uptr, *type_iptrdiff, *type_uptrdiff;
|
||||
extern Type *type_u128, *type_i128;
|
||||
extern Type *type_compint, *type_compfloat;
|
||||
extern Type *type_typeid, *type_anyerr, *type_typeinfo, *type_varheader;
|
||||
extern Type *type_typeid, *type_anyerr, *type_typeinfo;
|
||||
extern Type *type_virtual, *type_virtual_generic;
|
||||
extern Type *type_complist;
|
||||
|
||||
extern const char *attribute_list[NUMBER_OF_ATTRIBUTES];
|
||||
|
||||
@@ -1740,7 +1718,6 @@ void context_register_external_symbol(Context *context, Decl *decl);
|
||||
bool context_add_import(Context *context, Path *path, Token symbol, Token alias, bool private_import);
|
||||
bool context_set_module_from_filename(Context *context);
|
||||
bool context_set_module(Context *context, Path *path, TokenId *generic_parameters, bool is_private);
|
||||
void context_print_ast(Context *context, FILE *file);
|
||||
|
||||
#pragma mark --- Decl functions
|
||||
|
||||
@@ -1753,7 +1730,7 @@ Decl *decl_new_generated_var(const char *name, Type *type, VarDeclKind kind, Sou
|
||||
#define DECL_NEW_VAR(_type, _kind, _vis) decl_new_var(context->tok.id, _type, _kind, _vis)
|
||||
void decl_set_external_name(Decl *decl);
|
||||
const char *decl_to_name(Decl *decl);
|
||||
const char *decl_var_to_string(VarDeclKind kind);
|
||||
|
||||
static inline Decl *decl_raw(Decl *decl);
|
||||
static inline bool decl_ok(Decl *decl) { return !decl || decl->decl_kind != DECL_POISONED; }
|
||||
static inline bool decl_poison(Decl *decl) { decl->decl_kind = DECL_POISONED; decl->resolve_status = RESOLVE_DONE; return false; }
|
||||
@@ -1815,7 +1792,7 @@ void expr_const_set_int(ExprConst *expr, uint64_t v, TypeKind kind);
|
||||
void expr_const_set_float(ExprConst *expr, Real d, TypeKind kind);
|
||||
void expr_const_set_bool(ExprConst *expr, bool b);
|
||||
void expr_const_set_null(ExprConst *expr);
|
||||
void expr_const_fprint(FILE *__restrict file, ExprConst *expr);
|
||||
|
||||
bool expr_const_int_overflowed(const ExprConst *expr);
|
||||
bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp op);
|
||||
bool expr_const_will_overflow(const ExprConst *expr, TypeKind kind);
|
||||
@@ -1824,6 +1801,11 @@ void expr_insert_deref(Expr *expr);
|
||||
Expr *expr_variable(Decl *decl);
|
||||
bool expr_is_constant_eval(Expr *expr);
|
||||
const char *expr_const_to_error_string(const ExprConst *expr);
|
||||
static inline bool expr_is_init_list(Expr *expr)
|
||||
{
|
||||
ExprKind kind = expr->expr_kind;
|
||||
return kind == EXPR_DESIGNATED_INITIALIZER_LIST || kind == EXPR_INITIALIZER_LIST;
|
||||
}
|
||||
static inline void expr_set_type(Expr *expr, Type *type)
|
||||
{
|
||||
assert(type);
|
||||
@@ -1831,10 +1813,6 @@ static inline void expr_set_type(Expr *expr, Type *type)
|
||||
expr->original_type = type;
|
||||
}
|
||||
|
||||
void fprint_decl(Context *context, FILE *file, Decl *dec);
|
||||
void fprint_type_info_recursive(Context *context, FILE *file, TypeInfo *type_info, int indent);
|
||||
void fprint_expr_recursive(Context *context, FILE *file, Expr *expr, int indent);
|
||||
|
||||
|
||||
#pragma mark --- Lexer functions
|
||||
|
||||
@@ -1871,8 +1849,6 @@ bool parse_file(File *file);
|
||||
Path *path_create_from_string(const char *string, size_t len, SourceSpan span);
|
||||
Path *path_find_parent_path(Path *path);
|
||||
|
||||
const char *resolve_status_to_string(ResolveStatus status);
|
||||
|
||||
#define SEMA_TOKEN_ERROR(_tok, ...) sema_error_range(source_span_from_token_id(_tok.id), __VA_ARGS__)
|
||||
#define SEMA_TOKID_ERROR(_tok_id, ...) sema_error_range(source_span_from_token_id(_tok_id), __VA_ARGS__)
|
||||
#define SEMA_ERROR(_node, ...) sema_error_range((_node)->span, __VA_ARGS__)
|
||||
@@ -2176,9 +2152,7 @@ static inline bool type_convert_will_trunc(Type *destination, Type *source)
|
||||
|
||||
|
||||
UnaryOp unaryop_from_token(TokenType type);
|
||||
TokenType unaryop_to_token(UnaryOp type);
|
||||
PostUnaryOp post_unaryop_from_token(TokenType type);
|
||||
TokenType postunaryop_to_token(PostUnaryOp type);
|
||||
BinaryOp binaryop_from_token(TokenType type);
|
||||
BinaryOp binaryop_assign_base_op(BinaryOp assign_binary_op);
|
||||
TokenType binaryop_to_token(BinaryOp type);
|
||||
|
||||
@@ -61,8 +61,8 @@ static bool filename_to_module_in_buffer(const char *path)
|
||||
if (path[i] == '/') last_slash = i;
|
||||
if (path[i] == '.') last_dot = i;
|
||||
}
|
||||
int namelen = last_dot - last_slash - 1;
|
||||
if (namelen < 1) return false;
|
||||
int name_len = last_dot - last_slash - 1;
|
||||
if (name_len < 1) return false;
|
||||
scratch_buffer_clear();
|
||||
for (int i = last_slash + 1; i < last_dot; i++)
|
||||
{
|
||||
@@ -280,30 +280,3 @@ bool context_add_import(Context *context, Path *path, Token token, Token alias,
|
||||
return true;
|
||||
}
|
||||
|
||||
void context_print_ast(Context *context, FILE *file)
|
||||
{
|
||||
VECEACH(context->enums, i)
|
||||
{
|
||||
fprint_decl(context, file, context->enums[i]);
|
||||
}
|
||||
VECEACH(context->global_decls, i)
|
||||
{
|
||||
fprint_decl(context, file, context->global_decls[i]);
|
||||
}
|
||||
VECEACH(context->vars, i)
|
||||
{
|
||||
fprint_decl(context, file, context->vars[i]);
|
||||
}
|
||||
VECEACH(context->types, i)
|
||||
{
|
||||
fprint_decl(context, file, context->types[i]);
|
||||
}
|
||||
VECEACH(context->functions, i)
|
||||
{
|
||||
fprint_decl(context, file, context->functions[i]);
|
||||
}
|
||||
VECEACH(context->ct_ifs, i)
|
||||
{
|
||||
fprint_decl(context, file, context->ct_ifs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,10 @@ Expr *copy_expr(Expr *source_expr)
|
||||
MACRO_COPY_EXPR(expr->access_expr.parent);
|
||||
return expr;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
MACRO_COPY_EXPR_LIST(expr->initializer_expr.initializer_expr);
|
||||
MACRO_COPY_EXPR_LIST(expr->initializer_list);
|
||||
return expr;
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
MACRO_COPY_EXPR_LIST(expr->designated_init_list);
|
||||
return expr;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
MACRO_COPY_EXPR_LIST(expr->expression_list);
|
||||
|
||||
@@ -203,6 +203,7 @@ typedef enum
|
||||
EXPR_IDENTIFIER,
|
||||
EXPR_FLATPATH,
|
||||
EXPR_INITIALIZER_LIST,
|
||||
EXPR_DESIGNATED_INITIALIZER_LIST,
|
||||
EXPR_LEN,
|
||||
EXPR_PLACEHOLDER,
|
||||
EXPR_POST_UNARY,
|
||||
@@ -224,6 +225,20 @@ typedef enum
|
||||
EXPR_NOP,
|
||||
} ExprKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONST_FLOAT,
|
||||
CONST_INTEGER,
|
||||
CONST_BOOL,
|
||||
CONST_ENUM,
|
||||
CONST_ERR,
|
||||
CONST_BYTES,
|
||||
CONST_STRING,
|
||||
CONST_POINTER,
|
||||
CONST_TYPEID,
|
||||
CONST_LIST,
|
||||
} ConstKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DESIGNATOR_FIELD,
|
||||
@@ -535,6 +550,7 @@ typedef enum
|
||||
TYPE_ARRAY,
|
||||
TYPE_SUBARRAY,
|
||||
TYPE_INFERRED_ARRAY,
|
||||
TYPE_UNTYPED_LIST,
|
||||
TYPE_TYPEINFO,
|
||||
TYPE_VECTOR,
|
||||
TYPE_VIRTUAL,
|
||||
@@ -542,7 +558,7 @@ typedef enum
|
||||
TYPE_LAST = TYPE_VIRTUAL_ANY
|
||||
} TypeKind;
|
||||
|
||||
#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_POISONED
|
||||
#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_UNTYPED_LIST: case TYPE_POISONED
|
||||
#define ALL_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128: \
|
||||
case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128: case TYPE_IXX
|
||||
#define ALL_SIGNED_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128
|
||||
|
||||
@@ -30,7 +30,7 @@ static void header_print_type(FILE *file, Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_BITSTRUCT:
|
||||
TODO
|
||||
@@ -111,7 +111,6 @@ static void header_print_type(FILE *file, Type *type)
|
||||
case TYPE_TYPEDEF:
|
||||
break;
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
UNREACHABLE
|
||||
case TYPE_ARRAY:
|
||||
break;
|
||||
@@ -120,8 +119,6 @@ static void header_print_type(FILE *file, Type *type)
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
break;
|
||||
case TYPE_TYPEINFO:
|
||||
break;
|
||||
case TYPE_VECTOR:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
|
||||
|
||||
static LLVMValueRef llvm_emit_const_initializer_simple(GenContext *c, Expr *expr, bool *modified)
|
||||
{
|
||||
Expr **elements = expr->initializer_expr.initializer_expr;
|
||||
Expr **elements = expr->initializer_list;
|
||||
unsigned element_count = vec_size(elements);
|
||||
LLVMValueRef* values = malloc_arena(element_count * sizeof(LLVMValueRef));
|
||||
Type *expr_type = expr->type->canonical;
|
||||
@@ -271,20 +271,6 @@ static LLVMValueRef llvm_emit_const_initializer_simple(GenContext *c, Expr *expr
|
||||
return LLVMConstNamedStruct(llvm_get_type(c, expr_type), values, element_count);
|
||||
}
|
||||
|
||||
LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified)
|
||||
{
|
||||
switch (expr->initializer_expr.init_type)
|
||||
{
|
||||
case INITIALIZER_UNKNOWN:
|
||||
case INITIALIZER_DESIGNATED:
|
||||
UNREACHABLE
|
||||
case INITIALIZER_CONST:
|
||||
return llvm_emit_const_initializer(c, expr->initializer_expr.initializer, modified);
|
||||
case INITIALIZER_NORMAL:
|
||||
return llvm_emit_const_initializer_simple(c, expr, modified);
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static void gencontext_emit_global_variable_definition(GenContext *c, Decl *decl)
|
||||
{
|
||||
@@ -352,9 +338,9 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
|
||||
Expr *init_expr = decl->var.init_expr;
|
||||
if (init_expr)
|
||||
{
|
||||
if (init_expr->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (init_expr->expr_kind == EXPR_CONST && init_expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
init_value = llvm_emit_const_aggregate(c, init_expr, &modified);
|
||||
init_value = llvm_emit_const_initializer(c, init_expr->const_expr.list, &modified);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -108,19 +108,17 @@ static bool x86_should_return_type_in_reg(Type *type)
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_POISONED:
|
||||
case TYPE_VOID:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_BITSTRUCT:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
|
||||
@@ -12,7 +12,7 @@ static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue
|
||||
static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Expr *expr);
|
||||
static inline LLVMValueRef llvm_emit_subscript_addr_with_base_new(GenContext *c, BEValue *parent, BEValue *index, SourceLocation *loc);
|
||||
static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, uint64_t offset, DesignatorElement** current, DesignatorElement **last, Expr *expr, BEValue *emitted_value);
|
||||
|
||||
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
|
||||
LLVMValueRef llvm_emit_is_no_error_value(GenContext *c, BEValue *value)
|
||||
{
|
||||
llvm_value_rvalue(c, value);
|
||||
@@ -693,7 +693,18 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_
|
||||
value->type = to_type;
|
||||
return;
|
||||
case CAST_SABOOL:
|
||||
TODO
|
||||
llvm_value_fold_failable(c, value);
|
||||
if (llvm_value_is_addr(value))
|
||||
{
|
||||
value->value = LLVMBuildStructGEP(c->builder, value->value, 1, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
value->value = LLVMBuildExtractValue(c->builder, value->value, 1, "");
|
||||
}
|
||||
value->type = type_usize->canonical;
|
||||
llvm_value_rvalue(c, value);
|
||||
llvm_emit_int_comp_zero(c, value, value, BINARYOP_NE);
|
||||
break;
|
||||
}
|
||||
value->type = to_type;
|
||||
@@ -778,7 +789,8 @@ static inline void llvm_emit_initialize_reference_temporary_const(GenContext *c,
|
||||
|
||||
Type *canonical = expr->type->canonical;
|
||||
|
||||
LLVMValueRef value = llvm_emit_const_aggregate(c, expr, &modified);
|
||||
assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST);
|
||||
LLVMValueRef value = llvm_emit_const_initializer(c, expr->const_expr.list, &modified);
|
||||
|
||||
// Create a global const.
|
||||
LLVMTypeRef type = modified ? LLVMTypeOf(value) : llvm_get_type(c, canonical);
|
||||
@@ -895,7 +907,8 @@ static void llvm_emit_inititialize_reference_const(GenContext *c, BEValue *ref,
|
||||
}
|
||||
static inline void llvm_emit_initialize_reference_const(GenContext *c, BEValue *ref, Expr *expr)
|
||||
{
|
||||
ConstInitializer *initializer = expr->initializer_expr.initializer;
|
||||
assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST);
|
||||
ConstInitializer *initializer = expr->const_expr.list;
|
||||
|
||||
// Make sure we have an address.
|
||||
llvm_value_addr(c, ref);
|
||||
@@ -908,7 +921,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r
|
||||
{
|
||||
// Getting ready to initialize, get the real type.
|
||||
Type *real_type = type_lowering(ref->type);
|
||||
Expr **elements = expr->initializer_expr.initializer_expr;
|
||||
Expr **elements = expr->initializer_list;
|
||||
|
||||
// Make sure we have an address.
|
||||
llvm_value_addr(c, ref);
|
||||
@@ -957,7 +970,12 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r
|
||||
llvm_value_set_address_align(&pointer, value, element->type, ref->alignment);
|
||||
}
|
||||
// If this is an initializer, we want to actually run the initialization recursively.
|
||||
if (element->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (element->expr_kind == EXPR_CONST && element->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
llvm_emit_const_initialize_reference(c, &pointer, element);
|
||||
continue;
|
||||
}
|
||||
if (expr_is_init_list(element))
|
||||
{
|
||||
llvm_emit_initialize_reference(c, &pointer, element);
|
||||
continue;
|
||||
@@ -1008,7 +1026,12 @@ static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, uint64_
|
||||
llvm_store_bevalue(c, ref, emitted_value);
|
||||
return;
|
||||
}
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
llvm_emit_const_initialize_reference(c, ref, expr);
|
||||
return;
|
||||
}
|
||||
if (expr_is_init_list(expr))
|
||||
{
|
||||
llvm_emit_initialize_reference(c, ref, expr);
|
||||
return;
|
||||
@@ -1063,7 +1086,7 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
||||
{
|
||||
// Getting ready to initialize, get the real type.
|
||||
Type *real_type = type_lowering(ref->type);
|
||||
Expr **elements = expr->initializer_expr.initializer_expr;
|
||||
Expr **elements = expr->designated_init_list;
|
||||
assert(vec_size(elements));
|
||||
|
||||
// Make sure we have an address.
|
||||
@@ -1081,6 +1104,29 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a constant aggregate type.
|
||||
*/
|
||||
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST);
|
||||
ConstInitializer *initializer = expr->const_expr.list;
|
||||
if (initializer->kind == CONST_INIT_ZERO)
|
||||
{
|
||||
// In case of a zero, optimize.
|
||||
llvm_emit_memclear(c, ref);
|
||||
return;
|
||||
}
|
||||
// In case of small const initializers, or full arrays - use copy.
|
||||
if (initializer->kind == CONST_INIT_ARRAY_FULL || type_size(expr->type) <= 32)
|
||||
{
|
||||
llvm_emit_initialize_reference_temporary_const(c, ref, expr);
|
||||
return;
|
||||
}
|
||||
llvm_emit_initialize_reference_const(c, ref, expr);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an aggregate type.
|
||||
*
|
||||
@@ -1092,34 +1138,12 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
||||
*/
|
||||
static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *ref, Expr *expr)
|
||||
{
|
||||
// In the case of a const, we have some optimizations:
|
||||
if (expr->initializer_expr.init_type == INITIALIZER_CONST)
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
ConstInitializer *initializer = expr->initializer_expr.initializer;
|
||||
if (initializer->kind == CONST_INIT_ZERO)
|
||||
{
|
||||
// In case of a zero, optimize.
|
||||
llvm_emit_memclear(c, ref);
|
||||
return;
|
||||
}
|
||||
// In case of small const initializers, or full arrays - use copy.
|
||||
if (initializer->kind == CONST_INIT_ARRAY_FULL || type_size(expr->type) <= 32)
|
||||
{
|
||||
llvm_emit_initialize_reference_temporary_const(c, ref, expr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (expr->initializer_expr.init_type)
|
||||
{
|
||||
case INITIALIZER_CONST:
|
||||
// Just clear memory
|
||||
llvm_emit_initialize_reference_const(c, ref, expr);
|
||||
break;
|
||||
case INITIALIZER_NORMAL:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
llvm_emit_initialize_reference_list(c, ref, expr);
|
||||
break;
|
||||
case INITIALIZER_DESIGNATED:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
llvm_emit_initialize_reference_designated(c, ref, expr);
|
||||
break;
|
||||
default:
|
||||
@@ -2613,6 +2637,12 @@ static LLVMValueRef llvm_emit_real(LLVMTypeRef type, Real f)
|
||||
return LLVMConstRealOfStringAndSize(type, global_context.scratch_buffer, global_context.scratch_buffer_len);
|
||||
}
|
||||
|
||||
static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_value_set_address(value, llvm_emit_alloca_aligned(c, expr->type, "literal"), expr->type);
|
||||
llvm_emit_initialize_reference_const(c, value, expr);
|
||||
}
|
||||
|
||||
static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Type *type = type_reduced_from_expr(expr)->canonical;
|
||||
@@ -2644,6 +2674,9 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
llvm_value_set(be_value, llvm_const_int(c, type, bigint_as_signed(&expr->const_expr.i)), type);
|
||||
}
|
||||
return;
|
||||
case CONST_LIST:
|
||||
llvm_emit_const_initializer_list_expr(c, be_value, expr);
|
||||
return;
|
||||
case CONST_FLOAT:
|
||||
llvm_value_set(be_value, llvm_emit_real(llvm_get_type(c, type), expr->const_expr.f), type);
|
||||
return;
|
||||
@@ -3545,7 +3578,12 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
}
|
||||
BEValue value;
|
||||
if (expr->expr_kind == EXPR_COMPOUND_LITERAL) expr = expr->expr_compound_literal.initializer;
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
llvm_emit_const_initialize_reference(c, ref, expr);
|
||||
value = *ref;
|
||||
}
|
||||
else if (expr_is_init_list(expr))
|
||||
{
|
||||
llvm_emit_initialize_reference(c, ref, expr);
|
||||
value = *ref;
|
||||
@@ -3595,6 +3633,7 @@ static inline void gencontext_emit_failable(GenContext *context, BEValue *be_val
|
||||
llvm_value_set(be_value, LLVMGetUndef(llvm_get_type(context, expr->type)), expr->type);
|
||||
}
|
||||
|
||||
|
||||
static inline void llvm_emit_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_value_set_address(value, llvm_emit_alloca_aligned(c, expr->type, "literal"), expr->type);
|
||||
@@ -3799,6 +3838,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
UNREACHABLE
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
llvm_emit_initializer_list_expr(c, value, expr);
|
||||
return;
|
||||
case EXPR_EXPR_BLOCK:
|
||||
|
||||
@@ -236,8 +236,7 @@ void llvm_emit_debug_local_var(GenContext *c, Decl *var);
|
||||
void llvm_emit_debug_global_var(GenContext *c, Decl *global);
|
||||
void llvm_emit_defer(GenContext *c, AstId defer_start, AstId defer_end);
|
||||
void llvm_emit_extern_decl(GenContext *context, Decl *decl);
|
||||
|
||||
LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified);
|
||||
LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_init, bool *modified);
|
||||
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr);
|
||||
void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type);
|
||||
void llvm_emit_global_variable_init(GenContext *c, Decl *decl);
|
||||
|
||||
@@ -5,46 +5,6 @@
|
||||
#include "compiler_internal.h"
|
||||
|
||||
|
||||
void expr_const_fprint(FILE *__restrict file, ExprConst *expr)
|
||||
{
|
||||
switch (expr->const_kind)
|
||||
{
|
||||
case CONST_POINTER:
|
||||
fprintf(file, "null");
|
||||
break;
|
||||
case CONST_BOOL:
|
||||
fprintf(file, expr->b ? "true" : "false");
|
||||
break;
|
||||
case CONST_INTEGER:
|
||||
bigint_fprint(file, &expr->i, 10);
|
||||
break;
|
||||
case CONST_FLOAT:
|
||||
#if LONG_DOUBLE
|
||||
fprintf(file, "%Lg", expr->f);
|
||||
#else
|
||||
fprintf(file, "%g", expr->f);
|
||||
#endif
|
||||
break;
|
||||
case CONST_STRING:
|
||||
fprintf(file, "%.*s", expr->string.len, expr->string.chars);
|
||||
break;
|
||||
case CONST_BYTES:
|
||||
fprintf(file, "[byte data]");
|
||||
break;
|
||||
case CONST_ENUM:
|
||||
fprintf(file, "%s", expr->enum_val->name);
|
||||
break;
|
||||
case CONST_ERR:
|
||||
fprintf(file, "%s", expr->err_val->name);
|
||||
break;
|
||||
case CONST_TYPEID:
|
||||
fprintf(file, "%s", expr->typeid->name);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void expr_const_set_int(ExprConst *expr, uint64_t v, TypeKind kind)
|
||||
{
|
||||
if (type_kind_is_signed(kind))
|
||||
@@ -293,6 +253,8 @@ const char *expr_const_to_error_string(const ExprConst *expr)
|
||||
return expr->err_val->name;
|
||||
case CONST_TYPEID:
|
||||
return expr->typeid->name;
|
||||
case CONST_LIST:
|
||||
return "constant list";
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -50,12 +50,8 @@ static Expr *parse_precedence(Context *context, Precedence precedence)
|
||||
return parse_precedence_with_left_side(context, left_side, precedence);
|
||||
}
|
||||
|
||||
static inline Expr *parse_expr_or_initializer_list(Context *context)
|
||||
Expr *parse_expr_or_initializer_list(Context *context)
|
||||
{
|
||||
if (TOKEN_IS(TOKEN_LBRACE))
|
||||
{
|
||||
return parse_initializer_list(context);
|
||||
}
|
||||
return parse_expr(context);
|
||||
}
|
||||
|
||||
@@ -501,10 +497,6 @@ Expr *parse_initializer(Context *context)
|
||||
advance(context);
|
||||
return expr;
|
||||
}
|
||||
if (TOKEN_IS(TOKEN_LBRACE))
|
||||
{
|
||||
return parse_initializer_list(context);
|
||||
}
|
||||
return parse_expr(context);
|
||||
}
|
||||
|
||||
@@ -522,15 +514,47 @@ Expr *parse_initializer(Context *context)
|
||||
* @param elements
|
||||
* @return
|
||||
*/
|
||||
Expr *parse_initializer_list(Context *context)
|
||||
Expr *parse_initializer_list(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST, context->tok);
|
||||
initializer_list->initializer_expr.init_type = INITIALIZER_UNKNOWN;
|
||||
CONSUME_OR(TOKEN_LBRACE, poisoned_expr);
|
||||
advance_and_verify(context, TOKEN_LBRACE);
|
||||
if (!try_consume(context, TOKEN_RBRACE))
|
||||
{
|
||||
if (!parse_arg_list(context, &initializer_list->initializer_expr.initializer_expr, TOKEN_RBRACE, NULL)) return poisoned_expr;
|
||||
Expr **exprs = NULL;
|
||||
if (!parse_arg_list(context, &exprs, TOKEN_RBRACE, NULL)) return poisoned_expr;
|
||||
int designated = -1;
|
||||
VECEACH(exprs, i)
|
||||
{
|
||||
Expr *expr = exprs[i];
|
||||
if (expr->expr_kind == EXPR_DESIGNATOR)
|
||||
{
|
||||
if (designated == 0)
|
||||
{
|
||||
SEMA_ERROR(expr, "Designated initialization with '[] = ...' and '.param = ...' cannot be mixed with normal initialization.");
|
||||
return poisoned_expr;
|
||||
}
|
||||
designated = 1;
|
||||
continue;
|
||||
}
|
||||
if (designated == 1)
|
||||
{
|
||||
SEMA_ERROR(expr, "Normal initialization cannot be mixed with designated initialization.");
|
||||
return poisoned_expr;
|
||||
}
|
||||
designated = 0;
|
||||
}
|
||||
CONSUME_OR(TOKEN_RBRACE, poisoned_expr);
|
||||
RANGE_EXTEND_PREV(initializer_list);
|
||||
if (designated == 1)
|
||||
{
|
||||
initializer_list->designated_init_list = exprs;
|
||||
initializer_list->expr_kind = EXPR_DESIGNATED_INITIALIZER_LIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
initializer_list->initializer_list = exprs;
|
||||
}
|
||||
}
|
||||
RANGE_EXTEND_PREV(initializer_list);
|
||||
return initializer_list;
|
||||
@@ -557,21 +581,14 @@ static Expr *parse_binary(Context *context, Expr *left_side)
|
||||
advance(context);
|
||||
|
||||
Expr *right_side;
|
||||
if (TOKEN_IS(TOKEN_LBRACE) && operator_type == TOKEN_EQ)
|
||||
// Assignment operators have precedence right -> left.
|
||||
if (rules[operator_type].precedence == PREC_ASSIGNMENT)
|
||||
{
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_initializer_list(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assignment operators have precedence right -> left.
|
||||
if (rules[operator_type].precedence == PREC_ASSIGNMENT)
|
||||
{
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr);
|
||||
}
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr);
|
||||
}
|
||||
|
||||
Expr *expr = EXPR_NEW_EXPR(EXPR_BINARY, left_side);
|
||||
@@ -1265,7 +1282,8 @@ Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *ty
|
||||
{
|
||||
Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type_info->span);
|
||||
expr->expr_compound_literal.type_info = type_info;
|
||||
ASSIGN_EXPR_ELSE(expr->expr_compound_literal.initializer, parse_initializer_list(context), poisoned_expr);
|
||||
EXPECT_OR(TOKEN_LBRACE, poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr->expr_compound_literal.initializer, parse_initializer_list(context, NULL), poisoned_expr);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
}
|
||||
@@ -1423,4 +1441,6 @@ ParseRule rules[TOKEN_EOF + 1] = {
|
||||
[TOKEN_CT_NAMEOF] = { parse_ct_call, NULL, PREC_NONE },
|
||||
[TOKEN_CT_QNAMEOF] = { parse_ct_call, NULL, PREC_NONE },
|
||||
[TOKEN_CT_TYPEOF] = { parse_typeof_expr, NULL, PREC_NONE },
|
||||
|
||||
[TOKEN_LBRACE] = { parse_initializer_list, NULL, PREC_NONE },
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ Expr *parse_try_expr_after_try(Context *context, bool is_try);
|
||||
TypeInfo *parse_type(Context *context);
|
||||
TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info);
|
||||
Expr* parse_constant_expr(Context *context);
|
||||
Expr *parse_initializer_list(Context *context);
|
||||
Expr *parse_initializer(Context *context);
|
||||
void parse_imports(Context *context);
|
||||
Decl *parse_decl(Context *context);
|
||||
|
||||
@@ -411,6 +411,7 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
return CAST_ERROR;
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -493,6 +494,9 @@ bool cast_may_explicit(Type *from_type, Type *to_type)
|
||||
return to_kind == TYPE_POINTER;
|
||||
case TYPE_VECTOR:
|
||||
return type_is_structurally_equivalent(type_get_array(from->vector.base, from->vector.len), to);
|
||||
case TYPE_UNTYPED_LIST:
|
||||
REMINDER("Look at untyped list explicit conversions");
|
||||
return false;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -808,6 +812,32 @@ bool cast_implicit_bit_width(Expr *expr, Type *to_type)
|
||||
return cast_implicit(expr, to_type);
|
||||
}
|
||||
|
||||
static inline bool subarray_to_bool(Expr *expr)
|
||||
{
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
ConstInitializer *list = expr->const_expr.list;
|
||||
switch (list->kind)
|
||||
{
|
||||
case CONST_INIT_ZERO:
|
||||
expr_const_set_bool(&expr->const_expr, false);
|
||||
return true;
|
||||
case CONST_INIT_ARRAY:
|
||||
expr_const_set_bool(&expr->const_expr, vec_size(list->init_array.elements) > 0);
|
||||
return true;
|
||||
case CONST_INIT_ARRAY_FULL:
|
||||
expr_const_set_bool(&expr->const_expr, vec_size(list->init_array_full) > 0);
|
||||
return true;
|
||||
case CONST_INIT_STRUCT:
|
||||
case CONST_INIT_UNION:
|
||||
case CONST_INIT_VALUE:
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return insert_cast(expr, CAST_SABOOL, type_bool);
|
||||
}
|
||||
|
||||
bool cast(Expr *expr, Type *to_type)
|
||||
{
|
||||
Type *from_type = type_flatten(expr->type->canonical);
|
||||
@@ -901,6 +931,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
if (canonical->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_SAPTR, canonical);
|
||||
if (canonical->type_kind == TYPE_BOOL) return subarray_to_bool(expr);
|
||||
break;
|
||||
case TYPE_VECTOR:
|
||||
TODO
|
||||
|
||||
@@ -586,15 +586,13 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl)
|
||||
decl->distinct_decl.base_type = base;
|
||||
switch (base->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_IXX:
|
||||
case TYPE_FXX:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_TYPEINFO:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
return false;
|
||||
case TYPE_VIRTUAL_ANY:
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
* - Disallow jumping in and out of an expression block.
|
||||
*/
|
||||
|
||||
static inline void expr_set_as_const_list(Expr *expr, ConstInitializer *list)
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_LIST;
|
||||
expr->const_expr.list = list;
|
||||
}
|
||||
static inline bool sema_cast_rvalue(Context *context, Type *to, Expr *expr);
|
||||
|
||||
int BINOP_PREC_REQ[BINARYOP_LAST] =
|
||||
@@ -527,20 +533,21 @@ bool expr_is_constant_eval(Expr *expr)
|
||||
return expr_is_constant_eval(expr->expr_compound_literal.initializer);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
{
|
||||
Expr** init_exprs = expr->initializer_expr.initializer_expr;
|
||||
switch (expr->initializer_expr.init_type)
|
||||
Expr** init_exprs = expr->initializer_list;
|
||||
VECEACH(init_exprs, i)
|
||||
{
|
||||
case INITIALIZER_NORMAL:
|
||||
{
|
||||
VECEACH(init_exprs, i)
|
||||
{
|
||||
if (!expr_is_constant_eval(init_exprs[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
if (!expr_is_constant_eval(init_exprs[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
{
|
||||
Expr** init_exprs = expr->designated_init_list;
|
||||
VECEACH(init_exprs, i)
|
||||
{
|
||||
if (!expr_is_constant_eval(init_exprs[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@@ -2635,10 +2642,10 @@ static void sema_create_const_initializer_value(ConstInitializer *const_init, Ex
|
||||
{
|
||||
// Possibly this is already a const initializers, in that case
|
||||
// overwrite what is inside, eg [1] = { .a = 1 }
|
||||
if (value->expr_kind == EXPR_INITIALIZER_LIST && value->initializer_expr.init_type == INITIALIZER_CONST)
|
||||
if (value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
*const_init = *value->initializer_expr.initializer;
|
||||
value->initializer_expr.initializer = const_init;
|
||||
*const_init = *value->const_expr.list;
|
||||
value->const_expr.list = const_init;
|
||||
return;
|
||||
}
|
||||
const_init->init_value = value;
|
||||
@@ -2648,7 +2655,8 @@ static void sema_create_const_initializer_value(ConstInitializer *const_init, Ex
|
||||
|
||||
static bool is_empty_initializer_list(Expr *value)
|
||||
{
|
||||
return value->initializer_expr.init_type == INITIALIZER_CONST && value->initializer_expr.initializer->kind == CONST_INIT_ZERO;
|
||||
return value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_LIST
|
||||
&& value->const_expr.list->kind == CONST_INIT_ZERO;
|
||||
}
|
||||
static void sema_create_const_initializer(ConstInitializer *const_init, Expr *initializer);
|
||||
|
||||
@@ -2908,7 +2916,7 @@ static void sema_create_const_initializer(ConstInitializer *const_init, Expr *in
|
||||
const_init->type = type_flatten(initializer->type);
|
||||
|
||||
// Loop through the initializers.
|
||||
Expr **init_expressions = initializer->initializer_expr.initializer_expr;
|
||||
Expr **init_expressions = initializer->initializer_list;
|
||||
VECEACH(init_expressions, i)
|
||||
{
|
||||
Expr *expr = init_expressions[i];
|
||||
@@ -2918,80 +2926,9 @@ static void sema_create_const_initializer(ConstInitializer *const_init, Expr *in
|
||||
}
|
||||
}
|
||||
|
||||
static void debug_dump_const_initializer(ConstInitializer *init, const char *name, unsigned indent)
|
||||
{
|
||||
for (unsigned i = 0; i < indent; i++) printf(" ");
|
||||
if (name)
|
||||
{
|
||||
printf("%s : %s", name, init->type->name ? init->type->name : "WTF");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", init->type->name ? init->type->name : "WTF");
|
||||
}
|
||||
switch (init->kind)
|
||||
{
|
||||
case CONST_INIT_ZERO:
|
||||
printf(" = 0\n");
|
||||
return;
|
||||
case CONST_INIT_UNION:
|
||||
{
|
||||
printf(" ->\n");
|
||||
Decl** members = init->type->decl->strukt.members;
|
||||
debug_dump_const_initializer(init->init_union.element, members[init->init_union.index]->name, indent + 1);
|
||||
return;
|
||||
}
|
||||
case CONST_INIT_STRUCT:
|
||||
{
|
||||
printf(" ->\n");
|
||||
Decl** members = init->type->decl->strukt.members;
|
||||
unsigned member_count = vec_size(members);
|
||||
for (unsigned i = 0; i < member_count; i++)
|
||||
{
|
||||
debug_dump_const_initializer(init->init_struct[i], members[i]->name, indent + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
{
|
||||
printf(" [%llu] ->\n", (unsigned long long)init->init_array_value.index);
|
||||
debug_dump_const_initializer(init->init_array_value.element, "", indent + 1);
|
||||
return;
|
||||
}
|
||||
case CONST_INIT_VALUE:
|
||||
{
|
||||
assert(init->init_value->expr_kind == EXPR_CONST);
|
||||
printf(" = ");
|
||||
expr_const_fprint(stdout, &init->init_value->const_expr);
|
||||
puts("");
|
||||
return;
|
||||
}
|
||||
case CONST_INIT_ARRAY:
|
||||
printf(" [//] ->\n");
|
||||
{
|
||||
VECEACH(init->init_array.elements, i)
|
||||
{
|
||||
debug_dump_const_initializer(init->init_array.elements[i], NULL, indent + 1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case CONST_INIT_ARRAY_FULL:
|
||||
printf(" [: ->\n");
|
||||
{
|
||||
VECEACH(init->init_array_full, i)
|
||||
{
|
||||
debug_dump_const_initializer(init->init_array_full[i], NULL, indent + 1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_designated_initializer(Context *context, Type *assigned, Expr *initializer)
|
||||
{
|
||||
Expr **init_expressions = initializer->initializer_expr.initializer_expr;
|
||||
Expr **init_expressions = initializer->designated_init_list;
|
||||
Type *original = assigned->canonical;
|
||||
bool is_structlike = type_is_structlike(assigned->canonical);
|
||||
|
||||
@@ -3020,11 +2957,9 @@ static bool sema_expr_analyse_designated_initializer(Context *context, Type *ass
|
||||
{
|
||||
ConstInitializer *const_init = MALLOC(sizeof(ConstInitializer));
|
||||
sema_create_const_initializer(const_init, initializer);
|
||||
initializer->initializer_expr.init_type = INITIALIZER_CONST;
|
||||
initializer->initializer_expr.initializer = const_init;
|
||||
expr_set_as_const_list(initializer, const_init);
|
||||
return true;
|
||||
}
|
||||
initializer->initializer_expr.init_type = INITIALIZER_DESIGNATED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3037,9 +2972,8 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context,
|
||||
initializer->pure = true;
|
||||
initializer->constant = true;
|
||||
|
||||
Expr **elements = initializer->initializer_expr.initializer_expr;
|
||||
Expr **elements = initializer->initializer_list;
|
||||
Decl **members = assigned->strukt.members;
|
||||
initializer->initializer_expr.init_type = INITIALIZER_NORMAL;
|
||||
unsigned size = vec_size(elements);
|
||||
unsigned expected_members = vec_size(members);
|
||||
|
||||
@@ -3093,10 +3027,9 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context,
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
Expr *expr = elements[i];
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
assert(expr->constant);
|
||||
inits[i] = expr->initializer_expr.initializer;
|
||||
inits[i] = expr->const_expr.list;
|
||||
continue;
|
||||
}
|
||||
ConstInitializer *element_init = MALLOC(sizeof(ConstInitializer));
|
||||
@@ -3104,8 +3037,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context,
|
||||
inits[i] = element_init;
|
||||
}
|
||||
const_init->init_struct = inits;
|
||||
initializer->initializer_expr.init_type = INITIALIZER_CONST;
|
||||
initializer->initializer_expr.initializer = const_init;
|
||||
expr_set_as_const_list(initializer, const_init);
|
||||
}
|
||||
|
||||
// 7. Done!
|
||||
@@ -3122,14 +3054,11 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T
|
||||
initializer->pure = true;
|
||||
initializer->constant = true;
|
||||
|
||||
Expr **elements = initializer->initializer_expr.initializer_expr;
|
||||
|
||||
assert((assigned->type_kind == TYPE_ARRAY) && "The other types are not done yet.");
|
||||
Expr **elements = initializer->initializer_list;
|
||||
|
||||
Type *inner_type = type_get_indexed_type(assigned);
|
||||
assert(inner_type);
|
||||
|
||||
initializer->initializer_expr.init_type = INITIALIZER_NORMAL;
|
||||
unsigned size = vec_size(elements);
|
||||
unsigned expected_members = assigned->array.len;
|
||||
if (assigned->type_kind != TYPE_ARRAY) expected_members = size;
|
||||
@@ -3171,10 +3100,9 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
Expr *expr = elements[i];
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST)
|
||||
{
|
||||
assert(expr->constant);
|
||||
inits[i] = expr->initializer_expr.initializer;
|
||||
inits[i] = expr->const_expr.list;
|
||||
continue;
|
||||
}
|
||||
ConstInitializer *element_init = MALLOC(sizeof(ConstInitializer));
|
||||
@@ -3182,17 +3110,58 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T
|
||||
inits[i] = element_init;
|
||||
}
|
||||
const_init->init_array_full = inits;
|
||||
initializer->initializer_expr.init_type = INITIALIZER_CONST;
|
||||
initializer->initializer_expr.initializer = const_init;
|
||||
expr_set_as_const_list(initializer, const_init);
|
||||
}
|
||||
|
||||
// 7. Done!
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_untyped_initializer(Context *context, Expr *initializer)
|
||||
{
|
||||
initializer->pure = true;
|
||||
initializer->constant = true;
|
||||
|
||||
Expr **elements = initializer->initializer_list;
|
||||
|
||||
unsigned size = vec_size(elements);
|
||||
|
||||
Type *element_type = NULL;
|
||||
bool no_common_elements = false;
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
Expr *element = elements[i];
|
||||
if (!sema_analyse_expr(context, NULL, element)) return false;
|
||||
initializer->failable |= element->failable;
|
||||
initializer->pure &= element->pure;
|
||||
initializer->constant &= element->constant;
|
||||
if (no_common_elements) continue;
|
||||
if (element_type == NULL)
|
||||
{
|
||||
element_type = element->type;
|
||||
continue;
|
||||
}
|
||||
element_type = type_find_max_type(element->type, element_type);
|
||||
if (!element_type) no_common_elements = true;
|
||||
}
|
||||
TODO
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_initializer(Context *context, Type *external_type, Type *assigned, Expr *expr)
|
||||
{
|
||||
Expr **init_expressions = expr->initializer_expr.initializer_expr;
|
||||
// Note at this point this we either have
|
||||
// EXPR_DESIGNATED_INITIALIZER_LIST
|
||||
// or EXPR_INITIALIZER_LIST
|
||||
|
||||
if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST)
|
||||
{
|
||||
expr_set_type(expr, external_type);
|
||||
return sema_expr_analyse_designated_initializer(context, assigned, expr);
|
||||
}
|
||||
|
||||
assert(expr->expr_kind == EXPR_INITIALIZER_LIST);
|
||||
|
||||
Expr **init_expressions = expr->initializer_list;
|
||||
|
||||
unsigned init_expression_count = vec_size(init_expressions);
|
||||
|
||||
@@ -3200,32 +3169,26 @@ static inline bool sema_expr_analyse_initializer(Context *context, Type *externa
|
||||
if (init_expression_count == 0)
|
||||
{
|
||||
external_type = sema_type_lower_by_size(external_type, 0);
|
||||
assigned = sema_type_lower_by_size(assigned, 0);
|
||||
expr_set_type(expr, external_type);
|
||||
ConstInitializer *initializer = CALLOCS(ConstInitializer);
|
||||
initializer->kind = CONST_INIT_ZERO;
|
||||
initializer->type = type_flatten(expr->type);
|
||||
expr->initializer_expr.init_type = INITIALIZER_CONST;
|
||||
expr->initializer_expr.initializer = initializer;
|
||||
expr_set_as_const_list(expr, initializer);
|
||||
expr->constant = true;
|
||||
expr->pure = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Check if we might have a designated initializer
|
||||
// this means that in this case we're actually not resolving macros here.
|
||||
if (init_expressions[0]->expr_kind == EXPR_DESIGNATOR)
|
||||
{
|
||||
expr_set_type(expr, external_type);
|
||||
return sema_expr_analyse_designated_initializer(context, assigned, expr);
|
||||
}
|
||||
|
||||
external_type = sema_type_lower_by_size(external_type, init_expression_count);
|
||||
assigned = sema_type_lower_by_size(assigned, init_expression_count);
|
||||
expr_set_type(expr, external_type);
|
||||
|
||||
if (external_type == type_complist)
|
||||
{
|
||||
return sema_expr_analyse_untyped_initializer(context, expr);
|
||||
}
|
||||
// 3. Otherwise use the plain initializer.
|
||||
if (assigned->type_kind == TYPE_ARRAY || assigned->type_kind == TYPE_INFERRED_ARRAY)
|
||||
if (assigned->type_kind == TYPE_UNTYPED_LIST || assigned->type_kind == TYPE_ARRAY || assigned->type_kind == TYPE_INFERRED_ARRAY || assigned->type_kind == TYPE_SUBARRAY)
|
||||
{
|
||||
return sema_expr_analyse_array_plain_initializer(context, assigned, expr);
|
||||
}
|
||||
@@ -3235,6 +3198,10 @@ static inline bool sema_expr_analyse_initializer(Context *context, Type *externa
|
||||
|
||||
static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
if (!to)
|
||||
{
|
||||
return sema_expr_analyse_initializer(context, type_complist, type_complist, expr);
|
||||
}
|
||||
assert(to);
|
||||
Type *assigned = type_flatten(to);
|
||||
switch (assigned->type_kind)
|
||||
@@ -3243,6 +3210,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to
|
||||
case TYPE_UNION:
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
return sema_expr_analyse_initializer(context, to, assigned, expr);
|
||||
default:
|
||||
break;
|
||||
@@ -4672,52 +4640,21 @@ static bool sema_expr_analyse_bit_not(Context *context, Type *to, Expr *expr, Ex
|
||||
|
||||
static bool sema_expr_analyse_not(Expr *expr, Expr *inner)
|
||||
{
|
||||
if (!type_may_convert_to_boolean(inner->type))
|
||||
if (!cast_may_implicit(inner->type, type_bool))
|
||||
{
|
||||
SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean valure.", type_quoted_error_string(inner->type));
|
||||
SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean value.", type_quoted_error_string(inner->type));
|
||||
return false;
|
||||
}
|
||||
if (!cast_implicit(inner, type_bool)) return false;
|
||||
expr_copy_properties(expr, inner);
|
||||
expr_set_type(expr, type_bool);
|
||||
|
||||
if (inner->expr_kind == EXPR_CONST)
|
||||
{
|
||||
assert(inner->const_expr.const_kind == CONST_BOOL);
|
||||
expr->const_expr.const_kind = CONST_BOOL;
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
switch (inner->const_expr.const_kind)
|
||||
{
|
||||
case CONST_INTEGER:
|
||||
expr->const_expr.b = bigint_cmp_zero(&inner->const_expr.i) == CMP_EQ;
|
||||
return true;
|
||||
case CONST_BOOL:
|
||||
expr->const_expr.b = !inner->const_expr.b;
|
||||
return true;
|
||||
case CONST_FLOAT:
|
||||
expr->const_expr.b = inner->const_expr.f == 0.0;
|
||||
return true;
|
||||
case CONST_STRING:
|
||||
expr->const_expr.b = !inner->const_expr.string.len;
|
||||
return true;
|
||||
case CONST_BYTES:
|
||||
expr->const_expr.b = !inner->const_expr.bytes.len;
|
||||
return true;
|
||||
case CONST_POINTER:
|
||||
expr->const_expr.b = true;
|
||||
return true;
|
||||
case CONST_ERR:
|
||||
expr->const_expr.b = inner->const_expr.err_val == NULL;
|
||||
return true;
|
||||
case CONST_ENUM:
|
||||
{
|
||||
Expr *value = inner->const_expr.enum_val->enum_constant.expr;
|
||||
assert(value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_INTEGER);
|
||||
expr->const_expr.b = bigint_cmp_zero(&value->const_expr.i) == CMP_EQ;
|
||||
return true;
|
||||
}
|
||||
case CONST_TYPEID:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
expr->const_expr.b = !inner->const_expr.b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -4907,7 +4844,7 @@ static inline bool sema_expr_analyse_unary(Context *context, Type *to, Expr *exp
|
||||
if (!sema_analyse_expr(context, to, inner)) return false;
|
||||
return sema_expr_analyse_bit_not(context, to, expr, inner);
|
||||
case UNARYOP_NOT:
|
||||
if (!sema_analyse_expr(context, NULL, inner)) return false;
|
||||
if (!sema_analyse_expr(context, type_bool, inner)) return false;
|
||||
return sema_expr_analyse_not(expr, inner);
|
||||
case UNARYOP_DEC:
|
||||
case UNARYOP_INC:
|
||||
@@ -6146,6 +6083,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
case EXPR_ACCESS:
|
||||
return sema_expr_analyse_access(context, expr);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
return sema_expr_analyse_initializer_list(context, to, expr);
|
||||
case EXPR_CAST:
|
||||
return sema_expr_analyse_cast(context, to, expr);
|
||||
@@ -6245,24 +6183,62 @@ bool sema_analyse_expr_value(Context *context, Type *to, Expr *expr)
|
||||
|
||||
ArrayIndex sema_get_initializer_const_array_size(Context *context, Expr *initializer, bool *may_be_array, bool *is_const_size)
|
||||
{
|
||||
assert(initializer->expr_kind == EXPR_INITIALIZER_LIST);
|
||||
Expr **initializers = initializer->initializer_expr.initializer_expr;
|
||||
*may_be_array = true;
|
||||
*is_const_size = true;
|
||||
unsigned element_count = vec_size(initializers);
|
||||
// If it's empty or the first element is not a designator, we assume an array list
|
||||
// with that many elements.
|
||||
if (!element_count || initializers[0]->expr_kind != EXPR_DESIGNATOR) return element_count;
|
||||
if (initializer->expr_kind == EXPR_CONST)
|
||||
{
|
||||
assert(initializer->const_expr.const_kind == CONST_LIST);
|
||||
ConstInitializer *init = initializer->const_expr.list;
|
||||
Type *type = type_lowering(initializer->type);
|
||||
*is_const_size = true;
|
||||
switch (init->kind)
|
||||
{
|
||||
case CONST_INIT_ZERO:
|
||||
if (type->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
*may_be_array = true;
|
||||
return type->array.len;
|
||||
}
|
||||
if (type->type_kind == TYPE_SUBARRAY)
|
||||
{
|
||||
*may_be_array = true;
|
||||
return 0;
|
||||
}
|
||||
*may_be_array = false;
|
||||
return 0;
|
||||
case CONST_INIT_ARRAY:
|
||||
*may_be_array = true;
|
||||
return VECLAST(init->init_array.elements)->init_array_value.index + 1;
|
||||
case CONST_INIT_ARRAY_FULL:
|
||||
*may_be_array = true;
|
||||
return vec_size(init->init_array_full);
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
UNREACHABLE;
|
||||
case CONST_INIT_STRUCT:
|
||||
case CONST_INIT_UNION:
|
||||
case CONST_INIT_VALUE:
|
||||
*may_be_array = false;
|
||||
return 0;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
switch (initializer->expr_kind)
|
||||
{
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
*may_be_array = true;
|
||||
*is_const_size = true;
|
||||
return vec_size(initializer->initializer_list);
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
Expr **initializers = initializer->designated_init_list;
|
||||
ArrayIndex size = 0;
|
||||
// Otherwise we assume everything's a designator.
|
||||
VECEACH(initializers, i)
|
||||
{
|
||||
Expr *sub_initializer = initializers[i];
|
||||
if (sub_initializer->expr_kind != EXPR_DESIGNATOR)
|
||||
{
|
||||
// Simply messed up: a mix of designators and regular ones.
|
||||
return -1;
|
||||
}
|
||||
assert(sub_initializer->expr_kind == EXPR_DESIGNATOR);
|
||||
|
||||
DesignatorElement *element = sub_initializer->designator_expr.path[0];
|
||||
switch (element->kind)
|
||||
{
|
||||
|
||||
@@ -1141,7 +1141,7 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement)
|
||||
Type *inferred_type = NULL;
|
||||
|
||||
// We may have an initializer list, in this case we rely on an inferred type.
|
||||
if (enumerator->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
if (expr_is_init_list(enumerator) || (enumerator->expr_kind == EXPR_CONST && enumerator->const_expr.const_kind == CONST_LIST))
|
||||
{
|
||||
bool may_be_array;
|
||||
bool is_const_size;
|
||||
|
||||
@@ -155,6 +155,8 @@ bool sema_resolve_type(Context *context, Type *type)
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
return true;
|
||||
case TYPE_POINTER:
|
||||
return sema_resolve_type(context, type->pointer);
|
||||
@@ -170,8 +172,6 @@ bool sema_resolve_type(Context *context, Type *type)
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
return sema_resolve_type(context, type->array.base);
|
||||
case TYPE_TYPEINFO:
|
||||
TODO
|
||||
case TYPE_VIRTUAL:
|
||||
TODO;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ static struct
|
||||
Type u8, u16, u32, u64, u128;
|
||||
Type f16, f32, f64, f128, fxx;
|
||||
Type usz, isz, uptr, iptr, uptrdiff, iptrdiff;
|
||||
Type voidstar, typeid, anyerr, typeinfo;
|
||||
Type str, varheader, virtual, virtual_generic;
|
||||
Type voidstar, typeid, anyerr, typeinfo, ctlist;
|
||||
Type str, virtual, virtual_generic;
|
||||
} t;
|
||||
|
||||
Type *type_bool = &t.u1;
|
||||
@@ -46,7 +46,7 @@ Type *type_compint = &t.ixx;
|
||||
Type *type_compfloat = &t.fxx;
|
||||
Type *type_compstr = &t.str;
|
||||
Type *type_anyerr = &t.anyerr;
|
||||
Type *type_varheader = &t.varheader;
|
||||
Type *type_complist = &t.ctlist;
|
||||
|
||||
static unsigned size_subarray;
|
||||
static AlignSize alignment_subarray;
|
||||
@@ -126,6 +126,7 @@ const char *type_to_error_string(Type *type)
|
||||
case TYPE_VIRTUAL_ANY:
|
||||
case TYPE_VIRTUAL:
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
return type->name;
|
||||
case TYPE_FUNC:
|
||||
return strcat_arena("func ", type->func.mangled_function_signature);
|
||||
@@ -202,9 +203,7 @@ ByteSize type_size(Type *type)
|
||||
}
|
||||
return width;
|
||||
}
|
||||
case TYPE_POISONED:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE;
|
||||
case TYPE_TYPEDEF:
|
||||
return type_size(type->canonical);
|
||||
@@ -365,6 +364,7 @@ bool type_is_abi_aggregate(Type *type)
|
||||
return true;
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -502,15 +502,13 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
type = type->decl->bitstruct.base_type->type;
|
||||
goto RETRY;
|
||||
case TYPE_FXX:
|
||||
case TYPE_POISONED:
|
||||
case TYPE_IXX:
|
||||
case TYPE_VOID:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case CT_TYPES:
|
||||
return false;
|
||||
case TYPE_VIRTUAL:
|
||||
case TYPE_VIRTUAL_ANY:
|
||||
@@ -705,6 +703,7 @@ AlignSize type_abi_alignment(Type *type)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
UNREACHABLE;
|
||||
case TYPE_BITSTRUCT:
|
||||
return type_abi_alignment(type->decl->bitstruct.base_type->type);
|
||||
@@ -992,7 +991,6 @@ Type *type_get_indexed_type(Type *type)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Type *type_create_array(Type *element_type, uint64_t len, bool vector, bool canonical)
|
||||
{
|
||||
if (canonical) element_type = element_type->canonical;
|
||||
@@ -1146,6 +1144,7 @@ static void type_append_name_to_scratch(Type *type)
|
||||
case TYPE_IXX:
|
||||
case TYPE_FXX:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_TYPEINFO:
|
||||
UNREACHABLE
|
||||
@@ -1240,6 +1239,7 @@ void type_setup(PlatformTarget *target)
|
||||
|
||||
|
||||
type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1);
|
||||
type_create("complist", &t.ctlist, TYPE_UNTYPED_LIST, 1, 1, 1);
|
||||
type_init("typeid", &t.typeid, TYPE_TYPEID, target->width_pointer, target->align_pointer);
|
||||
|
||||
type_init("void*", &t.voidstar, TYPE_POINTER, target->width_pointer, target->align_pointer);
|
||||
@@ -1409,6 +1409,7 @@ bool type_may_convert_to_boolean(Type *type)
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_ERRTYPE:
|
||||
case TYPE_STRLIT:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
return true;
|
||||
case TYPE_FUNC:
|
||||
case TYPE_ARRAY:
|
||||
@@ -1596,6 +1597,7 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
case TYPE_ANYERR:
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
TODO
|
||||
case TYPE_TYPEDEF:
|
||||
UNREACHABLE
|
||||
|
||||
27
test/test_suite/initializer_lists/general_tests.c3t
Normal file
27
test/test_suite/initializer_lists/general_tests.c3t
Normal file
@@ -0,0 +1,27 @@
|
||||
// #skip
|
||||
|
||||
union Baz
|
||||
{
|
||||
int x;
|
||||
double y;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
func int test()
|
||||
{
|
||||
Baz ffe = { .x = 1 };
|
||||
int[1] azz = {};
|
||||
int[*] a = {};
|
||||
var $foo = { 1, 2, 3 };
|
||||
bool x = ! int[] { 1, 2, 3 };
|
||||
Bar b = {};
|
||||
Baz z = {};
|
||||
int[] sub = {};
|
||||
Bar[] foo = {};
|
||||
Baz[3] baz = {};
|
||||
return 1;
|
||||
}
|
||||
51
test/test_suite/initializer_lists/zero_init.c3t
Normal file
51
test/test_suite/initializer_lists/zero_init.c3t
Normal file
@@ -0,0 +1,51 @@
|
||||
// #target: x64-darwin
|
||||
|
||||
union Baz
|
||||
{
|
||||
int x;
|
||||
double y;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
func int test()
|
||||
{
|
||||
int[1] azz = {};
|
||||
int[*] a = {};
|
||||
Bar b = {};
|
||||
Baz z = {};
|
||||
int[] sub = {};
|
||||
Bar[] foo = {};
|
||||
Baz[3] baz = {};
|
||||
return 1;
|
||||
}
|
||||
|
||||
// #expect: zero_init.ll
|
||||
|
||||
define i32 @zero_init.test() #0 {
|
||||
entry:
|
||||
%azz = alloca [1 x i32], align 4
|
||||
%a = alloca [0 x i32], align 4
|
||||
%b = alloca %Bar, align 4
|
||||
%z = alloca %Baz, align 8
|
||||
%sub = alloca %"int[]", align 8
|
||||
%foo = alloca %"Bar[]", align 8
|
||||
%baz = alloca [3 x %Baz], align 16
|
||||
%0 = bitcast [1 x i32]* %azz to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 4, i1 false)
|
||||
%1 = bitcast [0 x i32]* %a to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 0, i1 false)
|
||||
%2 = bitcast %Bar* %b to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %2, i8 0, i64 8, i1 false)
|
||||
%3 = bitcast %Baz* %z to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false)
|
||||
%4 = bitcast %"int[]"* %sub to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %4, i8 0, i64 16, i1 false)
|
||||
%5 = bitcast %"Bar[]"* %foo to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %5, i8 0, i64 16, i1 false)
|
||||
%6 = bitcast [3 x %Baz]* %baz to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 16 %6, i8 0, i64 24, i1 false)
|
||||
ret i32 1
|
||||
}
|
||||
@@ -52,8 +52,3 @@ func void test8()
|
||||
foreach (int a : { z }) foo(); // #error: 'int[3]' into 'int'
|
||||
}
|
||||
|
||||
func void test9()
|
||||
{
|
||||
foreach (int a : { [2] = 1 }) foo();
|
||||
foreach (int a : { [2] = 2, 1 }) foo(); // #error: The initializer mixes designated initialization with array initialization
|
||||
}
|
||||
5
test/test_suite/statements/foreach_parse_error.c3
Normal file
5
test/test_suite/statements/foreach_parse_error.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
func void test9()
|
||||
{
|
||||
foreach (int a : { [2] = 1 }) foo();
|
||||
foreach (int a : { [2] = 2, 1 }) foo(); // #error: Normal initialization cannot be mixed with designated initialization.
|
||||
}
|
||||
Reference in New Issue
Block a user