diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-10-12 17:51:36 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-10-12 17:51:36 +0100 |
| commit | f3209584a3ae22afc84f2bde6899e248bc86a154 (patch) | |
| tree | 603caa5452dbd3b03ea0b7f6b3cf352f9ad640f4 /src | |
| parent | f5318c46d13ed3f3de20e0f61c4193e6ad46a42b (diff) | |
Add Pointer Arithmetic
Diffstat (limited to 'src')
| -rw-r--r-- | src/checker/checker.cpp | 41 | ||||
| -rw-r--r-- | src/checker/expr.cpp | 101 | ||||
| -rw-r--r-- | src/checker/stmt.cpp | 6 | ||||
| -rw-r--r-- | src/checker/type.cpp | 46 | ||||
| -rw-r--r-- | src/codegen/codegen.cpp | 9 | ||||
| -rw-r--r-- | src/codegen/print_llvm.cpp | 27 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 57 | ||||
| -rw-r--r-- | src/exact_value.cpp | 4 |
8 files changed, 220 insertions, 71 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index a62d95042..f044b6f36 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -126,8 +126,8 @@ enum BuiltinProcId { BuiltinProc_swizzle, - BuiltinProc_ptr_offset, - BuiltinProc_ptr_sub, + // BuiltinProc_ptr_offset, + // BuiltinProc_ptr_sub, BuiltinProc_slice_ptr, BuiltinProc_min, @@ -170,8 +170,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT("swizzle"), 1, true, Expr_Expr}, - {STR_LIT("ptr_offset"), 2, false, Expr_Expr}, - {STR_LIT("ptr_sub"), 2, false, Expr_Expr}, + // {STR_LIT("ptr_offset"), 2, false, Expr_Expr}, + // {STR_LIT("ptr_sub"), 2, false, Expr_Expr}, {STR_LIT("slice_ptr"), 2, true, Expr_Expr}, {STR_LIT("min"), 2, false, Expr_Expr}, @@ -757,6 +757,10 @@ void add_type_info_type(Checker *c, Type *t) { } } break; + case Type_Maybe: + add_type_info_type(c, bt->Maybe.elem); + break; + case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break; @@ -905,25 +909,26 @@ void init_preload_types(Checker *c) { t_type_info_member = record->other_fields[0]->type; t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member); - if (record->field_count != 17) { + if (record->field_count != 18) { compiler_error("Invalid `Type_Info` layout"); } t_type_info_named = record->fields[ 1]->type; t_type_info_integer = record->fields[ 2]->type; t_type_info_float = record->fields[ 3]->type; - t_type_info_string = record->fields[ 4]->type; - t_type_info_boolean = record->fields[ 5]->type; - t_type_info_pointer = record->fields[ 6]->type; - t_type_info_maybe = record->fields[ 7]->type; - t_type_info_procedure = record->fields[ 8]->type; - t_type_info_array = record->fields[ 9]->type; - t_type_info_slice = record->fields[10]->type; - t_type_info_vector = record->fields[11]->type; - t_type_info_tuple = record->fields[12]->type; - t_type_info_struct = record->fields[13]->type; - t_type_info_union = record->fields[14]->type; - t_type_info_raw_union = record->fields[15]->type; - t_type_info_enum = record->fields[16]->type; + t_type_info_any = record->fields[ 4]->type; + t_type_info_string = record->fields[ 5]->type; + t_type_info_boolean = record->fields[ 6]->type; + t_type_info_pointer = record->fields[ 7]->type; + t_type_info_maybe = record->fields[ 8]->type; + t_type_info_procedure = record->fields[ 9]->type; + t_type_info_array = record->fields[10]->type; + t_type_info_slice = record->fields[11]->type; + t_type_info_vector = record->fields[12]->type; + t_type_info_tuple = record->fields[13]->type; + t_type_info_struct = record->fields[14]->type; + t_type_info_union = record->fields[15]->type; + t_type_info_raw_union = record->fields[16]->type; + t_type_info_enum = record->fields[17]->type; } if (t_allocator == NULL) { diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index c0c2e3a18..44fe990f0 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -555,6 +555,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke struct_type->Record.fields = reordered_fields; } + + type_set_offsets(c->sizes, c->allocator, struct_type); } void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) { @@ -1232,13 +1234,27 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { // TODO(bill): Handle errors correctly Type *type = base_type(base_vector_type(o->type)); switch (op.kind) { - case Token_Add: case Token_Sub: + case Token_SubEq: + if (!is_type_numeric(type) && !is_type_pointer(type)) { + error(op, "Operator `%.*s` is only allowed with numeric or pointer expressions", LIT(op.string)); + return false; + } + if (is_type_pointer(type)) { + o->type = t_int; + } + if (base_type(type) == t_rawptr) { + gbString str = type_to_string(type); + defer (gb_string_free(str)); + error(ast_node_token(o->expr), "Invalid pointer type for pointer arithmetic: `%s`", str); + return false; + } + break; + + case Token_Add: case Token_Mul: case Token_Quo: - case Token_AddEq: - case Token_SubEq: case Token_MulEq: case Token_QuoEq: if (!is_type_numeric(type)) { @@ -1732,6 +1748,44 @@ String check_down_cast_name(Type *dst_, Type *src_) { return result; } +Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offset, AstNode *node) { + GB_ASSERT(node->kind == AstNode_BinaryExpr); + ast_node(be, BinaryExpr, node); + GB_ASSERT(is_type_pointer(ptr->type)); + GB_ASSERT(is_type_integer(offset->type)); + GB_ASSERT(op == Token_Add || op == Token_Sub); + + Operand operand = {}; + operand.mode = Addressing_Value; + operand.type = ptr->type; + operand.expr = node; + + if (base_type(ptr->type) == t_rawptr) { + gbString str = type_to_string(ptr->type); + defer (gb_string_free(str)); + error(ast_node_token(node), "Invalid pointer type for pointer arithmetic: `%s`", str); + operand.mode = Addressing_Invalid; + return operand; + } + + + if (ptr->mode == Addressing_Constant && offset->mode == Addressing_Constant) { + i64 elem_size = type_size_of(c->sizes, c->allocator, ptr->type); + i64 ptr_val = ptr->value.value_pointer; + i64 offset_val = exact_value_to_integer(offset->value).value_integer; + i64 new_ptr_val = ptr_val; + if (op == Token_Add) { + new_ptr_val += elem_size*offset_val; + } else { + new_ptr_val -= elem_size*offset_val; + } + operand.mode = Addressing_Constant; + operand.value = make_exact_value_pointer(new_ptr_val); + } + + return operand; +} + void check_binary_expr(Checker *c, Operand *x, AstNode *node) { PROF_PROC(); @@ -1904,14 +1958,35 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { Token op = be->op; - if (token_is_shift(op)) { check_shift(c, x, y, node); return; } + if (op.kind == Token_Add || op.kind == Token_Sub) { + if (is_type_pointer(x->type) && is_type_integer(y->type)) { + *x = check_ptr_addition(c, op.kind, x, y, node); + return; + } else if (is_type_integer(x->type) && is_type_pointer(y->type)) { + if (op.kind == Token_Sub) { + gbString lhs = expr_to_string(x->expr); + gbString rhs = expr_to_string(y->expr); + defer (gb_string_free(lhs)); + defer (gb_string_free(rhs)); + error(ast_node_token(node), "Invalid pointer arithmetic, did you mean `%s %.*s %s`?", rhs, LIT(op.string), lhs); + x->mode = Addressing_Invalid; + return; + } + *x = check_ptr_addition(c, op.kind, y, x, node); + return; + } + } + + convert_to_typed(c, x, y->type); - if (x->mode == Addressing_Invalid) return; + if (x->mode == Addressing_Invalid) { + return; + } convert_to_typed(c, y, x->type); if (y->mode == Addressing_Invalid) { x->mode = Addressing_Invalid; @@ -1952,12 +2027,14 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { b32 fail = false; switch (y->value.kind) { case ExactValue_Integer: - if (y->value.value_integer == 0) + if (y->value.value_integer == 0) { fail = true; + } break; case ExactValue_Float: - if (y->value.value_float == 0.0) + if (y->value.value_float == 0.0) { fail = true; + } break; } @@ -1975,6 +2052,14 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { ExactValue b = y->value; Type *type = base_type(x->type); + if (is_type_pointer(type)) { + GB_ASSERT(op.kind == Token_Sub); + i64 bytes = a.value_pointer - b.value_pointer; + i64 diff = bytes/type_size_of(c->sizes, c->allocator, type); + x->value = make_exact_value_pointer(diff); + return; + } + if (type->kind != Type_Basic) { gbString xt = type_to_string(x->type); defer (gb_string_free(xt)); @@ -2788,6 +2873,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) operand->mode = Addressing_Value; } break; +#if 0 case BuiltinProc_ptr_offset: { // ptr_offset :: proc(ptr: ^T, offset: int) -> ^T // ^T cannot be rawptr @@ -2890,6 +2976,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) operand->mode = Addressing_Value; } } break; +#endif case BuiltinProc_slice_ptr: { // slice_ptr :: proc(a: ^T, len: int[, cap: int]) -> []T diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index e4927345e..0b703edac 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -1007,14 +1007,16 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { Operand operand = {Addressing_Invalid}; AstNode binary_expr = {AstNode_BinaryExpr}; ast_node(be, BinaryExpr, &binary_expr); - be->op = op; + be->op = op; + be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add)); // NOTE(bill): Only use the first one will be used be->left = as->lhs[0]; be->right = as->rhs[0]; check_binary_expr(c, &operand, &binary_expr); - if (operand.mode == Addressing_Invalid) + if (operand.mode == Addressing_Invalid) { return; + } // NOTE(bill): Only use the first one will be used check_assignment_variable(c, &operand, as->lhs[0]); } break; diff --git a/src/checker/type.cpp b/src/checker/type.cpp index bf8a0bd6b..e7122c072 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -367,6 +367,7 @@ gb_global Type *t_type_info_member_ptr = NULL; gb_global Type *t_type_info_named = NULL; gb_global Type *t_type_info_integer = NULL; gb_global Type *t_type_info_float = NULL; +gb_global Type *t_type_info_any = NULL; gb_global Type *t_type_info_string = NULL; gb_global Type *t_type_info_boolean = NULL; gb_global Type *t_type_info_pointer = NULL; @@ -380,7 +381,6 @@ gb_global Type *t_type_info_struct = NULL; gb_global Type *t_type_info_union = NULL; gb_global Type *t_type_info_raw_union = NULL; gb_global Type *t_type_info_enum = NULL; -gb_global Type *t_type_info_any = NULL; gb_global Type *t_allocator = NULL; gb_global Type *t_allocator_ptr = NULL; @@ -990,8 +990,11 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t); i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index); i64 align_formula(i64 size, i64 align) { - i64 result = size + align-1; - return result - result%align; + if (align > 0) { + i64 result = size + align-1; + return result - result%align; + } + return size; } i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { @@ -1025,16 +1028,7 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { case Type_Record: { switch (t->Record.kind) { case TypeRecord_Struct: - if (!t->Record.struct_is_packed) { - i64 max = 1; - for (isize i = 0; i < t->Record.field_count; i++) { - i64 align = type_align_of(s, allocator, t->Record.fields[i]->type); - if (max < align) { - max = align; - } - } - return max; - } else if (t->Record.field_count > 0) { + if (t->Record.field_count > 0) { return type_align_of(s, allocator, t->Record.fields[0]->type); } break; @@ -1141,17 +1135,19 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { i64 total_size_in_bits = bit_size * count; i64 total_size = (total_size_in_bits+7)/8; return total_size; - - // i64 alignment = align_formula(size, align); - // return alignment*(count-1) + size; } break; case Type_Slice: // ptr + len + cap return 3 * s.word_size; - case Type_Maybe: // value + bool - return type_size_of(s, allocator, t->Maybe.elem) + type_size_of(s, allocator, t_bool); + case Type_Maybe: { // value + bool + Type *elem = t->Maybe.elem; + i64 align = type_align_of(s, allocator, elem); + i64 size = align_formula(type_size_of(s, allocator, elem), align); + size += type_size_of(s, allocator, t_bool); + return align_formula(size, align); + } case Type_Record: { switch (t->Record.kind) { @@ -1161,7 +1157,10 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { return 0; } type_set_offsets(s, allocator, t); - return t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type); + // TODO(bill): Is this how it should work? + i64 size = t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type); + i64 align = type_align_of(s, allocator, t); + return align_formula(size, align); } break; case TypeRecord_Union: { @@ -1174,7 +1173,10 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { max = size; } // NOTE(bill): Align to int - return align_formula(max, s.word_size) + type_size_of(s, allocator, t_int); + i64 align = type_align_of(s, allocator, t); + isize size = align_formula(max, s.word_size); + size += type_size_of(s, allocator, t_int); + return align_formula(size, align); } break; case TypeRecord_RawUnion: { @@ -1185,7 +1187,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { if (max < size) max = size; } - return max; + // TODO(bill): Is this how it should work? + i64 align = type_align_of(s, allocator, t); + return align_formula(max, align); } break; case TypeRecord_Enum: { diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 6ca29902a..7d84a6c7b 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -377,6 +377,10 @@ void ssa_gen_tree(ssaGen *s) { case Basic_string: tag = ssa_add_local_generated(proc, t_type_info_string); break; + + case Basic_any: + tag = ssa_add_local_generated(proc, t_type_info_any); + break; } break; @@ -445,13 +449,12 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index); type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet - for (isize i = 0; i < t->Record.field_count; i++) { + for (isize source_index = 0; source_index < t->Record.field_count; source_index++) { // TODO(bill): Order fields in source order not layout order - Entity *f = t->Record.fields_in_src_order[i]; + Entity *f = t->Record.fields_in_src_order[source_index]; ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type); i64 foffset = t->Record.struct_offsets[f->Variable.field_index]; GB_ASSERT(f->kind == Entity_Variable && f->Variable.field); - isize source_index = f->Variable.field_index; ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index)); ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr); diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index 427407570..1c2e0929d 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -268,6 +268,16 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) { void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type); void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Type *elem_type) { + ssa_print_type(f, m, elem_type); + ssa_fprintf(f, " "); + + if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { + Type *t = base_type(elem_type)->Maybe.elem; + ssa_fprintf(f, "{"); + ssa_print_type(f, m, t); + ssa_fprintf(f, " "); + } + if (v.kind == ExactValue_Invalid) { ssa_fprintf(f, "zeroinitializer"); } else if (v.kind == ExactValue_String) { @@ -290,6 +300,13 @@ void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Ty } else { ssa_print_exact_value(f, m, v, elem_type); } + + if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { + ssa_fprintf(f, ", "); + ssa_print_type(f, m, t_bool); + ssa_fprintf(f, " "); + ssa_fprintf(f, "true}"); + } } void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type) { @@ -367,9 +384,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ if (i > 0) { ssa_fprintf(f, ", "); } - ssa_print_type(f, m, elem_type); - ssa_fprintf(f, " "); - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]); GB_ASSERT(tav != NULL); ssa_print_compound_element(f, m, tav->value, elem_type); @@ -402,8 +416,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ if (i > 0) { ssa_fprintf(f, ", "); } - ssa_print_type(f, m, elem_type); - ssa_fprintf(f, " "); ssa_print_compound_element(f, m, tav->value, elem_type); } } else { @@ -411,9 +423,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ if (i > 0) { ssa_fprintf(f, ", "); } - ssa_print_type(f, m, elem_type); - ssa_fprintf(f, " "); - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]); GB_ASSERT(tav != NULL); ssa_print_compound_element(f, m, tav->value, elem_type); @@ -476,8 +485,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ } Type *elem_type = type->Record.fields[i]->type; - ssa_print_type(f, m, elem_type); - ssa_fprintf(f, " "); ssa_print_compound_element(f, m, values[i], elem_type); } diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 3b6f7d8b7..9a4508aa2 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -1462,8 +1462,47 @@ void ssa_pop_target_list(ssaProcedure *proc) { } +ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offset) { + ssaValue *gep = NULL; + offset = ssa_emit_conv(proc, offset, t_int); + gep = ssa_make_instr_get_element_ptr(proc, ptr, offset, NULL, 1, false); + gep->Instr.GetElementPtr.result_type = ssa_type(ptr); + return ssa_emit(proc, gep); +} ssaValue *ssa_emit_arith(ssaProcedure *proc, TokenKind op, ssaValue *left, ssaValue *right, Type *type) { + Type *t_left = ssa_type(left); + Type *t_right = ssa_type(right); + + if (op == Token_Add) { + if (is_type_pointer(t_left)) { + ssaValue *ptr = ssa_emit_conv(proc, left, type); + ssaValue *offset = right; + return ssa_emit_ptr_offset(proc, ptr, offset); + } else if (is_type_pointer(ssa_type(right))) { + ssaValue *ptr = ssa_emit_conv(proc, right, type); + ssaValue *offset = left; + return ssa_emit_ptr_offset(proc, ptr, offset); + } + } else if (op == Token_Sub) { + if (is_type_pointer(t_left) && is_type_integer(t_right)) { + // ptr - int + ssaValue *ptr = ssa_emit_conv(proc, left, type); + ssaValue *offset = right; + return ssa_emit_ptr_offset(proc, ptr, offset); + } else if (is_type_pointer(t_left) && is_type_pointer(t_right)) { + GB_ASSERT(is_type_integer(type)); + Type *ptr_type = t_left; + ssaModule *m = proc->module; + ssaValue *x = ssa_emit_conv(proc, left, type); + ssaValue *y = ssa_emit_conv(proc, right, type); + ssaValue *diff = ssa_emit_arith(proc, op, x, y, type); + ssaValue *elem_size = ssa_make_const_int(m->allocator, type_size_of(m->sizes, m->allocator, ptr_type)); + return ssa_emit_arith(proc, Token_Quo, diff, elem_size, type); + } + } + + switch (op) { case Token_AndNot: { // NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1) @@ -1510,13 +1549,7 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, TokenKind op_kind, ssaValue *left, s return ssa_emit(proc, ssa_make_instr_binary_op(proc, op_kind, left, right, result)); } -ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offset) { - ssaValue *gep = NULL; - offset = ssa_emit_conv(proc, offset, t_int); - gep = ssa_make_instr_get_element_ptr(proc, ptr, offset, NULL, 1, false); - gep->Instr.GetElementPtr.result_type = ssa_type(ptr); - return ssa_emit(proc, gep); -} + ssaValue *ssa_emit_zero_gep(ssaProcedure *proc, ssaValue *s) { ssaValue *gep = NULL; @@ -2824,6 +2857,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; +#if 0 case BuiltinProc_ptr_offset: { ssa_emit_comment(proc, make_string("ptr_offset")); ssaValue *ptr = ssa_build_expr(proc, ce->args[0]); @@ -2847,6 +2881,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue return v; } break; +#endif case BuiltinProc_slice_ptr: { ssa_emit_comment(proc, make_string("slice_ptr")); @@ -3440,7 +3475,13 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { void ssa_build_assign_op(ssaProcedure *proc, ssaAddr lhs, ssaValue *value, TokenKind op) { ssaValue *old_value = ssa_lvalue_load(proc, lhs); Type *type = ssa_type(old_value); - ssaValue *change = ssa_emit_conv(proc, value, type); + + ssaValue *change = value; + if (is_type_pointer(type) && is_type_integer(ssa_type(value))) { + change = ssa_emit_conv(proc, value, default_type(ssa_type(value))); + } else { + change = ssa_emit_conv(proc, value, type); + } ssaValue *new_value = ssa_emit_arith(proc, op, old_value, change, type); ssa_lvalue_store(proc, lhs, new_value); } diff --git a/src/exact_value.cpp b/src/exact_value.cpp index c8c47ea60..c83dc2d75 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -91,9 +91,9 @@ ExactValue make_exact_value_float(f64 f) { return result; } -ExactValue make_exact_value_pointer(void *ptr) { +ExactValue make_exact_value_pointer(i64 ptr) { ExactValue result = {ExactValue_Pointer}; - result.value_pointer = cast(i64)cast(intptr)ptr; + result.value_pointer = ptr; return result; } |