Translate an arithmetic expression with a pointer operand and a signed-integer operand. Zig requires a usize argument for pointer arithmetic, so we intCast to isize and then bitcast to usize; pointer wraparound makes the math work. Zig pointer addition is not commutative (unlike C); the pointer operand needs to be on the left. The + operator in C is not a sequence point so it should be safe to switch the order if necessary.
fn transPointerArithmeticSignedOp(t: *Translator, scope: *Scope, bin: Node.Binary, op_id: ZigTag) TransError!ZigNode
fn transPointerArithmeticSignedOp(t: *Translator, scope: *Scope, bin: Node.Binary, op_id: ZigTag) TransError!ZigNode {
std.debug.assert(op_id == .add or op_id == .sub);
const lhs_qt = bin.lhs.qt(t.tree);
const swap_operands = op_id == .add and t.signedness(lhs_qt) == .signed;
const swizzled_lhs = if (swap_operands) bin.rhs else bin.lhs;
const swizzled_rhs = if (swap_operands) bin.lhs else bin.rhs;
const lhs_node = try t.transExpr(scope, swizzled_lhs, .used);
const rhs_node = try t.transExpr(scope, swizzled_rhs, .used);
const bitcast_node = try t.usizeCastForWrappingPtrArithmetic(rhs_node);
return t.createBinOpNode(op_id, lhs_node, bitcast_node);
}