This commit is contained in:
2026-06-23 17:22:41 +02:00
parent f16f352d1e
commit 2f68fc966a
16 changed files with 809 additions and 38 deletions
+21 -15
View File
@@ -189,11 +189,16 @@ function_result_type :: proc(function: ir.Function, store: ^types.Store) -> stri
return llvm_type(function.result, store)
}
c_abi_extension :: proc(value: types.Type, selected: target.Target) -> string {
if !types.is_concrete_integer(value) {
c_abi_extension :: proc(value: types.Type, store: ^types.Store) -> string {
resolved := types.runtime_representation(value, store)
if !types.is_concrete_integer(resolved) {
return ""
}
switch target.c_integer_extension(selected, types.bits(value, selected), types.is_signed(value, selected)) {
switch target.c_integer_extension(
store.selected,
types.bits(resolved, store.selected),
types.is_signed(resolved, store.selected),
) {
case .Sign: return "signext"
case .Zero: return "zeroext"
case .None: return ""
@@ -203,7 +208,7 @@ c_abi_extension :: proc(value: types.Type, selected: target.Target) -> string {
emit_function_result :: proc(builder: ^strings.Builder, function: ir.Function, store: ^types.Store) {
if function.calling_convention == .C {
extension := c_abi_extension(function.result, store.selected)
extension := c_abi_extension(function.result, store)
if len(extension) > 0 {
fmt.sbprintf(builder, "%s ", extension)
}
@@ -423,7 +428,7 @@ emit_call_args :: proc(
(instructions[arg].type if valid_instruction(instructions, arg) else types.INVALID)
fmt.sbprintf(builder, "%s ", llvm_type(arg_type, store))
if c_abi && index < len(param_types) {
extension := c_abi_extension(arg_type, store.selected)
extension := c_abi_extension(arg_type, store)
if len(extension) > 0 {
fmt.sbprintf(builder, "%s ", extension)
}
@@ -1200,11 +1205,12 @@ emit_instruction_stream :: proc(
}
from_type := instructions[instruction.a].type
if types.equal(from_type, instruction.type) ||
!types.equal(types.c_vararg_promotion(from_type, emitter.module.target), instruction.type) {
!types.equal(types.c_vararg_promotion(from_type, emitter.module.target, &emitter.module.types), instruction.type) {
emit_recovery_value(emitter, instruction_index, instruction, "invalid C variadic promotion operand")
continue
}
if types.bits(from_type, emitter.module.target) == types.bits(instruction.type, emitter.module.target) {
from_repr := types.runtime_representation(from_type, &emitter.module.types)
if types.bits(from_repr, emitter.module.target) == types.bits(instruction.type, emitter.module.target) {
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, from_type, &emitter.module.types)
@@ -1213,8 +1219,8 @@ emit_instruction_stream :: proc(
strings.write_string(&emitter.builder, "\n")
continue
}
operation := "fpext" if types.is_float(from_type, emitter.module.target) else
("sext" if types.is_signed(from_type, emitter.module.target) else "zext")
operation := "fpext" if types.is_float(from_repr, emitter.module.target) else
("sext" if types.is_signed(from_repr, emitter.module.target) else "zext")
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))
@@ -1367,7 +1373,7 @@ emit_instruction_stream :: proc(
(instructions[arg].type if valid_instruction(instructions, arg) else types.INVALID)
if index >= len(param_fields) &&
(!types.is_c_vararg_type(expected, &emitter.module.types) ||
!types.equal(types.c_vararg_promotion(expected, emitter.module.target), expected)) {
!types.equal(types.c_vararg_promotion(expected, emitter.module.target, &emitter.module.types), expected)) {
valid_args = false
break
}
@@ -1409,7 +1415,7 @@ emit_instruction_stream :: proc(
strings.write_string(&emitter.builder, "fastcc ")
}
if function_item.c_abi {
extension := c_abi_extension(function_item.child, emitter.module.target)
extension := c_abi_extension(function_item.child, &emitter.module.types)
if len(extension) > 0 {
fmt.sbprintf(&emitter.builder, "%s ", extension)
}
@@ -1455,7 +1461,7 @@ emit_instruction_stream :: proc(
} else {
fmt.sbprintf(&emitter.builder, "%s ", llvm_type(arg_type, &emitter.module.types))
if function_item.c_abi && fixed {
extension := c_abi_extension(arg_type, emitter.module.target)
extension := c_abi_extension(arg_type, &emitter.module.types)
if len(extension) > 0 {
fmt.sbprintf(&emitter.builder, "%s ", extension)
}
@@ -1490,7 +1496,7 @@ emit_instruction_stream :: proc(
(instructions[arg].type if valid_instruction(instructions, arg) else types.INVALID)
if index >= len(target.param_types) &&
(!types.is_c_vararg_type(expected, &emitter.module.types) ||
!types.equal(types.c_vararg_promotion(expected, emitter.module.target), expected)) {
!types.equal(types.c_vararg_promotion(expected, emitter.module.target, &emitter.module.types), expected)) {
valid_args = false
break
}
@@ -1572,7 +1578,7 @@ emit_instruction_stream :: proc(
} else {
fmt.sbprintf(&emitter.builder, "%s ", llvm_type(arg_type, &emitter.module.types))
if target.calling_convention == .C && fixed {
extension := c_abi_extension(arg_type, emitter.module.target)
extension := c_abi_extension(arg_type, &emitter.module.types)
if len(extension) > 0 {
fmt.sbprintf(&emitter.builder, "%s ", extension)
}
@@ -1898,7 +1904,7 @@ emit_functions :: proc(emitter: ^Emitter) {
type_name := c_abi_param_type(param_type, &emitter.module.types) if function.calling_convention == .C else llvm_type(param_type, &emitter.module.types)
fmt.sbprintf(&emitter.builder, "%s", type_name)
if function.calling_convention == .C && !types.is_record(param_type, &emitter.module.types) {
extension := c_abi_extension(param_type, emitter.module.target)
extension := c_abi_extension(param_type, &emitter.module.types)
if len(extension) > 0 {
fmt.sbprintf(&emitter.builder, " %s", extension)
}