Skip to content

Commit

Permalink
Separate const slice. Fix #1489. Fix const slice appending. Remove un…
Browse files Browse the repository at this point in the history
…intended print of `char[]` as String. Support const conversion of array -> slice.
  • Loading branch information
lerno committed Oct 3, 2024
1 parent 7f66d59 commit 02e9bfa
Show file tree
Hide file tree
Showing 39 changed files with 1,675 additions and 607 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ jobs:
fail-fast: false
matrix:
build_type: [Release, Debug]
llvm_version: [17, 18, 19]
llvm_version: [17, 18, 19, 20]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -375,7 +375,7 @@ jobs:
fail-fast: false
matrix:
build_type: [Release, Debug]
llvm_version: [17, 18, 19]
llvm_version: [17, 18, 19, 20]
steps:
- uses: actions/checkout@v4
- name: Install common deps
Expand Down Expand Up @@ -496,7 +496,7 @@ jobs:
matrix:
ubuntu_version: [20.04, 22.04]
build_type: [Release, Debug]
llvm_version: [17, 18, 19]
llvm_version: [17, 18, 19, 20]

steps:
- uses: actions/checkout@v4
Expand Down
8 changes: 4 additions & 4 deletions lib/std/io/formatter.c3
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ fn usz! Formatter.out_str(&self, any arg) @private
case FUNC:
return self.out_substr("<function>");
case DISTINCT:
if (arg.type == String.typeid)
{
return self.out_substr(*(String*)arg);
}
if (arg.type == ZString.typeid)
{
return self.out_substr(*(ZString*)arg ? ((ZString*)arg).str_view() : "(null)");
Expand Down Expand Up @@ -255,10 +259,6 @@ fn usz! Formatter.out_str(&self, any arg) @private
case SLICE:
// this is SomeType[] so grab the "SomeType"
typeid inner = arg.type.inner;
if (inner == char.typeid)
{
return self.out_substr(*(String*)arg);
}
if (inner == void.typeid) inner = char.typeid;
PrintFlags flags = self.flags;
uint width = self.width;
Expand Down
12 changes: 12 additions & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# C3C Release Notes

## 0.6.4 Change list

### Changes / improvements
- Const vector -> const slice implicit conversion.
- Slicing arrays, slices and bytes at compile time #1466.

### Fixes
- `Unsupported int[*] $x = { 1, 2, 3, 4 }` #1489.

### Stdlib changes
- Remove unintended print of `char[]` as String

## 0.6.3 Change list

### Changes / improvements
Expand Down
37 changes: 35 additions & 2 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ typedef struct
Decl *enum_err_val;
Type *typeid;
ConstInitializer *initializer;
ConstInitializer *slice_init;
Expr **untyped_list;
struct
{
Expand Down Expand Up @@ -2269,7 +2270,7 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr, CondResult *result

bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_optional, bool *no_match_ref,
bool as_binary);
ArrayIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size);

bool sema_analyse_expr(SemaContext *context, Expr *expr);
bool sema_cast_const(Expr *expr);

Expand Down Expand Up @@ -3206,10 +3207,11 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc);
bool const_init_local_init_may_be_global(ConstInitializer *init);
ConstInitializer *const_init_new_zero(Type *type);
ConstInitializer *const_init_new_value(Expr *value);
ConstInitializer *const_init_new_array(Type *type, ConstInitializer **elements);
ConstInitializer *const_init_new_array(Type *type, ConstInitializer **elements) UNUSED;
ConstInitializer *const_init_new_struct(Type *type, Expr **elements);
ConstInitializer *const_init_new_array_full(Type *type, ConstInitializer **elements);
ConstInitializer *const_init_new_zero_array_value(Type *type, ArrayIndex index);
ConstInitializer *const_init_new_array_value(Expr *expr, ArrayIndex index);
void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value);
void const_init_rewrite_to_zero(ConstInitializer *init, Type *type);

