fallible ergonomics
This commit is contained in:
+53
-1
@@ -254,7 +254,7 @@ valid_value :: proc(
|
||||
switch instructions[value_id].op {
|
||||
case .Param, .Const, .String, .Aggregate, .None, .Optional_Some,
|
||||
.Load_Global, .Function_Address, .Address_Of, .Load, .Union_Tag, .Slice, .Length, .Slice_Ptr,
|
||||
.Extract, .Select, .Unwrap,
|
||||
.Fallible_Error, .Extract, .Select, .Unwrap,
|
||||
.Optional_Is_Some, .Optional_Value, .Orelse,
|
||||
.Widen, .Sum_Widen, .C_Coerce, .C_Vararg_Promote, .Retype, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer,
|
||||
.Neg_Checked, .Add_Checked, .Sub_Checked, .Mul_Checked, .Div_Checked, .Pointer_Add, .Not, .Compare, .Call:
|
||||
@@ -1056,6 +1056,37 @@ emit_instruction_stream :: proc(
|
||||
llvm_type(instruction.type, &emitter.module.types),
|
||||
instruction.a,
|
||||
)
|
||||
case .Fallible_Error:
|
||||
channel_type := instructions[instruction.a].type if valid_instruction(instructions, instruction.a) else types.INVALID
|
||||
error_type := types.fallible_error(channel_type, &emitter.module.types)
|
||||
if !types.equal(error_type, instruction.type) ||
|
||||
!valid_address(instructions, instruction.a, channel_type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid fallible error operand")
|
||||
continue
|
||||
}
|
||||
if types.is_enum(error_type, &emitter.module.types) {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%v%d\n", instruction_index, llvm_type(error_type, &emitter.module.types), instruction.a)
|
||||
continue
|
||||
}
|
||||
if types.is_tagged_union(error_type, &emitter.module.types) {
|
||||
type_name := llvm_type(error_type, &emitter.module.types)
|
||||
align := types.alignment_of(error_type, &emitter.module.types, emitter.module.target)
|
||||
fmt.sbprintf(&emitter.builder, " %%fallible_error_slot%d = alloca %s, align %d\n", instruction_index, type_name, align)
|
||||
fmt.sbprintf(&emitter.builder, " store %s zeroinitializer, ptr %%fallible_error_slot%d\n", type_name, instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%fallible_error_code%d = load i16, ptr %%v%d\n", instruction_index, instruction.a)
|
||||
fmt.sbprintf(&emitter.builder, " store i16 %%fallible_error_code%d, ptr %%fallible_error_slot%d\n", instruction_index, instruction_index)
|
||||
payload_size := types.sum_payload_size(error_type, &emitter.module.types, emitter.module.target)
|
||||
if payload_size > 0 {
|
||||
source_offset := types.fallible_payload_offset(channel_type, &emitter.module.types, emitter.module.target)
|
||||
target_offset := types.union_payload_offset(error_type, &emitter.module.types, emitter.module.target)
|
||||
fmt.sbprintf(&emitter.builder, " %%fallible_error_source%d = getelementptr i8, ptr %%v%d, i64 %d\n", instruction_index, instruction.a, source_offset)
|
||||
fmt.sbprintf(&emitter.builder, " %%fallible_error_payload%d = getelementptr i8, ptr %%fallible_error_slot%d, i64 %d\n", instruction_index, instruction_index, target_offset)
|
||||
fmt.sbprintf(&emitter.builder, " call void @llvm.memcpy.p0.p0.i64(ptr %%fallible_error_payload%d, ptr %%fallible_error_source%d, i64 %d, i1 false)\n", instruction_index, instruction_index, payload_size)
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%fallible_error_slot%d\n", instruction_index, type_name, instruction_index)
|
||||
continue
|
||||
}
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "unsupported fallible error type")
|
||||
case .Store:
|
||||
if !valid_address(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type, &emitter.module.types) {
|
||||
@@ -1324,6 +1355,27 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, ", %s zeroinitializer\n", type_name)
|
||||
continue
|
||||
}
|
||||
if types.is_enum(from_type, &emitter.module.types) && types.is_tagged_union(instruction.type, &emitter.module.types) {
|
||||
to_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
to_align := types.alignment_of(instruction.type, &emitter.module.types, emitter.module.target)
|
||||
fmt.sbprintf(&emitter.builder, " %%sum_to_slot%d = alloca %s, align %d\n", instruction_index, to_name, to_align)
|
||||
fmt.sbprintf(&emitter.builder, " store %s zeroinitializer, ptr %%sum_to_slot%d\n", to_name, instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " store i16 ")
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", ptr %%sum_to_slot%d\n", instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%sum_to_slot%d\n", instruction_index, to_name, instruction_index)
|
||||
continue
|
||||
}
|
||||
if types.is_tagged_union(from_type, &emitter.module.types) && types.is_enum(instruction.type, &emitter.module.types) {
|
||||
from_name := llvm_type(from_type, &emitter.module.types)
|
||||
from_align := types.alignment_of(from_type, &emitter.module.types, emitter.module.target)
|
||||
fmt.sbprintf(&emitter.builder, " %%sum_from_slot%d = alloca %s, align %d\n", instruction_index, from_name, from_align)
|
||||
fmt.sbprintf(&emitter.builder, " store %s ", from_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", ptr %%sum_from_slot%d\n", instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%sum_from_slot%d\n", instruction_index, llvm_type(instruction.type, &emitter.module.types), instruction_index)
|
||||
continue
|
||||
}
|
||||
if types.is_tagged_union(from_type, &emitter.module.types) && types.is_tagged_union(instruction.type, &emitter.module.types) {
|
||||
from_name := llvm_type(from_type, &emitter.module.types)
|
||||
to_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
|
||||
Reference in New Issue
Block a user