mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
An initial printf. Added type.inner and type.len. Bump to 0.2.15
This commit is contained in:
committed by
Christoffer Lerno
parent
28a8e17690
commit
3f6b0646b3
1107
lib/std/io_printf.c3
1107
lib/std/io_printf.c3
File diff suppressed because it is too large
Load Diff
@@ -228,7 +228,6 @@ bool expr_is_pure(Expr *expr)
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_BUILTIN:
|
||||
case EXPR_TYPEID_KIND:
|
||||
return false;
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_CONST:
|
||||
@@ -294,6 +293,8 @@ bool expr_is_pure(Expr *expr)
|
||||
if (!expr_is_pure(expr->expression_list[i])) return false;
|
||||
}
|
||||
return true;
|
||||
case EXPR_TYPEID_INFO:
|
||||
return exprid_is_pure(expr->typeid_info_expr.parent);
|
||||
case EXPR_TYPEOFANY:
|
||||
case EXPR_CT_EVAL:
|
||||
return expr_is_pure(expr->inner_expr);
|
||||
@@ -329,7 +330,7 @@ bool expr_is_simple(Expr *expr)
|
||||
expr = expr->inner_expr;
|
||||
goto RETRY;
|
||||
case EXPR_TERNARY:
|
||||
return false;
|
||||
return expr_is_simple(exprptr(expr->ternary_expr.else_expr)) && expr_is_simple(exprptr(expr->ternary_expr.then_expr));
|
||||
case EXPR_RETHROW:
|
||||
expr = expr->rethrow_expr.inner;
|
||||
goto RETRY;
|
||||
|
||||
@@ -909,6 +909,12 @@ typedef struct
|
||||
};
|
||||
} ExprVariantSwitch;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ExprId parent;
|
||||
TypeIdInfoKind kind;
|
||||
} ExprTypeidInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Decl *argc;
|
||||
@@ -922,6 +928,7 @@ struct Expr_
|
||||
ExprKind expr_kind : 8;
|
||||
ResolveStatus resolve_status : 4;
|
||||
union {
|
||||
ExprTypeidInfo typeid_info_expr;
|
||||
ExprVariantSwitch variant_switch; // 32
|
||||
ExprLen len_expr; // 8
|
||||
ExprCast cast_expr; // 12
|
||||
@@ -1593,6 +1600,7 @@ extern const char *kw_distinct;
|
||||
extern const char *kw_inline;
|
||||
extern const char *kw_inf;
|
||||
extern const char *kw_kind;
|
||||
extern const char *kw_inner;
|
||||
extern const char *kw_elementat;
|
||||
extern const char *kw_elementref;
|
||||
extern const char *kw_elementset;
|
||||
|
||||
@@ -241,9 +241,11 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
||||
case EXPR_PTR:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_TYPEID_KIND:
|
||||
MACRO_COPY_EXPR(expr->inner_expr);
|
||||
return expr;
|
||||
case EXPR_TYPEID_INFO:
|
||||
MACRO_COPY_EXPRID(expr->typeid_info_expr.parent);
|
||||
return expr;
|
||||
case EXPR_COND:
|
||||
MACRO_COPY_EXPR_LIST(expr->cond_expr);
|
||||
return expr;
|
||||
|
||||
@@ -247,9 +247,18 @@ typedef enum
|
||||
EXPR_UNARY,
|
||||
EXPR_VARIANTSWITCH,
|
||||
EXPR_NOP,
|
||||
EXPR_TYPEID_KIND,
|
||||
EXPR_TYPEID_INFO,
|
||||
} ExprKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TYPEID_INFO_KIND,
|
||||
TYPEID_INFO_MIN,
|
||||
TYPEID_INFO_MAX,
|
||||
TYPEID_INFO_INNER,
|
||||
TYPEID_INFO_LEN,
|
||||
} TypeIdInfoKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONST_FLOAT,
|
||||
|
||||
@@ -5296,13 +5296,85 @@ static inline void llvm_emit_ptr(GenContext *c, BEValue *value, Expr *expr)
|
||||
llvm_emit_subarray_pointer(c, value, value);
|
||||
}
|
||||
|
||||
static inline void llvm_emit_typeid_kind(GenContext *c, BEValue *value, Expr *expr)
|
||||
static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_emit_expr(c, value, expr->inner_expr);
|
||||
llvm_emit_exprid(c, value, expr->typeid_info_expr.parent);
|
||||
llvm_value_rvalue(c, value);
|
||||
LLVMValueRef ref = LLVMBuildIntToPtr(c->builder, value->value, llvm_get_ptr_type(c, type_char), "");
|
||||
LLVMValueRef kind = llvm_load(c, c->byte_type, ref, 1, "");
|
||||
llvm_value_set(value, kind, expr->type);
|
||||
|
||||
LLVMValueRef kind;
|
||||
if (active_target.feature.safe_mode || expr->typeid_info_expr.kind == TYPEID_INFO_KIND)
|
||||
{
|
||||
LLVMValueRef ref = LLVMBuildIntToPtr(c->builder, value->value, llvm_get_ptr_type(c, type_char), "");
|
||||
kind = llvm_load(c, c->byte_type, ref, 1, "");
|
||||
}
|
||||
switch (expr->typeid_info_expr.kind)
|
||||
{
|
||||
case TYPEID_INFO_KIND:
|
||||
llvm_value_set(value, kind, expr->type);
|
||||
return;
|
||||
case TYPEID_INFO_INNER:
|
||||
if (active_target.feature.safe_mode)
|
||||
{
|
||||
BEValue check;
|
||||
LLVMBasicBlockRef exit = llvm_basic_block_new(c, "check_type_ok");
|
||||
IntrospectType checks[7] = { INTROSPECT_TYPE_ARRAY, INTROSPECT_TYPE_POINTER,
|
||||
INTROSPECT_TYPE_VECTOR,
|
||||
INTROSPECT_TYPE_SUBARRAY, INTROSPECT_TYPE_DISTINCT,
|
||||
INTROSPECT_TYPE_FAILABLE, INTROSPECT_TYPE_SUBARRAY };
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
llvm_emit_int_comp(c, &check, type_char, type_char, kind, llvm_const_int(c, type_char, checks[i]), BINARYOP_EQ);
|
||||
LLVMBasicBlockRef next = llvm_basic_block_new(c, "check_next");
|
||||
llvm_emit_cond_br(c, &check, exit, next);
|
||||
llvm_emit_block(c, next);
|
||||
}
|
||||
File *file = source_file_by_id(expr->span.file_id);
|
||||
llvm_emit_panic(c, "Attempted to access 'inner' on non composite type", file->name, c->cur_func_decl->name, expr->span.row);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_block(c, exit);
|
||||
}
|
||||
{
|
||||
LLVMTypeRef typeid = llvm_get_type(c, type_typeid);
|
||||
LLVMValueRef ref = LLVMBuildIntToPtr(c->builder, value->value, llvm_get_ptr_type(c, type_typeid), "");
|
||||
LLVMValueRef val = llvm_emit_pointer_gep_raw(c, typeid, ref, llvm_const_int(c, type_usize, 1));
|
||||
val = llvm_load(c, typeid, val, type_abi_alignment(type_typeid), "");
|
||||
llvm_value_set(value, val, expr->type);
|
||||
}
|
||||
break;
|
||||
case TYPEID_INFO_LEN:
|
||||
if (active_target.feature.safe_mode)
|
||||
{
|
||||
BEValue check;
|
||||
LLVMBasicBlockRef exit = llvm_basic_block_new(c, "check_type_ok");
|
||||
IntrospectType checks[3] = { INTROSPECT_TYPE_ARRAY, INTROSPECT_TYPE_VECTOR,
|
||||
INTROSPECT_TYPE_SUBARRAY };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
llvm_emit_int_comp(c, &check, type_char, type_char, kind, llvm_const_int(c, type_char, checks[i]), BINARYOP_EQ);
|
||||
LLVMBasicBlockRef next = llvm_basic_block_new(c, "check_next");
|
||||
llvm_emit_cond_br(c, &check, exit, next);
|
||||
llvm_emit_block(c, next);
|
||||
}
|
||||
File *file = source_file_by_id(expr->span.file_id);
|
||||
llvm_emit_panic(c, "Attempted to access 'len' on non array type", file->name, c->cur_func_decl->name, expr->span.row);
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
LLVMBuildUnreachable(c->builder);
|
||||
llvm_emit_block(c, exit);
|
||||
}
|
||||
{
|
||||
LLVMTypeRef typeid = llvm_get_type(c, type_usize);
|
||||
LLVMValueRef ref = LLVMBuildIntToPtr(c->builder, value->value, llvm_get_ptr_type(c, type_usize), "");
|
||||
LLVMValueRef val = llvm_emit_pointer_gep_raw(c, typeid, ref, llvm_const_int(c, type_usize, 2));
|
||||
val = llvm_load(c, typeid, val, type_abi_alignment(type_usize), "");
|
||||
llvm_value_set(value, val, expr->type);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
void llvm_emit_try_unwrap_chain(GenContext *c, BEValue *value, Expr *expr)
|
||||
@@ -5463,8 +5535,8 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_PTR:
|
||||
llvm_emit_ptr(c, value, expr);
|
||||
return;
|
||||
case EXPR_TYPEID_KIND:
|
||||
llvm_emit_typeid_kind(c, value, expr);
|
||||
case EXPR_TYPEID_INFO:
|
||||
llvm_emit_typeid_info(c, value, expr);
|
||||
return;
|
||||
case EXPR_BUILTIN:
|
||||
UNREACHABLE;
|
||||
|
||||
@@ -780,6 +780,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_RETVAL:
|
||||
case EXPR_TYPEID_INFO:
|
||||
if (type_size(expr->type) > type_size(type)) return expr;
|
||||
return NULL;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
@@ -835,7 +836,6 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_TYPEID_KIND:
|
||||
UNREACHABLE
|
||||
case EXPR_POST_UNARY:
|
||||
return recursive_may_narrow_float(expr->unary_expr.expr, type);
|
||||
@@ -935,6 +935,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_RETVAL:
|
||||
case EXPR_TYPEID_INFO:
|
||||
if (type_size(expr->type) > type_size(type)) return expr;
|
||||
return NULL;
|
||||
case EXPR_LEN:
|
||||
@@ -988,7 +989,6 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_TYPEID_KIND:
|
||||
UNREACHABLE
|
||||
case EXPR_POST_UNARY:
|
||||
return recursive_may_narrow_int(expr->unary_expr.expr, type);
|
||||
|
||||
@@ -370,9 +370,11 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
|
||||
}
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
return expr_list_is_constant_eval(expr->expression_list, eval_kind);
|
||||
case EXPR_TYPEID_INFO:
|
||||
expr = exprptr(expr->typeid_info_expr.parent);
|
||||
goto RETRY;
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_GROUP:
|
||||
case EXPR_TYPEID_KIND:
|
||||
expr = expr->inner_expr;
|
||||
goto RETRY;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
@@ -591,7 +593,11 @@ bool sema_expr_check_assign(SemaContext *c, Expr *expr)
|
||||
SEMA_ERROR(expr, "An assignable expression, like a variable, was expected here.");
|
||||
return false;
|
||||
}
|
||||
if (expr->expr_kind == EXPR_IDENTIFIER) expr->identifier_expr.decl->var.is_written = true;
|
||||
if (expr->expr_kind == EXPR_BITACCESS || expr->expr_kind == EXPR_ACCESS) expr = expr->access_expr.parent;
|
||||
if (expr->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
expr->identifier_expr.decl->var.is_written = true;
|
||||
}
|
||||
if (expr->expr_kind != EXPR_UNARY) return true;
|
||||
Expr *inner = expr->inner_expr;
|
||||
if (inner->expr_kind != EXPR_IDENTIFIER) return true;
|
||||
@@ -3283,6 +3289,92 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sema_rewrite_typeid_kind(Expr *expr, Expr *parent, Expr *current_parent)
|
||||
{
|
||||
Module *module = global_context_find_module(kw_std__core__types);
|
||||
Decl *type_kind = module ? module_find_symbol(module, kw_typekind) : NULL;
|
||||
Type *type_for_kind = type_kind ? type_kind->type : type_char;
|
||||
if (current_parent->expr_kind == EXPR_CONST)
|
||||
{
|
||||
unsigned val = type_get_introspection_kind(current_parent->const_expr.typeid->type_kind);
|
||||
expr_rewrite_to_int_const(expr, type_for_kind, val, false);
|
||||
return;
|
||||
}
|
||||
expr->expr_kind = EXPR_TYPEID_INFO;
|
||||
expr->typeid_info_expr.parent = exprid(parent);
|
||||
expr->typeid_info_expr.kind = TYPEID_INFO_KIND;
|
||||
expr->type = type_for_kind;
|
||||
}
|
||||
|
||||
static inline bool sema_rewrite_typeid_inner(Expr *expr, Expr *parent, Expr *current_parent)
|
||||
{
|
||||
if (current_parent->expr_kind == EXPR_CONST)
|
||||
{
|
||||
Type *type = type_flatten_distinct(current_parent->const_expr.typeid);
|
||||
Type *inner = NULL;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
inner = type->pointer;
|
||||
break;
|
||||
case TYPE_FAILABLE:
|
||||
inner = type->failable;
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
inner = type->array.base;
|
||||
break;
|
||||
default:
|
||||
inner = NULL;
|
||||
break;
|
||||
}
|
||||
if (!inner)
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot access 'inner' of non pointer/array type %s.", type_quoted_error_string(current_parent->const_expr.typeid));
|
||||
return false;
|
||||
}
|
||||
expr_replace(expr, current_parent);
|
||||
expr->const_expr.typeid = inner;
|
||||
return true;
|
||||
}
|
||||
expr->expr_kind = EXPR_TYPEID_INFO;
|
||||
expr->typeid_info_expr.parent = exprid(parent);
|
||||
expr->typeid_info_expr.kind = TYPEID_INFO_INNER;
|
||||
expr->type = type_typeid;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_rewrite_typeid_len(Expr *expr, Expr *parent, Expr *current_parent)
|
||||
{
|
||||
if (current_parent->expr_kind == EXPR_CONST)
|
||||
{
|
||||
Type *type = type_flatten_distinct(current_parent->const_expr.typeid);
|
||||
size_t len;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
len = type->array.len;
|
||||
default:
|
||||
SEMA_ERROR(expr, "Cannot access 'len' of non array/vector type %s.", type_quoted_error_string(current_parent->const_expr.typeid));
|
||||
return false;
|
||||
}
|
||||
expr_rewrite_to_int_const(expr, type_usize, len, true);
|
||||
return true;
|
||||
}
|
||||
expr->expr_kind = EXPR_TYPEID_INFO;
|
||||
expr->typeid_info_expr.parent = exprid(parent);
|
||||
expr->typeid_info_expr.kind = TYPEID_INFO_LEN;
|
||||
expr->type = type_usize;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyse "x.y"
|
||||
*/
|
||||
@@ -3380,23 +3472,23 @@ CHECK_DEEPER:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (kw == kw_kind && flat_type->type_kind == TYPE_TYPEID)
|
||||
if (flat_type->type_kind == TYPE_TYPEID)
|
||||
{
|
||||
Module *module = global_context_find_module(kw_std__core__types);
|
||||
Decl *type_kind = module ? module_find_symbol(module, kw_typekind) : NULL;
|
||||
Type *type_for_kind = type_kind ? type_kind->type : type_char;
|
||||
if (current_parent->expr_kind == EXPR_CONST)
|
||||
if (kw == kw_kind)
|
||||
{
|
||||
unsigned val = type_get_introspection_kind(current_parent->const_expr.typeid->type_kind);
|
||||
expr_rewrite_to_int_const(expr, type_for_kind, val, false);
|
||||
sema_rewrite_typeid_kind(expr, parent, current_parent);
|
||||
return true;
|
||||
}
|
||||
expr->expr_kind = EXPR_TYPEID_KIND;
|
||||
expr->inner_expr = parent;
|
||||
expr->type = type_for_kind;
|
||||
return true;
|
||||
if (kw == kw_inner)
|
||||
{
|
||||
return sema_rewrite_typeid_inner(expr, parent, current_parent);
|
||||
}
|
||||
if (kw == kw_len)
|
||||
{
|
||||
return sema_rewrite_typeid_len(expr, parent, current_parent);
|
||||
}
|
||||
}
|
||||
|
||||
// Hard coded ptr on subarrays and variant
|
||||
if (kw == kw_ptr)
|
||||
{
|
||||
@@ -7036,7 +7128,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
|
||||
case EXPR_CATCH_UNWRAP:
|
||||
case EXPR_PTR:
|
||||
case EXPR_VARIANTSWITCH:
|
||||
case EXPR_TYPEID_KIND:
|
||||
case EXPR_TYPEID_INFO:
|
||||
UNREACHABLE
|
||||
case EXPR_STRINGIFY:
|
||||
if (!sema_expr_analyse_ct_stringify(context, expr)) return false;
|
||||
|
||||
@@ -55,6 +55,7 @@ const char *kw_type;
|
||||
const char *kw_inf;
|
||||
const char *kw_inline;
|
||||
const char *kw_kind;
|
||||
const char *kw_inner;
|
||||
const char *kw_elementat;
|
||||
const char *kw_elementref;
|
||||
const char *kw_elementset;
|
||||
@@ -160,6 +161,7 @@ void symtab_init(uint32_t capacity)
|
||||
kw_noinline = KW_DEF("noinline");
|
||||
kw_ordinal = KW_DEF("ordinal");
|
||||
kw_ptr = KW_DEF("ptr");
|
||||
kw_inner = KW_DEF("inner");
|
||||
kw_pure = KW_DEF("pure");
|
||||
kw_std = KW_DEF("std");
|
||||
kw_values = KW_DEF("values");
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.2.14"
|
||||
#define COMPILER_VERSION "0.2.15"
|
||||
24
test/test_suite2/bitstruct/param_bitstruct.c3t
Normal file
24
test/test_suite2/bitstruct/param_bitstruct.c3t
Normal file
@@ -0,0 +1,24 @@
|
||||
// #target: macos-x64
|
||||
module foo;
|
||||
|
||||
bitstruct Abc : uint
|
||||
{
|
||||
bool x : 0;
|
||||
}
|
||||
|
||||
fn void test(Abc x)
|
||||
{
|
||||
x.x = false;
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
define void @foo.test(i32 %0) #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
store i32 %0, ptr %x, align 4
|
||||
%1 = load i32, ptr %x, align 4
|
||||
%2 = and i32 %1, -2
|
||||
store i32 %2, ptr %x, align 4
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user