Expand Down Expand Up @@ -3521,6 +3523,15 @@ INLINE void expr_rewrite_const_null(Expr *expr, Type *type)
expr->resolve_status = RESOLVE_DONE;
}

INLINE void expr_rewrite_const_empty_slice(Expr *expr, Type *type)
{
assert(type_flatten(type)->type_kind == TYPE_SLICE);
expr->const_expr = (ExprConst) { .const_kind = CONST_SLICE, .initializer = NULL };
expr->expr_kind = EXPR_CONST;
expr->type = type;
expr->resolve_status = RESOLVE_DONE;
}

INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements)
{
expr->expr_kind = EXPR_CONST;
Expand All @@ -3531,13 +3542,24 @@ INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements)

INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer)
{
assert(type_flatten(type)->type_kind != TYPE_SLICE);
assert(type != type_untypedlist);
expr->expr_kind = EXPR_CONST;
expr->type = type;
expr->const_expr = (ExprConst) { .initializer = initializer, .const_kind = CONST_INITIALIZER };
expr->resolve_status = RESOLVE_DONE;
}

INLINE void expr_rewrite_const_slice(Expr *expr, Type *type, ConstInitializer *initializer)
{
assert(type_flatten(type)->type_kind == TYPE_SLICE);
assert(type != type_untypedlist);
expr->expr_kind = EXPR_CONST;
expr->type = type;
expr->const_expr = (ExprConst) { .slice_init = initializer, .const_kind = CONST_SLICE };
expr->resolve_status = RESOLVE_DONE;
}

INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type)
{
expr->expr_kind = EXPR_CONST;
Expand Down Expand Up @@ -3680,6 +3702,12 @@ INLINE unsigned arg_bits_max(AsmArgBits bits, unsigned limit)
return 0;
}

INLINE bool expr_is_empty_const_slice(Expr *expr)
{
return expr->expr_kind == EXPR_CONST
&& expr->const_expr.const_kind == CONST_SLICE
&& expr->const_expr.slice_init == NULL;
}

INLINE bool expr_is_const(Expr *expr)
{
Expand Down Expand Up @@ -3738,6 +3766,11 @@ INLINE bool expr_is_const_initializer(Expr *expr)
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_INITIALIZER;
}

INLINE bool expr_is_const_slice(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_SLICE;
}

