mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Updated casts (#684)
Cast code rework. Remove llvm_set_bool and friends.
This commit is contained in:
committed by
GitHub
parent
e2b4a19c81
commit
f46697bc54
@@ -961,7 +961,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
CastKind kind : 8;
|
||||
bool implicit : 1;
|
||||
ExprId expr;
|
||||
TypeInfoId type_info;
|
||||
} ExprCast;
|
||||
@@ -2027,10 +2026,14 @@ INLINE AsmRegister *asm_reg_by_index(unsigned index);
|
||||
|
||||
AsmRegister *asm_reg_by_index(unsigned index);
|
||||
|
||||
bool cast_implicit_silent(SemaContext *context, Expr *expr, Type *to_type);
|
||||
bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
bool cast_implicit_maybe_failable(SemaContext *context, Expr *expr, Type *to_type, bool may_be_failable);
|
||||
bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
|
||||
bool cast(Expr *expr, Type *to_type);
|
||||
bool cast_may_implicit(Type *from_type, Type *to_type, CastOption option);
|
||||
bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability, bool is_const);
|
||||
bool cast_may_bool_convert(Type *type);
|
||||
|
||||
Type *cast_infer_len(Type *to_infer, Type *actual_type);
|
||||
bool cast_to_index(Expr *index);
|
||||
|
||||
@@ -2312,6 +2315,9 @@ bool type_flat_is_boolintlike(Type *type);
|
||||
bool type_flat_is_numlike(Type *type);
|
||||
bool type_may_have_sub_elements(Type *type);
|
||||
bool type_may_have_method(Type *type);
|
||||
|
||||
bool type_is_pointer_equivalent(Type *pointer1, Type *pointer2, bool flatten_distinct);
|
||||
bool type_array_element_is_equivalent(Type *element1, Type *element2, bool is_explicit);
|
||||
const char *type_to_error_string(Type *type);
|
||||
const char *type_quoted_error_string(Type *type);
|
||||
INLINE bool type_may_negate(Type *type);
|
||||
@@ -3214,6 +3220,11 @@ INLINE bool expr_is_const_string(Expr *expr)
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_STRING;
|
||||
}
|
||||
|
||||
INLINE bool expr_is_const_pointer(Expr *expr)
|
||||
{
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_POINTER;
|
||||
}
|
||||
|
||||
INLINE bool expr_is_const_initializer(Expr *expr)
|
||||
{
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_INITIALIZER;
|
||||
|
||||
@@ -125,9 +125,14 @@ typedef enum
|
||||
{
|
||||
CAST_OPTION_NONE = 0x00,
|
||||
CAST_OPTION_SIMPLE_EXPR = 0x01,
|
||||
CAST_OPTION_ALLOW_OPTIONAL = 0x02,
|
||||
|
||||
} CastOption;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAST_TYPE_NO_ERROR_REPORT = 0x08,
|
||||
CAST_TYPE_NO_OPTIONAL = 0x02,
|
||||
} CastType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -774,22 +774,6 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
||||
}
|
||||
|
||||
|
||||
void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value)
|
||||
{
|
||||
value->value = llvm_value;
|
||||
value->alignment = type_abi_alignment(type_bool);
|
||||
value->kind = BE_BOOLEAN;
|
||||
value->type = type_bool;
|
||||
}
|
||||
|
||||
void llvm_value_set_bool_vector(BEValue *value, LLVMValueRef llvm_value, Type *type)
|
||||
{
|
||||
value->value = llvm_value;
|
||||
value->alignment = type_abi_alignment(type);
|
||||
value->kind = BE_BOOLVECTOR;
|
||||
value->type = type;
|
||||
}
|
||||
|
||||
void llvm_value_set_int(GenContext *c, BEValue *value, Type *type, uint64_t i)
|
||||
{
|
||||
llvm_value_set(value, llvm_const_int(c, type, i), type);
|
||||
|
||||
@@ -384,7 +384,7 @@ static void llvm_emit_overflow_builtin(GenContext *c, BEValue *be_value, Expr *e
|
||||
LLVMValueRef failed = llvm_emit_extract_value(c, result, 1);
|
||||
LLVMValueRef value = llvm_emit_extract_value(c, result, 0);
|
||||
llvm_store_raw(c, &ref, value);
|
||||
llvm_value_set_bool(be_value, failed);
|
||||
llvm_value_set(be_value, failed, type_bool);
|
||||
}
|
||||
|
||||
static void llvm_emit_wrap_builtin(GenContext *c, BEValue *result_value, Expr *expr, BuiltinFunction func)
|
||||
@@ -508,7 +508,7 @@ static void llvm_emit_veccomp(GenContext *c, BEValue *value, Expr *expr, Builtin
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
llvm_value_set_bool_vector(value, res, expr->type);
|
||||
llvm_value_set(value, res, expr->type);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ static void llvm_convert_vector_comparison(GenContext *c, BEValue *be_value, LLV
|
||||
}
|
||||
unsigned intrinsic = is_equals ? intrinsic_id.vector_reduce_and : intrinsic_id.vector_reduce_or;
|
||||
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic, &llvm_type, 1, &val, 1);
|
||||
llvm_value_set_bool(be_value, result);
|
||||
llvm_value_set(be_value, result, type_bool);
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_emit_coerce_alignment(GenContext *c, BEValue *be_value, LLVMTypeRef coerce_type, AlignSize target_alignment, AlignSize *resulting_alignment)
|
||||
@@ -776,7 +776,7 @@ static inline void llvm_extract_bool_bit_from_array(GenContext *c, BEValue *be_v
|
||||
// Truncate to i1.
|
||||
element = LLVMBuildTrunc(c->builder, element, c->bool_type, "");
|
||||
// Done!
|
||||
llvm_value_set_bool(be_value, element);
|
||||
llvm_value_set(be_value, element, type_bool);
|
||||
}
|
||||
|
||||
static inline LLVMValueRef llvm_bswap_non_integral(GenContext *c, LLVMValueRef value, unsigned bitsize)
|
||||
@@ -2383,7 +2383,7 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
DEBUG_LOG("Unexpectedly tried to not %s", type_quoted_error_string(inner->type));
|
||||
UNREACHABLE
|
||||
}
|
||||
llvm_value_set_bool(value, llvm_value);
|
||||
llvm_value_set(value, llvm_value, type_bool);
|
||||
return;
|
||||
case UNARYOP_BITNEG:
|
||||
llvm_emit_expr(c, value, inner);
|
||||
@@ -2897,7 +2897,7 @@ static void llvm_emit_logical_and_or(GenContext *c, BEValue *be_value, Expr *exp
|
||||
if (!lhs_end_block)
|
||||
{
|
||||
// Just set any value.
|
||||
llvm_value_set_bool(be_value, result_on_skip);
|
||||
llvm_value_set(be_value, result_on_skip, type_bool);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2932,7 +2932,7 @@ static void llvm_emit_logical_and_or(GenContext *c, BEValue *be_value, Expr *exp
|
||||
// One possibility here is that a return happens inside of the expression.
|
||||
if (!rhs_end_block)
|
||||
{
|
||||
llvm_value_set_bool(be_value, result_on_skip);
|
||||
llvm_value_set(be_value, result_on_skip, type_bool);
|
||||
return;
|
||||
}
|
||||
LLVMValueRef phi = LLVMBuildPhi(c->builder, c->bool_type, "val");
|
||||
@@ -2940,7 +2940,7 @@ static void llvm_emit_logical_and_or(GenContext *c, BEValue *be_value, Expr *exp
|
||||
LLVMBasicBlockRef blocks[2] = { lhs_end_block, rhs_end_block };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
|
||||
llvm_value_set_bool(be_value, phi);
|
||||
llvm_value_set(be_value, phi, type_bool);
|
||||
}
|
||||
|
||||
void llvm_emit_int_comp_zero(GenContext *c, BEValue *result, BEValue *lhs, BinaryOp binary_op)
|
||||
@@ -3060,7 +3060,7 @@ void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type
|
||||
llvm_convert_vector_comparison(c, result, value, lhs_type, binary_op == BINARYOP_EQ);
|
||||
return;
|
||||
}
|
||||
llvm_value_set_bool(result, value);
|
||||
llvm_value_set(result, value, type_bool);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3101,7 +3101,7 @@ void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type
|
||||
llvm_convert_vector_comparison(c, result, comp_value, lhs_type, binary_op == BINARYOP_EQ);
|
||||
return;
|
||||
}
|
||||
llvm_value_set_bool(result, comp_value);
|
||||
llvm_value_set(result, comp_value, type_bool);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3147,7 +3147,7 @@ void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type
|
||||
llvm_convert_vector_comparison(c, result, comp_value, lhs_type, BINARYOP_EQ == binary_op);
|
||||
return;
|
||||
}
|
||||
llvm_value_set_bool(result, comp_value);
|
||||
llvm_value_set(result, comp_value, type_bool);
|
||||
}
|
||||
|
||||
static void llvm_emit_ptr_comparison(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
|
||||
@@ -3180,7 +3180,7 @@ static void llvm_emit_ptr_comparison(GenContext *c, BEValue *result, BEValue *lh
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
llvm_value_set_bool(result, val);
|
||||
llvm_value_set(result, val, type_bool);
|
||||
}
|
||||
|
||||
static inline LLVMValueRef llvm_emit_mult_int(GenContext *c, Type *type, LLVMValueRef left, LLVMValueRef right, SourceSpan loc)
|
||||
@@ -3282,9 +3282,13 @@ static void llvm_emit_subarray_comp(GenContext *c, BEValue *be_value, BEValue *l
|
||||
LLVMBasicBlockRef blocks[3] = { all_match_block, no_match_block, match_fail_block };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 3);
|
||||
|
||||
llvm_value_set_bool(be_value, phi);
|
||||
llvm_value_set(be_value, phi, type_bool);
|
||||
|
||||
}
|
||||
|
||||
static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
static void llvm_emit_float_comp(GenContext *c, BEValue *be_value, BEValue *lhs, BEValue *rhs, BinaryOp binary_op, Type *vector_type)
|
||||
@@ -3324,7 +3328,7 @@ static void llvm_emit_float_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
llvm_convert_vector_comparison(c, be_value, val, vector_type, BINARYOP_EQ == binary_op);
|
||||
return;
|
||||
}
|
||||
llvm_value_set_bool(be_value, val);
|
||||
llvm_value_set(be_value, val, type_bool);
|
||||
}
|
||||
|
||||
void llvm_emit_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
|
||||
@@ -3365,6 +3369,11 @@ void llvm_emit_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs,
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (lhs->type->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
llvm_emit_array_comp(c, result, lhs, rhs, binary_op);
|
||||
return;
|
||||
}
|
||||
TODO
|
||||
}
|
||||
|
||||
@@ -3432,7 +3441,7 @@ static void llvm_emit_else(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
LLVMValueRef phi = LLVMBuildPhi(c->builder, c->bool_type, "val");
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
llvm_value_set_bool(be_value, phi);
|
||||
llvm_value_set(be_value, phi, type_bool);
|
||||
return;
|
||||
}
|
||||
LLVMValueRef phi = LLVMBuildPhi(c->builder, llvm_get_type(c, expr->type), "val");
|
||||
@@ -3703,16 +3712,6 @@ void llvm_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValue *lhs
|
||||
UNREACHABLE
|
||||
}
|
||||
assert(val);
|
||||
if (lhs.type == type_bool)
|
||||
{
|
||||
llvm_value_set_bool(be_value, val);
|
||||
return;
|
||||
}
|
||||
if (lhs.kind == BE_BOOLVECTOR)
|
||||
{
|
||||
llvm_value_set_bool_vector(be_value, val, expr->type);
|
||||
return;
|
||||
}
|
||||
llvm_value_set(be_value, val, expr->type);
|
||||
}
|
||||
|
||||
@@ -3787,7 +3786,7 @@ void llvm_emit_try_assign_try_catch(GenContext *c, bool is_try, BEValue *be_valu
|
||||
LLVMBasicBlockRef blocks[2] = { success_block, catch_block };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
|
||||
llvm_value_set_bool(be_value, phi);
|
||||
llvm_value_set(be_value, phi, type_bool);
|
||||
|
||||
}
|
||||
|
||||
@@ -4078,14 +4077,7 @@ static inline void llvm_emit_elvis_expr(GenContext *c, BEValue *value, Expr *exp
|
||||
llvm_emit_expr(c, &right, else_expr);
|
||||
llvm_value_rvalue(c, &right);
|
||||
LLVMValueRef val = LLVMBuildSelect(c->builder, value->value, lhs, right.value, "elvis");
|
||||
if (right.type == type_bool)
|
||||
{
|
||||
llvm_value_set_bool(value, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_value_set(value, val, right.type);
|
||||
}
|
||||
llvm_value_set(value, val, right.type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4176,14 +4168,7 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
llvm_emit_expr(c, &right, else_expr);
|
||||
llvm_value_rvalue(c, &right);
|
||||
LLVMValueRef val = LLVMBuildSelect(c->builder, value->value, lhs_value, right.value, "ternary");
|
||||
if (right.type == type_bool)
|
||||
{
|
||||
llvm_value_set_bool(value, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
llvm_value_set(value, val, right.type);
|
||||
}
|
||||
llvm_value_set(value, val, right.type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4228,24 +4213,14 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
if (!rhs_exit)
|
||||
{
|
||||
if (!lhs_value) lhs_value = LLVMGetUndef(llvm_get_type(c, expr->type));
|
||||
if (LLVMTypeOf(lhs_value) == c->bool_type)
|
||||
{
|
||||
llvm_value_set_bool(value, lhs_value);
|
||||
return;
|
||||
}
|
||||
llvm_value_set(value, lhs_value, type_flatten(expr->type));
|
||||
llvm_value_set(value, lhs_value, expr->type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lhs_exit)
|
||||
{
|
||||
if (!rhs_value) rhs_value = LLVMGetUndef(llvm_get_type(c, expr->type));
|
||||
if (LLVMTypeOf(rhs_value) == c->bool_type)
|
||||
{
|
||||
llvm_value_set_bool(value, rhs_value);
|
||||
return;
|
||||
}
|
||||
llvm_value_set(value, rhs_value, type_flatten(expr->type));
|
||||
llvm_value_set(value, rhs_value, expr->type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4255,11 +4230,6 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
LLVMValueRef logic_values[2] = { lhs_value, rhs_value };
|
||||
LLVMBasicBlockRef blocks[2] = { lhs_exit, rhs_exit };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
if (expr_type == type_bool)
|
||||
{
|
||||
llvm_value_set_bool(value, phi);
|
||||
return;
|
||||
}
|
||||
llvm_value_set(value, phi, expr_type);
|
||||
}
|
||||
static LLVMValueRef llvm_emit_real(LLVMTypeRef type, Float f)
|
||||
@@ -4346,7 +4316,7 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
}
|
||||
return;
|
||||
case CONST_BOOL:
|
||||
llvm_value_set_bool(be_value, LLVMConstInt(c->bool_type, expr->const_expr.b ? 1 : 0, 0));
|
||||
llvm_value_set(be_value, LLVMConstInt(c->bool_type, expr->const_expr.b ? 1 : 0, 0), type_bool);
|
||||
return;
|
||||
case CONST_STRING:
|
||||
{
|
||||
@@ -5672,7 +5642,7 @@ static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *exp
|
||||
LLVMValueRef fail_ref = decl_optional_ref(expr->try_unwrap_expr.decl);
|
||||
LLVMValueRef errv = llvm_load(c, llvm_get_type(c, type_anyerr), fail_ref, type_abi_alignment(type_anyerr), "load.err");
|
||||
LLVMValueRef result = LLVMBuildICmp(c->builder, LLVMIntEQ, errv, llvm_get_zero(c, type_anyerr), "result");
|
||||
llvm_value_set_bool(value, result);
|
||||
llvm_value_set(value, result, type_bool);
|
||||
return;
|
||||
}
|
||||
BEValue addr;
|
||||
@@ -5914,7 +5884,7 @@ void llvm_emit_try_unwrap_chain(GenContext *c, BEValue *value, Expr *expr)
|
||||
LLVMBasicBlockRef blocks[2] = { next_block, fail_block };
|
||||
LLVMAddIncoming(chain_result, logic_values, blocks, 2);
|
||||
|
||||
llvm_value_set_bool(value, chain_result);
|
||||
llvm_value_set(value, chain_result, type_bool);
|
||||
|
||||
}
|
||||
|
||||
@@ -5958,7 +5928,7 @@ static inline void llvm_emit_argv_to_subarray(GenContext *c, BEValue *value, Exp
|
||||
|
||||
// Check if zero:
|
||||
BEValue cond;
|
||||
llvm_value_set_bool(&cond, LLVMBuildICmp(c->builder, LLVMIntEQ, count, llvm_get_zero(c, argc_value.type), ""));
|
||||
llvm_value_set(&cond, LLVMBuildICmp(c->builder, LLVMIntEQ, count, llvm_get_zero(c, argc_value.type), ""), type_bool);
|
||||
LLVMBasicBlockRef exit_block = llvm_basic_block_new(c, "exit_loop");
|
||||
LLVMBasicBlockRef pre_loop_block = llvm_basic_block_new(c, "pre_loop");
|
||||
|
||||
@@ -6006,7 +5976,7 @@ static inline void llvm_emit_argv_to_subarray(GenContext *c, BEValue *value, Exp
|
||||
|
||||
// Add index
|
||||
LLVMValueRef index_plus = LLVMBuildNUWAdd(c->builder, index_var, llvm_const_int(c, type_usize, 1), "");
|
||||
llvm_value_set_bool(&cond, LLVMBuildICmp(c->builder, LLVMIntULT, index_plus, size, ""));
|
||||
llvm_value_set(&cond, LLVMBuildICmp(c->builder, LLVMIntULT, index_plus, size, ""), type_bool);
|
||||
llvm_emit_cond_br(c, &cond, body_block, exit_block);
|
||||
LLVMValueRef values[2] = { index_plus, zero };
|
||||
LLVMBasicBlockRef blocks[2] = { body_block, pre_loop_block };
|
||||
|
||||
@@ -258,8 +258,6 @@ static inline bool llvm_value_is_addr(BEValue *value) { return value->kind == BE
|
||||
static inline bool llvm_value_is_bool(BEValue *value) { return value->kind == BE_BOOLEAN; }
|
||||
bool llvm_value_is_const(BEValue *value);
|
||||
void llvm_value_rvalue(GenContext *context, BEValue *value);
|
||||
void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value);
|
||||
void llvm_value_set_bool_vector(BEValue *value, LLVMValueRef llvm_value, Type *type);
|
||||
void llvm_value_set(BEValue *value, LLVMValueRef llvm_value, Type *type);
|
||||
void llvm_value_set_int(GenContext *c, BEValue *value, Type *type, uint64_t i);
|
||||
void llvm_value_set_address(BEValue *value, LLVMValueRef llvm_value, Type *type, AlignSize alignment);
|
||||
|
||||
@@ -141,7 +141,7 @@ void llvm_emit_decl_expr_list(GenContext *context, BEValue *be_value, Expr *expr
|
||||
LLVMValueRef decl_value = llvm_get_ref(context, last->decl_expr);
|
||||
if (bool_cast && last->decl_expr->var.unwrap)
|
||||
{
|
||||
llvm_value_set_bool(be_value, LLVMConstInt(context->bool_type, 1, false));
|
||||
llvm_value_set(be_value, LLVMConstInt(context->bool_type, 1, false), type_bool);
|
||||
return;
|
||||
}
|
||||
llvm_value_set_address_abi_aligned(be_value, decl_value, type);
|
||||
@@ -638,7 +638,7 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
llvm_emit_comp(c, &le, &be_value, switch_value, BINARYOP_LE);
|
||||
BEValue ge;
|
||||
llvm_emit_comp(c, &ge, &to_value, switch_value, BINARYOP_GE);
|
||||
llvm_value_set_bool(&equals, llvm_emit_and(c, &le, &ge));
|
||||
llvm_value_set(&equals, llvm_emit_and(c, &le, &ge), type_bool);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1344,7 +1344,7 @@ void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *pani
|
||||
LLVMBasicBlockRef panic_block = llvm_basic_block_new(c, "panic");
|
||||
LLVMBasicBlockRef ok_block = llvm_basic_block_new(c, "checkok");
|
||||
BEValue be_value;
|
||||
llvm_value_set_bool(&be_value, value);
|
||||
llvm_value_set(&be_value, value, type_bool);
|
||||
llvm_emit_cond_br(c, &be_value, panic_block, ok_block);
|
||||
llvm_emit_block(c, panic_block);
|
||||
llvm_emit_panic(c, panic_name, loc);
|
||||
|
||||
@@ -8,6 +8,26 @@ void llvm_value_set(BEValue *value, LLVMValueRef llvm_value, Type *type)
|
||||
value->alignment = type_abi_alignment(type);
|
||||
value->kind = BE_VALUE;
|
||||
value->type = type;
|
||||
|
||||
if (type == type_bool)
|
||||
{
|
||||
LLVMTypeRef llvm_type = LLVMTypeOf(llvm_value);
|
||||
LLVMContextRef context = LLVMGetTypeContext(llvm_type);
|
||||
if (llvm_type == LLVMIntTypeInContext(context, 1))
|
||||
{
|
||||
value->kind = BE_BOOLEAN;
|
||||
}
|
||||
}
|
||||
if (type_kind_is_any_vector(type->type_kind) && type->array.base == type_bool)
|
||||
{
|
||||
LLVMTypeRef llvm_type = LLVMTypeOf(llvm_value);
|
||||
LLVMTypeRef element = LLVMGetElementType(llvm_type);
|
||||
LLVMContextRef context = LLVMGetTypeContext(llvm_type);
|
||||
if (element == LLVMIntTypeInContext(context, 1))
|
||||
{
|
||||
value->kind = BE_BOOLVECTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llvm_value_set_address(BEValue *value, LLVMValueRef llvm_value, Type *type, AlignSize alignment)
|
||||
|
||||
@@ -171,20 +171,30 @@ bool expr_const_float_fits_type(const ExprConst *expr_const, TypeKind kind)
|
||||
|
||||
bool expr_const_will_overflow(const ExprConst *expr, TypeKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
switch (expr->const_kind)
|
||||
{
|
||||
case ALL_INTS:
|
||||
return !int_fits(expr->ixx, kind);
|
||||
case TYPE_F16:
|
||||
case TYPE_F32:
|
||||
case TYPE_F64:
|
||||
case TYPE_F128:
|
||||
case CONST_FLOAT:
|
||||
return !expr_const_float_fits_type(expr, kind);
|
||||
case TYPE_BOOL:
|
||||
case CONST_INTEGER:
|
||||
return !int_fits(expr->ixx, kind);
|
||||
case CONST_BOOL:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE
|
||||
case CONST_ENUM:
|
||||
{
|
||||
Int i = { .i = { .low = expr->enum_err_val->var.index }, .type = type_flatten(expr->enum_err_val->type)->type_kind };
|
||||
return !int_fits(i, kind);
|
||||
}
|
||||
case CONST_ERR:
|
||||
case CONST_BYTES:
|
||||
case CONST_STRING:
|
||||
case CONST_POINTER:
|
||||
case CONST_TYPEID:
|
||||
case CONST_INITIALIZER:
|
||||
case CONST_UNTYPED_LIST:
|
||||
case CONST_MEMBER:
|
||||
UNREACHABLE;
|
||||
}
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
const char *expr_const_to_error_string(const ExprConst *expr)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -910,7 +910,25 @@ static inline bool sema_binary_promote_top_down(SemaContext *context, Expr *bina
|
||||
|
||||
static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right)
|
||||
{
|
||||
return (int)sema_analyse_expr(context, left) & (int)sema_analyse_expr(context, right);
|
||||
if (right->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
{
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(left->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
}
|
||||
return sema_analyse_expr(context, right);
|
||||
}
|
||||
if (left->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
{
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (type_kind_is_any_vector(type_flatten(right->type)->type_kind))
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, right->type, right);
|
||||
}
|
||||
return sema_analyse_expr(context, left);
|
||||
}
|
||||
return sema_analyse_expr(context, left) && sema_analyse_expr(context, right);
|
||||
}
|
||||
|
||||
static inline bool sema_binary_analyse_arithmetic_subexpr(SemaContext *context, Expr *expr, const char *error, bool bool_is_allowed)
|
||||
@@ -1804,14 +1822,13 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
inferred_len = false;
|
||||
}
|
||||
}
|
||||
if (!cast_may_implicit(type, rtype, CAST_OPTION_SIMPLE_EXPR | (may_failable ? CAST_OPTION_ALLOW_OPTIONAL : 0)) || inferred_len)
|
||||
bool success = cast_implicit_silent(context, ret_expr, rtype);
|
||||
if (inferred_len || (!may_failable && IS_OPTIONAL(ret_expr)) || !success)
|
||||
{
|
||||
SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype),
|
||||
type_quoted_error_string(type));
|
||||
return SCOPE_POP_ERROR();
|
||||
}
|
||||
bool success = cast_implicit(context, ret_expr, rtype);
|
||||
assert(success);
|
||||
if (may_failable) ret_expr->type = type_add_optional(ret_expr->type, may_failable);
|
||||
}
|
||||
call_expr->type = type_add_optional(rtype, failable);
|
||||
@@ -2523,7 +2540,12 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr)
|
||||
if (end && end->type != start->type)
|
||||
{
|
||||
Type *common = type_find_max_type(start->type, end->type);
|
||||
if (!common || !cast_implicit(context, start, common) || !cast_implicit(context, end, common)) return false;
|
||||
if (!common)
|
||||
{
|
||||
SEMA_ERROR(expr, "No common type can be found between start and end index.");
|
||||
return false;
|
||||
}
|
||||
if (!cast_implicit(context, start, common) || !cast_implicit(context, end, common)) return false;
|
||||
}
|
||||
|
||||
bool start_from_end = expr->subscript_expr.range.start_from_end;
|
||||
@@ -3816,14 +3838,7 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr)
|
||||
expr_replace(expr, inner);
|
||||
return true;
|
||||
}
|
||||
if (!cast_may_explicit(inner->type, target_type, true, inner->expr_kind == EXPR_CONST))
|
||||
{
|
||||
return sema_error_failed_cast(expr, type_no_optional(inner->type), target_type);
|
||||
}
|
||||
if (!cast(inner, target_type))
|
||||
{
|
||||
return expr_poison(expr);
|
||||
}
|
||||
if (!cast_explicit(context, inner, target_type)) return expr_poison(expr);
|
||||
expr_replace(expr, inner);
|
||||
return true;
|
||||
}
|
||||
@@ -3853,8 +3868,7 @@ static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Typ
|
||||
Range *left_range = &left->subscript_expr.range;
|
||||
Range *right_range = &right->subscript_expr.range;
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (cast_may_implicit(right->type, base, CAST_OPTION_SIMPLE_EXPR)) goto ASSIGN;
|
||||
if (!cast_implicit(context, right, left_type)) return false;
|
||||
if (!cast_implicit_silent(context, right, left_type)) goto ASSIGN;
|
||||
IndexDiff left_len = range_const_len(left_range);
|
||||
IndexDiff right_len = range_const_len(right_range);
|
||||
if (left_len >= 0 && right_len >= 0 && left_len != right_len)
|
||||
@@ -3885,8 +3899,9 @@ bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type
|
||||
}
|
||||
|
||||
// 1. Evaluate right side to required type.
|
||||
if (!sema_analyse_expr_rhs(context, left_type, right, true)) return false;
|
||||
if (IS_OPTIONAL(right) && !type_is_optional(left_type))
|
||||
bool to_optional = left_type && type_is_optional(left_type);
|
||||
if (!sema_analyse_expr_rhs(context, left_type, right, is_unwrapped || to_optional)) return false;
|
||||
if (IS_OPTIONAL(right) && !to_optional)
|
||||
{
|
||||
if (is_unwrapped)
|
||||
{
|
||||
@@ -4112,12 +4127,7 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
|
||||
|
||||
// 5. Cast the right hand side to the one on the left
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (!cast_implicit(context, right, no_fail)) return false;
|
||||
if (IS_OPTIONAL(right) && !IS_OPTIONAL(left))
|
||||
{
|
||||
SEMA_ERROR(right, "This expression cannot be failable, since the assigned variable isn't.");
|
||||
return false;
|
||||
}
|
||||
if (!cast_implicit_maybe_failable(context, right, no_fail, IS_OPTIONAL(left))) return false;
|
||||
// 6. Check for zero in case of div or mod.
|
||||
if (right->expr_kind == EXPR_CONST)
|
||||
{
|
||||
@@ -4252,7 +4262,8 @@ static bool sema_binary_arithmetic_promotion(SemaContext *context, Expr *left, E
|
||||
SEMA_ERROR(parent, error_message, type_quoted_error_string(left->type), type_quoted_error_string(right->type));
|
||||
return false;
|
||||
}
|
||||
return cast_implicit(context, left, max) && cast_implicit(context, right, max);
|
||||
return cast_implicit(context, left, max) &&
|
||||
cast_implicit(context, right, max);
|
||||
}
|
||||
|
||||
static void sema_binary_unify_voidptr(Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref)
|
||||
@@ -4276,8 +4287,7 @@ static Type *defer_iptr_cast(Expr *maybe_pointer, Expr *maybe_diff)
|
||||
// (iptr)((char*)(ptr) +- 1)
|
||||
if (maybe_pointer->expr_kind == EXPR_CAST
|
||||
&& maybe_pointer->cast_expr.kind == CAST_PTRXI
|
||||
&& type_flatten(maybe_pointer->type) == type_flatten(type_iptr)
|
||||
&& cast_may_implicit(maybe_diff->type, maybe_diff->type, CAST_OPTION_SIMPLE_EXPR | CAST_OPTION_ALLOW_OPTIONAL))
|
||||
&& type_flatten(maybe_pointer->type) == type_flatten(type_iptr))
|
||||
{
|
||||
Type *cast_to_iptr = maybe_pointer->type;
|
||||
maybe_pointer->cast_expr.kind = CAST_PTRPTR;
|
||||
@@ -4858,7 +4868,7 @@ static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Exp
|
||||
static bool sema_expr_analyse_and_or(SemaContext *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!sema_binary_analyse_subexpr(context, expr, left, right)) return false;
|
||||
if (!cast_implicit(context, left, type_bool) || !cast_implicit(context, right, type_bool)) return false;
|
||||
if (!cast_explicit(context, left, type_bool) || !cast_explicit(context, right, type_bool)) return false;
|
||||
|
||||
if (expr_both_const(left, right))
|
||||
{
|
||||
@@ -5330,17 +5340,35 @@ static inline bool sema_expr_analyse_not(SemaContext *context, Expr *expr)
|
||||
|
||||
// 2. Check whether the type is a vector
|
||||
Type *type = type_no_optional(inner->type);
|
||||
if (type_flat_is_vector(type))
|
||||
Type *flat = type_flatten_distinct(type);
|
||||
if (type_kind_is_any_vector(flat->type_kind))
|
||||
{
|
||||
// 3. This always works, so we're done.
|
||||
expr->type = type_add_optional(type_get_vector_bool(type), IS_OPTIONAL(inner));
|
||||
return true;
|
||||
// This may be some form of bool vector.
|
||||
if (type_flatten(flat->array.base) == type_bool)
|
||||
{
|
||||
// If so then we're done.
|
||||
expr->type = type;
|
||||
return true;
|
||||
}
|
||||
Type *canonical = type->canonical;
|
||||
switch (canonical->type_kind)
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
expr->type = type_get_vector(type_bool, canonical->array.len);
|
||||
return true;
|
||||
case TYPE_SCALED_VECTOR:
|
||||
expr->type = type_get_scaled_vector(type_bool);
|
||||
return true;
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
UNREACHABLE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Let's see if it's possible to cast it implicitly
|
||||
if (!cast_may_implicit(type, type_bool, CAST_OPTION_SIMPLE_EXPR | CAST_OPTION_ALLOW_OPTIONAL))
|
||||
if (!cast_may_bool_convert(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));
|
||||
SEMA_ERROR(expr, "The %s can't be converted to a boolean value.", type_quoted_error_string(inner->type));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5348,7 +5376,7 @@ static inline bool sema_expr_analyse_not(SemaContext *context, Expr *expr)
|
||||
|
||||
if (inner->expr_kind == EXPR_CONST)
|
||||
{
|
||||
bool success = cast_implicit(context, inner, expr->type);
|
||||
bool success = cast_explicit(context, inner, expr->type);
|
||||
assert(success);
|
||||
assert(inner->const_expr.const_kind == CONST_BOOL);
|
||||
expr->const_expr.const_kind = CONST_BOOL;
|
||||
@@ -6856,7 +6884,7 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr)
|
||||
type_quoted_error_string(expr->type));
|
||||
return false;
|
||||
}
|
||||
return cast_implicit(context, expr, type_bool);
|
||||
return cast_explicit(context, expr, type_bool);
|
||||
}
|
||||
|
||||
|
||||
@@ -6877,7 +6905,7 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (to && !cast_implicit(context, expr, to)) return false;
|
||||
if (to && !cast_implicit_maybe_failable(context, expr, to, allow_failable)) return false;
|
||||
if (!allow_failable && IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "You cannot have a failable here.");
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
#define POP_BREAKCONT() POP_CONTINUE(); POP_BREAK()
|
||||
#define IS_CONST(_x) ((_x)->expr_kind == EXPR_CONST)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REPORT_ERROR,
|
||||
REPORT_NONE,
|
||||
} ReportType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPLIT_PATH_IDENT,
|
||||
|
||||
@@ -898,21 +898,16 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 3a. Check for failables in case of an expression.
|
||||
// 3a. Check for optional in case of an expression.
|
||||
if (IS_OPTIONAL(last))
|
||||
{
|
||||
if (!cast_to_bool || cast_may_implicit(type_no_optional(last->type), type_bool, CAST_OPTION_NONE))
|
||||
{
|
||||
SEMA_ERROR(last, "The expression may not be a failable, but was %s.", type_quoted_error_string(last->type));
|
||||
return false;
|
||||
}
|
||||
sema_error_failed_cast(last, type_no_optional(last->type), type_bool);
|
||||
SEMA_ERROR(last, "The expression may not be an optional, but was %s.", type_quoted_error_string(last->type));
|
||||
return false;
|
||||
}
|
||||
// 3b. Cast to bool if that is needed
|
||||
if (cast_to_bool)
|
||||
{
|
||||
if (!cast_implicit(context, last, type_bool)) return false;
|
||||
if (!cast_explicit(context, last, type_bool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1633,6 +1633,71 @@ Type *type_from_token(TokenType type)
|
||||
}
|
||||
}
|
||||
|
||||
bool type_array_element_is_equivalent(Type *element1, Type *element2, bool is_explicit)
|
||||
{
|
||||
RETRY:
|
||||
if (is_explicit)
|
||||
{
|
||||
element1 = type_flatten_distinct(element1);
|
||||
element2 = type_flatten_distinct(element2);
|
||||
}
|
||||
else
|
||||
{
|
||||
element1 = element1->canonical;
|
||||
element2 = element2->canonical;
|
||||
}
|
||||
if (element1 == element2) return true;
|
||||
switch (element1->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
if (element2->type_kind != TYPE_POINTER) return false;
|
||||
return type_is_pointer_equivalent(element1, element2, is_explicit);
|
||||
case TYPE_ARRAY:
|
||||
if (element2->type_kind != TYPE_INFERRED_ARRAY && element1->array.len != element2->array.len) return false;
|
||||
element1 = element1->array.base;
|
||||
element2 = element2->array.base;
|
||||
goto RETRY;
|
||||
case TYPE_VECTOR:
|
||||
if (element2->type_kind != TYPE_INFERRED_VECTOR && element1->array.len != element2->array.len) return false;
|
||||
element1 = element1->array.base;
|
||||
element2 = element2->array.base;
|
||||
goto RETRY;
|
||||
case TYPE_STRUCT:
|
||||
if (is_explicit) return type_is_structurally_equivalent(element1, element2);
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool type_is_pointer_equivalent(Type *pointer1, Type *pointer2, bool flatten_distinct)
|
||||
{
|
||||
RETRY:
|
||||
if (flatten_distinct)
|
||||
{
|
||||
pointer1 = type_flatten_distinct(pointer1);
|
||||
pointer2 = type_flatten_distinct(pointer2);
|
||||
}
|
||||
if (pointer1 == type_voidptr || pointer2 == type_voidptr) return true;
|
||||
Type *pointee1 = pointer1->pointer->canonical;
|
||||
Type *pointee2 = pointer2->pointer->canonical;
|
||||
if (flatten_distinct)
|
||||
{
|
||||
pointee1 = type_flatten_distinct(pointee1);
|
||||
pointee2 = type_flatten_distinct(pointee2);
|
||||
}
|
||||
if (pointee1->type_kind != pointee2->type_kind) return false;
|
||||
if (pointee1->type_kind == TYPE_POINTER)
|
||||
{
|
||||
pointer1 = pointee1;
|
||||
pointer2 = pointee2;
|
||||
goto RETRY;
|
||||
}
|
||||
if (!type_is_arraylike(pointee1)) return false;
|
||||
if (pointee1->array.len != pointee2->array.len) return false;
|
||||
return type_array_element_is_equivalent(pointee1->array.base, pointer2->array.base, flatten_distinct);
|
||||
}
|
||||
|
||||
bool type_may_have_method(Type *type)
|
||||
{
|
||||
DECL_TYPE_KIND_REAL(kind, type)
|
||||
|
||||
Reference in New Issue
Block a user