| ... | ... | @@ -201,6 +201,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) { |
| 201 | 201 | return IrInstructionIdSetFnTest; |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) { |
| 205 | return IrInstructionIdSetDebugSafety; |
| 206 | } |
| 207 | |
| 204 | 208 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) { |
| 205 | 209 | return IrInstructionIdArrayType; |
| 206 | 210 | } |
| ... | ... | @@ -786,6 +790,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node, |
| 786 | 790 | return &instruction->base; |
| 787 | 791 | } |
| 788 | 792 | |
| 793 | static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, AstNode *source_node, |
| 794 | IrInstruction *scope_value, IrInstruction *debug_safety_on) |
| 795 | { |
| 796 | IrInstructionSetDebugSafety *instruction = ir_build_instruction<IrInstructionSetDebugSafety>(irb, source_node); |
| 797 | instruction->scope_value = scope_value; |
| 798 | instruction->debug_safety_on = debug_safety_on; |
| 799 | |
| 800 | ir_ref_instruction(scope_value); |
| 801 | ir_ref_instruction(debug_safety_on); |
| 802 | |
| 803 | return &instruction->base; |
| 804 | } |
| 805 | |
| 789 | 806 | static IrInstruction *ir_build_array_type(IrBuilder *irb, AstNode *source_node, IrInstruction *size, |
| 790 | 807 | IrInstruction *child_type) |
| 791 | 808 | { |
| ... | ... | @@ -1291,6 +1308,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1291 | 1308 | |
| 1292 | 1309 | return ir_build_set_fn_test(irb, node, arg0_value, arg1_value); |
| 1293 | 1310 | } |
| 1311 | case BuiltinFnIdSetDebugSafety: |
| 1312 | { |
| 1313 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 1314 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); |
| 1315 | if (arg0_value == irb->codegen->invalid_instruction) |
| 1316 | return arg0_value; |
| 1317 | |
| 1318 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); |
| 1319 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context); |
| 1320 | if (arg1_value == irb->codegen->invalid_instruction) |
| 1321 | return arg1_value; |
| 1322 | |
| 1323 | return ir_build_set_debug_safety(irb, node, arg0_value, arg1_value); |
| 1324 | } |
| 1294 | 1325 | case BuiltinFnIdMemcpy: |
| 1295 | 1326 | case BuiltinFnIdMemset: |
| 1296 | 1327 | case BuiltinFnIdSizeof: |
| ... | ... | @@ -1325,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1325 | 1356 | case BuiltinFnIdSetFnVisible: |
| 1326 | 1357 | case BuiltinFnIdSetFnStaticEval: |
| 1327 | 1358 | case BuiltinFnIdSetFnNoInline: |
| 1328 | | case BuiltinFnIdSetDebugSafety: |
| 1329 | 1359 | zig_panic("TODO IR gen more builtin functions"); |
| 1330 | 1360 | } |
| 1331 | 1361 | zig_unreachable(); |
| ... | ... | @@ -2260,6 +2290,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value |
| 2260 | 2290 | return const_val->data.x_type; |
| 2261 | 2291 | } |
| 2262 | 2292 | |
| 2293 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 2294 | if (value->static_value.special != ConstValSpecialStatic) { |
| 2295 | add_node_error(ira->codegen, value->source_node, |
| 2296 | buf_sprintf("unable to evaluate constant expression")); |
| 2297 | return nullptr; |
| 2298 | } |
| 2299 | return &value->static_value; |
| 2300 | } |
| 2301 | |
| 2263 | 2302 | static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) { |
| 2264 | 2303 | if (bool_value == ira->codegen->invalid_instruction) |
| 2265 | 2304 | return false; |
| ... | ... | @@ -2273,12 +2312,9 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out |
| 2273 | 2312 | return false; |
| 2274 | 2313 | } |
| 2275 | 2314 | |
| 2276 | | ConstExprValue *const_val = &bool_value->static_value; |
| 2277 | | if (const_val->special == ConstValSpecialRuntime) { |
| 2278 | | add_node_error(ira->codegen, bool_value->source_node, |
| 2279 | | buf_sprintf("unable to evaluate constant expression")); |
| 2315 | ConstExprValue *const_val = ir_resolve_const(ira, bool_value); |
| 2316 | if (!const_val) |
| 2280 | 2317 | return false; |
| 2281 | | } |
| 2282 | 2318 | |
| 2283 | 2319 | *out = const_val->data.x_bool; |
| 2284 | 2320 | return true; |
| ... | ... | @@ -4027,12 +4063,67 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira, |
| 4027 | 4063 | } |
| 4028 | 4064 | fn_entry->fn_test_set_node = source_node; |
| 4029 | 4065 | |
| 4030 | | ira->codegen->test_fn_count += 1; |
| 4066 | if (fn_entry->is_test) |
| 4067 | ira->codegen->test_fn_count += 1; |
| 4031 | 4068 | |
| 4032 | 4069 | ir_build_const_from(ira, &set_fn_test_instruction->base, false); |
| 4033 | 4070 | return ira->codegen->builtin_types.entry_void; |
| 4034 | 4071 | } |
| 4035 | 4072 | |
| 4073 | static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, |
| 4074 | IrInstructionSetDebugSafety *set_debug_safety_instruction) |
| 4075 | { |
| 4076 | IrInstruction *target_instruction = set_debug_safety_instruction->scope_value->other; |
| 4077 | TypeTableEntry *target_type = target_instruction->type_entry; |
| 4078 | if (target_type->id == TypeTableEntryIdInvalid) |
| 4079 | return ira->codegen->builtin_types.entry_invalid; |
| 4080 | ConstExprValue *target_val = ir_resolve_const(ira, target_instruction); |
| 4081 | if (!target_val) |
| 4082 | return ira->codegen->builtin_types.entry_invalid; |
| 4083 | |
| 4084 | BlockContext *target_context; |
| 4085 | if (target_type->id == TypeTableEntryIdBlock) { |
| 4086 | target_context = target_val->data.x_block; |
| 4087 | } else if (target_type->id == TypeTableEntryIdFn) { |
| 4088 | target_context = target_val->data.x_fn->fn_def_node->data.fn_def.block_context; |
| 4089 | } else if (target_type->id == TypeTableEntryIdMetaType) { |
| 4090 | TypeTableEntry *type_arg = target_val->data.x_type; |
| 4091 | if (type_arg->id == TypeTableEntryIdStruct) { |
| 4092 | target_context = type_arg->data.structure.block_context; |
| 4093 | } else if (type_arg->id == TypeTableEntryIdEnum) { |
| 4094 | target_context = type_arg->data.enumeration.block_context; |
| 4095 | } else if (type_arg->id == TypeTableEntryIdUnion) { |
| 4096 | target_context = type_arg->data.unionation.block_context; |
| 4097 | } else { |
| 4098 | add_node_error(ira->codegen, target_instruction->source_node, |
| 4099 | buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name))); |
| 4100 | return ira->codegen->builtin_types.entry_invalid; |
| 4101 | } |
| 4102 | } else { |
| 4103 | add_node_error(ira->codegen, target_instruction->source_node, |
| 4104 | buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name))); |
| 4105 | return ira->codegen->builtin_types.entry_invalid; |
| 4106 | } |
| 4107 | |
| 4108 | IrInstruction *debug_safety_on_value = set_debug_safety_instruction->debug_safety_on->other; |
| 4109 | bool want_debug_safety; |
| 4110 | if (!ir_resolve_bool(ira, debug_safety_on_value, &want_debug_safety)) |
| 4111 | return ira->codegen->builtin_types.entry_invalid; |
| 4112 | |
| 4113 | AstNode *source_node = set_debug_safety_instruction->base.source_node; |
| 4114 | if (target_context->safety_set_node) { |
| 4115 | ErrorMsg *msg = add_node_error(ira->codegen, source_node, |
| 4116 | buf_sprintf("function test attribute set twice")); |
| 4117 | add_error_note(ira->codegen, msg, target_context->safety_set_node, buf_sprintf("first set here")); |
| 4118 | return ira->codegen->builtin_types.entry_invalid; |
| 4119 | } |
| 4120 | target_context->safety_set_node = source_node; |
| 4121 | target_context->safety_off = !want_debug_safety; |
| 4122 | |
| 4123 | ir_build_const_from(ira, &set_debug_safety_instruction->base, false); |
| 4124 | return ira->codegen->builtin_types.entry_void; |
| 4125 | } |
| 4126 | |
| 4036 | 4127 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 4037 | 4128 | IrInstructionSliceType *slice_type_instruction) |
| 4038 | 4129 | { |
| ... | ... | @@ -4164,6 +4255,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4164 | 4255 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 4165 | 4256 | case IrInstructionIdSetFnTest: |
| 4166 | 4257 | return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); |
| 4258 | case IrInstructionIdSetDebugSafety: |
| 4259 | return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); |
| 4167 | 4260 | case IrInstructionIdSliceType: |
| 4168 | 4261 | return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); |
| 4169 | 4262 | case IrInstructionIdAsm: |
| ... | ... | @@ -4257,6 +4350,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 4257 | 4350 | case IrInstructionIdReturn: |
| 4258 | 4351 | case IrInstructionIdUnreachable: |
| 4259 | 4352 | case IrInstructionIdSetFnTest: |
| 4353 | case IrInstructionIdSetDebugSafety: |
| 4260 | 4354 | return true; |
| 4261 | 4355 | case IrInstructionIdPhi: |
| 4262 | 4356 | case IrInstructionIdUnOp: |
| ... | ... | @@ -4854,64 +4948,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 4854 | 4948 | // return g->builtin_types.entry_void; |
| 4855 | 4949 | //} |
| 4856 | 4950 | // |
| 4857 | | //static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import, |
| 4858 | | // BlockContext *parent_context, AstNode *node) |
| 4859 | | //{ |
| 4860 | | // AstNode **target_node = &node->data.fn_call_expr.params.at(0); |
| 4861 | | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); |
| 4862 | | // |
| 4863 | | // TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node); |
| 4864 | | // BlockContext *target_context; |
| 4865 | | // ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val; |
| 4866 | | // if (target_type->id == TypeTableEntryIdInvalid) { |
| 4867 | | // return g->builtin_types.entry_invalid; |
| 4868 | | // } |
| 4869 | | // if (!const_val->ok) { |
| 4870 | | // add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression")); |
| 4871 | | // return g->builtin_types.entry_invalid; |
| 4872 | | // } |
| 4873 | | // if (target_type->id == TypeTableEntryIdBlock) { |
| 4874 | | // target_context = const_val->data.x_block; |
| 4875 | | // } else if (target_type->id == TypeTableEntryIdFn) { |
| 4876 | | // target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context; |
| 4877 | | // } else if (target_type->id == TypeTableEntryIdMetaType) { |
| 4878 | | // TypeTableEntry *type_arg = const_val->data.x_type; |
| 4879 | | // if (type_arg->id == TypeTableEntryIdStruct) { |
| 4880 | | // target_context = type_arg->data.structure.block_context; |
| 4881 | | // } else if (type_arg->id == TypeTableEntryIdEnum) { |
| 4882 | | // target_context = type_arg->data.enumeration.block_context; |
| 4883 | | // } else if (type_arg->id == TypeTableEntryIdUnion) { |
| 4884 | | // target_context = type_arg->data.unionation.block_context; |
| 4885 | | // } else { |
| 4886 | | // add_node_error(g, *target_node, |
| 4887 | | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name))); |
| 4888 | | // return g->builtin_types.entry_invalid; |
| 4889 | | // } |
| 4890 | | // } else { |
| 4891 | | // add_node_error(g, *target_node, |
| 4892 | | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name))); |
| 4893 | | // return g->builtin_types.entry_invalid; |
| 4894 | | // } |
| 4895 | | // |
| 4896 | | // bool want_debug_safety; |
| 4897 | | // bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety); |
| 4898 | | // if (!ok) { |
| 4899 | | // return g->builtin_types.entry_invalid; |
| 4900 | | // } |
| 4901 | | // |
| 4902 | | // if (target_context->safety_set_node) { |
| 4903 | | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice")); |
| 4904 | | // add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here")); |
| 4905 | | // return g->builtin_types.entry_invalid; |
| 4906 | | // } |
| 4907 | | // target_context->safety_set_node = node; |
| 4908 | | // |
| 4909 | | // target_context->safety_off = !want_debug_safety; |
| 4910 | | // |
| 4911 | | // return g->builtin_types.entry_void; |
| 4912 | | //} |
| 4913 | | |
| 4914 | | |
| 4915 | 4951 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4916 | 4952 | // TypeTableEntry *expected_type, AstNode *node) |
| 4917 | 4953 | //{ |
| ... | ... | @@ -5215,8 +5251,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 5215 | 5251 | // return analyze_set_fn_static_eval(g, import, context, node); |
| 5216 | 5252 | // case BuiltinFnIdSetFnVisible: |
| 5217 | 5253 | // return analyze_set_fn_visible(g, import, context, node); |
| 5218 | | // case BuiltinFnIdSetDebugSafety: |
| 5219 | | // return analyze_set_debug_safety(g, import, context, node); |
| 5220 | 5254 | // } |
| 5221 | 5255 | // zig_unreachable(); |
| 5222 | 5256 | //} |