INLINE bool expr_is_const_bytes(Expr *expr)
{
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_BYTES;
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/copying.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ INLINE ConstInitializer **copy_const_initializer_list(CopyStruct *c, ConstInitia

static inline void copy_const_initializer(CopyStruct *c, ConstInitializer **initializer_ref)
{
if (!*initializer_ref) return;
ConstInitializer *copy = MALLOCS(ConstInitializer);
*copy = **initializer_ref;
*initializer_ref = copy;
Expand Down Expand Up @@ -272,6 +273,9 @@ INLINE Expr *copy_const_expr(CopyStruct *c, Expr *expr)
case CONST_POINTER:
case CONST_TYPEID:
break;
case CONST_SLICE:
copy_const_initializer(c, &expr->const_expr.slice_init);
break;
case CONST_INITIALIZER:
copy_const_initializer(c, &expr->const_expr.initializer);
break;
Expand Down
1 change: 1 addition & 0 deletions src/compiler/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ typedef enum
CONST_STRING,
CONST_POINTER,
CONST_TYPEID,
CONST_SLICE,
CONST_INITIALIZER,
CONST_UNTYPED_LIST,
CONST_REF,
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,12 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
case TYPE_SLICE:
expr_rewrite_const_empty_slice(expr, type);
return;
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_BITSTRUCT:
case TYPE_SLICE:
case TYPE_VECTOR:
case TYPE_ARRAY:
expr_rewrite_const_initializer(expr, type, const_init_new_zero(type));
Expand Down
1 change: 1 addition & 0 deletions src/compiler/headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ static void header_gen_global_var(HeaderContext *c, Decl *decl, bool fn_globals,
case CONST_ERR:
PRINTF("%s\n", decl_get_extname(init->const_expr.enum_err_val));
return;
case CONST_SLICE:
case CONST_TYPEID:
case CONST_MEMBER:
case CONST_INITIALIZER:
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/llvm_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,13 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
switch (const_init->kind)
{
case CONST_INIT_ZERO:
assert(const_init->type->type_kind != TYPE_SLICE);
return llvm_get_zero(c, const_init->type);
case CONST_INIT_ARRAY_VALUE:
UNREACHABLE
case CONST_INIT_ARRAY_FULL:
{
assert(const_init->type->type_kind != TYPE_SLICE);
bool was_modified = false;
Type *array_type = const_init->type;
Type *element_type = array_type->array.base;
Expand Down Expand Up @@ -258,6 +260,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_

case CONST_INIT_ARRAY:
{
assert(const_init->type->type_kind != TYPE_SLICE);
bool was_modified = false;
Type *array_type = const_init->type;
Type *element_type = array_type->array.base;
Expand Down Expand Up @@ -492,6 +495,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
{
if (expr_is_const_initializer(init_expr))
{
assert(type_flatten(init_expr->type)->type_kind != TYPE_SLICE);
ConstInitializer *list = init_expr->const_expr.initializer;
init_value = llvm_emit_const_initializer(c, list);
}
Expand Down
53 changes: 44 additions & 9 deletions src/compiler/llvm_codegen_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,6 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
Type *to_type_original = to_type;
to_type = type_flatten(to_type);
from_type = type_flatten(from_type);

switch (cast_kind)
{
case CAST_BSBOOL:
Expand Down Expand Up @@ -1756,7 +1755,7 @@ static inline void llvm_emit_const_initialize_bitstruct_ref(GenContext *c, BEVal
llvm_store_raw(c, ref, llvm_emit_const_bitstruct(c, initializer));
}

static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializer *const_init)
static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializer *const_init, bool top)
{
if (const_init->type->type_kind == TYPE_VECTOR)
{
Expand All @@ -1778,7 +1777,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
// In case of small const initializers, or full arrays - use copy.
if (const_init->kind == CONST_INIT_ARRAY_FULL || type_size(const_init->type) <= 32)
{
if (const_init_local_init_may_be_global(const_init))
if (top && const_init_local_init_may_be_global(const_init))
{
llvm_emit_initialize_reference_temporary_const(c, ref, const_init);
return;
Expand Down Expand Up @@ -1814,7 +1813,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
LLVMValueRef array_pointer = llvm_emit_array_gep_raw(c, array_ref, array_type_llvm, (unsigned)i, ref->alignment, &alignment);
BEValue value;
llvm_value_set_address(&value, array_pointer, element_type, alignment);
llvm_emit_const_init_ref(c, &value, const_init->init_array_full[i]);
llvm_emit_const_init_ref(c, &value, const_init->init_array_full[i], false);
}
return;
}
Expand All @@ -1836,7 +1835,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
LLVMValueRef array_pointer = llvm_emit_array_gep_raw(c, array_ref, array_type_llvm, (unsigned)element_index, ref->alignment, &alignment);
BEValue value;
llvm_value_set_address(&value, array_pointer, element_type, alignment);
llvm_emit_const_init_ref(c, &value, element->init_array_value.element);
llvm_emit_const_init_ref(c, &value, element->init_array_value.element, false);
}
return;
}
Expand All @@ -1850,7 +1849,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
llvm_value_bitcast(c, &value, type);
// llvm_value_set_address_abi_aligned(&value, llvm_emit_bitcast_ptr(c, ref->value, type), type);
// Emit our value.
llvm_emit_const_init_ref(c, &value, const_init->init_union.element);
llvm_emit_const_init_ref(c, &value, const_init->init_union.element, false);
return;
}
case CONST_INIT_STRUCT:
Expand All @@ -1861,7 +1860,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
{
BEValue value;
llvm_value_struct_gep(c, &value, ref, (unsigned)i);
llvm_emit_const_init_ref(c, &value, init);
llvm_emit_const_init_ref(c, &value, init, false);
}
return;
}
Expand Down Expand Up @@ -1941,6 +1940,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r
{
Type *type = type_flatten(expr->type);
Expr **elements = expr->initializer_list;
assert(type->type_kind != TYPE_SLICE);

if (type->type_kind == TYPE_BITSTRUCT)
{
Expand Down Expand Up @@ -2169,8 +2169,8 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
{
Expr **elements = expr->designated_init_list;
assert(vec_size(elements));

Type *type = type_flatten(expr->type);
assert(type->type_kind != TYPE_SLICE);
if (type->type_kind == TYPE_BITSTRUCT)
{
llvm_emit_initialize_reference_designated_bitstruct(c, ref, type->decl, elements);
Expand Down Expand Up @@ -2339,7 +2339,8 @@ LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initiali
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr)
{
assert(expr_is_const_initializer(expr));
llvm_emit_const_init_ref(c, ref, expr->const_expr.initializer);
assert(type_flatten(expr->type)->type_kind != TYPE_SLICE);
llvm_emit_const_init_ref(c, ref, expr->const_expr.initializer, true);
return;
}

Expand Down Expand Up @@ -4992,6 +4993,7 @@ static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue
{
if (llvm_is_global_eval(c) || type_flat_is_vector(expr->type) || type_flatten(expr->type)->type_kind == TYPE_BITSTRUCT)
{
assert(type_flatten(expr->type)->type_kind != TYPE_SLICE);
llvm_value_set(value, llvm_emit_const_initializer(c, expr->const_expr.initializer), expr->type);
return;
}
Expand Down Expand Up @@ -5038,6 +5040,39 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
case CONST_FLOAT:
llvm_value_set(be_value, llvm_emit_real(llvm_get_type(c, type), expr->const_expr.fxx), type);
return;
case CONST_SLICE:
if (!expr->const_expr.slice_init)
{
llvm_value_set(be_value, llvm_get_zero(c, type), type);
return;
}
else
{
ConstInitializer *init = expr->const_expr.slice_init;
if (llvm_is_global_eval(c) || type_flat_is_vector(expr->type) || type_flatten(expr->type)->type_kind == TYPE_BITSTRUCT)
{
LLVMValueRef value = llvm_emit_const_initializer(c, init);
AlignSize alignment = type_alloca_alignment(init->type);
LLVMTypeRef val_type = llvm_get_type(c, init->type);
LLVMValueRef global_copy = llvm_add_global_raw(c, ".__const_slice", val_type, alignment);
LLVMSetInitializer(global_copy, value);
llvm_set_private_linkage(global_copy);
LLVMSetUnnamedAddress(global_copy, LLVMGlobalUnnamedAddr);
assert(type_is_arraylike(init->type));
LLVMValueRef val = llvm_emit_aggregate_two(c, type, global_copy,
llvm_const_int(c, type_usz, init->type->array.len));
llvm_value_set(be_value, val, type);
}
else
{
assert(type_is_arraylike(init->type));
llvm_value_set_address_abi_aligned(be_value, llvm_emit_alloca_aligned(c, init->type, "literal"), init->type);
llvm_emit_const_init_ref(c, be_value, init, true);
LLVMValueRef val = llvm_emit_aggregate_two(c, type, be_value->value, llvm_const_int(c, type_usz, init->type->array.len));
llvm_value_set(be_value, val, type);
}
}
return;
case CONST_POINTER:
if (!expr->const_expr.ptr)
{
Expand Down
Loading

0 comments on commit 02e9bfa

Please sign in to comment.