for loops
This commit is contained in:
+59
-5
@@ -146,6 +146,10 @@ llvm_type :: proc(value: types.Type, store: ^types.Store = nil) -> string {
|
||||
return "ptr"
|
||||
case .Slice:
|
||||
return "{ ptr, i64 }"
|
||||
case .Range:
|
||||
item, _ := types.node(store, value)
|
||||
child := llvm_type(item.child, store)
|
||||
return fmt.tprintf("{{ %s, %s, i1 }}", child, child)
|
||||
case .Array:
|
||||
item, _ := types.node(store, value)
|
||||
return fmt.tprintf("[%d x %s]", types.physical_count(value, store), llvm_type(item.child, store))
|
||||
@@ -232,7 +236,8 @@ valid_value :: proc(
|
||||
}
|
||||
switch instructions[value_id].op {
|
||||
case .Param, .Const, .String, .Aggregate, .None, .Optional_Some,
|
||||
.Load_Global, .Function_Address, .Address_Of, .Load, .Slice, .Length, .Slice_Ptr, .Unwrap,
|
||||
.Load_Global, .Function_Address, .Address_Of, .Load, .Slice, .Length, .Slice_Ptr,
|
||||
.Extract, .Select, .Unwrap,
|
||||
.Optional_Is_Some, .Optional_Value, .Orelse,
|
||||
.Widen, .C_Vararg_Promote, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer,
|
||||
.Neg_Checked, .Add_Checked, .Pointer_Add, .Not, .Compare, .Call:
|
||||
@@ -551,6 +556,8 @@ emit_instruction_stream :: proc(
|
||||
expected_count = int(item.field_count)
|
||||
} else if ok && item.kind == .Union {
|
||||
expected_count = 1
|
||||
} else if ok && item.kind == .Range {
|
||||
expected_count = 3
|
||||
} else {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid aggregate type")
|
||||
continue
|
||||
@@ -585,6 +592,8 @@ emit_instruction_stream :: proc(
|
||||
element_type := item.child
|
||||
if item.kind == .Struct {
|
||||
element_type = types.fields_for(&emitter.module.types, instruction.type)[arg_index].type
|
||||
} else if item.kind == .Range && arg_index == 2 {
|
||||
element_type = types.BOOL
|
||||
}
|
||||
final := arg_index == total-1
|
||||
if final {
|
||||
@@ -924,6 +933,46 @@ emit_instruction_stream :: proc(
|
||||
} else {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid container pointer")
|
||||
}
|
||||
case .Extract:
|
||||
if !valid_instruction(instructions, instruction.a) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid aggregate extraction")
|
||||
continue
|
||||
}
|
||||
aggregate_type := instructions[instruction.a].type
|
||||
item, ok := types.node(&emitter.module.types, aggregate_type)
|
||||
field_index := int(instruction.integer)
|
||||
expected_type := types.INVALID
|
||||
if ok && item.kind == .Range && field_index >= 0 && field_index < 3 {
|
||||
expected_type = types.BOOL if field_index == 2 else item.child
|
||||
}
|
||||
if !types.equal(expected_type, instruction.type) ||
|
||||
!valid_value(instructions, instruction.a, aggregate_type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid aggregate extraction")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = extractvalue %s %%v%d, %d\n",
|
||||
instruction_index,
|
||||
llvm_type(aggregate_type, &emitter.module.types),
|
||||
instruction.a,
|
||||
field_index,
|
||||
)
|
||||
case .Select:
|
||||
if len(instruction.args) != 2 ||
|
||||
!valid_value(instructions, instruction.a, types.BOOL, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.args[0], instruction.type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.args[1], instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid selection")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 ", instruction_index)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, types.BOOL, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %s ", llvm_type(instruction.type, &emitter.module.types))
|
||||
write_operand(&emitter.builder, instructions, instruction.args[0], instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %s ", llvm_type(instruction.type, &emitter.module.types))
|
||||
write_operand(&emitter.builder, instructions, instruction.args[1], instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
case .Unwrap:
|
||||
optional_type := instructions[instruction.a].type if valid_instruction(instructions, instruction.a) else types.INVALID
|
||||
item, ok := types.node(&emitter.module.types, optional_type)
|
||||
@@ -1152,14 +1201,19 @@ emit_instruction_stream :: proc(
|
||||
emit_trap_call(emitter, message)
|
||||
fmt.sbprintf(&emitter.builder, " unreachable\noverflow_continue%d:\n", instruction_index)
|
||||
case .Pointer_Add:
|
||||
item, ok := types.node(&emitter.module.types, instruction.type)
|
||||
if !ok || item.kind != .Pointer || !item.many ||
|
||||
!valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
result_item, result_ok := types.node(&emitter.module.types, instruction.type)
|
||||
base_type := instructions[instruction.a].type if valid_instruction(instructions, instruction.a) else types.INVALID
|
||||
base_item, base_ok := types.node(&emitter.module.types, base_type)
|
||||
if !result_ok || result_item.kind != .Pointer ||
|
||||
!base_ok || base_item.kind != .Pointer || !base_item.many ||
|
||||
result_item.child != base_item.child ||
|
||||
result_item.mutable != base_item.mutable ||
|
||||
!valid_value(instructions, instruction.a, base_type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.b, types.USIZE, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid pointer offset")
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %%v%d, i64 ", instruction_index, llvm_type(item.child, &emitter.module.types), instruction.a)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %%v%d, i64 ", instruction_index, llvm_type(result_item.child, &emitter.module.types), instruction.a)
|
||||
write_operand(&emitter.builder, instructions, instruction.b, types.USIZE, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
case .Call:
|
||||
|
||||
Reference in New Issue
Block a user