compound assignment
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user