Pass 'select'

This commit is contained in:
David Gonzalez Martin 2025-06-13 13:00:45 -06:00
parent 4269226470
commit 6b56a1b9c0

View File

@ -1751,6 +1751,7 @@ ValueId = enum
va_arg,
unreachable,
undefined,
select,
}
ValueConstantInteger = struct
@ -1964,6 +1965,13 @@ ValueAggregateInitialization = struct
is_zero: u1,
}
ValueSelect = struct
{
condition: &Value,
true_value: &Value,
false_value: &Value,
}
ValueContent = union
{
constant_integer: ValueConstantInteger,
@ -1981,6 +1989,7 @@ ValueContent = union
string_literal: []u8,
va_arg: ValueVaArg,
aggregate_initialization: ValueAggregateInitialization,
select: ValueSelect,
}
ValueKind = enum
@ -2466,6 +2475,8 @@ llvm_create_global_variable = fn (module: &LLVMModule, type: &LLVMType, is_const
[extern] LLVMBuildPhi = fn [cc(c)] (builder: &LLVMBuilder, type: &LLVMType, name: &u8) &LLVMValue;
[extern] LLVMAddIncoming = fn [cc(c)] (phi: &LLVMValue, values: &&LLVMValue, blocks: &&LLVMBasicBlock, count: u32) void;
[extern] LLVMBuildSelect = fn [cc(c)] (builder: &LLVMBuilder, condition: &LLVMValue, true_value: &LLVMValue, false_value: &LLVMValue, name: &u8) &LLVMValue;
[extern] LLVMBuildIntToPtr = fn [cc(c)] (builder: &LLVMBuilder, value: &LLVMValue, type: &LLVMType, name: &u8) &LLVMValue;
[extern] LLVMBuildPtrToInt = fn [cc(c)] (builder: &LLVMBuilder, value: &LLVMValue, type: &LLVMType, name: &u8) &LLVMValue;
[extern] LLVMBuildIntCast2 = fn [cc(c)] (builder: &LLVMBuilder, value: &LLVMValue, type: &LLVMType, signed: s32, name: &u8) &LLVMValue;
@ -5073,7 +5084,36 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
},
.select =>
{
#trap();
skip_space(module);
expect_character(module, left_parenthesis);
skip_space(module);
>condition = parse_value(module, scope, zero);
expect_character(module, ',');
skip_space(module);
>true_value = parse_value(module, scope, zero);
expect_character(module, ',');
skip_space(module);
>false_value = parse_value(module, scope, zero);
skip_space(module);
expect_character(module, right_parenthesis);
result.& = {
.content = {
.select = {
.condition = condition,
.true_value = true_value,
.false_value = false_value,
},
},
.id = .select,
zero,
};
},
.string_to_enum =>
{
@ -9162,6 +9202,28 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
value_type = expected_type;
},
.select =>
{
>condition = value.content.select.condition;
>true_value = value.content.select.true_value;
>false_value = value.content.select.false_value;
analyze_type(module, condition, zero, { .must_be_constant = analysis.must_be_constant, zero });
>is_boolean: u1 = 0;
analyze_binary_type(module, true_value, false_value, is_boolean, expected_type, analysis.must_be_constant);
>true_type = true_value.type;
>false_type = false_value.type;
check_types(module, true_type, false_type);
assert(true_type == false_type);
>result_type = true_type;
typecheck(module, expected_type, result_type);
value_type = result_type;
},
else =>
{
#trap();
@ -11188,6 +11250,35 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
{
llvm_value = LLVMConstNull(get_llvm_type(resolved_value_type, type_kind));
},
.select =>
{
>condition = value.content.select.condition;
>true_value = value.content.select.true_value;
>false_value = value.content.select.false_value;
emit_value(module, condition, .abi, must_be_constant);
>llvm_condition = condition.llvm;
>condition_type = condition.type;
switch (condition_type.id)
{
.integer =>
{
>bit_count = condition_type.content.integer.bit_count;
if (bit_count != 1)
{
#trap();
}
},
else => { #trap(); },
}
emit_value(module, true_value, type_kind, must_be_constant);
emit_value(module, false_value, type_kind, must_be_constant);
llvm_value = LLVMBuildSelect(module.llvm.builder, llvm_condition, true_value.llvm, false_value.llvm, "");
},
else =>
{
#trap();
@ -13147,6 +13238,7 @@ names: [_][]u8 =
"ret_c_bool",
"return_type_builtin",
"return_u64_u64",
"select",
];
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32