| ... | ... | @@ -263,6 +263,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTag *) { |
| 263 | 263 | return IrInstructionIdEnumTag; |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | static constexpr IrInstructionId ir_instruction_id(IrInstructionStaticEval *) { |
| 267 | return IrInstructionIdStaticEval; |
| 268 | } |
| 269 | |
| 266 | 270 | template<typename T> |
| 267 | 271 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 268 | 272 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1074,6 +1078,15 @@ static IrInstruction *ir_build_enum_tag_from(IrBuilder *irb, IrInstruction *old_ |
| 1074 | 1078 | return new_instruction; |
| 1075 | 1079 | } |
| 1076 | 1080 | |
| 1081 | static IrInstruction *ir_build_static_eval(IrBuilder *irb, AstNode *source_node, IrInstruction *value) { |
| 1082 | IrInstructionStaticEval *instruction = ir_build_instruction<IrInstructionStaticEval>(irb, source_node); |
| 1083 | instruction->value = value; |
| 1084 | |
| 1085 | ir_ref_instruction(value); |
| 1086 | |
| 1087 | return &instruction->base; |
| 1088 | } |
| 1089 | |
| 1077 | 1090 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 1078 | 1091 | bool gen_error_defers, bool gen_maybe_defers) |
| 1079 | 1092 | { |
| ... | ... | @@ -1606,6 +1619,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1606 | 1619 | |
| 1607 | 1620 | return ir_build_clz(irb, node, arg0_value); |
| 1608 | 1621 | } |
| 1622 | case BuiltinFnIdStaticEval: |
| 1623 | { |
| 1624 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 1625 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); |
| 1626 | if (arg0_value == irb->codegen->invalid_instruction) |
| 1627 | return arg0_value; |
| 1628 | |
| 1629 | return ir_build_static_eval(irb, node, arg0_value); |
| 1630 | } |
| 1609 | 1631 | case BuiltinFnIdMemcpy: |
| 1610 | 1632 | case BuiltinFnIdMemset: |
| 1611 | 1633 | case BuiltinFnIdAlignof: |
| ... | ... | @@ -1620,7 +1642,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1620 | 1642 | case BuiltinFnIdCDefine: |
| 1621 | 1643 | case BuiltinFnIdCUndef: |
| 1622 | 1644 | case BuiltinFnIdCompileErr: |
| 1623 | | case BuiltinFnIdConstEval: |
| 1624 | 1645 | case BuiltinFnIdImport: |
| 1625 | 1646 | case BuiltinFnIdCImport: |
| 1626 | 1647 | case BuiltinFnIdErrName: |
| ... | ... | @@ -2285,14 +2306,18 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { |
| 2285 | 2306 | IrInstruction *start_value = ir_gen_node(irb, start_node, node->block_context); |
| 2286 | 2307 | if (start_value == irb->codegen->invalid_instruction) |
| 2287 | 2308 | return irb->codegen->invalid_instruction; |
| 2309 | |
| 2288 | 2310 | IrInstruction *end_value = ir_gen_node(irb, end_node, node->block_context); |
| 2289 | 2311 | if (end_value == irb->codegen->invalid_instruction) |
| 2290 | 2312 | return irb->codegen->invalid_instruction; |
| 2291 | 2313 | |
| 2314 | IrInstruction *start_value_const = ir_build_static_eval(irb, start_node, start_value); |
| 2315 | IrInstruction *end_value_const = ir_build_static_eval(irb, start_node, end_value); |
| 2316 | |
| 2292 | 2317 | IrInstruction *lower_range_ok = ir_build_bin_op(irb, item_node, IrBinOpCmpGreaterOrEq, |
| 2293 | | target_value, start_value); |
| 2318 | target_value, start_value_const); |
| 2294 | 2319 | IrInstruction *upper_range_ok = ir_build_bin_op(irb, item_node, IrBinOpCmpLessOrEq, |
| 2295 | | target_value, end_value); |
| 2320 | target_value, end_value_const); |
| 2296 | 2321 | IrInstruction *both_ok = ir_build_bin_op(irb, item_node, IrBinOpBoolAnd, |
| 2297 | 2322 | lower_range_ok, upper_range_ok); |
| 2298 | 2323 | if (ok_bit) { |
| ... | ... | @@ -3291,16 +3316,21 @@ static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructio |
| 3291 | 3316 | } |
| 3292 | 3317 | |
| 3293 | 3318 | static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 3294 | | IrInstruction *op1 = bin_op_instruction->op1; |
| 3295 | | IrInstruction *op2 = bin_op_instruction->op2; |
| 3319 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 3320 | if (op1->type_entry->id == TypeTableEntryIdInvalid) |
| 3321 | return ira->codegen->builtin_types.entry_invalid; |
| 3322 | |
| 3323 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 3324 | if (op2->type_entry->id == TypeTableEntryIdInvalid) |
| 3325 | return ira->codegen->builtin_types.entry_invalid; |
| 3296 | 3326 | |
| 3297 | 3327 | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; |
| 3298 | 3328 | |
| 3299 | | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, bool_type); |
| 3329 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, bool_type); |
| 3300 | 3330 | if (casted_op1 == ira->codegen->invalid_instruction) |
| 3301 | 3331 | return ira->codegen->builtin_types.entry_invalid; |
| 3302 | 3332 | |
| 3303 | | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, bool_type); |
| 3333 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, bool_type); |
| 3304 | 3334 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 3305 | 3335 | return ira->codegen->builtin_types.entry_invalid; |
| 3306 | 3336 | |
| ... | ... | @@ -3310,8 +3340,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 3310 | 3340 | bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 3311 | 3341 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 3312 | 3342 | |
| 3313 | | assert(op1->type_entry->id == TypeTableEntryIdBool); |
| 3314 | | assert(op2->type_entry->id == TypeTableEntryIdBool); |
| 3343 | assert(casted_op1->type_entry->id == TypeTableEntryIdBool); |
| 3344 | assert(casted_op2->type_entry->id == TypeTableEntryIdBool); |
| 3315 | 3345 | if (bin_op_instruction->op_id == IrBinOpBoolOr) { |
| 3316 | 3346 | out_val->data.x_bool = op1_val->data.x_bool || op2_val->data.x_bool; |
| 3317 | 3347 | } else if (bin_op_instruction->op_id == IrBinOpBoolAnd) { |
| ... | ... | @@ -3322,7 +3352,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 3322 | 3352 | return bool_type; |
| 3323 | 3353 | } |
| 3324 | 3354 | |
| 3325 | | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other); |
| 3355 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, casted_op1, casted_op2); |
| 3326 | 3356 | return bool_type; |
| 3327 | 3357 | } |
| 3328 | 3358 | |
| ... | ... | @@ -5238,11 +5268,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 5238 | 5268 | if (casted_new_value->type_entry->id == TypeTableEntryIdInvalid) |
| 5239 | 5269 | continue; |
| 5240 | 5270 | |
| 5241 | | if (casted_new_value->static_value.special != ConstValSpecialStatic) { |
| 5242 | | add_node_error(ira->codegen, casted_new_value->source_node, |
| 5243 | | buf_sprintf("unable to evaluate constant expression")); |
| 5271 | if (!ir_resolve_const(ira, casted_new_value)) |
| 5244 | 5272 | continue; |
| 5245 | | } |
| 5246 | 5273 | |
| 5247 | 5274 | new_case->value = casted_new_value; |
| 5248 | 5275 | } |
| ... | ... | @@ -5340,6 +5367,22 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag(IrAnalyze *ira, |
| 5340 | 5367 | zig_panic("TODO ir_analyze_instruction_enum_tag"); |
| 5341 | 5368 | } |
| 5342 | 5369 | |
| 5370 | static TypeTableEntry *ir_analyze_instruction_static_eval(IrAnalyze *ira, |
| 5371 | IrInstructionStaticEval *static_eval_instruction) |
| 5372 | { |
| 5373 | IrInstruction *value = static_eval_instruction->value->other; |
| 5374 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 5375 | return ira->codegen->builtin_types.entry_invalid; |
| 5376 | |
| 5377 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 5378 | if (!val) |
| 5379 | return ira->codegen->builtin_types.entry_invalid; |
| 5380 | |
| 5381 | ConstExprValue *out_val = ir_build_const_from(ira, &static_eval_instruction->base, val->depends_on_compile_var); |
| 5382 | *out_val = *val; |
| 5383 | return value->type_entry; |
| 5384 | } |
| 5385 | |
| 5343 | 5386 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 5344 | 5387 | switch (instruction->id) { |
| 5345 | 5388 | case IrInstructionIdInvalid: |
| ... | ... | @@ -5414,6 +5457,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 5414 | 5457 | return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); |
| 5415 | 5458 | case IrInstructionIdEnumTag: |
| 5416 | 5459 | return ir_analyze_instruction_enum_tag(ira, (IrInstructionEnumTag *)instruction); |
| 5460 | case IrInstructionIdStaticEval: |
| 5461 | return ir_analyze_instruction_static_eval(ira, (IrInstructionStaticEval *)instruction); |
| 5417 | 5462 | case IrInstructionIdCast: |
| 5418 | 5463 | case IrInstructionIdContainerInitList: |
| 5419 | 5464 | case IrInstructionIdContainerInitFields: |
| ... | ... | @@ -5533,6 +5578,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5533 | 5578 | case IrInstructionIdSwitchVar: |
| 5534 | 5579 | case IrInstructionIdSwitchTarget: |
| 5535 | 5580 | case IrInstructionIdEnumTag: |
| 5581 | case IrInstructionIdStaticEval: |
| 5536 | 5582 | return false; |
| 5537 | 5583 | case IrInstructionIdAsm: |
| 5538 | 5584 | { |
| ... | ... | @@ -6243,26 +6289,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6243 | 6289 | // case BuiltinFnIdCUndef: |
| 6244 | 6290 | // zig_panic("TODO"); |
| 6245 | 6291 | // |
| 6246 | | // case BuiltinFnIdConstEval: |
| 6247 | | // { |
| 6248 | | // AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; |
| 6249 | | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node); |
| 6250 | | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| 6251 | | // return resolved_type; |
| 6252 | | // } |
| 6253 | | // |
| 6254 | | // ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val; |
| 6255 | | // |
| 6256 | | // if (!const_expr_val->ok) { |
| 6257 | | // add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression")); |
| 6258 | | // return g->builtin_types.entry_invalid; |
| 6259 | | // } |
| 6260 | | // |
| 6261 | | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 6262 | | // *const_val = *const_expr_val; |
| 6263 | | // |
| 6264 | | // return resolved_type; |
| 6265 | | // } |
| 6266 | 6292 | // case BuiltinFnIdImport: |
| 6267 | 6293 | // return analyze_import(g, import, context, node); |
| 6268 | 6294 | // case BuiltinFnIdCImport: |
| ... | ... | @@ -8553,7 +8579,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no |
| 8553 | 8579 | // case BuiltinFnIdMinValue: |
| 8554 | 8580 | // case BuiltinFnIdMaxValue: |
| 8555 | 8581 | // case BuiltinFnIdMemberCount: |
| 8556 | | // case BuiltinFnIdConstEval: |
| 8557 | 8582 | // case BuiltinFnIdEmbedFile: |
| 8558 | 8583 | // // caught by constant expression eval codegen |
| 8559 | 8584 | // zig_unreachable(); |