sema: add abs, max/min, div, aggregate_init, cross-module re-export resolution; enable divdc3
Port missing builtins and operations needed for divdc3.zig corpus test: - @abs: emit AIR_INST_ABS (ty_op) for float operands - @max/@min: emit AIR_INST_MAX/AIR_INST_MIN at runtime (bin_op) - div: emit AIR_INST_DIV_FLOAT for floats, AIR_INST_DIV_TRUNC for ints - struct_init: runtime path emits AIR_INST_AGGREGATE_INIT - Cross-module import chain: follow re-exports (e.g. scalbn -> ldexp) - Fix return type resolution for generic anytype params (use semaTypeOf) - Add comptime_float peer type resolution - Skip test/comptime decls in findFuncInstInZir - Handle validate_ref_ty as validation-only (no AIR) - Remove leftover debug fprintf traces Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
214
stage0/sema.c
214
stage0/sema.c
@@ -566,6 +566,10 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) {
|
||||
case AIR_INST_SHL:
|
||||
case AIR_INST_SHL_SAT:
|
||||
case AIR_INST_SHR:
|
||||
case AIR_INST_MAX:
|
||||
case AIR_INST_MIN:
|
||||
case AIR_INST_DIV_FLOAT:
|
||||
case AIR_INST_DIV_TRUNC:
|
||||
return semaTypeOf(sema, sema->air_inst_datas[inst_idx].bin_op.lhs);
|
||||
// cmp bin_op: result type is bool.
|
||||
case AIR_INST_CMP_LT:
|
||||
@@ -592,6 +596,7 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) {
|
||||
case AIR_INST_CTZ:
|
||||
case AIR_INST_POPCOUNT:
|
||||
case AIR_INST_BYTE_SWAP:
|
||||
case AIR_INST_ABS:
|
||||
case AIR_INST_DBG_INLINE_BLOCK:
|
||||
case AIR_INST_BLOCK:
|
||||
case AIR_INST_STRUCT_FIELD_PTR_INDEX_0:
|
||||
@@ -600,6 +605,7 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) {
|
||||
case AIR_INST_STRUCT_FIELD_PTR_INDEX_3:
|
||||
return AIR_REF_TO_IP(sema->air_inst_datas[inst_idx].ty_op.ty_ref);
|
||||
case AIR_INST_STRUCT_FIELD_VAL:
|
||||
case AIR_INST_AGGREGATE_INIT:
|
||||
return AIR_REF_TO_IP(sema->air_inst_datas[inst_idx].ty_pl.ty_ref);
|
||||
// call: return type from side table (populated by zirCall).
|
||||
case AIR_INST_CALL:
|
||||
@@ -657,6 +663,10 @@ static TypeIndex semaResolvePeerTypes(
|
||||
return cIntToRegularInt(rhs_ty);
|
||||
if (rhs_ty == IP_INDEX_COMPTIME_INT_TYPE)
|
||||
return cIntToRegularInt(lhs_ty);
|
||||
if (lhs_ty == IP_INDEX_COMPTIME_FLOAT_TYPE)
|
||||
return rhs_ty;
|
||||
if (rhs_ty == IP_INDEX_COMPTIME_FLOAT_TYPE)
|
||||
return lhs_ty;
|
||||
// When both types are concrete int types, pick the wider type.
|
||||
// Ported from src/Sema.zig peer_resolve_int_int (fixed_int strategy).
|
||||
if (sema->ip->items[lhs_ty].tag == IP_KEY_INT_TYPE
|
||||
@@ -1064,6 +1074,25 @@ static uint16_t smallestUnsignedBits(uint16_t max) {
|
||||
return count;
|
||||
}
|
||||
|
||||
// zirAbs: handle @abs ZIR instruction.
|
||||
// Ported from src/Sema.zig zirAbs.
|
||||
// For floats/comptime_float: result_ty = operand_ty.
|
||||
// For signed ints: result_ty = toUnsigned(operand_ty).
|
||||
// For unsigned ints: identity (return operand).
|
||||
static AirInstRef zirAbs(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
ZirInstRef operand_ref = sema->code.inst_datas[inst].un_node.operand;
|
||||
AirInstRef operand = resolveInst(sema, operand_ref);
|
||||
TypeIndex operand_ty = semaTypeOf(sema, operand);
|
||||
|
||||
// For floats, result type is the same as operand type.
|
||||
// Emit AIR_INST_ABS as ty_op.
|
||||
AirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.ty_op.ty_ref = AIR_REF_FROM_IP(operand_ty);
|
||||
data.ty_op.operand = operand;
|
||||
return semaAddInst(block, AIR_INST_ABS, data);
|
||||
}
|
||||
|
||||
// zirBitCount: handle clz/ctz/pop_count ZIR instructions.
|
||||
// Ported from src/Sema.zig zirBitCount.
|
||||
// Result type is smallestUnsignedInt(operand_bits).
|
||||
@@ -1248,6 +1277,35 @@ emit_runtime:;
|
||||
return semaAddInst(block, air_tag, data);
|
||||
}
|
||||
|
||||
// zirDiv: handle div ZIR instruction (/ operator).
|
||||
// Ported from src/Sema.zig zirDiv.
|
||||
// For floats: emits AIR_INST_DIV_FLOAT (strict mode).
|
||||
// For unsigned ints: emits AIR_INST_DIV_TRUNC.
|
||||
static AirInstRef zirDiv(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
uint32_t payload_index = sema->code.inst_datas[inst].pl_node.payload_index;
|
||||
ZirInstRef zir_lhs = sema->code.extra[payload_index];
|
||||
ZirInstRef zir_rhs = sema->code.extra[payload_index + 1];
|
||||
AirInstRef lhs = resolveInst(sema, zir_lhs);
|
||||
AirInstRef rhs = resolveInst(sema, zir_rhs);
|
||||
|
||||
TypeIndex peer_ty = semaResolvePeerTypes(sema, lhs, rhs);
|
||||
lhs = semaCoerce(sema, block, peer_ty, lhs);
|
||||
rhs = semaCoerce(sema, block, peer_ty, rhs);
|
||||
|
||||
// Determine air_tag based on scalar type.
|
||||
AirInstTag air_tag = AIR_INST_DIV_FLOAT; // default for floats
|
||||
InternPoolKey pk = ipIndexToKey(sema->ip, peer_ty);
|
||||
if (pk.tag == IP_KEY_INT_TYPE) {
|
||||
air_tag = AIR_INST_DIV_TRUNC;
|
||||
}
|
||||
|
||||
AirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.bin_op.lhs = lhs;
|
||||
data.bin_op.rhs = rhs;
|
||||
return semaAddInst(block, air_tag, data);
|
||||
}
|
||||
|
||||
// zirBitwise: handle bitwise operation ZIR instructions.
|
||||
// Ported from src/Sema.zig zirBitwise.
|
||||
static AirInstRef zirBitwise(
|
||||
@@ -2259,6 +2317,11 @@ static uint32_t findFuncInstInZir(const Zir* zir, const char* func_name) {
|
||||
uint32_t flags_1 = zir->extra[payload + 5];
|
||||
uint32_t id = (flags_1 >> 27) & 0x1F;
|
||||
|
||||
// Skip test declarations (unnamed_test=0, test=1, decltest=2)
|
||||
// and comptime blocks (3) — only look at const/var/export decls.
|
||||
if (id <= 3)
|
||||
continue;
|
||||
|
||||
uint32_t di = payload + 6;
|
||||
|
||||
// Extract declaration name.
|
||||
@@ -2846,18 +2909,6 @@ static AirInstRef zirCall(
|
||||
}
|
||||
}
|
||||
|
||||
// Debug: save callee name before chain resolution changes sema->code.
|
||||
char dbg_callee[64] = "?";
|
||||
if (callee_name_idx) {
|
||||
const char* nm
|
||||
= (const char*)&sema->code.string_bytes[callee_name_idx];
|
||||
size_t nl = strlen(nm);
|
||||
if (nl > 63)
|
||||
nl = 63;
|
||||
memcpy(dbg_callee, nm, nl);
|
||||
dbg_callee[nl] = 0;
|
||||
}
|
||||
|
||||
// Find the inline function's ZIR instruction.
|
||||
uint32_t func_inst = findDeclFuncInst(sema, callee_name_idx);
|
||||
// Fallback: during cross-module inline expansion, sema->decl_names
|
||||
@@ -3004,19 +3055,29 @@ static AirInstRef zirCall(
|
||||
zirDeinit(&cur_zir);
|
||||
astDeinit(&cur_ast);
|
||||
if (fn_zir.inst_len > 0) {
|
||||
// Function should be directly in this
|
||||
// module with same name.
|
||||
// Try direct lookup first, then follow
|
||||
// re-exports (e.g. scalbn -> ldexp).
|
||||
char fn_src_dir[1024];
|
||||
computeSourceDir(NULL, cur_dir, fn_import,
|
||||
fn_src_dir, sizeof(fn_src_dir));
|
||||
func_inst
|
||||
= findFuncInstInZir(&fn_zir, fn_name);
|
||||
= findFuncInModuleZir(fn_src_dir, &fn_zir,
|
||||
&fn_ast, fn_name, import_source_dir,
|
||||
sizeof(import_source_dir));
|
||||
if (func_inst != UINT32_MAX) {
|
||||
// If findFuncInModuleZir found it
|
||||
// directly (no re-export), it did
|
||||
// not write import_source_dir.
|
||||
// Set it to fn_src_dir as fallback.
|
||||
if (import_source_dir[0] == '\0')
|
||||
snprintf(import_source_dir,
|
||||
sizeof(import_source_dir), "%s",
|
||||
fn_src_dir);
|
||||
saved_code = sema->code;
|
||||
sema->code = fn_zir;
|
||||
import_zir = fn_zir;
|
||||
import_ast = fn_ast;
|
||||
is_cross_module = true;
|
||||
computeSourceDir(NULL, cur_dir, fn_import,
|
||||
import_source_dir,
|
||||
sizeof(import_source_dir));
|
||||
} else {
|
||||
zirDeinit(&fn_zir);
|
||||
astDeinit(&fn_ast);
|
||||
@@ -3844,19 +3905,6 @@ static AirInstRef zirCall(
|
||||
sema->code = arg_code;
|
||||
}
|
||||
|
||||
// Ported from src/Sema.zig line 7480:
|
||||
// if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
|
||||
// call_dbg_node is the ZIR instruction preceding the call (inst - 1).
|
||||
// Must use the caller's ZIR for cross-module calls.
|
||||
if (inst > 0 && !block->is_comptime) {
|
||||
Zir dbg_code = sema->code;
|
||||
if (is_cross_module)
|
||||
sema->code = saved_code;
|
||||
zirDbgStmt(sema, block, inst - 1);
|
||||
if (is_cross_module)
|
||||
sema->code = dbg_code;
|
||||
}
|
||||
|
||||
// Handle type-returning functions whose result can be computed from
|
||||
// the comptime arguments without inlining.
|
||||
// Upstream always reserves a dead BLOCK before inlining; we match
|
||||
@@ -4255,8 +4303,15 @@ static AirInstRef zirCall(
|
||||
if (param_body[p] == ret_ty_inst && pi < args_len) {
|
||||
// Return type ref matches this param.
|
||||
// For comptime type params, the arg value IS
|
||||
// the type.
|
||||
ret_ty = AIR_REF_TO_IP(arg_refs[pi]);
|
||||
// the type (an IP ref). For runtime params
|
||||
// (including anytype), use semaTypeOf to get
|
||||
// the argument's type.
|
||||
if (ptag == ZIR_INST_PARAM_COMPTIME
|
||||
|| ptag == ZIR_INST_PARAM_ANYTYPE_COMPTIME) {
|
||||
ret_ty = AIR_REF_TO_IP(arg_refs[pi]);
|
||||
} else {
|
||||
ret_ty = semaTypeOf(sema, arg_refs[pi]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pi++;
|
||||
@@ -4278,12 +4333,6 @@ static AirInstRef zirCall(
|
||||
|| ret_ty == IP_INDEX_ENUM_LITERAL_TYPE);
|
||||
bool is_inline_call
|
||||
= func_info.is_inline || block->is_comptime || is_comptime_only_ret;
|
||||
if (strcmp(dbg_callee, "copysign") == 0)
|
||||
fprintf(stderr,
|
||||
" COPYSIGN_PATH: is_inline=%d is_comptime=%d ct_only_ret=%d"
|
||||
" ret_ty=%u is_generic=%d\n",
|
||||
func_info.is_inline, block->is_comptime, is_comptime_only_ret,
|
||||
ret_ty, is_generic);
|
||||
if (!is_inline_call) {
|
||||
// Dummy allocs for generic runtime params are now emitted
|
||||
// interleaved in the arg evaluation loop above (Fix A).
|
||||
@@ -4359,8 +4408,12 @@ static AirInstRef zirCall(
|
||||
semaAddExtra(sema, runtime_arg_refs[a]);
|
||||
|
||||
// Ported from Sema.zig:7480: AstGen ensures a dbg_stmt
|
||||
// always precedes a call instruction. For cross-module
|
||||
// calls, inst-1 is in the calling module's ZIR.
|
||||
// always precedes a call instruction. Use the caller's ZIR
|
||||
// for cross-module calls. Note: the general dbg_stmt at the
|
||||
// top of zirCall (before arg evaluation) may have been
|
||||
// followed by arg instructions, so emit another one here
|
||||
// to directly precede the call. zirDbgStmt de-duplicates
|
||||
// when the previous block instruction is already a dbg_stmt.
|
||||
if (is_cross_module) {
|
||||
Zir temp = sema->code;
|
||||
sema->code = saved_code;
|
||||
@@ -4440,6 +4493,18 @@ static AirInstRef zirCall(
|
||||
}
|
||||
}
|
||||
|
||||
// Ported from src/Sema.zig line 7480: emit dbg_stmt for inline
|
||||
// calls, just before the inline block. Use the caller's ZIR
|
||||
// for cross-module calls.
|
||||
if (inst > 0 && !block->is_comptime) {
|
||||
Zir dbg_code = sema->code;
|
||||
if (is_cross_module)
|
||||
sema->code = saved_code;
|
||||
zirDbgStmt(sema, block, inst - 1);
|
||||
if (is_cross_module)
|
||||
sema->code = dbg_code;
|
||||
}
|
||||
|
||||
// Upstream: need_debug_scope = !block.isComptime() && ...
|
||||
// When comptime (or all args comptime), use BLOCK; otherwise
|
||||
// DBG_INLINE_BLOCK.
|
||||
@@ -5884,11 +5949,11 @@ static InternPoolIndex resolveUnsignedIntType(InternPool* ip, uint32_t bits) {
|
||||
}
|
||||
}
|
||||
|
||||
// zirStructInitComptime: handle struct_init in comptime context.
|
||||
// For @Type(.{.int = .{.signedness = .unsigned, .bits = N}}):
|
||||
// - inner struct: extract signedness and bits, track as CT_TAG_INT_INFO
|
||||
// - outer struct: extract field name (.int), track as CT_TAG_REIFY_INT
|
||||
static AirInstRef zirStructInitComptime(Sema* sema, uint32_t inst) {
|
||||
// zirStructInit: handle struct_init ZIR instruction.
|
||||
// Comptime case: @Type(.{.int = .{.signedness = .unsigned, .bits = N}})
|
||||
// Runtime case: emits AIR_INST_AGGREGATE_INIT with field values.
|
||||
// Ported from src/Sema.zig zirStructInit / finishStructInit.
|
||||
static AirInstRef zirStructInit(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
uint32_t payload_index = sema->code.inst_datas[inst].pl_node.payload_index;
|
||||
// StructInit payload: abs_node, abs_line, fields_len, then Items.
|
||||
uint32_t fields_len = sema->code.extra[payload_index + 2];
|
||||
@@ -5967,7 +6032,32 @@ static AirInstRef zirStructInitComptime(Sema* sema, uint32_t inst) {
|
||||
return AIR_REF_FROM_IP(marker);
|
||||
}
|
||||
|
||||
return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE);
|
||||
// Runtime struct init: emit aggregate_init.
|
||||
// Ported from Sema.zig finishStructInit line 19655.
|
||||
// The field_type instructions provide the container type.
|
||||
// Resolve the container type from the first field_type's container ref.
|
||||
{
|
||||
uint32_t ft_payload0
|
||||
= sema->code.inst_datas[items[0]].pl_node.payload_index;
|
||||
ZirInstRef container_ref = sema->code.extra[ft_payload0];
|
||||
AirInstRef container_air = resolveInst(sema, container_ref);
|
||||
TypeIndex container_ty = AIR_REF_IS_IP(container_air)
|
||||
? AIR_REF_TO_IP(container_air)
|
||||
: IP_INDEX_VOID_TYPE;
|
||||
|
||||
// Build aggregate_init extra: element refs in field order.
|
||||
uint32_t extra_idx = sema->air_extra_len;
|
||||
for (uint32_t f = 0; f < fields_len; f++) {
|
||||
ZirInstRef init_ref2 = items[f * 2 + 1];
|
||||
AirInstRef init_air2 = resolveInst(sema, init_ref2);
|
||||
semaAddExtra(sema, init_air2);
|
||||
}
|
||||
AirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.ty_pl.ty_ref = AIR_REF_FROM_IP(container_ty);
|
||||
data.ty_pl.payload = extra_idx;
|
||||
return semaAddInst(block, AIR_INST_AGGREGATE_INIT, data);
|
||||
}
|
||||
}
|
||||
|
||||
// zirReifyComptime: handle @Type(...) in comptime context.
|
||||
@@ -6629,6 +6719,10 @@ static bool analyzeBodyInner(
|
||||
zirArithmetic(sema, block, inst, AIR_INST_MUL_WRAP));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_DIV:
|
||||
instMapPut(&sema->inst_map, inst, zirDiv(sema, block, inst));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_ADD_SAT:
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
zirArithmetic(sema, block, inst, AIR_INST_ADD_SAT));
|
||||
@@ -6724,8 +6818,18 @@ static bool analyzeBodyInner(
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
AIR_REF_FROM_IP(ipIntern(sema->ip, key)));
|
||||
} else {
|
||||
// Runtime: emit AIR_INST_MAX or AIR_INST_MIN.
|
||||
TypeIndex peer_ty
|
||||
= semaResolvePeerTypes(sema, min_lhs, min_rhs);
|
||||
AirInstRef c_lhs = semaCoerce(sema, block, peer_ty, min_lhs);
|
||||
AirInstRef c_rhs = semaCoerce(sema, block, peer_ty, min_rhs);
|
||||
AirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.bin_op.lhs = c_lhs;
|
||||
data.bin_op.rhs = c_rhs;
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE));
|
||||
semaAddInst(
|
||||
block, is_max ? AIR_INST_MAX : AIR_INST_MIN, data));
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
@@ -6860,9 +6964,16 @@ static bool analyzeBodyInner(
|
||||
i++;
|
||||
continue;
|
||||
|
||||
// @abs.
|
||||
case ZIR_INST_ABS:
|
||||
instMapPut(&sema->inst_map, inst, zirAbs(sema, block, inst));
|
||||
i++;
|
||||
continue;
|
||||
|
||||
// Validation-only (no AIR emitted).
|
||||
case ZIR_INST_VALIDATE_DEREF:
|
||||
case ZIR_INST_VALIDATE_CONST:
|
||||
case ZIR_INST_VALIDATE_REF_TY:
|
||||
i++;
|
||||
continue;
|
||||
|
||||
@@ -7078,10 +7189,10 @@ static bool analyzeBodyInner(
|
||||
i++;
|
||||
continue;
|
||||
|
||||
// struct_init: comptime struct initialization.
|
||||
// struct_init: struct initialization (comptime or runtime).
|
||||
case ZIR_INST_STRUCT_INIT:
|
||||
instMapPut(
|
||||
&sema->inst_map, inst, zirStructInitComptime(sema, inst));
|
||||
&sema->inst_map, inst, zirStructInit(sema, block, inst));
|
||||
i++;
|
||||
continue;
|
||||
|
||||
@@ -7676,8 +7787,6 @@ static bool analyzeBodyInner(
|
||||
}
|
||||
semaAddExtra(sema, sub_br_idx);
|
||||
sema->air_inst_tags[br] = AIR_INST_BLOCK;
|
||||
fprintf(
|
||||
stderr, " REWRITE_BR_BLOCK: air_idx=%u\n", br);
|
||||
sema->air_inst_datas[br].ty_pl.ty_ref
|
||||
= AIR_REF_FROM_IP(resolved_ty);
|
||||
sema->air_inst_datas[br].ty_pl.payload = sub_extra;
|
||||
@@ -8127,7 +8236,6 @@ static bool analyzeBodyInner(
|
||||
// For all other instructions, produce a void mapping and skip.
|
||||
// As handlers are implemented, they will replace this default.
|
||||
default: {
|
||||
fprintf(stderr, " UNHANDLED: inst=%u tag=%u\n", inst, inst_tag);
|
||||
AirInstRef air_ref = AIR_REF_FROM_IP(IP_INDEX_VOID_TYPE);
|
||||
instMapPut(&sema->inst_map, inst, air_ref);
|
||||
i++;
|
||||
|
||||
@@ -456,6 +456,7 @@ fn airDataRefSlots(tag_val: u8) [2]bool {
|
||||
c.AIR_INST_STRUCT_FIELD_PTR,
|
||||
c.AIR_INST_DBG_INLINE_BLOCK,
|
||||
c.AIR_INST_BLOCK,
|
||||
c.AIR_INST_AGGREGATE_INIT,
|
||||
=> .{ true, false },
|
||||
// bin_op: lhs(Ref) + rhs(Ref)
|
||||
c.AIR_INST_ADD,
|
||||
@@ -488,6 +489,19 @@ fn airDataRefSlots(tag_val: u8) [2]bool {
|
||||
c.AIR_INST_CMP_GTE,
|
||||
c.AIR_INST_CMP_GT,
|
||||
c.AIR_INST_CMP_NEQ,
|
||||
c.AIR_INST_MAX,
|
||||
c.AIR_INST_MIN,
|
||||
c.AIR_INST_DIV_FLOAT,
|
||||
c.AIR_INST_DIV_FLOAT_OPTIMIZED,
|
||||
c.AIR_INST_DIV_TRUNC,
|
||||
c.AIR_INST_DIV_TRUNC_OPTIMIZED,
|
||||
c.AIR_INST_DIV_FLOOR,
|
||||
c.AIR_INST_DIV_FLOOR_OPTIMIZED,
|
||||
c.AIR_INST_DIV_EXACT,
|
||||
c.AIR_INST_DIV_EXACT_OPTIMIZED,
|
||||
c.AIR_INST_ADD_SAT,
|
||||
c.AIR_INST_SUB_SAT,
|
||||
c.AIR_INST_MUL_SAT,
|
||||
=> .{ true, true },
|
||||
// ty_op: type(Ref) + operand(Ref)
|
||||
c.AIR_INST_BITCAST,
|
||||
@@ -515,6 +529,7 @@ fn airDataRefSlots(tag_val: u8) [2]bool {
|
||||
c.AIR_INST_CTZ,
|
||||
c.AIR_INST_POPCOUNT,
|
||||
c.AIR_INST_BYTE_SWAP,
|
||||
c.AIR_INST_ABS,
|
||||
c.AIR_INST_STRUCT_FIELD_PTR_INDEX_0,
|
||||
c.AIR_INST_STRUCT_FIELD_PTR_INDEX_1,
|
||||
c.AIR_INST_STRUCT_FIELD_PTR_INDEX_2,
|
||||
@@ -1342,3 +1357,19 @@ test "sema air: inline fn with += call inside two conditionals" {
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: @abs float" {
|
||||
try semaAirRawCheck("export fn f(x: f64) f64 { return @abs(x); }");
|
||||
}
|
||||
|
||||
test "sema air: @max float" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return @max(x, y); }");
|
||||
}
|
||||
|
||||
test "sema air: @min float" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return @min(x, y); }");
|
||||
}
|
||||
|
||||
test "sema air: f64 div" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return x / y; }");
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ const corpus_files = .{
|
||||
"../lib/compiler_rt/mulhc3.zig", // 425
|
||||
"../lib/compiler_rt/mulsc3.zig", // 425
|
||||
"../lib/compiler_rt/mulxc3.zig", // 425
|
||||
//"../lib/compiler_rt/divdc3.zig", // 434
|
||||
"../lib/compiler_rt/divdc3.zig", // 434
|
||||
//"../lib/compiler_rt/divhc3.zig", // 434
|
||||
//"../lib/compiler_rt/divsc3.zig", // 434
|
||||
//"../lib/compiler_rt/divxc3.zig", // 434
|
||||
|
||||
Reference in New Issue
Block a user