An initial printf. Added type.inner and type.len. Bump to 0.2.15

This commit is contained in:
Christoffer Lerno
2022-07-14 02:16:51 +02:00
committed by Christoffer Lerno
parent 28a8e17690
commit 3f6b0646b3
11 changed files with 1000 additions and 375 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.2.14"
#define COMPILER_VERSION "0.2.15"

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