mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- Crash in slice expression when it contains a rethrow #2872
- Multiple issues when rethrowing inside of expressions #2873
This commit is contained in:
@@ -148,6 +148,8 @@
|
||||
- Vector shift by optional scalar failed #2868
|
||||
- Initializer did not correctly handle second rethrow #2870
|
||||
- Crash encountering panic in if-else style switch #2871
|
||||
- Crash in slice expression when it contains a rethrow #2872
|
||||
- Multiple issues when rethrowing inside of expressions #2873
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// #target: macos-x64
|
||||
// #safe: yes
|
||||
module abc_faults;
|
||||
module abc <Type>;
|
||||
import std::io, abc_faults, std::collections::list;
|
||||
struct TextTemplate
|
||||
{
|
||||
TextTag tags;
|
||||
}
|
||||
struct TextTag
|
||||
{
|
||||
usz start;
|
||||
}
|
||||
fn void? TextTemplate.init(&self, String template, String tag_start = "", String tag_end = "", Allocator using )
|
||||
{
|
||||
String tmpl = template;
|
||||
while (true)
|
||||
{
|
||||
usz? end = tmpl.index_of(tag_end);
|
||||
if (catch end) return ;
|
||||
tmpl = tmpl[end + io::EOF~!..];
|
||||
}
|
||||
}
|
||||
module text_test;
|
||||
import abc;
|
||||
alias FooTmpl = TextTemplate{Foo};
|
||||
alias BarTmpl = TextTemplate{Bar};
|
||||
struct Foo
|
||||
{
|
||||
BarTmpl bar;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
String bar;
|
||||
}
|
||||
fn void main()
|
||||
{
|
||||
String foo_tmpl = "";
|
||||
FooTmpl ft;
|
||||
ft.init(foo_tmpl, using: tmem)!!;
|
||||
}
|
||||
197
test/test_suite/expressions/optional_rethrow_multi.c3t
Normal file
197
test/test_suite/expressions/optional_rethrow_multi.c3t
Normal file
@@ -0,0 +1,197 @@
|
||||
// #target: macos-x64
|
||||
// #safe: yes
|
||||
module test;
|
||||
import std;
|
||||
struct Doc { Head *head; }
|
||||
struct Head { char[]* title; }
|
||||
struct Summary
|
||||
{
|
||||
char* title;
|
||||
}
|
||||
macro dupe(value)
|
||||
{
|
||||
$typeof(&value) temp = malloc($sizeof(value));
|
||||
if (!temp) return OUT_OF_MEMORY~;
|
||||
return temp;
|
||||
}
|
||||
faultdef BAD_READ, OUT_OF_MEMORY;
|
||||
fn Doc? readDoc(char[] )
|
||||
{
|
||||
char* str = malloc( + 1);
|
||||
return { dupe((Head) { .title = dupe(str[..io::EOF~! - 1])! })! };
|
||||
}
|
||||
fn Summary buildSummary(Doc )
|
||||
{
|
||||
return {
|
||||
};
|
||||
}
|
||||
fn Summary readAndBuildSummary(char[] url)
|
||||
{
|
||||
return buildSummary(readDoc(url)) ?? (Summary) { .title = null, };
|
||||
}
|
||||
fn void main()
|
||||
{
|
||||
const char[][] URLS = { "", "", "", "", };
|
||||
foreach ( url : URLS)
|
||||
{
|
||||
Summary summary = readAndBuildSummary(url);
|
||||
}
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i64 @test.readDoc(ptr %0, ptr %1, i64 %2) #0 {
|
||||
entry:
|
||||
%.anon = alloca %"char[]", align 8
|
||||
%str = alloca ptr, align 8
|
||||
%reterr = alloca i64, align 8
|
||||
%literal = alloca %Doc, align 8
|
||||
%error_var = alloca i64, align 8
|
||||
%literal1 = alloca %Head, align 8
|
||||
%error_var2 = alloca i64, align 8
|
||||
%error_var3 = alloca i64, align 8
|
||||
store ptr %1, ptr %.anon, align 8
|
||||
%ptradd = getelementptr inbounds i8, ptr %.anon, i64 8
|
||||
store i64 %2, ptr %ptradd, align 8
|
||||
%3 = call ptr @std.core.mem.malloc(i64 1) #3
|
||||
store ptr %3, ptr %str, align 8
|
||||
store ptr null, ptr %literal1, align 8
|
||||
%4 = load ptr, ptr %str, align 8
|
||||
store i64 ptrtoint (ptr @std.io.EOF to i64), ptr %error_var3, align 8
|
||||
br label %guard_block
|
||||
|
||||
guard_block: ; preds = %entry
|
||||
%5 = load i64, ptr %error_var3, align 8
|
||||
ret i64 %5
|
||||
}
|
||||
|
||||
define ptr @test.buildSummary(ptr %0) #0 {
|
||||
entry:
|
||||
%.anon = alloca %Doc, align 8
|
||||
%literal = alloca %Summary, align 8
|
||||
store ptr %0, ptr %.anon, align 8
|
||||
store ptr null, ptr %literal, align 8
|
||||
%1 = load ptr, ptr %literal, align 8
|
||||
ret ptr %1
|
||||
}
|
||||
|
||||
define ptr @test.readAndBuildSummary(ptr %0, i64 %1) #0 {
|
||||
entry:
|
||||
%url = alloca %"char[]", align 8
|
||||
%retparam = alloca %Doc, align 8
|
||||
%result = alloca %Summary, align 8
|
||||
%literal = alloca %Summary, align 8
|
||||
store ptr %0, ptr %url, align 8
|
||||
%ptradd = getelementptr inbounds i8, ptr %url, i64 8
|
||||
store i64 %1, ptr %ptradd, align 8
|
||||
%lo = load ptr, ptr %url, align 8
|
||||
%ptradd1 = getelementptr inbounds i8, ptr %url, i64 8
|
||||
%hi = load i64, ptr %ptradd1, align 8
|
||||
%2 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi)
|
||||
%not_err = icmp eq i64 %2, 0
|
||||
%3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %3, label %after_check, label %else_block
|
||||
|
||||
after_check: ; preds = %entry
|
||||
%4 = load ptr, ptr %retparam, align 8
|
||||
%5 = call ptr @test.buildSummary(ptr %4)
|
||||
store ptr %5, ptr %result, align 8
|
||||
br label %phi_block
|
||||
|
||||
else_block: ; preds = %entry
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false)
|
||||
br label %phi_block
|
||||
|
||||
phi_block: ; preds = %else_block, %after_check
|
||||
%val = phi ptr [ %result, %after_check ], [ %literal, %else_block ]
|
||||
%6 = load ptr, ptr %val, align 8
|
||||
ret ptr %6
|
||||
}
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%.anon = alloca i64, align 8
|
||||
%url = alloca %"char[]", align 8
|
||||
%taddr = alloca i64, align 8
|
||||
%taddr1 = alloca i64, align 8
|
||||
%varargslots = alloca [2 x %any], align 16
|
||||
%indirectarg = alloca %"any[]", align 8
|
||||
%taddr3 = alloca i64, align 8
|
||||
%taddr4 = alloca i64, align 8
|
||||
%varargslots5 = alloca [2 x %any], align 16
|
||||
%indirectarg8 = alloca %"any[]", align 8
|
||||
%summary = alloca %Summary, align 8
|
||||
%result = alloca %Summary, align 8
|
||||
%0 = load i64, ptr getelementptr inbounds (i8, ptr @main.URLS, i64 8), align 8
|
||||
store i64 0, ptr %.anon, align 8
|
||||
br label %loop.cond
|
||||
|
||||
loop.cond: ; preds = %checkok9, %entry
|
||||
%1 = load i64, ptr %.anon, align 8
|
||||
%lt = icmp ult i64 %1, %0
|
||||
br i1 %lt, label %loop.body, label %loop.exit
|
||||
|
||||
loop.body: ; preds = %loop.cond
|
||||
%2 = load i64, ptr getelementptr inbounds (i8, ptr @main.URLS, i64 8), align 8
|
||||
%3 = load ptr, ptr @main.URLS, align 8
|
||||
%4 = load i64, ptr %.anon, align 8
|
||||
%ge = icmp uge i64 %4, %2
|
||||
%5 = call i1 @llvm.expect.i1(i1 %ge, i1 false)
|
||||
br i1 %5, label %panic, label %checkok
|
||||
|
||||
checkok: ; preds = %loop.body
|
||||
%ptroffset = getelementptr inbounds [16 x i8], ptr %3, i64 %4
|
||||
%6 = ptrtoint ptr %ptroffset to i64
|
||||
%7 = urem i64 %6, 8
|
||||
%8 = icmp ne i64 %7, 0
|
||||
%9 = call i1 @llvm.expect.i1(i1 %8, i1 false)
|
||||
br i1 %9, label %panic2, label %checkok9
|
||||
|
||||
checkok9: ; preds = %checkok
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false)
|
||||
%lo = load ptr, ptr %url, align 8
|
||||
%ptradd10 = getelementptr inbounds i8, ptr %url, i64 8
|
||||
%hi = load i64, ptr %ptradd10, align 8
|
||||
%10 = call ptr @test.readAndBuildSummary(ptr %lo, i64 %hi)
|
||||
store ptr %10, ptr %result, align 8
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 8, i1 false)
|
||||
%11 = load i64, ptr %.anon, align 8
|
||||
%addnuw = add nuw i64 %11, 1
|
||||
store i64 %addnuw, ptr %.anon, align 8
|
||||
br label %loop.cond
|
||||
|
||||
loop.exit: ; preds = %loop.cond
|
||||
ret void
|
||||
|
||||
panic: ; preds = %loop.body
|
||||
store i64 %2, ptr %taddr, align 8
|
||||
%12 = insertvalue %any undef, ptr %taddr, 0
|
||||
%13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1
|
||||
store i64 %4, ptr %taddr1, align 8
|
||||
%14 = insertvalue %any undef, ptr %taddr1, 0
|
||||
%15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1
|
||||
store %any %13, ptr %varargslots, align 16
|
||||
%ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16
|
||||
store %any %15, ptr %ptradd, align 16
|
||||
%16 = insertvalue %"any[]" undef, ptr %varargslots, 0
|
||||
%"$$temp" = insertvalue %"any[]" %16, i64 2, 1
|
||||
store %"any[]" %"$$temp", ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.panic_msg, i64 59, ptr @.file, i64 25, ptr @.func, i64 4, i32 33, ptr byval(%"any[]") align 8 %indirectarg) #4
|
||||
unreachable
|
||||
|
||||
panic2: ; preds = %checkok
|
||||
store i64 8, ptr %taddr3, align 8
|
||||
%17 = insertvalue %any undef, ptr %taddr3, 0
|
||||
%18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1
|
||||
store i64 %7, ptr %taddr4, align 8
|
||||
%19 = insertvalue %any undef, ptr %taddr4, 0
|
||||
%20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1
|
||||
store %any %18, ptr %varargslots5, align 16
|
||||
%ptradd6 = getelementptr inbounds i8, ptr %varargslots5, i64 16
|
||||
store %any %20, ptr %ptradd6, align 16
|
||||
%21 = insertvalue %"any[]" undef, ptr %varargslots5, 0
|
||||
%"$$temp7" = insertvalue %"any[]" %21, i64 2, 1
|
||||
store %"any[]" %"$$temp7", ptr %indirectarg8, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 94, ptr @.file, i64 25, ptr @.func, i64 4, i32 33, ptr byval(%"any[]") align 8 %indirectarg8) #4
|
||||
unreachable
|
||||
}
|
||||
Reference in New Issue
Block a user