Select
All checks were successful
CI / ci (ReleaseFast, ubuntu-latest) (push) Successful in 1m6s
CI / ci (ReleaseSmall, ubuntu-latest) (push) Successful in 1m6s
CI / ci (ReleaseSafe, ubuntu-latest) (push) Successful in 1m14s
CI / ci (Debug, ubuntu-latest) (push) Successful in 1m48s

This commit is contained in:
David Gonzalez Martin 2025-04-13 11:45:34 -06:00
parent c59a77e7a0
commit 0625988c51
2 changed files with 54 additions and 8 deletions

View File

@ -216,7 +216,6 @@ pub const Enumerator = struct {
}; };
}; };
pub const Type = struct { pub const Type = struct {
bb: union(enum) { bb: union(enum) {
void, void,
@ -721,7 +720,7 @@ pub const Value = struct {
int_from_enum: *Value, int_from_enum: *Value,
int_from_pointer: *Value, int_from_pointer: *Value,
pointer_cast: *Value, pointer_cast: *Value,
select, select: Select,
trap, trap,
truncate: *Value, truncate: *Value,
va_start, va_start,
@ -746,6 +745,13 @@ pub const Value = struct {
va_copy, va_copy,
va_arg, va_arg,
}; };
const Select = struct {
condition: *Value,
true_value: *Value,
false_value: *Value,
};
const VaArg = struct { const VaArg = struct {
list: *Value, list: *Value,
type: *Type, type: *Type,
@ -1084,7 +1090,6 @@ pub const Module = struct {
} }
for (options.argument_type_abis) |argument_type_abi| { for (options.argument_type_abis) |argument_type_abi| {
for (argument_type_abi.abi_start..argument_type_abi.abi_start + argument_type_abi.abi_count) |abi_index| { for (argument_type_abi.abi_start..argument_type_abi.abi_start + argument_type_abi.abi_count) |abi_index| {
const argument_attribute = &argument_attributes[abi_index]; const argument_attribute = &argument_attributes[abi_index];
@ -2556,6 +2561,29 @@ pub const Module = struct {
}, },
}; };
}, },
.select => blk: {
module.skip_space();
module.expect_character(left_parenthesis);
module.skip_space();
const condition = module.parse_value(function, .{});
module.expect_character(',');
module.skip_space();
const true_value = module.parse_value(function, .{});
module.expect_character(',');
module.skip_space();
const false_value = module.parse_value(function, .{});
module.skip_space();
module.expect_character(right_parenthesis);
break :blk .{ .bb = .{
.intrinsic = .{
.select = .{
.condition = condition,
.true_value = true_value,
.false_value = false_value,
},
},
} };
},
.trap => blk: { .trap => blk: {
module.skip_space(); module.skip_space();
module.expect_character(left_parenthesis); module.expect_character(left_parenthesis);
@ -3666,7 +3694,6 @@ pub const Module = struct {
.scalar => module.create_load(.{ .type = va_arg.type, .value = llvm_address }), .scalar => module.create_load(.{ .type = va_arg.type, .value = llvm_address }),
.aggregate => if (left) |l| b: { .aggregate => if (left) |l| b: {
_ = module.llvm.builder.create_memcpy(l.llvm.?, l.type.?.bb.pointer.alignment, llvm_address, va_arg.type.get_byte_alignment(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(va_arg.type.get_byte_size(), 0).to_value()); _ = module.llvm.builder.create_memcpy(l.llvm.?, l.type.?.bb.pointer.alignment, llvm_address, va_arg.type.get_byte_alignment(), module.integer_type(64, false).resolve(module).handle.to_integer().get_constant(va_arg.type.get_byte_size(), 0).to_value());
// pub extern fn LLVMBuildMemCpy(builder: *llvm.Builder, destination: *llvm.Value, destination_alignment: c_uint, source: *llvm.Value, source_alignment: c_uint, size: *llvm.Value) *llvm.Value;
break :b l.llvm.?; break :b l.llvm.?;
} else llvm_address, } else llvm_address,
.complex => @trap(), .complex => @trap(),
@ -3941,7 +3968,6 @@ pub const Module = struct {
@trap(); @trap();
} }
// const indirect_alignment = argument_abi.attributes.indirect.alignment; // const indirect_alignment = argument_abi.attributes.indirect.alignment;
// const address_alignment = semantic_argument_type.get_byte_alignment(); // const address_alignment = semantic_argument_type.get_byte_alignment();
// const get_or_enforce_known_alignment = indirect_alignment; // const get_or_enforce_known_alignment = indirect_alignment;
@ -4848,6 +4874,11 @@ pub const Module = struct {
module.report_error(); module.report_error();
} }
}, },
.select => |select| {
module.analyze_value_type(function, select.condition, .{});
module.analyze_value_type(function, select.true_value, .{ .type = expected_type });
module.analyze_value_type(function, select.false_value, .{ .type = expected_type });
},
.truncate => |value_to_truncate| { .truncate => |value_to_truncate| {
module.analyze_value_type(function, value_to_truncate, .{}); module.analyze_value_type(function, value_to_truncate, .{});
if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) { if (expected_type.get_bit_size() >= value_to_truncate.type.?.get_bit_size()) {
@ -5415,6 +5446,20 @@ pub const Module = struct {
module.emit_value(function, pointer_value); module.emit_value(function, pointer_value);
break :blk pointer_value.llvm.?; break :blk pointer_value.llvm.?;
}, },
.select => |select| blk: {
module.emit_value(function, select.condition);
const condition = switch (select.condition.type.?.bb) {
.integer => |integer| switch (integer.bit_count) {
1 => select.condition.llvm.?,
else => @trap(),
},
else => @trap(),
};
module.emit_value(function, select.true_value);
module.emit_value(function, select.false_value);
const result = module.llvm.builder.create_select(condition, select.true_value.llvm.?, select.false_value.llvm.?);
break :blk result;
},
.trap => blk: { .trap => blk: {
// TODO: lookup in advance // TODO: lookup in advance
const intrinsic_id = module.llvm.intrinsic_table.trap; const intrinsic_id = module.llvm.intrinsic_table.trap;

View File

@ -227,4 +227,5 @@ const names = &[_][]const u8{
"ret_c_bool", "ret_c_bool",
"return_type_builtin", "return_type_builtin",
"return_u64_u64", "return_u64_u64",
"select",
}; };