compact compiler ids and spans to reduce memory usage
This commit is contained in:
+46
-43
@@ -49,11 +49,11 @@ sentinel :: proc(value_type: types.Type) -> i64 {
|
||||
}
|
||||
}
|
||||
|
||||
valid_instruction :: proc(instructions: []ir.Instruction, instruction_id: int) -> bool {
|
||||
return instruction_id >= 0 && instruction_id < len(instructions)
|
||||
valid_instruction :: proc(instructions: []ir.Instruction, instruction_id: ir.Instruction_Id) -> bool {
|
||||
return instruction_id != ir.INVALID_INSTRUCTION && int(instruction_id) < len(instructions)
|
||||
}
|
||||
|
||||
valid_value :: proc(instructions: []ir.Instruction, value_id: int, expected: types.Type) -> bool {
|
||||
valid_value :: proc(instructions: []ir.Instruction, value_id: ir.Instruction_Id, expected: types.Type) -> bool {
|
||||
if !valid_instruction(instructions, value_id) ||
|
||||
!types.is_concrete_integer(expected) ||
|
||||
!types.equal(instructions[value_id].type, expected) {
|
||||
@@ -68,7 +68,7 @@ valid_value :: proc(instructions: []ir.Instruction, value_id: int, expected: typ
|
||||
return false
|
||||
}
|
||||
|
||||
write_operand :: proc(builder: ^strings.Builder, instructions: []ir.Instruction, value_id: int, expected: types.Type) {
|
||||
write_operand :: proc(builder: ^strings.Builder, instructions: []ir.Instruction, value_id: ir.Instruction_Id, expected: types.Type) {
|
||||
if !valid_value(instructions, value_id, expected) {
|
||||
fmt.sbprintf(builder, "%d", sentinel(expected))
|
||||
return
|
||||
@@ -88,8 +88,8 @@ register_message :: proc(emitter: ^Emitter, text: string) -> int {
|
||||
return id
|
||||
}
|
||||
|
||||
diagnostic_message :: proc(emitter: ^Emitter, diagnostic: int, span: source.Span, fallback: string) -> int {
|
||||
if diagnostic >= 0 && diagnostic < len(emitter.diagnostics.items) {
|
||||
diagnostic_message :: proc(emitter: ^Emitter, diagnostic: source.Diagnostic_Id, span: source.Span, fallback: string) -> int {
|
||||
if _, ok := source.diagnostic_index(diagnostic, len(emitter.diagnostics.items)); ok {
|
||||
message := source.format(emitter.diagnostics, diagnostic, emitter.allocator)
|
||||
id := register_message(emitter, message)
|
||||
delete(message, emitter.allocator)
|
||||
@@ -137,7 +137,7 @@ emit_recovery_value :: proc(emitter: ^Emitter, instruction_id: int, instruction:
|
||||
}
|
||||
}
|
||||
|
||||
emit_call_args :: proc(builder: ^strings.Builder, instructions: []ir.Instruction, args: []int, param_types: []types.Type) {
|
||||
emit_call_args :: proc(builder: ^strings.Builder, instructions: []ir.Instruction, args: []ir.Instruction_Id, param_types: []types.Type) {
|
||||
for arg, index in args {
|
||||
if index > 0 {
|
||||
strings.write_string(builder, ", ")
|
||||
@@ -152,60 +152,62 @@ emit_instruction_stream :: proc(
|
||||
instructions: []ir.Instruction,
|
||||
function: ir.Function,
|
||||
global_initializer := false,
|
||||
) -> int {
|
||||
return_value := -1
|
||||
) -> ir.Instruction_Id {
|
||||
return_value := ir.INVALID_INSTRUCTION
|
||||
after_return := false
|
||||
for instruction, instruction_id in instructions {
|
||||
for instruction, instruction_index in instructions {
|
||||
instruction_id := ir.instruction_id(instruction_index)
|
||||
if after_return {
|
||||
fmt.sbprintf(&emitter.builder, "recover_after_return_%d:\n", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, "recover_after_return_%d:\n", instruction_index)
|
||||
after_return = false
|
||||
}
|
||||
switch instruction.op {
|
||||
case .Param, .Const:
|
||||
case .Load_Global:
|
||||
if instruction.target < 0 || instruction.target >= len(emitter.module.globals) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid global reference")
|
||||
global_id := ir.as_global(instruction.target)
|
||||
if global_id == ir.INVALID_GLOBAL || int(global_id) >= len(emitter.module.globals) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid global reference")
|
||||
continue
|
||||
}
|
||||
global := emitter.module.globals[instruction.target]
|
||||
global := emitter.module.globals[global_id]
|
||||
if !types.equal(instruction.type, global.type) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid global reference type")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid global reference type")
|
||||
continue
|
||||
}
|
||||
if global.is_static {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = load %s, ptr @bro.g.%d\n",
|
||||
instruction_id,
|
||||
instruction_index,
|
||||
llvm_type(global.type),
|
||||
instruction.target,
|
||||
global_id,
|
||||
)
|
||||
} else {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = call %s @bro.get.%d()\n",
|
||||
instruction_id,
|
||||
instruction_index,
|
||||
llvm_type(global.type),
|
||||
instruction.target,
|
||||
global_id,
|
||||
)
|
||||
}
|
||||
case .Alloca:
|
||||
if !types.is_concrete_integer(instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid allocation type")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid allocation type")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = alloca %s\n", instruction_id, llvm_type(instruction.type))
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = alloca %s\n", instruction_index, llvm_type(instruction.type))
|
||||
case .Load:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
instructions[instruction.a].op != .Alloca ||
|
||||
!types.equal(instructions[instruction.a].type, instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid load slot")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid load slot")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = load %s, ptr %%v%d\n",
|
||||
instruction_id,
|
||||
instruction_index,
|
||||
llvm_type(instruction.type),
|
||||
instruction.a,
|
||||
)
|
||||
@@ -214,7 +216,7 @@ emit_instruction_stream :: proc(
|
||||
instructions[instruction.a].op != .Alloca ||
|
||||
!types.equal(instructions[instruction.a].type, instruction.type) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid store operand")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid store operand")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " store %s ", llvm_type(instruction.type))
|
||||
@@ -225,50 +227,51 @@ emit_instruction_stream :: proc(
|
||||
!types.is_concrete_integer(instructions[instruction.a].type) ||
|
||||
!types.is_concrete_integer(instruction.type) ||
|
||||
instructions[instruction.a].type.bits >= instruction.type.bits {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid widening operand")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid widening operand")
|
||||
continue
|
||||
}
|
||||
from_type := instructions[instruction.a].type
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = sext %s ", instruction_id, llvm_type(from_type))
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = sext %s ", instruction_index, llvm_type(from_type))
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type)
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type))
|
||||
case .Add_Checked:
|
||||
if !valid_value(instructions, instruction.a, instruction.type) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid addition operand")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid addition operand")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type)
|
||||
fmt.sbprintf(&emitter.builder, " %%pair%d = call ", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, " %%pair%d = call ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } @llvm.sadd.with.overflow.%s(%s ", type_name, type_name, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type)
|
||||
fmt.sbprintf(&emitter.builder, ", %s ", type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.b, instruction.type)
|
||||
fmt.sbprintf(&emitter.builder, ")\n")
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = extractvalue ", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = extractvalue ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 0\n", type_name, instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, " %%overflow%d = extractvalue ", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 0\n", type_name, instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%overflow%d = extractvalue ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 1\n", type_name, instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 1\n", type_name, instruction_index)
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" br i1 %%overflow%d, label %%overflow_trap%d, label %%overflow_continue%d\n",
|
||||
instruction_id,
|
||||
instruction_id,
|
||||
instruction_id,
|
||||
instruction_index,
|
||||
instruction_index,
|
||||
instruction_index,
|
||||
)
|
||||
fmt.sbprintf(&emitter.builder, "overflow_trap%d:\n", instruction_id)
|
||||
message := diagnostic_message(emitter, -1, instruction.span, "signed integer addition overflow")
|
||||
fmt.sbprintf(&emitter.builder, "overflow_trap%d:\n", instruction_index)
|
||||
message := diagnostic_message(emitter, source.INVALID_DIAGNOSTIC, instruction.span, "signed integer addition overflow")
|
||||
emit_trap_call(emitter, message)
|
||||
fmt.sbprintf(&emitter.builder, " unreachable\noverflow_continue%d:\n", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, " unreachable\noverflow_continue%d:\n", instruction_index)
|
||||
case .Call:
|
||||
if instruction.target < 0 || instruction.target >= len(emitter.module.functions) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid function specialization")
|
||||
function_id := ir.as_function(instruction.target)
|
||||
if function_id == ir.INVALID_FUNCTION || int(function_id) >= len(emitter.module.functions) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid function specialization")
|
||||
continue
|
||||
}
|
||||
target := emitter.module.functions[instruction.target]
|
||||
target := emitter.module.functions[function_id]
|
||||
valid_args := len(instruction.args) == len(target.param_types)
|
||||
if valid_args {
|
||||
for arg, index in instruction.args {
|
||||
@@ -283,11 +286,11 @@ emit_instruction_stream :: proc(
|
||||
target_result = types.I32
|
||||
}
|
||||
if !valid_args || !types.equal(instruction.type, target_result) {
|
||||
emit_recovery_value(emitter, instruction_id, instruction, "invalid function call operands")
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid function call operands")
|
||||
continue
|
||||
}
|
||||
if instruction.type.kind != .Void {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = ", instruction_id)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = ", instruction_index)
|
||||
} else {
|
||||
strings.write_string(&emitter.builder, " ")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user