distinct type aliasing
This commit is contained in:
+49
-21
@@ -135,35 +135,39 @@ c_abi_result_type :: proc(value: types.Type, store: ^types.Store) -> string {
|
||||
}
|
||||
|
||||
llvm_type :: proc(value: types.Type, store: ^types.Store = nil) -> string {
|
||||
if types.is_void(value) {
|
||||
resolved := value
|
||||
if store != nil {
|
||||
resolved = types.runtime_representation(value, store)
|
||||
}
|
||||
if types.is_void(resolved) {
|
||||
return "void"
|
||||
}
|
||||
if types.is_bool(value) {
|
||||
if types.is_bool(resolved) {
|
||||
return "i1"
|
||||
}
|
||||
#partial switch types.kind(value, store) {
|
||||
#partial switch types.kind(resolved, store) {
|
||||
case .Pointer:
|
||||
return "ptr"
|
||||
case .Slice:
|
||||
return "{ ptr, i64 }"
|
||||
case .Range:
|
||||
item, _ := types.node(store, value)
|
||||
item, _ := types.node(store, resolved)
|
||||
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))
|
||||
item, _ := types.node(store, resolved)
|
||||
return fmt.tprintf("[%d x %s]", types.physical_count(resolved, store), llvm_type(item.child, store))
|
||||
case .Optional:
|
||||
item, _ := types.node(store, value)
|
||||
item, _ := types.node(store, resolved)
|
||||
if types.is_pointer(item.child, store) {
|
||||
return "ptr"
|
||||
}
|
||||
return fmt.tprintf("{{ i1, %s }}", llvm_type(item.child, store))
|
||||
case .Struct, .Union:
|
||||
return fmt.tprintf("%%bro.type.%d", value)
|
||||
return fmt.tprintf("%%bro.type.%d", resolved)
|
||||
}
|
||||
selected := store.selected if store != nil else target.DEFAULT
|
||||
repr := types.representation(value, selected)
|
||||
repr := types.representation(resolved, selected)
|
||||
if types.is_float(repr) {
|
||||
return "float" if types.bits(repr) == 32 else "double"
|
||||
}
|
||||
@@ -207,11 +211,15 @@ emit_function_result :: proc(builder: ^strings.Builder, function: ir.Function, s
|
||||
strings.write_string(builder, function_result_type(function, store))
|
||||
}
|
||||
|
||||
sentinel :: proc(value_type: types.Type, selected := target.DEFAULT) -> i64 {
|
||||
if types.is_bool(value_type) {
|
||||
sentinel :: proc(value_type: types.Type, store: ^types.Store = nil, selected := target.DEFAULT) -> i64 {
|
||||
repr := value_type
|
||||
if store != nil {
|
||||
repr = types.runtime_representation(value_type, store)
|
||||
}
|
||||
if types.is_bool(repr) {
|
||||
return 0
|
||||
}
|
||||
switch types.bits(value_type, selected) {
|
||||
switch types.bits(repr, selected) {
|
||||
case 8: return -86
|
||||
case 16: return -21846
|
||||
case 32: return -1431655766
|
||||
@@ -239,7 +247,7 @@ valid_value :: proc(
|
||||
.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,
|
||||
.Widen, .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:
|
||||
return true
|
||||
case .Address_Global, .Alloca, .Index_Address, .Field_Address, .Orelse_Begin,
|
||||
@@ -270,18 +278,22 @@ valid_address :: proc(
|
||||
}
|
||||
|
||||
write_constant :: proc(builder: ^strings.Builder, value: i64, value_type: types.Type, store: ^types.Store = nil) {
|
||||
if !types.is_concrete_scalar(value_type) {
|
||||
resolved := value_type
|
||||
if store != nil {
|
||||
resolved = types.runtime_representation(value_type, store)
|
||||
}
|
||||
if !types.is_concrete_scalar(resolved) {
|
||||
strings.write_string(builder, "zeroinitializer")
|
||||
return
|
||||
}
|
||||
if types.is_bool(value_type) {
|
||||
if types.is_bool(resolved) {
|
||||
strings.write_string(builder, "true" if value != 0 else "false")
|
||||
return
|
||||
}
|
||||
selected := store.selected if store != nil else target.DEFAULT
|
||||
if types.is_float(value_type, selected) {
|
||||
if types.is_float(resolved, selected) {
|
||||
text := ""
|
||||
if types.bits(value_type, selected) == 32 {
|
||||
if types.bits(resolved, selected) == 32 {
|
||||
bits := u32(value)
|
||||
number := transmute(f32)bits
|
||||
text = fmt.tprintf("%.9g", number)
|
||||
@@ -306,7 +318,7 @@ write_operand :: proc(
|
||||
store: ^types.Store,
|
||||
) {
|
||||
if !valid_value(instructions, value_id, expected, store) {
|
||||
write_constant(builder, sentinel(expected, store.selected), expected, store)
|
||||
write_constant(builder, sentinel(expected, store, store.selected), expected, store)
|
||||
return
|
||||
}
|
||||
value := instructions[value_id]
|
||||
@@ -378,7 +390,7 @@ emit_recovery_value :: proc(emitter: ^Emitter, instruction_id: int, instruction:
|
||||
" %%v%d = add %s 0, %d\n",
|
||||
instruction_id,
|
||||
llvm_type(instruction.type, &emitter.module.types),
|
||||
sentinel(instruction.type, emitter.module.target),
|
||||
sentinel(instruction.type, &emitter.module.types, emitter.module.target),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -388,9 +400,9 @@ emit_recovery_value :: proc(emitter: ^Emitter, instruction_id: int, instruction:
|
||||
instruction_id,
|
||||
llvm_type(instruction.type, &emitter.module.types),
|
||||
)
|
||||
write_constant(&emitter.builder, sentinel(instruction.type, emitter.module.target), instruction.type, &emitter.module.types)
|
||||
write_constant(&emitter.builder, sentinel(instruction.type, &emitter.module.types, emitter.module.target), instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %s ", llvm_type(instruction.type, &emitter.module.types))
|
||||
write_constant(&emitter.builder, sentinel(instruction.type, emitter.module.target), instruction.type, &emitter.module.types)
|
||||
write_constant(&emitter.builder, sentinel(instruction.type, &emitter.module.types, emitter.module.target), instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
}
|
||||
}
|
||||
@@ -1206,6 +1218,22 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = %s %s ", instruction_index, operation, llvm_type(from_type, &emitter.module.types))
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type, &emitter.module.types))
|
||||
case .Retype:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_construct_distinct(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid distinct type construction")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 true, %s ", instruction_index, type_name)
|
||||
write_operand(
|
||||
&emitter.builder,
|
||||
instructions,
|
||||
instruction.a,
|
||||
instructions[instruction.a].type,
|
||||
&emitter.module.types,
|
||||
)
|
||||
fmt.sbprintf(&emitter.builder, ", %s zeroinitializer\n", type_name)
|
||||
case .Weaken_Pointer:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_weaken_pointer(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
|
||||
Reference in New Issue
Block a user