| ... | ... | @@ -1111,6 +1111,22 @@ fn transOffsetOfExpr( |
| 1111 | 1111 | return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{}); |
| 1112 | 1112 | } |
| 1113 | 1113 | |
| 1114 | /// Cast a signed integer node to a usize, for use in pointer arithmetic. Negative numbers |
| 1115 | /// will become very large positive numbers but that is ok since we only use this in |
| 1116 | /// pointer arithmetic expressions, where wraparound will ensure we get the correct value. |
| 1117 | /// node -> @bitCast(usize, @intCast(isize, node)) |
| 1118 | fn usizeCastForWrappingPtrArithmetic(gpa: *mem.Allocator, node: Node) TransError!Node { |
| 1119 | const intcast_node = try Tag.int_cast.create(gpa, .{ |
| 1120 | .lhs = try Tag.identifier.create(gpa, "isize"), |
| 1121 | .rhs = node, |
| 1122 | }); |
| 1123 | |
| 1124 | return Tag.bit_cast.create(gpa, .{ |
| 1125 | .lhs = try Tag.identifier.create(gpa, "usize"), |
| 1126 | .rhs = intcast_node, |
| 1127 | }); |
| 1128 | } |
| 1129 | |
| 1114 | 1130 | /// Translate an arithmetic expression with a pointer operand and a signed-integer operand. |
| 1115 | 1131 | /// Zig requires a usize argument for pointer arithmetic, so we intCast to isize and then |
| 1116 | 1132 | /// bitcast to usize; pointer wraparound make the math work. |
| ... | ... | @@ -1133,15 +1149,7 @@ fn transCreatePointerArithmeticSignedOp( |
| 1133 | 1149 | const lhs_node = try transExpr(c, scope, swizzled_lhs, .used); |
| 1134 | 1150 | const rhs_node = try transExpr(c, scope, swizzled_rhs, .used); |
| 1135 | 1151 | |
| 1136 | | const intcast_node = try Tag.int_cast.create(c.arena, .{ |
| 1137 | | .lhs = try Tag.identifier.create(c.arena, "isize"), |
| 1138 | | .rhs = rhs_node, |
| 1139 | | }); |
| 1140 | | |
| 1141 | | const bitcast_node = try Tag.bit_cast.create(c.arena, .{ |
| 1142 | | .lhs = try Tag.identifier.create(c.arena, "usize"), |
| 1143 | | .rhs = intcast_node, |
| 1144 | | }); |
| 1152 | const bitcast_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node); |
| 1145 | 1153 | |
| 1146 | 1154 | const arith_args = .{ .lhs = lhs_node, .rhs = bitcast_node }; |
| 1147 | 1155 | const arith_node = try if (is_add) Tag.add.create(c.arena, arith_args) else Tag.sub.create(c.arena, arith_args); |
| ... | ... | @@ -3035,6 +3043,7 @@ fn transCreateCompoundAssign( |
| 3035 | 3043 | const lhs_qt = getExprQualType(c, lhs); |
| 3036 | 3044 | const rhs_qt = getExprQualType(c, rhs); |
| 3037 | 3045 | const is_signed = cIsSignedInteger(lhs_qt); |
| 3046 | const is_ptr_op_signed = qualTypeIsPtr(lhs_qt) and cIsSignedInteger(rhs_qt); |
| 3038 | 3047 | const requires_int_cast = blk: { |
| 3039 | 3048 | const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt); |
| 3040 | 3049 | const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt); |
| ... | ... | @@ -3061,6 +3070,10 @@ fn transCreateCompoundAssign( |
| 3061 | 3070 | else |
| 3062 | 3071 | try transExpr(c, scope, rhs, .used); |
| 3063 | 3072 | |
| 3073 | if (is_ptr_op_signed) { |
| 3074 | rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node); |
| 3075 | } |
| 3076 | |
| 3064 | 3077 | if (is_shift or requires_int_cast) { |
| 3065 | 3078 | // @intCast(rhs) |
| 3066 | 3079 | const cast_to_type = if (is_shift) |
| ... | ... | @@ -3113,6 +3126,9 @@ fn transCreateCompoundAssign( |
| 3113 | 3126 | |
| 3114 | 3127 | rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 3115 | 3128 | } |
| 3129 | if (is_ptr_op_signed) { |
| 3130 | rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node); |
| 3131 | } |
| 3116 | 3132 | |
| 3117 | 3133 | const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used); |
| 3118 | 3134 | try block_scope.statements.append(assign); |