feat: supply process arguments through native startup
This commit is contained in:
@@ -1756,16 +1756,47 @@ configure_entry_point :: proc(checker: ^Checker) {
|
||||
if io_package == ast.INVALID_PACKAGE {
|
||||
return
|
||||
}
|
||||
init_item, init_ok := types.node(&checker.module.types, parameter_type)
|
||||
init_fields := types.fields_for(&checker.module.types, parameter_type)
|
||||
io_field_name := symbol.intern(checker.symbols, "io")
|
||||
if !init_ok || init_item.kind != .Struct || init_item.tuple || init_item.c_layout ||
|
||||
len(init_fields) != 1 || init_fields[0].name != u32(io_field_name) ||
|
||||
!types.equal(types.resolve_alias(init_fields[0].type, &checker.module.types), io_type) {
|
||||
args_name := symbol.intern(checker.symbols, "Args")
|
||||
args_type := types.resolve_alias(
|
||||
types.find_named(&checker.module.types, u32(process_package), u32(args_name)),
|
||||
&checker.module.types,
|
||||
)
|
||||
args_item, args_ok := types.node(&checker.module.types, args_type)
|
||||
args_fields := types.fields_for(&checker.module.types, args_type)
|
||||
values_name := symbol.intern(checker.symbols, "values")
|
||||
argument_pointer := types.pointer(&checker.module.types, types.U8, false, true, true, 0)
|
||||
argument_values := types.slice(&checker.module.types, argument_pointer, false)
|
||||
if !args_ok || args_item.kind != .Struct || args_item.tuple || args_item.c_layout ||
|
||||
len(args_fields) != 1 || args_fields[0].name != u32(values_name) ||
|
||||
!types.equal(types.resolve_alias(args_fields[0].type, &checker.module.types), argument_values) {
|
||||
checker.template_diagnostics[main_template] = source.add(
|
||||
checker.diagnostics,
|
||||
main.span,
|
||||
"@std/process Init must be an auto-layout record containing exactly 'io io.Io'",
|
||||
"@std/process Args must be an auto-layout record containing exactly 'values [][*;0]u8'",
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
init_item, init_ok := types.node(&checker.module.types, parameter_type)
|
||||
init_fields := types.fields_for(&checker.module.types, parameter_type)
|
||||
io_field_name := symbol.intern(checker.symbols, "io")
|
||||
args_field_name := symbol.intern(checker.symbols, "args")
|
||||
io_field_ok, args_field_ok := false, false
|
||||
for field in init_fields {
|
||||
field_type := types.resolve_alias(field.type, &checker.module.types)
|
||||
if field.name == u32(io_field_name) && types.equal(field_type, io_type) {
|
||||
io_field_ok = true
|
||||
}
|
||||
if field.name == u32(args_field_name) && types.equal(field_type, args_type) {
|
||||
args_field_ok = true
|
||||
}
|
||||
}
|
||||
if !init_ok || init_item.kind != .Struct || init_item.tuple || init_item.c_layout ||
|
||||
len(init_fields) != 2 || !io_field_ok || !args_field_ok {
|
||||
checker.template_diagnostics[main_template] = source.add(
|
||||
checker.diagnostics,
|
||||
main.span,
|
||||
"@std/process Init must be an auto-layout record containing exactly 'io io.Io' and 'args Args'",
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1782,8 +1782,56 @@ append_injected_main :: proc(module: ^ir.Module, hir_module: ^hir.Module, alloca
|
||||
|
||||
instructions: [dynamic]ir.Instruction
|
||||
instructions.allocator = allocator
|
||||
param_types: []types.Type
|
||||
args: []ir.Instruction_Id
|
||||
if param_index >= 0 {
|
||||
init_type := main_function.locals[param_index].type
|
||||
init_fields := types.fields_for(&module.types, init_type)
|
||||
io_index := 0
|
||||
if !types.equal(
|
||||
types.resolve_alias(init_fields[0].type, &module.types),
|
||||
types.resolve_alias(hir_module.functions[provider_index].result, &module.types),
|
||||
) {
|
||||
io_index = 1
|
||||
}
|
||||
args_index := 1 - io_index
|
||||
args_type := types.resolve_alias(init_fields[args_index].type, &module.types)
|
||||
values_type := types.resolve_alias(types.fields_for(&module.types, args_type)[0].type, &module.types)
|
||||
argument_pointer := types.child_type(values_type, &module.types)
|
||||
argv_type := types.pointer(&module.types, argument_pointer, false, true)
|
||||
param_types = make([]types.Type, 2, allocator)
|
||||
param_types[0] = types.C_INT
|
||||
param_types[1] = argv_type
|
||||
for param_type, index in param_types {
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Param, type=param_type, target=ir.local_ref(ir.Local_Id(index)),
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
count := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Scalar_Cast, type=types.USIZE, target=ir.INVALID_REF,
|
||||
a=ir.Instruction_Id(0), b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
slice_args := make([]ir.Instruction_Id, 2, allocator)
|
||||
slice_args[0] = ir.INVALID_INSTRUCTION
|
||||
slice_args[1] = count
|
||||
values := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Slice, type=values_type, args=slice_args, target=ir.INVALID_REF,
|
||||
a=ir.Instruction_Id(1), b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
values_args := make([]ir.Instruction_Id, 1, allocator)
|
||||
values_args[0] = values
|
||||
process_args := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Aggregate, type=args_type, args=values_args, target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
provider_call := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Call,
|
||||
@@ -1793,12 +1841,13 @@ append_injected_main :: proc(module: ^ir.Module, hir_module: ^hir.Module, alloca
|
||||
b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
init_args := make([]ir.Instruction_Id, 1, allocator)
|
||||
init_args[0] = provider_call
|
||||
init_args := make([]ir.Instruction_Id, len(init_fields), allocator)
|
||||
init_args[io_index] = provider_call
|
||||
init_args[args_index] = process_args
|
||||
init_value := ir.instruction_id(len(instructions))
|
||||
append(&instructions, ir.Instruction{
|
||||
op=.Aggregate,
|
||||
type=main_function.locals[param_index].type,
|
||||
type=init_type,
|
||||
args=init_args,
|
||||
target=ir.INVALID_REF,
|
||||
a=ir.INVALID_INSTRUCTION,
|
||||
@@ -1923,6 +1972,7 @@ append_injected_main :: proc(module: ^ir.Module, hir_module: ^hir.Module, alloca
|
||||
implementation=.Definition,
|
||||
linkage=.External,
|
||||
is_main=true,
|
||||
param_types=param_types,
|
||||
result=types.I32,
|
||||
instructions=instructions[:],
|
||||
problematic=problematic,
|
||||
|
||||
Reference in New Issue
Block a user