compact compiler ids and spans to reduce memory usage
This commit is contained in:
+92
-82
@@ -10,20 +10,20 @@ import "core:mem"
|
||||
State :: struct {
|
||||
hir_module: ^hir.Module,
|
||||
instructions: [dynamic]ir.Instruction,
|
||||
local_values: []int,
|
||||
local_slots: []int,
|
||||
local_values: []ir.Instruction_Id,
|
||||
local_slots: []ir.Instruction_Id,
|
||||
expr_stack: [dynamic]Lower_Expr_Frame,
|
||||
allocator: mem.Allocator,
|
||||
}
|
||||
|
||||
append_instruction :: proc(state: ^State, instruction: ir.Instruction) -> int {
|
||||
id := len(state.instructions)
|
||||
append_instruction :: proc(state: ^State, instruction: ir.Instruction) -> ir.Instruction_Id {
|
||||
id := ir.instruction_id(len(state.instructions))
|
||||
append(&state.instructions, instruction)
|
||||
return id
|
||||
}
|
||||
|
||||
clone_args :: proc(values: []int, allocator: mem.Allocator) -> []int {
|
||||
result := make([]int, len(values), allocator)
|
||||
clone_args :: proc(values: []ir.Instruction_Id, allocator: mem.Allocator) -> []ir.Instruction_Id {
|
||||
result := make([]ir.Instruction_Id, len(values), allocator)
|
||||
copy(result, values)
|
||||
return result
|
||||
}
|
||||
@@ -37,14 +37,19 @@ sentinel :: proc(value_type: types.Type) -> i64 {
|
||||
}
|
||||
}
|
||||
|
||||
append_recovery_value :: proc(state: ^State, span: source.Span, value_type: types.Type, diagnostic := -1) -> int {
|
||||
append_recovery_value :: proc(
|
||||
state: ^State,
|
||||
span: source.Span,
|
||||
value_type: types.Type,
|
||||
diagnostic := source.INVALID_DIAGNOSTIC,
|
||||
) -> ir.Instruction_Id {
|
||||
append_instruction(state, ir.Instruction{
|
||||
op=.Trap,
|
||||
span=span,
|
||||
type=types.VOID,
|
||||
target=-1,
|
||||
a=-1,
|
||||
b=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=diagnostic,
|
||||
})
|
||||
fallback := value_type
|
||||
@@ -56,22 +61,22 @@ append_recovery_value :: proc(state: ^State, span: source.Span, value_type: type
|
||||
span=span,
|
||||
type=fallback,
|
||||
integer=sentinel(fallback),
|
||||
target=-1,
|
||||
a=-1,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
|
||||
Lower_Expr_Frame :: struct {
|
||||
expr: int,
|
||||
expr: hir.Expr_Id,
|
||||
stage: u8,
|
||||
left: int,
|
||||
left: ir.Instruction_Id,
|
||||
arg_index: int,
|
||||
args: []int,
|
||||
args: []ir.Instruction_Id,
|
||||
}
|
||||
|
||||
lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
|
||||
stack := state.expr_stack
|
||||
clear_dynamic_array(&stack)
|
||||
defer {
|
||||
@@ -82,11 +87,11 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
state.expr_stack = stack
|
||||
}
|
||||
append(&stack, Lower_Expr_Frame{expr=expr_id})
|
||||
last := -1
|
||||
last := ir.INVALID_INSTRUCTION
|
||||
for len(stack) > 0 {
|
||||
frame_index := len(stack)-1
|
||||
frame := stack[frame_index]
|
||||
if frame.expr < 0 || frame.expr >= len(state.hir_module.exprs) {
|
||||
if frame.expr == hir.INVALID_EXPR || int(frame.expr) >= len(state.hir_module.exprs) {
|
||||
last = append_recovery_value(state, source.Span{}, types.I64)
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
@@ -100,31 +105,33 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
case .Integer:
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Const, span=expr.span, type=expr.type, integer=expr.integer,
|
||||
target=-1, a=-1, b=-1, diagnostic=-1,
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = pop(&stack)
|
||||
case .Local:
|
||||
last = -1
|
||||
if expr.target >= 0 && expr.target < len(state.local_slots) && state.local_slots[expr.target] >= 0 {
|
||||
last = ir.INVALID_INSTRUCTION
|
||||
local := hir.as_local(expr.target)
|
||||
if local != hir.INVALID_LOCAL && int(local) < len(state.local_slots) && state.local_slots[local] != ir.INVALID_INSTRUCTION {
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Load, span=expr.span, type=expr.type, target=-1,
|
||||
a=state.local_slots[expr.target], b=-1, diagnostic=-1,
|
||||
op=.Load, span=expr.span, type=expr.type, target=ir.INVALID_REF,
|
||||
a=state.local_slots[local], b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else if expr.target >= 0 && expr.target < len(state.local_values) &&
|
||||
state.local_values[expr.target] >= 0 {
|
||||
last = state.local_values[expr.target]
|
||||
} else if local != hir.INVALID_LOCAL && int(local) < len(state.local_values) &&
|
||||
state.local_values[local] != ir.INVALID_INSTRUCTION {
|
||||
last = state.local_values[local]
|
||||
}
|
||||
if last < 0 {
|
||||
if last == ir.INVALID_INSTRUCTION {
|
||||
last = append_recovery_value(state, expr.span, expr.type, expr.diagnostic)
|
||||
}
|
||||
_ = pop(&stack)
|
||||
case .Global:
|
||||
if expr.target < 0 || expr.target >= len(state.hir_module.globals) {
|
||||
global := hir.as_global(expr.target)
|
||||
if global == hir.INVALID_GLOBAL || int(global) >= len(state.hir_module.globals) {
|
||||
last = append_recovery_value(state, expr.span, expr.type, expr.diagnostic)
|
||||
} else {
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Load_Global, span=expr.span, type=expr.type, target=expr.target,
|
||||
a=-1, b=-1, diagnostic=-1,
|
||||
op=.Load_Global, span=expr.span, type=expr.type, target=ir.global_ref(ir.Global_Id(global)),
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
_ = pop(&stack)
|
||||
@@ -135,12 +142,13 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
stack[frame_index].stage = 2
|
||||
append(&stack, Lower_Expr_Frame{expr=expr.left})
|
||||
case .Call:
|
||||
if expr.target < 0 || expr.target >= len(state.hir_module.functions) {
|
||||
function := hir.as_function(expr.target)
|
||||
if function == hir.INVALID_FUNCTION || int(function) >= len(state.hir_module.functions) {
|
||||
last = append_recovery_value(state, expr.span, expr.type, expr.diagnostic)
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
stack[frame_index].args = make([]int, len(expr.args), state.allocator)
|
||||
stack[frame_index].args = make([]ir.Instruction_Id, len(expr.args), state.allocator)
|
||||
stack[frame_index].stage = 4
|
||||
if len(expr.args) > 0 {
|
||||
append(&stack, Lower_Expr_Frame{expr=expr.args[0]})
|
||||
@@ -150,8 +158,8 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
}
|
||||
if frame.stage == 1 {
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Widen, span=expr.span, type=expr.type, target=-1,
|
||||
a=last, b=-1, diagnostic=-1,
|
||||
op=.Widen, span=expr.span, type=expr.type, target=ir.INVALID_REF,
|
||||
a=last, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
@@ -164,8 +172,8 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
}
|
||||
if frame.stage == 3 {
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Add_Checked, span=expr.span, type=expr.type, target=-1,
|
||||
a=frame.left, b=last, diagnostic=-1,
|
||||
op=.Add_Checked, span=expr.span, type=expr.type, target=ir.INVALID_REF,
|
||||
a=frame.left, b=last, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
@@ -180,8 +188,8 @@ lower_expr :: proc(state: ^State, expr_id: int) -> int {
|
||||
}
|
||||
}
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Call, span=expr.span, type=expr.type, target=expr.target,
|
||||
a=-1, b=-1, args=stack[frame_index].args, diagnostic=-1,
|
||||
op=.Call, span=expr.span, type=expr.type, target=ir.function_ref(ir.Function_Id(hir.as_function(expr.target))),
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, args=stack[frame_index].args, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
stack[frame_index].args = nil
|
||||
_ = pop(&stack)
|
||||
@@ -194,8 +202,8 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
state := State{
|
||||
hir_module=hir_module,
|
||||
allocator=allocator,
|
||||
local_values=make([]int, len(function.locals), allocator),
|
||||
local_slots=make([]int, len(function.locals), allocator),
|
||||
local_values=make([]ir.Instruction_Id, len(function.locals), allocator),
|
||||
local_slots=make([]ir.Instruction_Id, len(function.locals), allocator),
|
||||
}
|
||||
state.instructions.allocator = allocator
|
||||
state.expr_stack.allocator = allocator
|
||||
@@ -205,17 +213,17 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
delete(state.expr_stack)
|
||||
}
|
||||
for _, index in state.local_values {
|
||||
state.local_values[index] = -1
|
||||
state.local_slots[index] = -1
|
||||
state.local_values[index] = ir.INVALID_INSTRUCTION
|
||||
state.local_slots[index] = ir.INVALID_INSTRUCTION
|
||||
}
|
||||
for local_id in function.params {
|
||||
param := append_instruction(&state, ir.Instruction{
|
||||
op=.Param,
|
||||
type=function.locals[local_id].type,
|
||||
target=local_id,
|
||||
a=-1,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
target=ir.local_ref(ir.Local_Id(local_id)),
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
state.local_values[local_id] = param
|
||||
}
|
||||
@@ -225,10 +233,10 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
switch statement.kind {
|
||||
case .Declaration:
|
||||
value := lower_expr(&state, statement.expr)
|
||||
if statement.local < 0 || statement.local >= len(function.locals) {
|
||||
if statement.local == hir.INVALID_LOCAL || int(statement.local) >= len(function.locals) {
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Trap, span=statement.span, type=types.VOID,
|
||||
target=-1, a=-1, b=-1, diagnostic=statement.diagnostic,
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=statement.diagnostic,
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -238,34 +246,34 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
op=.Alloca,
|
||||
span=statement.span,
|
||||
type=local.type,
|
||||
target=statement.local,
|
||||
a=-1,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
target=ir.local_ref(ir.Local_Id(statement.local)),
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
state.local_slots[statement.local] = slot
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Store,
|
||||
span=statement.span,
|
||||
type=local.type,
|
||||
target=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=slot,
|
||||
b=value,
|
||||
diagnostic=-1,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
state.local_values[statement.local] = value
|
||||
}
|
||||
case .Assignment:
|
||||
value := lower_expr(&state, statement.expr)
|
||||
slot := -1
|
||||
if statement.local >= 0 && statement.local < len(state.local_slots) {
|
||||
slot := ir.INVALID_INSTRUCTION
|
||||
if statement.local != hir.INVALID_LOCAL && int(statement.local) < len(state.local_slots) {
|
||||
slot = state.local_slots[statement.local]
|
||||
}
|
||||
if slot < 0 || statement.local < 0 || statement.local >= len(function.locals) {
|
||||
if slot == ir.INVALID_INSTRUCTION || statement.local == hir.INVALID_LOCAL || int(statement.local) >= len(function.locals) {
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Trap, span=statement.span, type=types.VOID,
|
||||
target=-1, a=-1, b=-1, diagnostic=statement.diagnostic,
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=statement.diagnostic,
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -273,21 +281,21 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
op=.Store,
|
||||
span=statement.span,
|
||||
type=function.locals[statement.local].type,
|
||||
target=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=slot,
|
||||
b=value,
|
||||
diagnostic=-1,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
case .Return:
|
||||
if statement.expr < 0 {
|
||||
if statement.expr == hir.INVALID_EXPR {
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Return_Void,
|
||||
span=statement.span,
|
||||
type=types.VOID,
|
||||
target=-1,
|
||||
a=-1,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
value := lower_expr(&state, statement.expr)
|
||||
@@ -295,10 +303,10 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
op=.Return,
|
||||
span=statement.span,
|
||||
type=function.result,
|
||||
target=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=value,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
case .Expression, .Sink:
|
||||
@@ -308,9 +316,9 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
op=.Trap,
|
||||
span=statement.span,
|
||||
type=types.VOID,
|
||||
target=-1,
|
||||
a=-1,
|
||||
b=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=statement.diagnostic,
|
||||
})
|
||||
}
|
||||
@@ -319,18 +327,18 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
(state.instructions[len(state.instructions)-1].op != .Return &&
|
||||
state.instructions[len(state.instructions)-1].op != .Return_Void) {
|
||||
if function.result.kind == .Void {
|
||||
append_instruction(&state, ir.Instruction{op=.Return_Void, type=types.VOID, target=-1, a=-1, b=-1, diagnostic=-1})
|
||||
append_instruction(&state, ir.Instruction{op=.Return_Void, type=types.VOID, target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC})
|
||||
} else {
|
||||
value := append_instruction(&state, ir.Instruction{
|
||||
op=.Const,
|
||||
type=function.result,
|
||||
integer=sentinel(function.result),
|
||||
target=-1,
|
||||
a=-1,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append_instruction(&state, ir.Instruction{op=.Return, type=function.result, target=-1, a=value, b=-1, diagnostic=-1})
|
||||
append_instruction(&state, ir.Instruction{op=.Return, type=function.result, target=ir.INVALID_REF, a=value, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC})
|
||||
}
|
||||
}
|
||||
return state.instructions[:]
|
||||
@@ -345,10 +353,10 @@ lower_global_initializer :: proc(hir_module: ^hir.Module, global: hir.Global, al
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Return,
|
||||
type=global.type,
|
||||
target=-1,
|
||||
target=ir.INVALID_REF,
|
||||
a=value,
|
||||
b=-1,
|
||||
diagnostic=-1,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return state.instructions[:]
|
||||
}
|
||||
@@ -356,6 +364,7 @@ lower_global_initializer :: proc(hir_module: ^hir.Module, global: hir.Global, al
|
||||
lower :: proc(hir_module: ^hir.Module, allocator := context.allocator) -> ir.Module {
|
||||
module := ir.init_module(allocator)
|
||||
for global in hir_module.globals {
|
||||
_ = ir.global_id(len(module.globals))
|
||||
append(&module.globals, ir.Global{
|
||||
name=global.name,
|
||||
type=global.type,
|
||||
@@ -371,6 +380,7 @@ lower :: proc(hir_module: ^hir.Module, allocator := context.allocator) -> ir.Mod
|
||||
for local_id, index in function.params {
|
||||
param_types[index] = function.locals[local_id].type
|
||||
}
|
||||
_ = ir.function_id(len(module.functions))
|
||||
append(&module.functions, ir.Function{
|
||||
link_name=fmt.aprintf("%s", function.link_name, allocator=allocator),
|
||||
calling_convention=.C if function.calling_convention == .C else .Brolang,
|
||||
|
||||
Reference in New Issue
Block a user