- Crash in slice expression when it contains a rethrow #2872

- Multiple issues when rethrowing inside of expressions #2873
This commit is contained in:
Christoffer Lerno
2026-01-29 00:42:20 +01:00
parent 414c0c9438
commit 50718cb905
5 changed files with 327 additions and 85 deletions

View File

@@ -811,13 +811,11 @@ static inline void llvm_emit_pointer_offset(GenContext *c, BEValue *value, Expr
Expr *offset_expr = exprptr(expr->pointer_offset_expr.offset);
// Emit the pointer
llvm_emit_expr(c, value, pointer);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, pointer)) RETURN_EMPTY_BLOCK(value);
// Now calculate the offset:
BEValue offset;
llvm_emit_expr(c, &offset, offset_expr);
llvm_value_rvalue(c, &offset);
if (!llvm_emit_rvalue_in_block(c, &offset, offset_expr)) RETURN_EMPTY_BLOCK(value);
Type *element = type_is_vec(value->type) ? value->type->array.base->pointer : value->type->pointer;
value->value = llvm_emit_pointer_gep_raw(c, value->value, offset.value, type_size(element));
@@ -1653,6 +1651,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r
// Now walk through the elements.
FOREACH_IDX(i, Expr *, element, elements)
{
RETURN_ON_EMPTY_BLOCK(ref);
BEValue pointer;
if (is_struct)
{
@@ -1680,6 +1679,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r
}
BEValue init_value;
llvm_emit_expr(c, &init_value, element);
RETURN_ON_EMPTY_BLOCK(ref);
llvm_store(c, &pointer, &init_value);
}
}
@@ -2381,14 +2381,7 @@ static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, T
default:
break;
}
llvm_emit_expr(c, value, inner);
if (!c->current_block)
{
value->type = type_void;
*value = (BEValue) { .type = type_void, .kind = BE_VALUE, .value = NULL };
return;
}
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
AlignSize alignment = type_abi_alignment(type);
bool is_const = expr_is_const(inner);
if (is_const)
@@ -2446,7 +2439,7 @@ static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *e
// Retrieve the address, creating a temp in case this is
// a temporary value (this gives us a lot of flexibility for temporaries)
BEValue addr;
llvm_emit_expr(c, &addr, expr);
if (!llvm_emit_folded_in_block(c, &addr, expr)) RETURN_EMPTY_BLOCK(value);
llvm_value_addr(c, &addr);
// Perform the actual dec/inc to generate the new value.
@@ -2455,8 +2448,7 @@ static inline void llvm_emit_post_inc_dec(GenContext *c, BEValue *value, Expr *e
static void llvm_emit_dynamic_method_addr(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->access_resolved_expr.parent);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->access_resolved_expr.parent)) RETURN_EMPTY_BLOCK(value);
llvm_emit_type_from_any(c, value);
LLVMValueRef introspect = LLVMBuildIntToPtr(c->builder, value->value, c->ptr_type, "");
@@ -2479,10 +2471,9 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
// Folded
UNREACHABLE_VOID
case UNARYOP_NOT:
llvm_emit_expr(c, value, inner);
if (!llvm_emit_rvalue_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
if (type_flat_is_vector(type))
{
llvm_value_rvalue(c, value);
Type *vec_type = type_vector_type(type);
LLVMValueRef llvm_value;
if (type_is_float(vec_type))
@@ -2498,11 +2489,10 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_value_set(value, llvm_value, res_type);
return;
}
llvm_value_rvalue(c, value);
value->value = LLVMBuildNot(c->builder, value->value, "not");
return;
case UNARYOP_BITNEG:
llvm_emit_expr(c, value, inner);
if (!llvm_emit_folded_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
if (value->type->type_kind == TYPE_ARRAY)
{
llvm_value_addr(c, value);
@@ -2518,8 +2508,7 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
value->value = LLVMBuildNot(c->builder, value->value, "bnot");
return;
case UNARYOP_NEG:
llvm_emit_expr(c, value, inner);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
if (type_is_floatlike(type))
{
value->value = LLVMBuildFNeg(c->builder, value->value, "fneg");
@@ -2548,7 +2537,7 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
}
FALLTHROUGH;
case UNARYOP_TADDR:
llvm_emit_expr(c, value, inner);
if (!llvm_emit_folded_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
// Create an addr
llvm_value_addr(c, value);
// Transform to value
@@ -2661,12 +2650,14 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
parent_type = type_no_optional(parent_type);
BEValue parent_addr_x;
llvm_emit_expr(c, &parent_addr_x, parent_expr);
RETURN_ON_EMPTY_BLOCK_VOID();
LLVMValueRef parent_load_value = NULL;
LLVMValueRef parent_base = NULL;
LLVMValueRef parent_addr = NULL;
if (parent_type->type_kind == TYPE_POINTER)
{
llvm_value_rvalue(c, &parent_addr_x);
RETURN_ON_EMPTY_BLOCK_VOID();
parent_load_value = parent_base = parent_addr_x.value;
}
else
@@ -2703,8 +2694,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
case RANGE_DYNAMIC:
case RANGE_CONST_LEN:
case RANGE_CONST_END:
llvm_emit_exprid(c, &start_index, range.start);
llvm_value_rvalue(c, &start_index);
if (!llvm_emit_rvalue_id_in_block(c, &start_index, range.start)) return;
start_type = start_index.type;
break;
case RANGE_CONST_RANGE:
@@ -2752,6 +2742,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
ASSERT(len.value);
BEValue exceeds_size;
llvm_emit_int_comp(c, &exceeds_size, &start_index, &len, BINARYOP_GT);
RETURN_ON_EMPTY_BLOCK_VOID();
llvm_emit_panic_if_true(c, &exceeds_size, "Index exceeds array len", slice->span, "Index exceeds array length (array had size %d, index was %d).", &len, &start_index);
}
@@ -2808,6 +2799,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
if (is_len_range)
{
llvm_emit_int_comp(c, &excess, &start_index, &end_index, BINARYOP_GT);
RETURN_ON_EMPTY_BLOCK_VOID();
BEValue actual_end_len = end_index;
actual_end_len.value = llvm_emit_sub_int(c, end_index.type, end_index.value, start_index.value, slice->span);
actual_end_len.type = type_isz;
@@ -2815,6 +2807,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
if (len.value)
{
llvm_emit_int_comp(c, &excess, &len, &end_index, BINARYOP_LT);
RETURN_ON_EMPTY_BLOCK_VOID();
BEValue actual_end_index = end_index;
actual_end_index.value = llvm_emit_sub_int(c, end_index.type, end_index.value, llvm_const_int(c, type_isz, 1), slice->span);
llvm_emit_panic_if_true(c, &excess, "End index out of bounds", slice->span, "End index out of bounds (end index of %d exceeds size of %d)", &actual_end_index, &len);
@@ -2824,15 +2817,18 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
{
llvm_value_rvalue(c, &start_index);
llvm_value_rvalue(c, &end_index);
RETURN_ON_EMPTY_BLOCK_VOID();
LLVMValueRef val = llvm_emit_add_int(c, end_index.type, end_index.value, llvm_const_int(c, end_index.type, 1), slice->span);
BEValue plus_one_end_index;
llvm_value_set(&plus_one_end_index, val, end_index.type);
llvm_emit_int_comp(c, &excess, &start_index, &plus_one_end_index, BINARYOP_GT);
RETURN_ON_EMPTY_BLOCK_VOID();
llvm_emit_panic_if_true(c, &excess, "Negative size", slice->span, "Negative size (slice was: [%d..%d])", &start_index, &end_index);
if (len.value)
{
llvm_emit_int_comp(c, &excess, &len, &end_index, BINARYOP_LE);
RETURN_ON_EMPTY_BLOCK_VOID();
llvm_emit_panic_if_true(c, &excess, "End index out of bounds", slice->span, "End index out of bounds (end index of %d exceeds size of %d)", &end_index, &len);
}
}
@@ -2860,8 +2856,10 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr)
BEValue end;
bool is_exclusive;
llvm_emit_slice_values(c, expr, &parent, &start, &end, &is_exclusive);
RETURN_ON_EMPTY_BLOCK(be_value);
llvm_value_rvalue(c, &start);
llvm_value_rvalue(c, &end);
RETURN_ON_EMPTY_BLOCK(be_value);
// Calculate the size
LLVMValueRef size;
@@ -2900,24 +2898,23 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr)
llvm_value_aggregate_two(c, be_value, type_lowering(expr->type), start_pointer, size);
}
static void llvm_emit_slice_copy(GenContext *c, BEValue *be_value, Expr *expr)
static void llvm_emit_slice_copy(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_exprid(c, be_value, expr->slice_assign_expr.right);
llvm_value_rvalue(c, be_value);
if (!llvm_emit_rvalue_id_in_block(c, value, expr->slice_assign_expr.right)) RETURN_EMPTY_BLOCK(value);
BEValue assigned_to;
llvm_emit_exprid(c, &assigned_to, expr->slice_assign_expr.left);
llvm_value_rvalue(c, &assigned_to);
if (!llvm_emit_rvalue_id_in_block(c, &assigned_to, expr->slice_assign_expr.left)) RETURN_EMPTY_BLOCK(value);
BEValue to_pointer;
llvm_emit_slice_pointer(c, &assigned_to, &to_pointer);
llvm_value_rvalue(c, &to_pointer);
RETURN_ON_EMPTY_BLOCK(value);
BEValue from_pointer;
BEValue from_len;
llvm_emit_slice_pointer(c, be_value, &from_pointer);
llvm_emit_slice_pointer(c, value, &from_pointer);
llvm_value_rvalue(c, &from_pointer);
llvm_emit_slice_len(c, be_value, &from_len);
llvm_emit_slice_len(c, value, &from_len);
llvm_value_rvalue(c, &from_len);
if (safe_mode_enabled())
@@ -2926,6 +2923,7 @@ static void llvm_emit_slice_copy(GenContext *c, BEValue *be_value, Expr *expr)
llvm_emit_slice_len(c, &assigned_to, &to_len);
BEValue comp;
llvm_emit_int_comp(c, &comp, &to_len, &from_len, BINARYOP_NE);
RETURN_ON_EMPTY_BLOCK_VOID();
llvm_emit_panic_if_true(c, &comp, "Length mismatch", expr->span, "Slice copy length mismatch (%d != %d).", &to_len, &from_len);
}
@@ -3118,12 +3116,14 @@ void llvm_emit_int_comp_zero(GenContext *c, BEValue *result, BEValue *lhs, Binar
BEValue zero;
llvm_value_set_int(c, &zero, lhs->type, 0);
llvm_emit_int_comp(c, result, lhs, &zero, binary_op);
RETURN_ON_EMPTY_BLOCK_VOID();
}
void llvm_emit_int_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
{
llvm_value_rvalue(c, lhs);
llvm_value_rvalue(c, rhs);
RETURN_ON_EMPTY_BLOCK(result);
llvm_emit_int_comp_raw(c, result, lhs->type, rhs->type, lhs->value, rhs->value, binary_op);
}
void llvm_emit_int_comp_raw(GenContext *c, BEValue *result, Type *lhs_type, Type *rhs_type, LLVMValueRef lhs_value, LLVMValueRef rhs_value, BinaryOp binary_op)
@@ -4402,15 +4402,11 @@ static inline void llvm_emit_rethrow_expr(GenContext *c, BEValue *be_value, Expr
PUSH_CATCH_VAR_BLOCK(error_var_ref.value, guard_block);
llvm_emit_expr(c, be_value, expr->rethrow_expr.inner);
// Fold the optional.
llvm_value_fold_optional(c, be_value);
llvm_emit_folded_in_block(c, be_value, expr->rethrow_expr.inner);
// Restore.
POP_CATCH();
// Emit success and to end.
bool emit_no_err = llvm_emit_br(c, no_err_block);
@@ -4456,8 +4452,7 @@ static inline void llvm_emit_force_unwrap_expr(GenContext *c, BEValue *be_value,
PUSH_CATCH_VAR_BLOCK(error_var_ref.value, panic_block);
llvm_emit_expr(c, be_value, expr->inner_expr);
llvm_value_fold_optional(c, be_value);
llvm_emit_folded_in_block(c, be_value, expr->inner_expr);
// Restore.
POP_CATCH();
@@ -4506,6 +4501,7 @@ static void llvm_emit_vector_assign_expr(GenContext *c, BEValue *be_value, Expr
// Emit the variable
llvm_emit_exprid(c, &addr, left->subscript_expr.expr);
}
RETURN_ON_EMPTY_BLOCK(be_value);
// Emit the variable
llvm_value_addr(c, &addr);
@@ -4526,7 +4522,9 @@ static void llvm_emit_vector_assign_expr(GenContext *c, BEValue *be_value, Expr
{
llvm_emit_expr(c, be_value, exprptr(expr->binary_expr.right));
}
RETURN_ON_EMPTY_BLOCK(be_value);
llvm_value_rvalue(c, be_value);
RETURN_ON_EMPTY_BLOCK(be_value);
const char *sw_ptr = left->swizzle_expr.swizzle;
unsigned vec_len = be_value->type->array.len;
LLVMValueRef result = be_value->value;
@@ -4544,6 +4542,7 @@ static void llvm_emit_vector_assign_expr(GenContext *c, BEValue *be_value, Expr
// Emit the index
BEValue index;
llvm_emit_exprid(c, &index, left->subscript_expr.index.expr);
RETURN_ON_EMPTY_BLOCK(be_value);
LLVMValueRef index_val = llvm_load_value_store(c, &index);
if (binary_op > BINARYOP_ASSIGN)
{
@@ -4552,10 +4551,12 @@ static void llvm_emit_vector_assign_expr(GenContext *c, BEValue *be_value, Expr
BEValue lhs;
llvm_value_set(&lhs, LLVMBuildExtractElement(c->builder, vector_value, index_val, "elem"), expr->type);
llvm_emit_binary(c, be_value, expr, &lhs, base_op);
RETURN_ON_EMPTY_BLOCK(be_value);
}
else
{
llvm_emit_expr(c, be_value, exprptr(expr->binary_expr.right));
RETURN_ON_EMPTY_BLOCK(be_value);
}
LLVMValueRef new_value = LLVMBuildInsertElement(c->builder, vector_value, llvm_load_value_store(c, be_value),
@@ -4583,15 +4584,15 @@ static void llvm_emit_binary_expr(GenContext *c, BEValue *be_value, Expr *expr)
// Get the left hand side, which must be an address.
BEValue addr;
llvm_emit_expr(c, &addr, exprptr(expr->binary_expr.left));
ASSERT(llvm_value_is_addr(&addr));
if (!llvm_emit_folded_in_block(c, &addr, exprptr(expr->binary_expr.left))) RETURN_EMPTY_BLOCK(be_value);
// Fold the optional.
llvm_value_fold_optional(c, &addr);
ASSERT(llvm_value_is_addr(&addr));
// Perform the binary operation, using the already loaded LHS.
llvm_emit_binary(c, be_value, expr, &addr, base_op);
RETURN_ON_EMPTY_BLOCK(be_value);
// Store it.
llvm_store(c, &addr, be_value);
return;
@@ -4657,8 +4658,7 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_cond_br(c, value, lhs_block, rhs_block);
llvm_emit_block(c, lhs_block);
BEValue lhs;
llvm_emit_expr(c, &lhs, then_expr);
llvm_value_rvalue(c, &lhs);
llvm_emit_rvalue_in_block(c, &lhs, then_expr);
LLVMValueRef lhs_value = lhs.value;
LLVMBasicBlockRef lhs_exit = llvm_get_current_block_if_in_use(c);
if (lhs.type == type_bool && LLVMTypeOf(lhs_value) != c->bool_type)
@@ -4669,8 +4669,7 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_block(c, rhs_block);
BEValue rhs;
llvm_emit_expr(c, &rhs, else_expr);
llvm_value_rvalue(c, &rhs);
llvm_emit_rvalue_in_block(c, &rhs, else_expr);
LLVMValueRef rhs_value = rhs.value;
if (rhs.type == type_bool && LLVMTypeOf(rhs_value) != c->bool_type)
{
@@ -4698,7 +4697,7 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
if (type_lowering(expr->type) == type_void)
{
llvm_value_set(value, NULL, expr->type);
llvm_value_set_empty(value);
return;
}
@@ -5893,8 +5892,7 @@ INLINE void llvm_emit_varargs_expr(GenContext *c, BEValue *value_ref, Expr **var
INLINE void llvm_emit_vasplat_expr(GenContext *c, BEValue *value_ref, Expr *vasplat, Type *param)
{
llvm_emit_expr(c, value_ref, vasplat);
llvm_value_fold_optional(c, value_ref);
if (!llvm_emit_folded_in_block(c, value_ref, vasplat)) RETURN_EMPTY_BLOCK(value_ref);
Type *type = value_ref->type;
switch (type->type_kind)
{
@@ -5922,7 +5920,6 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
llvm_emit_builtin_call(c, result_value, expr);
return;
}
LLVMTypeRef func_type;
LLVMValueRef func;
@@ -5947,6 +5944,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
// 1c. Evaluate the pointer expression.
BEValue func_value;
llvm_emit_expr(c, &func_value, function);
RETURN_ON_EMPTY_BLOCK(result_value);
// 1d. Load it as a value
func = llvm_load_value_store(c, &func_value);
@@ -6125,6 +6123,7 @@ static inline void llvm_emit_expression_list_expr(GenContext *c, BEValue *be_val
for (unsigned i = 0; i < last; i++)
{
llvm_emit_ignored_expr(c, list[i]);
RETURN_ON_EMPTY_BLOCK(be_value);
}
llvm_emit_expr(c, be_value, list[last]);
}
@@ -6358,6 +6357,7 @@ static inline void llvm_emit_optional(GenContext *c, BEValue *be_value, Expr *ex
{
ASSERT(c->catch.fault);
llvm_emit_expr(c, be_value, fail);
RETURN_ON_EMPTY_BLOCK(be_value);
llvm_store_to_ptr(c, c->catch.fault, be_value);
}
// Branch to the catch
@@ -6401,6 +6401,7 @@ static inline void llvm_emit_vector_initializer_list(GenContext *c, BEValue *val
FOREACH_IDX(i, Expr *, element, elements)
{
llvm_emit_expr(c, &val, element);
RETURN_ON_EMPTY_BLOCK(value);
vec_value = llvm_update_vector(c, vec_value, llvm_load_value_store(c, &val), (ArrayIndex)i);
}
}
@@ -6411,8 +6412,7 @@ static inline void llvm_emit_vector_initializer_list(GenContext *c, BEValue *val
if (splat)
{
BEValue splat_val;
llvm_emit_expr(c, &splat_val, splat);
llvm_value_rvalue(c, &splat_val);
if (!llvm_emit_rvalue_in_block(c, &splat_val, splat)) RETURN_ON_EMPTY_BLOCK(value);
vec_value = splat_val.value;
}
else
@@ -6425,18 +6425,19 @@ static inline void llvm_emit_vector_initializer_list(GenContext *c, BEValue *val
ASSERT(vec_size(designator->designator_expr.path) == 1);
DesignatorElement *element = designator->designator_expr.path[0];
llvm_emit_expr(c, &val, designator->designator_expr.value);
LLVMValueRef value = llvm_load_value_store(c, &val);
RETURN_ON_EMPTY_BLOCK(value);
LLVMValueRef value_ref = llvm_load_value_store(c, &val);
switch (element->kind)
{
case DESIGNATOR_ARRAY:
{
vec_value = llvm_update_vector(c, vec_value, value, element->index);
vec_value = llvm_update_vector(c, vec_value, value_ref, element->index);
break;
}
case DESIGNATOR_RANGE:
for (ArrayIndex idx = element->index; idx <= element->index_end; idx++)
{
vec_value = llvm_update_vector(c, vec_value, value, idx);
vec_value = llvm_update_vector(c, vec_value, value_ref, idx);
}
break;
case DESIGNATOR_FIELD:
@@ -6486,6 +6487,7 @@ static void llvm_emit_macro_body_expansion(GenContext *c, BEValue *value, Expr *
{
if (!expr) continue;
llvm_emit_expr(c, value, expr);
RETURN_ON_EMPTY_BLOCK(value);
llvm_store_to_ptr_aligned(c, declarations[j]->backend_ref, value, declarations[j]->alignment);
}
@@ -6515,6 +6517,7 @@ static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *exp
if (lhs)
{
llvm_emit_expr(c, &addr, lhs);
RETURN_ON_EMPTY_BLOCK(value);
}
else
{
@@ -6552,10 +6555,9 @@ void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr)
{
BEValue val;
LLVMBasicBlockRef block = llvm_basic_block_new(c, "testblock");
llvm_emit_br(c, block);
if (c->current_block) llvm_emit_br(c, block);
llvm_emit_block(c, block);
llvm_emit_expr(c, &val, e);
llvm_value_fold_optional(c, &val);
llvm_emit_folded_in_block(c, &val, e);
}
POP_CATCH();
@@ -6575,8 +6577,7 @@ static inline LLVMValueRef llvm_load_introspect(GenContext *c, LLVMValueRef ref,
}
static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_exprid(c, value, expr->typeid_info_expr.parent);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_id_in_block(c, value, expr->typeid_info_expr.parent)) RETURN_ON_EMPTY_BLOCK(value);
LLVMValueRef kind = NULL;
LLVMValueRef ref = LLVMBuildIntToPtr(c->builder, value->value, c->ptr_type, "introspect*");
@@ -6733,8 +6734,7 @@ void llvm_emit_try_unwrap_chain(GenContext *c, BEValue *value, Expr *expr)
next_block = llvm_basic_block_new(c, "chain_next");
Expr *link = exprs[i];
BEValue res;
llvm_emit_expr(c, &res, link);
llvm_value_rvalue(c, &res);
if (!llvm_emit_rvalue_in_block(c, &res, link)) break;
ASSERT(llvm_value_is_bool(&res));
llvm_emit_cond_br(c, &res, next_block, fail_block);
}
@@ -6786,6 +6786,7 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex
(void)inner_type;
ASSERT(inner_type->type_kind == TYPE_ANYFAULT);
llvm_value_rvalue(c, be_value);
RETURN_ON_EMPTY_BLOCK(be_value);
BEValue zero = llvm_emit_alloca_b(c, type_chars, "faultname_zero");
LLVMBasicBlockRef exit_block = llvm_basic_block_new(c, "faultname_exit");
@@ -6793,6 +6794,7 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex
LLVMBasicBlockRef ok_block = llvm_basic_block_new(c, "faultname_ok");
BEValue check;
llvm_emit_int_comp_zero(c, &check, be_value, BINARYOP_EQ);
RETURN_ON_EMPTY_BLOCK(be_value);
llvm_emit_cond_br(c, &check, zero_block, ok_block);
llvm_emit_block(c, zero_block);
llvm_store_zero(c, &zero);
@@ -6811,6 +6813,7 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex
Type *inner_type = type_no_optional(inner->type)->canonical;
ASSERT(inner_type->canonical->type_kind == TYPE_ENUM);
llvm_value_rvalue(c, be_value);
RETURN_ON_EMPTY_BLOCK(be_value);
LLVMValueRef to_introspect = LLVMBuildIntToPtr(c->builder, llvm_get_typeid(c, inner_type),
c->ptr_type, "");
LLVMValueRef ptr = LLVMBuildStructGEP2(c->builder, c->introspect_type, to_introspect, INTROSPECT_INDEX_ADDITIONAL, "");
@@ -6913,8 +6916,7 @@ static void llvm_emit_swizzle_from_value(GenContext *c, LLVMValueRef vector_valu
static void llvm_emit_swizzle(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_exprid(c, value, expr->swizzle_expr.parent);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_id_in_block(c, value, expr->swizzle_expr.parent)) RETURN_EMPTY_BLOCK(value);
llvm_emit_swizzle_from_value(c, value->value, value, expr);
}
@@ -6932,15 +6934,13 @@ static void llvm_emit_default_arg(GenContext *c, BEValue *value, Expr *expr)
DebugScope scope = { .lexical_block = init_def, .inline_loc = c->last_loc };
DebugScope *old = c->debug.block_stack;
c->debug.block_stack = &scope;
llvm_emit_expr(c, value, expr->default_arg_expr.inner);
llvm_value_fold_optional(c, value);
if (!llvm_emit_folded_in_block(c, value, expr->default_arg_expr.inner)) RETURN_EMPTY_BLOCK(value);
c->debug.block_stack = old;
c->last_emitted_loc.a = 0;
}
else
{
llvm_emit_expr(c, value, expr->default_arg_expr.inner);
llvm_value_fold_optional(c, value);
llvm_emit_folded_in_block(c, value, expr->default_arg_expr.inner);
}
}
@@ -7006,15 +7006,13 @@ void llvm_emit_array_to_vector(GenContext *c, BEValue *value, Type *to)
static void llvm_emit_vector_from_array(GenContext *c, BEValue *value, Expr *expr)
{
Expr *inner = expr->inner_expr;
llvm_emit_expr(c, value, inner);
llvm_value_fold_optional(c, value);
if (!llvm_emit_folded_in_block(c, value, inner)) RETURN_EMPTY_BLOCK(value);
llvm_emit_array_to_vector(c, value, expr->type);
}
static void llvm_emit_ptr_access(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_fold_optional(c, value);
if (!llvm_emit_folded_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
if (value->kind == BE_ADDRESS)
{
llvm_emit_struct_gep_ref(c, value, value, expr->type, 0);
@@ -7057,10 +7055,11 @@ static void llvm_emit_ext_trunc(GenContext *c, BEValue *value, Expr *expr)
void llvm_emit_enum_from_ord(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->inner_expr);
RETURN_ON_EMPTY_BLOCK(value);
if (safe_mode_enabled() && c->builder != c->global_builder)
{
llvm_value_rvalue(c, value);
RETURN_ON_EMPTY_BLOCK(value);
BEValue check;
Decl *decl = type_flatten(expr->type)->decl;
unsigned max = vec_size(decl->enums.values);
@@ -7069,6 +7068,7 @@ void llvm_emit_enum_from_ord(GenContext *c, BEValue *value, Expr *expr)
scratch_buffer_clear();
scratch_buffer_printf("Attempt to convert a negative value (%%d) to enum '%s' failed.", decl->name);
llvm_emit_int_comp_zero(c, &check, value, BINARYOP_LT);
RETURN_ON_EMPTY_BLOCK(value);
llvm_emit_panic_on_true(c, check.value, "Attempt to convert negative value to enum failed.", expr->span, scratch_buffer_copy(), value, NULL);
}
scratch_buffer_clear();
@@ -7091,6 +7091,7 @@ void llvm_emit_enum_from_ord(GenContext *c, BEValue *value, Expr *expr)
void llvm_emit_scalar_to_vector(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->inner_expr);
RETURN_ON_EMPTY_BLOCK(value);
LLVMValueRef val = llvm_load_value_store(c, value);
LLVMTypeRef type = llvm_get_type(c, expr->type);
unsigned elements = LLVMGetVectorSize(type);
@@ -7118,6 +7119,7 @@ void llvm_emit_vec_to_array(GenContext *c, BEValue *value, Type *type)
static inline void llvm_emit_vector_to_array(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->inner_expr);
RETURN_ON_EMPTY_BLOCK(value);
llvm_emit_vec_to_array(c, value, expr->type);
}
@@ -7142,8 +7144,7 @@ static inline void llvm_emit_make_slice(GenContext *c, BEValue *value, Expr *exp
LLVMValueRef pointer;
if (size)
{
llvm_emit_expr(c, value, expr->make_slice_expr.ptr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->make_slice_expr.ptr)) RETURN_EMPTY_BLOCK(value);
pointer = value->value;
}
else
@@ -7169,6 +7170,8 @@ bool llvm_emit_folded_in_block(GenContext *c, BEValue *value, Expr *expr)
return true;
}
bool llvm_emit_rvalue_in_block(GenContext *c, BEValue *value, Expr *expr)
{
if (llvm_is_global_eval(c))
@@ -7206,6 +7209,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
UNREACHABLE_VOID
case EXPR_TWO:
llvm_emit_expr(c, value, expr->two_expr.first);
RETURN_ON_EMPTY_BLOCK(value);
llvm_emit_expr(c, value, expr->two_expr.last);
return;
case EXPR_VECTOR_TO_ARRAY:
@@ -7227,8 +7231,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_make_any(c, value, expr);
return;
case EXPR_FLOAT_TO_INT:
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
if (type_is_signed_any(type_lowering(expr->type)))
{
llvm_value_set(value, LLVMBuildFPToSI(c->builder, value->value, llvm_get_type(c, expr->type), "fpsi"), expr->type);
@@ -7237,8 +7240,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_value_set(value, LLVMBuildFPToUI(c->builder, value->value, llvm_get_type(c, expr->type), "fpui"), expr->type);
return;
case EXPR_INT_TO_FLOAT:
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
if (type_is_signed_any(value->type))
{
llvm_value_set(value, LLVMBuildSIToFP(c->builder, value->value, llvm_get_type(c, expr->type), "sifp"), expr->type);
@@ -7253,17 +7255,16 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_ignored_expr(c, expr->inner_expr);
return;
case EXPR_PTR_TO_INT:
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
llvm_value_set(value, LLVMBuildPtrToInt(c->builder, value->value, llvm_get_type(c, expr->type), "ptrxi"), expr->type);
return;
case EXPR_INT_TO_PTR:
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
llvm_value_set(value, LLVMBuildIntToPtr(c->builder, value->value, llvm_get_type(c, expr->type), "intptr"), expr->type);
return;
case EXPR_ADDR_CONVERSION:
llvm_emit_expr(c, value, expr->inner_expr);
RETURN_ON_EMPTY_BLOCK(value);
llvm_value_addr(c, value);
value->type = type_lowering(expr->type);
return;
@@ -7272,8 +7273,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
value->type = type_lowering(expr->type);
return;
case EXPR_RVALUE:
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
value->type = type_lowering(expr->type);
return;
case EXPR_VECTOR_FROM_ARRAY:
@@ -7281,6 +7281,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
return;
case EXPR_SLICE_LEN:
llvm_emit_expr(c, value, expr->inner_expr);
RETURN_ON_EMPTY_BLOCK(value);
llvm_emit_slice_len(c, value, value);
return;
case EXPR_PTR_ACCESS:

View File

@@ -555,6 +555,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *ref_expr, Expr
INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr);
INLINE void llvm_emit_statement_chain(GenContext *c, AstId current);
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, ConstInitializer *initializer);
INLINE bool llvm_emit_rvalue_id_in_block(GenContext *c, BEValue *value, ExprId expr_id) { return llvm_emit_rvalue_in_block(c, value, exprptr(expr_id)); }
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);