AST printout removed. Split initializer types. Const list functionality.

This commit is contained in:
Christoffer Lerno
2021-09-06 09:59:28 +02:00
committed by Christoffer Lerno
parent c76e8e0713
commit bcda6d71c9
24 changed files with 480 additions and 1457 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -91,7 +91,6 @@ void compiler_parse(void)
global_context_clear_errors();
parse_file(file);
TODO; //context_print_ast(context, stdout);
}
exit(EXIT_SUCCESS);
}

View File

@@ -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);

View File

@@ -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]);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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
{

View File

@@ -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:

View File

@@ -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:

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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 },
};

View File

@@ -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);

View File

@@ -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

View File

@@ -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:

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View 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;
}

View 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
}

View File

@@ -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
}

View 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.
}