fallible main
This commit is contained in:
+129
-43
@@ -1752,41 +1752,49 @@ lower_global_initializer :: proc(hir_module: ^hir.Module, global: hir.Global, al
|
||||
|
||||
append_injected_main :: proc(module: ^ir.Module, hir_module: ^hir.Module, allocator: mem.Allocator) {
|
||||
main_index, main_ok := hir.index(hir_module.injected_main, hir.INVALID_FUNCTION, len(hir_module.functions))
|
||||
if !main_ok {
|
||||
return
|
||||
}
|
||||
main_function := &hir_module.functions[main_index]
|
||||
provider_index, provider_ok := hir.index(hir_module.io_provider, hir.INVALID_FUNCTION, len(hir_module.functions))
|
||||
if !main_ok || !provider_ok {
|
||||
param_index := -1
|
||||
if len(main_function.params) == 1 {
|
||||
param_index, main_ok = hir.index(main_function.params[0], hir.INVALID_LOCAL, len(main_function.locals))
|
||||
if !main_ok || !provider_ok {
|
||||
return
|
||||
}
|
||||
} else if len(main_function.params) != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
instructions: [dynamic]ir.Instruction
|
||||
instructions.allocator = allocator
|
||||
provider_call := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Call,
|
||||
type=hir_module.functions[provider_index].result,
|
||||
target=ir.function_ref(ir.Function_Id(provider_index)),
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
main_function := &hir_module.functions[main_index]
|
||||
param_index, param_ok := hir.index(main_function.params[0], hir.INVALID_LOCAL, len(main_function.locals))
|
||||
if !param_ok {
|
||||
return
|
||||
args: []ir.Instruction_Id
|
||||
if param_index >= 0 {
|
||||
provider_call := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Call,
|
||||
type=hir_module.functions[provider_index].result,
|
||||
target=ir.function_ref(ir.Function_Id(provider_index)),
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
init_args := make([]ir.Instruction_Id, 1, allocator)
|
||||
init_args[0] = provider_call
|
||||
init_value := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Aggregate,
|
||||
type=main_function.locals[param_index].type,
|
||||
args=init_args,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
args = make([]ir.Instruction_Id, 1, allocator)
|
||||
args[0] = init_value
|
||||
}
|
||||
init_args := make([]ir.Instruction_Id, 1, allocator)
|
||||
init_args[0] = provider_call
|
||||
init_value := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Aggregate,
|
||||
type=main_function.locals[param_index].type,
|
||||
args=init_args,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
args := make([]ir.Instruction_Id, 1, allocator)
|
||||
args[0] = init_value
|
||||
main_call := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Call,
|
||||
@@ -1797,36 +1805,114 @@ append_injected_main :: proc(module: ^ir.Module, hir_module: ^hir.Module, alloca
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
if types.is_void(hir_module.functions[main_index].result) {
|
||||
|
||||
if types.kind(main_function.result, &hir_module.types) == .Fallible {
|
||||
success := types.fallible_success(main_function.result, &hir_module.types)
|
||||
channel_slot := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Return_Void,
|
||||
type=types.VOID,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
op=.Alloca, type=main_function.result, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Return,
|
||||
type=hir_module.functions[main_index].result,
|
||||
target=ir.INVALID_REF,
|
||||
a=main_call,
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
op=.Store, type=main_function.result, target=ir.INVALID_REF,
|
||||
a=channel_slot, b=main_call, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
code := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Union_Tag, type=types.U16, target=ir.INVALID_REF,
|
||||
a=channel_slot, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
zero_tag := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Const, type=types.U16, integer=0, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
ok := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Compare, type=types.BOOL, integer=i64(ir.Compare_Predicate.Eq),
|
||||
target=ir.INVALID_REF, a=code, b=zero_tag,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Cond_Br, type=types.VOID, integer=1, target=ir.Ref(0), a=ok,
|
||||
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Label, type=types.VOID, integer=0, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
failure := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Const, type=types.I32, integer=1, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Return, type=types.I32, target=ir.INVALID_REF, a=failure,
|
||||
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Label, type=types.VOID, integer=1, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
success_value := ir.INVALID_INSTRUCTION
|
||||
if types.is_void(success) {
|
||||
success_value = ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Const, type=types.I32, integer=0, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
payload := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Field_Address, type=success, integer=0, target=ir.INVALID_REF,
|
||||
a=channel_slot, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
success_value = ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Load, type=success, target=ir.INVALID_REF, a=payload,
|
||||
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Return, type=types.I32, target=ir.INVALID_REF, a=success_value,
|
||||
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
exit_value := main_call
|
||||
if types.is_void(main_function.result) {
|
||||
exit_value = ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Const, type=types.I32, integer=0, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Return, type=types.I32, target=ir.INVALID_REF, a=exit_value,
|
||||
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
|
||||
problematic := main_function.problematic
|
||||
if provider_ok {
|
||||
problematic = problematic || hir_module.functions[provider_index].problematic
|
||||
}
|
||||
append(&module.functions, ir.Function{
|
||||
link_name=fmt.aprintf("main", allocator=allocator),
|
||||
calling_convention=.C,
|
||||
implementation=.Definition,
|
||||
linkage=.External,
|
||||
is_main=true,
|
||||
result=hir_module.functions[main_index].result,
|
||||
result=types.I32,
|
||||
instructions=instructions[:],
|
||||
problematic=hir_module.functions[main_index].problematic ||
|
||||
hir_module.functions[provider_index].problematic,
|
||||
problematic=problematic,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user