compound assignment

This commit is contained in:
2026-06-22 21:20:15 +02:00
parent 663f4dc658
commit 6512ccd543
14 changed files with 995 additions and 99 deletions
+52 -4
View File
@@ -124,9 +124,11 @@ lower_location :: proc(state: ^State, expr_id: hir.Expr_Id, for_write := false)
return lower_nested_expr(state, expr.left)
case .Index:
container_type := state.hir_module.exprs[expr.left].type
container := lower_nested_expr(state, expr.left)
container := ir.INVALID_INSTRUCTION
if types.is_array(container_type, &state.hir_module.types) {
container = lower_location(state, expr.left, for_write)
} else {
container = lower_nested_expr(state, expr.left)
}
index := lower_nested_expr(state, expr.right)
return append_instruction(state, ir.Instruction{
@@ -137,9 +139,11 @@ lower_location :: proc(state: ^State, expr_id: hir.Expr_Id, for_write := false)
})
case .Field:
base_type := state.hir_module.exprs[expr.left].type
base := lower_nested_expr(state, expr.left)
base := ir.INVALID_INSTRUCTION
if !types.is_pointer(base_type, &state.hir_module.types) {
base = lower_location(state, expr.left, for_write)
} else {
base = lower_nested_expr(state, expr.left)
}
return append_instruction(state, ir.Instruction{
op=.Field_Address, span=expr.span, type=expr.type, integer=expr.integer,
@@ -468,7 +472,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
case .Negate:
stack[frame_index].stage = 5
append(&stack, Lower_Expr_Frame{expr=expr.left})
case .Add, .Pointer_Add:
case .Add, .Sub, .Mul, .Div, .Pointer_Add:
stack[frame_index].stage = 2
append(&stack, Lower_Expr_Frame{expr=expr.left})
case .Call:
@@ -537,8 +541,15 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
continue
}
if frame.stage == 3 {
op := ir.Opcode.Add_Checked
#partial switch expr.kind {
case .Sub: op = .Sub_Checked
case .Mul: op = .Mul_Checked
case .Div: op = .Div_Checked
case .Pointer_Add: op = .Pointer_Add
}
last = append_instruction(state, ir.Instruction{
op=.Pointer_Add if expr.kind == .Pointer_Add else .Add_Checked,
op=op,
span=expr.span, type=expr.type, target=ir.INVALID_REF,
a=frame.left, b=last, diagnostic=source.INVALID_DIAGNOSTIC,
})
@@ -605,6 +616,43 @@ lower_statements :: proc(state: ^State, statements: []hir.Stmt_Id) {
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .Assignment:
if statement.assignment_op != .Set && statement.target != hir.INVALID_EXPR {
address := lower_location(state, statement.target, true)
target_type := types.INVALID
if int(statement.target) < len(hir_module.exprs) {
target_type = hir_module.exprs[statement.target].type
}
if address == ir.INVALID_INSTRUCTION || !types.is_valid(target_type) {
append_instruction(state, ir.Instruction{
op=.Trap, span=statement.span, type=types.VOID,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=statement.diagnostic,
})
continue
}
current := append_instruction(state, ir.Instruction{
op=.Load, span=statement.span, type=target_type,
target=ir.INVALID_REF, a=address, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
rhs := lower_expr(state, statement.expr)
op := ir.Opcode.Add_Checked
#partial switch statement.assignment_op {
case .Sub: op = .Sub_Checked
case .Mul: op = .Mul_Checked
case .Div: op = .Div_Checked
case .Pointer_Add: op = .Pointer_Add
}
value := append_instruction(state, ir.Instruction{
op=op, span=statement.span, type=target_type,
target=ir.INVALID_REF, a=current, b=rhs,
diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Store, span=statement.span, type=target_type,
target=ir.INVALID_REF, a=address, b=value, diagnostic=source.INVALID_DIAGNOSTIC,
})
continue
}
value := lower_expr(state, statement.expr)
slot := ir.INVALID_INSTRUCTION
value_type := types.INVALID