| ... | @@ -149,10 +149,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) { | ... | @@ -149,10 +149,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) { |
| 149 | return IrInstructionIdCall; | 149 | return IrInstructionIdCall; |
| 150 | } | 150 | } |
| 151 | | 151 | |
| 152 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBuiltinCall *) { | | |
| 153 | return IrInstructionIdBuiltinCall; | | |
| 154 | } | | |
| 155 | | | |
| 156 | static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) { | 152 | static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) { |
| 157 | return IrInstructionIdConst; | 153 | return IrInstructionIdConst; |
| 158 | } | 154 | } |
| ... | @@ -189,6 +185,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) | ... | @@ -189,6 +185,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) |
| 189 | return IrInstructionIdPtrTypeChild; | 185 | return IrInstructionIdPtrTypeChild; |
| 190 | } | 186 | } |
| 191 | | 187 | |
| | 188 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) { |
| | 189 | return IrInstructionIdSetFnTest; |
| | 190 | } |
| | 191 | |
| 192 | template<typename T> | 192 | template<typename T> |
| 193 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | 193 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 194 | T *special_instruction = allocate<T>(1); | 194 | T *special_instruction = allocate<T>(1); |
| ... | @@ -353,7 +353,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, | ... | @@ -353,7 +353,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node, |
| 353 | | 353 | |
| 354 | static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) { | 354 | static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) { |
| 355 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); | 355 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 356 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block; | 356 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool; |
| 357 | const_instruction->base.static_value.ok = true; | 357 | const_instruction->base.static_value.ok = true; |
| 358 | const_instruction->base.static_value.data.x_bool = value; | 358 | const_instruction->base.static_value.data.x_bool = value; |
| 359 | return &const_instruction->base; | 359 | return &const_instruction->base; |
| ... | @@ -505,20 +505,6 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst | ... | @@ -505,20 +505,6 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst |
| 505 | return new_instruction; | 505 | return new_instruction; |
| 506 | } | 506 | } |
| 507 | | 507 | |
| 508 | static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node, | | |
| 509 | BuiltinFnEntry *fn, IrInstruction **args) | | |
| 510 | { | | |
| 511 | IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node); | | |
| 512 | call_instruction->fn = fn; | | |
| 513 | call_instruction->args = args; | | |
| 514 | | | |
| 515 | for (size_t i = 0; i < fn->param_count; i += 1) { | | |
| 516 | ir_ref_instruction(args[i]); | | |
| 517 | } | | |
| 518 | | | |
| 519 | return &call_instruction->base; | | |
| 520 | } | | |
| 521 | | | |
| 522 | static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node, | 508 | static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node, |
| 523 | size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values) | 509 | size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values) |
| 524 | { | 510 | { |
| ... | @@ -717,6 +703,19 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, AstNode *source_no | ... | @@ -717,6 +703,19 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, AstNode *source_no |
| 717 | return &instruction->base; | 703 | return &instruction->base; |
| 718 | } | 704 | } |
| 719 | | 705 | |
| | 706 | static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node, IrInstruction *fn_value, |
| | 707 | IrInstruction *is_test) |
| | 708 | { |
| | 709 | IrInstructionSetFnTest *instruction = ir_build_instruction<IrInstructionSetFnTest>(irb, source_node); |
| | 710 | instruction->fn_value = fn_value; |
| | 711 | instruction->is_test = is_test; |
| | 712 | |
| | 713 | ir_ref_instruction(fn_value); |
| | 714 | ir_ref_instruction(is_test); |
| | 715 | |
| | 716 | return &instruction->base; |
| | 717 | } |
| | 718 | |
| 720 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { | 719 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 721 | // size_t result = 0; | 720 | // size_t result = 0; |
| 722 | // while (inner_block != outer_block) { | 721 | // while (inner_block != outer_block) { |
| ... | @@ -1066,10 +1065,6 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN | ... | @@ -1066,10 +1065,6 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN |
| 1066 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) { | 1065 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) { |
| 1067 | assert(node->type == NodeTypeSymbol); | 1066 | assert(node->type == NodeTypeSymbol); |
| 1068 | | 1067 | |
| 1069 | if (node->data.symbol_expr.override_type_entry) { | | |
| 1070 | zig_panic("TODO have parseh directly generate IR"); | | |
| 1071 | } | | |
| 1072 | | | |
| 1073 | Buf *variable_name = node->data.symbol_expr.symbol; | 1068 | Buf *variable_name = node->data.symbol_expr.symbol; |
| 1074 | | 1069 | |
| 1075 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); | 1070 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| ... | @@ -1163,26 +1158,71 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1163,26 +1158,71 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1163 | | 1158 | |
| 1164 | builtin_fn->ref_count += 1; | 1159 | builtin_fn->ref_count += 1; |
| 1165 | | 1160 | |
| 1166 | if (builtin_fn->id == BuiltinFnIdUnreachable) { | 1161 | switch (builtin_fn->id) { |
| 1167 | return ir_build_unreachable(irb, node); | 1162 | case BuiltinFnIdInvalid: |
| 1168 | } else if (builtin_fn->id == BuiltinFnIdTypeof) { | 1163 | zig_unreachable(); |
| 1169 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); | 1164 | case BuiltinFnIdUnreachable: |
| 1170 | IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context); | 1165 | return ir_build_unreachable(irb, node); |
| 1171 | if (arg == irb->codegen->invalid_instruction) | 1166 | case BuiltinFnIdTypeof: |
| 1172 | return arg; | 1167 | { |
| 1173 | return ir_build_typeof(irb, node, arg); | 1168 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); |
| 1174 | } | 1169 | IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context); |
| | 1170 | if (arg == irb->codegen->invalid_instruction) |
| | 1171 | return arg; |
| | 1172 | return ir_build_typeof(irb, node, arg); |
| | 1173 | } |
| | 1174 | case BuiltinFnIdSetFnTest: |
| | 1175 | { |
| | 1176 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| | 1177 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); |
| | 1178 | if (arg0_value == irb->codegen->invalid_instruction) |
| | 1179 | return arg0_value; |
| 1175 | | 1180 | |
| 1176 | IrInstruction **args = allocate<IrInstruction *>(actual_param_count); | 1181 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); |
| 1177 | for (size_t i = 0; i < actual_param_count; i += 1) { | 1182 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context); |
| 1178 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); | 1183 | if (arg1_value == irb->codegen->invalid_instruction) |
| 1179 | IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context); | 1184 | return arg1_value; |
| 1180 | if (arg == irb->codegen->invalid_instruction) | | |
| 1181 | return arg; | | |
| 1182 | args[i] = arg; | | |
| 1183 | } | | |
| 1184 | | 1185 | |
| 1185 | return ir_build_builtin_call(irb, node, builtin_fn, args); | 1186 | return ir_build_set_fn_test(irb, node, arg0_value, arg1_value); |
| | 1187 | } |
| | 1188 | case BuiltinFnIdMemcpy: |
| | 1189 | case BuiltinFnIdMemset: |
| | 1190 | case BuiltinFnIdSizeof: |
| | 1191 | case BuiltinFnIdAlignof: |
| | 1192 | case BuiltinFnIdMaxValue: |
| | 1193 | case BuiltinFnIdMinValue: |
| | 1194 | case BuiltinFnIdMemberCount: |
| | 1195 | case BuiltinFnIdAddWithOverflow: |
| | 1196 | case BuiltinFnIdSubWithOverflow: |
| | 1197 | case BuiltinFnIdMulWithOverflow: |
| | 1198 | case BuiltinFnIdShlWithOverflow: |
| | 1199 | case BuiltinFnIdCInclude: |
| | 1200 | case BuiltinFnIdCDefine: |
| | 1201 | case BuiltinFnIdCUndef: |
| | 1202 | case BuiltinFnIdCompileVar: |
| | 1203 | case BuiltinFnIdCompileErr: |
| | 1204 | case BuiltinFnIdConstEval: |
| | 1205 | case BuiltinFnIdCtz: |
| | 1206 | case BuiltinFnIdClz: |
| | 1207 | case BuiltinFnIdImport: |
| | 1208 | case BuiltinFnIdCImport: |
| | 1209 | case BuiltinFnIdErrName: |
| | 1210 | case BuiltinFnIdBreakpoint: |
| | 1211 | case BuiltinFnIdReturnAddress: |
| | 1212 | case BuiltinFnIdFrameAddress: |
| | 1213 | case BuiltinFnIdEmbedFile: |
| | 1214 | case BuiltinFnIdCmpExchange: |
| | 1215 | case BuiltinFnIdFence: |
| | 1216 | case BuiltinFnIdDivExact: |
| | 1217 | case BuiltinFnIdTruncate: |
| | 1218 | case BuiltinFnIdIntType: |
| | 1219 | case BuiltinFnIdSetFnVisible: |
| | 1220 | case BuiltinFnIdSetFnStaticEval: |
| | 1221 | case BuiltinFnIdSetFnNoInline: |
| | 1222 | case BuiltinFnIdSetDebugSafety: |
| | 1223 | zig_panic("TODO IR gen more builtin functions"); |
| | 1224 | } |
| | 1225 | zig_unreachable(); |
| 1186 | } | 1226 | } |
| 1187 | | 1227 | |
| 1188 | static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { | 1228 | static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { |
| ... | @@ -2044,6 +2084,53 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value | ... | @@ -2044,6 +2084,53 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value |
| 2044 | return const_val->data.x_type; | 2084 | return const_val->data.x_type; |
| 2045 | } | 2085 | } |
| 2046 | | 2086 | |
| | 2087 | static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) { |
| | 2088 | if (bool_value == ira->codegen->invalid_instruction) |
| | 2089 | return false; |
| | 2090 | |
| | 2091 | if (bool_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2092 | return false; |
| | 2093 | |
| | 2094 | if (bool_value->type_entry->id != TypeTableEntryIdBool) { |
| | 2095 | add_node_error(ira->codegen, bool_value->source_node, |
| | 2096 | buf_sprintf("expected type 'bool', found '%s'", buf_ptr(&bool_value->type_entry->name))); |
| | 2097 | return false; |
| | 2098 | } |
| | 2099 | |
| | 2100 | ConstExprValue *const_val = &bool_value->static_value; |
| | 2101 | if (!const_val->ok) { |
| | 2102 | add_node_error(ira->codegen, bool_value->source_node, |
| | 2103 | buf_sprintf("unable to evaluate constant expression")); |
| | 2104 | return false; |
| | 2105 | } |
| | 2106 | |
| | 2107 | *out = const_val->data.x_bool; |
| | 2108 | return true; |
| | 2109 | } |
| | 2110 | |
| | 2111 | static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| | 2112 | if (fn_value == ira->codegen->invalid_instruction) |
| | 2113 | return nullptr; |
| | 2114 | |
| | 2115 | if (fn_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2116 | return nullptr; |
| | 2117 | |
| | 2118 | if (fn_value->type_entry->id != TypeTableEntryIdFn) { |
| | 2119 | add_node_error(ira->codegen, fn_value->source_node, |
| | 2120 | buf_sprintf("expected function type, found '%s'", buf_ptr(&fn_value->type_entry->name))); |
| | 2121 | return nullptr; |
| | 2122 | } |
| | 2123 | |
| | 2124 | ConstExprValue *const_val = &fn_value->static_value; |
| | 2125 | if (!const_val->ok) { |
| | 2126 | add_node_error(ira->codegen, fn_value->source_node, |
| | 2127 | buf_sprintf("unable to evaluate constant expression")); |
| | 2128 | return nullptr; |
| | 2129 | } |
| | 2130 | |
| | 2131 | return const_val->data.x_fn; |
| | 2132 | } |
| | 2133 | |
| 2047 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 2134 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 2048 | IrInstruction *dest_type, IrInstruction *value) | 2135 | IrInstruction *dest_type, IrInstruction *value) |
| 2049 | { | 2136 | { |
| ... | @@ -2837,11 +2924,18 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction | ... | @@ -2837,11 +2924,18 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 2837 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { | 2924 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { |
| 2838 | // TODO fully port over the fn call analyze code to IR | 2925 | // TODO fully port over the fn call analyze code to IR |
| 2839 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn; | 2926 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn; |
| | 2927 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| | 2928 | |
| | 2929 | IrInstruction **casted_args = allocate<IrInstruction *>(call_instruction->arg_count); |
| | 2930 | for (size_t i = 0; i < call_instruction->arg_count; i += 1) { |
| | 2931 | TypeTableEntry *param_type = fn_type->data.fn.fn_type_id.param_info[i].type; |
| | 2932 | IrInstruction *old_arg = call_instruction->args[i]->other; |
| | 2933 | casted_args[i] = ir_get_casted_value(ira, old_arg, param_type); |
| | 2934 | } |
| 2840 | | 2935 | |
| 2841 | ir_build_call_from(&ira->new_irb, &call_instruction->base, | 2936 | ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 2842 | call_instruction->fn, call_instruction->arg_count, call_instruction->args); | 2937 | call_instruction->fn, call_instruction->arg_count, casted_args); |
| 2843 | | 2938 | |
| 2844 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | | |
| 2845 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | 2939 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 2846 | return return_type; | 2940 | return return_type; |
| 2847 | } else { | 2941 | } else { |
| ... | @@ -3075,1121 +3169,8 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio | ... | @@ -3075,1121 +3169,8 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3075 | zig_unreachable(); | 3169 | zig_unreachable(); |
| 3076 | } | 3170 | } |
| 3077 | | 3171 | |
| 3078 | //static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 3172 | static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { |
| 3079 | // AstNode *node, const char *err_format, bool is_max) | 3173 | IrBasicBlock *old_dest_block = br_instruction->dest_block; |
| 3080 | //{ | | |
| 3081 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3082 | // assert(node->data.fn_call_expr.params.length == 1); | | |
| 3083 | // | | |
| 3084 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3085 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 3086 | // | | |
| 3087 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 3088 | // return g->builtin_types.entry_invalid; | | |
| 3089 | // } else if (type_entry->id == TypeTableEntryIdInt) { | | |
| 3090 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); | | |
| 3091 | // return g->builtin_types.entry_num_lit_int; | | |
| 3092 | // } else if (type_entry->id == TypeTableEntryIdFloat) { | | |
| 3093 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); | | |
| 3094 | // return g->builtin_types.entry_num_lit_float; | | |
| 3095 | // } else if (type_entry->id == TypeTableEntryIdBool) { | | |
| 3096 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); | | |
| 3097 | // return type_entry; | | |
| 3098 | // } else { | | |
| 3099 | // add_node_error(g, node, | | |
| 3100 | // buf_sprintf(err_format, buf_ptr(&type_entry->name))); | | |
| 3101 | // return g->builtin_types.entry_invalid; | | |
| 3102 | // } | | |
| 3103 | //} | | |
| 3104 | | | |
| 3105 | //static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 3106 | // AstNode *node) | | |
| 3107 | //{ | | |
| 3108 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3109 | // | | |
| 3110 | // if (context->fn_entry) { | | |
| 3111 | // add_node_error(g, node, buf_sprintf("@import invalid inside function bodies")); | | |
| 3112 | // return g->builtin_types.entry_invalid; | | |
| 3113 | // } | | |
| 3114 | // | | |
| 3115 | // AstNode *first_param_node = node->data.fn_call_expr.params.at(0); | | |
| 3116 | // Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field); | | |
| 3117 | // if (!import_target_str) { | | |
| 3118 | // return g->builtin_types.entry_invalid; | | |
| 3119 | // } | | |
| 3120 | // | | |
| 3121 | // Buf *import_target_path; | | |
| 3122 | // Buf *search_dir; | | |
| 3123 | // assert(import->package); | | |
| 3124 | // PackageTableEntry *target_package; | | |
| 3125 | // auto package_entry = import->package->package_table.maybe_get(import_target_str); | | |
| 3126 | // if (package_entry) { | | |
| 3127 | // target_package = package_entry->value; | | |
| 3128 | // import_target_path = &target_package->root_src_path; | | |
| 3129 | // search_dir = &target_package->root_src_dir; | | |
| 3130 | // } else { | | |
| 3131 | // // try it as a filename | | |
| 3132 | // target_package = import->package; | | |
| 3133 | // import_target_path = import_target_str; | | |
| 3134 | // search_dir = &import->package->root_src_dir; | | |
| 3135 | // } | | |
| 3136 | // | | |
| 3137 | // Buf full_path = BUF_INIT; | | |
| 3138 | // os_path_join(search_dir, import_target_path, &full_path); | | |
| 3139 | // | | |
| 3140 | // Buf *import_code = buf_alloc(); | | |
| 3141 | // Buf *abs_full_path = buf_alloc(); | | |
| 3142 | // int err; | | |
| 3143 | // if ((err = os_path_real(&full_path, abs_full_path))) { | | |
| 3144 | // if (err == ErrorFileNotFound) { | | |
| 3145 | // add_node_error(g, node, | | |
| 3146 | // buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); | | |
| 3147 | // return g->builtin_types.entry_invalid; | | |
| 3148 | // } else { | | |
| 3149 | // g->error_during_imports = true; | | |
| 3150 | // add_node_error(g, node, | | |
| 3151 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); | | |
| 3152 | // return g->builtin_types.entry_invalid; | | |
| 3153 | // } | | |
| 3154 | // } | | |
| 3155 | // | | |
| 3156 | // auto import_entry = g->import_table.maybe_get(abs_full_path); | | |
| 3157 | // if (import_entry) { | | |
| 3158 | // return resolve_expr_const_val_as_import(g, node, import_entry->value); | | |
| 3159 | // } | | |
| 3160 | // | | |
| 3161 | // if ((err = os_fetch_file_path(abs_full_path, import_code))) { | | |
| 3162 | // if (err == ErrorFileNotFound) { | | |
| 3163 | // add_node_error(g, node, | | |
| 3164 | // buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); | | |
| 3165 | // return g->builtin_types.entry_invalid; | | |
| 3166 | // } else { | | |
| 3167 | // add_node_error(g, node, | | |
| 3168 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); | | |
| 3169 | // return g->builtin_types.entry_invalid; | | |
| 3170 | // } | | |
| 3171 | // } | | |
| 3172 | // ImportTableEntry *target_import = add_source_file(g, target_package, | | |
| 3173 | // abs_full_path, search_dir, import_target_path, import_code); | | |
| 3174 | // | | |
| 3175 | // scan_decls(g, target_import, target_import->block_context, target_import->root); | | |
| 3176 | // | | |
| 3177 | // return resolve_expr_const_val_as_import(g, node, target_import); | | |
| 3178 | //} | | |
| 3179 | // | | |
| 3180 | //static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import, | | |
| 3181 | // BlockContext *parent_context, AstNode *node) | | |
| 3182 | //{ | | |
| 3183 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3184 | // | | |
| 3185 | // if (parent_context->fn_entry) { | | |
| 3186 | // add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies")); | | |
| 3187 | // return g->builtin_types.entry_invalid; | | |
| 3188 | // } | | |
| 3189 | // | | |
| 3190 | // AstNode *block_node = node->data.fn_call_expr.params.at(0); | | |
| 3191 | // | | |
| 3192 | // BlockContext *child_context = new_block_context(node, parent_context); | | |
| 3193 | // child_context->c_import_buf = buf_alloc(); | | |
| 3194 | // | | |
| 3195 | // TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context, | | |
| 3196 | // g->builtin_types.entry_void, block_node); | | |
| 3197 | // | | |
| 3198 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 3199 | // return resolved_type; | | |
| 3200 | // } | | |
| 3201 | // | | |
| 3202 | // find_libc_include_path(g); | | |
| 3203 | // | | |
| 3204 | // ImportTableEntry *child_import = allocate<ImportTableEntry>(1); | | |
| 3205 | // child_import->c_import_node = node; | | |
| 3206 | // | | |
| 3207 | // ZigList<ErrorMsg *> errors = {0}; | | |
| 3208 | // | | |
| 3209 | // int err; | | |
| 3210 | // if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) { | | |
| 3211 | // zig_panic("unable to parse h file: %s\n", err_str(err)); | | |
| 3212 | // } | | |
| 3213 | // | | |
| 3214 | // if (errors.length > 0) { | | |
| 3215 | // ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed")); | | |
| 3216 | // for (size_t i = 0; i < errors.length; i += 1) { | | |
| 3217 | // ErrorMsg *err_msg = errors.at(i); | | |
| 3218 | // err_msg_add_note(parent_err_msg, err_msg); | | |
| 3219 | // } | | |
| 3220 | // | | |
| 3221 | // return g->builtin_types.entry_invalid; | | |
| 3222 | // } | | |
| 3223 | // | | |
| 3224 | // if (g->verbose) { | | |
| 3225 | // fprintf(stderr, "\nc_import:\n"); | | |
| 3226 | // fprintf(stderr, "-----------\n"); | | |
| 3227 | // ast_render(stderr, child_import->root, 4); | | |
| 3228 | // } | | |
| 3229 | // | | |
| 3230 | // child_import->di_file = parent_import->di_file; | | |
| 3231 | // child_import->block_context = new_block_context(child_import->root, nullptr); | | |
| 3232 | // | | |
| 3233 | // scan_decls(g, child_import, child_import->block_context, child_import->root); | | |
| 3234 | // return resolve_expr_const_val_as_import(g, node, child_import); | | |
| 3235 | //} | | |
| 3236 | // | | |
| 3237 | //static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import, | | |
| 3238 | // BlockContext *context, AstNode *node) | | |
| 3239 | //{ | | |
| 3240 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3241 | // | | |
| 3242 | // AstNode *err_value = node->data.fn_call_expr.params.at(0); | | |
| 3243 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, | | |
| 3244 | // g->builtin_types.entry_pure_error, err_value); | | |
| 3245 | // | | |
| 3246 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 3247 | // return resolved_type; | | |
| 3248 | // } | | |
| 3249 | // | | |
| 3250 | // g->generate_error_name_table = true; | | |
| 3251 | // | | |
| 3252 | // TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | | |
| 3253 | // return str_type; | | |
| 3254 | //} | | |
| 3255 | // | | |
| 3256 | //static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, | | |
| 3257 | // BlockContext *context, AstNode *node) | | |
| 3258 | //{ | | |
| 3259 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3260 | // | | |
| 3261 | // AstNode **first_param_node = &node->data.fn_call_expr.params.at(0); | | |
| 3262 | // Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node); | | |
| 3263 | // if (!rel_file_path) { | | |
| 3264 | // return g->builtin_types.entry_invalid; | | |
| 3265 | // } | | |
| 3266 | // | | |
| 3267 | // // figure out absolute path to resource | | |
| 3268 | // Buf source_dir_path = BUF_INIT; | | |
| 3269 | // os_path_dirname(import->path, &source_dir_path); | | |
| 3270 | // | | |
| 3271 | // Buf file_path = BUF_INIT; | | |
| 3272 | // os_path_resolve(&source_dir_path, rel_file_path, &file_path); | | |
| 3273 | // | | |
| 3274 | // // load from file system into const expr | | |
| 3275 | // Buf file_contents = BUF_INIT; | | |
| 3276 | // int err; | | |
| 3277 | // if ((err = os_fetch_file_path(&file_path, &file_contents))) { | | |
| 3278 | // if (err == ErrorFileNotFound) { | | |
| 3279 | // add_node_error(g, node, | | |
| 3280 | // buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); | | |
| 3281 | // return g->builtin_types.entry_invalid; | | |
| 3282 | // } else { | | |
| 3283 | // add_node_error(g, node, | | |
| 3284 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); | | |
| 3285 | // return g->builtin_types.entry_invalid; | | |
| 3286 | // } | | |
| 3287 | // } | | |
| 3288 | // | | |
| 3289 | // // TODO add dependency on the file we embedded so that we know if it changes | | |
| 3290 | // // we'll have to invalidate the cache | | |
| 3291 | // | | |
| 3292 | // return resolve_expr_const_val_as_string_lit(g, node, &file_contents); | | |
| 3293 | //} | | |
| 3294 | // | | |
| 3295 | //static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, | | |
| 3296 | // BlockContext *context, AstNode *node) | | |
| 3297 | //{ | | |
| 3298 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3299 | // | | |
| 3300 | // AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0); | | |
| 3301 | // AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1); | | |
| 3302 | // AstNode **new_arg = &node->data.fn_call_expr.params.at(2); | | |
| 3303 | // AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3); | | |
| 3304 | // AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4); | | |
| 3305 | // | | |
| 3306 | // TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg); | | |
| 3307 | // if (ptr_type->id == TypeTableEntryIdInvalid) { | | |
| 3308 | // return g->builtin_types.entry_invalid; | | |
| 3309 | // } else if (ptr_type->id != TypeTableEntryIdPointer) { | | |
| 3310 | // add_node_error(g, *ptr_arg, | | |
| 3311 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name))); | | |
| 3312 | // return g->builtin_types.entry_invalid; | | |
| 3313 | // } | | |
| 3314 | // | | |
| 3315 | // TypeTableEntry *child_type = ptr_type->data.pointer.child_type; | | |
| 3316 | // TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg); | | |
| 3317 | // TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg); | | |
| 3318 | // | | |
| 3319 | // TypeTableEntry *success_order_type = analyze_expression(g, import, context, | | |
| 3320 | // g->builtin_types.entry_atomic_order_enum, *success_order_arg); | | |
| 3321 | // TypeTableEntry *failure_order_type = analyze_expression(g, import, context, | | |
| 3322 | // g->builtin_types.entry_atomic_order_enum, *failure_order_arg); | | |
| 3323 | // | | |
| 3324 | // if (cmp_type->id == TypeTableEntryIdInvalid || | | |
| 3325 | // new_type->id == TypeTableEntryIdInvalid || | | |
| 3326 | // success_order_type->id == TypeTableEntryIdInvalid || | | |
| 3327 | // failure_order_type->id == TypeTableEntryIdInvalid) | | |
| 3328 | // { | | |
| 3329 | // return g->builtin_types.entry_invalid; | | |
| 3330 | // } | | |
| 3331 | // | | |
| 3332 | // ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val; | | |
| 3333 | // ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val; | | |
| 3334 | // if (!success_order_val->ok) { | | |
| 3335 | // add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression")); | | |
| 3336 | // return g->builtin_types.entry_invalid; | | |
| 3337 | // } else if (!failure_order_val->ok) { | | |
| 3338 | // add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression")); | | |
| 3339 | // return g->builtin_types.entry_invalid; | | |
| 3340 | // } | | |
| 3341 | // | | |
| 3342 | // if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) { | | |
| 3343 | // add_node_error(g, *success_order_arg, | | |
| 3344 | // buf_sprintf("success atomic ordering must be Monotonic or stricter")); | | |
| 3345 | // return g->builtin_types.entry_invalid; | | |
| 3346 | // } | | |
| 3347 | // if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) { | | |
| 3348 | // add_node_error(g, *failure_order_arg, | | |
| 3349 | // buf_sprintf("failure atomic ordering must be Monotonic or stricter")); | | |
| 3350 | // return g->builtin_types.entry_invalid; | | |
| 3351 | // } | | |
| 3352 | // if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) { | | |
| 3353 | // add_node_error(g, *failure_order_arg, | | |
| 3354 | // buf_sprintf("failure atomic ordering must be no stricter than success")); | | |
| 3355 | // return g->builtin_types.entry_invalid; | | |
| 3356 | // } | | |
| 3357 | // if (failure_order_val->data.x_enum.tag == AtomicOrderRelease || | | |
| 3358 | // failure_order_val->data.x_enum.tag == AtomicOrderAcqRel) | | |
| 3359 | // { | | |
| 3360 | // add_node_error(g, *failure_order_arg, | | |
| 3361 | // buf_sprintf("failure atomic ordering must not be Release or AcqRel")); | | |
| 3362 | // return g->builtin_types.entry_invalid; | | |
| 3363 | // } | | |
| 3364 | // | | |
| 3365 | // return g->builtin_types.entry_bool; | | |
| 3366 | //} | | |
| 3367 | // | | |
| 3368 | //static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import, | | |
| 3369 | // BlockContext *context, AstNode *node) | | |
| 3370 | //{ | | |
| 3371 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3372 | // | | |
| 3373 | // AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0); | | |
| 3374 | // TypeTableEntry *atomic_order_type = analyze_expression(g, import, context, | | |
| 3375 | // g->builtin_types.entry_atomic_order_enum, *atomic_order_arg); | | |
| 3376 | // | | |
| 3377 | // if (atomic_order_type->id == TypeTableEntryIdInvalid) { | | |
| 3378 | // return g->builtin_types.entry_invalid; | | |
| 3379 | // } | | |
| 3380 | // | | |
| 3381 | // ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val; | | |
| 3382 | // | | |
| 3383 | // if (!atomic_order_val->ok) { | | |
| 3384 | // add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression")); | | |
| 3385 | // return g->builtin_types.entry_invalid; | | |
| 3386 | // } | | |
| 3387 | // | | |
| 3388 | // return g->builtin_types.entry_void; | | |
| 3389 | //} | | |
| 3390 | // | | |
| 3391 | //static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import, | | |
| 3392 | // BlockContext *context, AstNode *node) | | |
| 3393 | //{ | | |
| 3394 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3395 | // | | |
| 3396 | // AstNode **op1 = &node->data.fn_call_expr.params.at(0); | | |
| 3397 | // AstNode **op2 = &node->data.fn_call_expr.params.at(1); | | |
| 3398 | // | | |
| 3399 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); | | |
| 3400 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); | | |
| 3401 | // | | |
| 3402 | // AstNode *op_nodes[] = {*op1, *op2}; | | |
| 3403 | // TypeTableEntry *op_types[] = {op1_type, op2_type}; | | |
| 3404 | // TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node, | | |
| 3405 | // op_nodes, op_types, 2); | | |
| 3406 | // | | |
| 3407 | // if (result_type->id == TypeTableEntryIdInvalid) { | | |
| 3408 | // return g->builtin_types.entry_invalid; | | |
| 3409 | // } else if (result_type->id == TypeTableEntryIdInt) { | | |
| 3410 | // return result_type; | | |
| 3411 | // } else if (result_type->id == TypeTableEntryIdNumLitInt) { | | |
| 3412 | // // check for division by zero | | |
| 3413 | // // check for non exact division | | |
| 3414 | // zig_panic("TODO"); | | |
| 3415 | // } else { | | |
| 3416 | // add_node_error(g, node, | | |
| 3417 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name))); | | |
| 3418 | // return g->builtin_types.entry_invalid; | | |
| 3419 | // } | | |
| 3420 | //} | | |
| 3421 | // | | |
| 3422 | //static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import, | | |
| 3423 | // BlockContext *context, AstNode *node) | | |
| 3424 | //{ | | |
| 3425 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 3426 | // | | |
| 3427 | // AstNode **op1 = &node->data.fn_call_expr.params.at(0); | | |
| 3428 | // AstNode **op2 = &node->data.fn_call_expr.params.at(1); | | |
| 3429 | // | | |
| 3430 | // TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1); | | |
| 3431 | // TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2); | | |
| 3432 | // | | |
| 3433 | // if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) { | | |
| 3434 | // return g->builtin_types.entry_invalid; | | |
| 3435 | // } else if (dest_type->id != TypeTableEntryIdInt) { | | |
| 3436 | // add_node_error(g, *op1, | | |
| 3437 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name))); | | |
| 3438 | // return g->builtin_types.entry_invalid; | | |
| 3439 | // } else if (src_type->id != TypeTableEntryIdInt) { | | |
| 3440 | // add_node_error(g, *op2, | | |
| 3441 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name))); | | |
| 3442 | // return g->builtin_types.entry_invalid; | | |
| 3443 | // } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | | |
| 3444 | // const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | | |
| 3445 | // add_node_error(g, *op2, | | |
| 3446 | // buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name))); | | |
| 3447 | // return g->builtin_types.entry_invalid; | | |
| 3448 | // } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) { | | |
| 3449 | // add_node_error(g, *op2, | | |
| 3450 | // buf_sprintf("type '%s' has same or fewer bits than destination type '%s'", | | |
| 3451 | // buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | | |
| 3452 | // return g->builtin_types.entry_invalid; | | |
| 3453 | // } | | |
| 3454 | // | | |
| 3455 | // // TODO const expr eval | | |
| 3456 | // | | |
| 3457 | // return dest_type; | | |
| 3458 | //} | | |
| 3459 | // | | |
| 3460 | //static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import, | | |
| 3461 | // BlockContext *context, AstNode *node) | | |
| 3462 | //{ | | |
| 3463 | // AstNode *first_param_node = node->data.fn_call_expr.params.at(0); | | |
| 3464 | // Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field); | | |
| 3465 | // if (!err_msg) { | | |
| 3466 | // return g->builtin_types.entry_invalid; | | |
| 3467 | // } | | |
| 3468 | // | | |
| 3469 | // add_node_error(g, node, err_msg); | | |
| 3470 | // | | |
| 3471 | // return g->builtin_types.entry_invalid; | | |
| 3472 | //} | | |
| 3473 | // | | |
| 3474 | //static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, | | |
| 3475 | // BlockContext *context, AstNode *node) | | |
| 3476 | //{ | | |
| 3477 | // AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); | | |
| 3478 | // AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); | | |
| 3479 | // | | |
| 3480 | // TypeTableEntry *bool_type = g->builtin_types.entry_bool; | | |
| 3481 | // TypeTableEntry *usize_type = g->builtin_types.entry_usize; | | |
| 3482 | // TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); | | |
| 3483 | // TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); | | |
| 3484 | // | | |
| 3485 | // if (is_signed_type->id == TypeTableEntryIdInvalid || | | |
| 3486 | // bit_count_type->id == TypeTableEntryIdInvalid) | | |
| 3487 | // { | | |
| 3488 | // return g->builtin_types.entry_invalid; | | |
| 3489 | // } | | |
| 3490 | // | | |
| 3491 | // ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; | | |
| 3492 | // ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; | | |
| 3493 | // | | |
| 3494 | // AstNode *bad_node = nullptr; | | |
| 3495 | // if (!is_signed_val->ok) { | | |
| 3496 | // bad_node = *is_signed_node; | | |
| 3497 | // } else if (!bit_count_val->ok) { | | |
| 3498 | // bad_node = *bit_count_node; | | |
| 3499 | // } | | |
| 3500 | // if (bad_node) { | | |
| 3501 | // add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); | | |
| 3502 | // return g->builtin_types.entry_invalid; | | |
| 3503 | // } | | |
| 3504 | // | | |
| 3505 | // bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var; | | |
| 3506 | // | | |
| 3507 | // TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, | | |
| 3508 | // bit_count_val->data.x_bignum.data.x_uint); | | |
| 3509 | // return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); | | |
| 3510 | // | | |
| 3511 | //} | | |
| 3512 | // | | |
| 3513 | //static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import, | | |
| 3514 | // BlockContext *context, AstNode *node) | | |
| 3515 | //{ | | |
| 3516 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); | | |
| 3517 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 3518 | // | | |
| 3519 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); | | |
| 3520 | // if (!fn_entry) { | | |
| 3521 | // return g->builtin_types.entry_invalid; | | |
| 3522 | // } | | |
| 3523 | // | | |
| 3524 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test); | | |
| 3525 | // if (!ok) { | | |
| 3526 | // return g->builtin_types.entry_invalid; | | |
| 3527 | // } | | |
| 3528 | // | | |
| 3529 | // if (fn_entry->fn_test_set_node) { | | |
| 3530 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice")); | | |
| 3531 | // add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here")); | | |
| 3532 | // return g->builtin_types.entry_invalid; | | |
| 3533 | // } | | |
| 3534 | // fn_entry->fn_test_set_node = node; | | |
| 3535 | // | | |
| 3536 | // g->test_fn_count += 1; | | |
| 3537 | // return g->builtin_types.entry_void; | | |
| 3538 | //} | | |
| 3539 | // | | |
| 3540 | //static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import, | | |
| 3541 | // BlockContext *context, AstNode *node) | | |
| 3542 | //{ | | |
| 3543 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); | | |
| 3544 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 3545 | // | | |
| 3546 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); | | |
| 3547 | // if (!fn_entry) { | | |
| 3548 | // return g->builtin_types.entry_invalid; | | |
| 3549 | // } | | |
| 3550 | // | | |
| 3551 | // bool is_noinline; | | |
| 3552 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline); | | |
| 3553 | // if (!ok) { | | |
| 3554 | // return g->builtin_types.entry_invalid; | | |
| 3555 | // } | | |
| 3556 | // | | |
| 3557 | // if (fn_entry->fn_no_inline_set_node) { | | |
| 3558 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice")); | | |
| 3559 | // add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here")); | | |
| 3560 | // return g->builtin_types.entry_invalid; | | |
| 3561 | // } | | |
| 3562 | // fn_entry->fn_no_inline_set_node = node; | | |
| 3563 | // | | |
| 3564 | // if (fn_entry->fn_inline == FnInlineAlways) { | | |
| 3565 | // add_node_error(g, node, buf_sprintf("function is both inline and noinline")); | | |
| 3566 | // fn_entry->proto_node->data.fn_proto.skip = true; | | |
| 3567 | // return g->builtin_types.entry_invalid; | | |
| 3568 | // } else if (is_noinline) { | | |
| 3569 | // fn_entry->fn_inline = FnInlineNever; | | |
| 3570 | // } | | |
| 3571 | // | | |
| 3572 | // return g->builtin_types.entry_void; | | |
| 3573 | //} | | |
| 3574 | // | | |
| 3575 | //static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import, | | |
| 3576 | // BlockContext *context, AstNode *node) | | |
| 3577 | //{ | | |
| 3578 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); | | |
| 3579 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 3580 | // | | |
| 3581 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); | | |
| 3582 | // if (!fn_entry) { | | |
| 3583 | // return g->builtin_types.entry_invalid; | | |
| 3584 | // } | | |
| 3585 | // | | |
| 3586 | // bool want_static_eval; | | |
| 3587 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval); | | |
| 3588 | // if (!ok) { | | |
| 3589 | // return g->builtin_types.entry_invalid; | | |
| 3590 | // } | | |
| 3591 | // | | |
| 3592 | // if (fn_entry->fn_static_eval_set_node) { | | |
| 3593 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice")); | | |
| 3594 | // add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here")); | | |
| 3595 | // return g->builtin_types.entry_invalid; | | |
| 3596 | // } | | |
| 3597 | // fn_entry->fn_static_eval_set_node = node; | | |
| 3598 | // | | |
| 3599 | // if (want_static_eval && !context->fn_entry->is_pure) { | | |
| 3600 | // add_node_error(g, node, buf_sprintf("attribute appears too late within function")); | | |
| 3601 | // return g->builtin_types.entry_invalid; | | |
| 3602 | // } | | |
| 3603 | // | | |
| 3604 | // if (want_static_eval) { | | |
| 3605 | // fn_entry->want_pure = WantPureTrue; | | |
| 3606 | // fn_entry->want_pure_attr_node = node; | | |
| 3607 | // } else { | | |
| 3608 | // fn_entry->want_pure = WantPureFalse; | | |
| 3609 | // fn_entry->is_pure = false; | | |
| 3610 | // } | | |
| 3611 | // | | |
| 3612 | // return g->builtin_types.entry_void; | | |
| 3613 | //} | | |
| 3614 | // | | |
| 3615 | //static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import, | | |
| 3616 | // BlockContext *context, AstNode *node) | | |
| 3617 | //{ | | |
| 3618 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); | | |
| 3619 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 3620 | // | | |
| 3621 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); | | |
| 3622 | // if (!fn_entry) { | | |
| 3623 | // return g->builtin_types.entry_invalid; | | |
| 3624 | // } | | |
| 3625 | // | | |
| 3626 | // bool want_export; | | |
| 3627 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export); | | |
| 3628 | // if (!ok) { | | |
| 3629 | // return g->builtin_types.entry_invalid; | | |
| 3630 | // } | | |
| 3631 | // | | |
| 3632 | // if (fn_entry->fn_export_set_node) { | | |
| 3633 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice")); | | |
| 3634 | // add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here")); | | |
| 3635 | // return g->builtin_types.entry_invalid; | | |
| 3636 | // } | | |
| 3637 | // fn_entry->fn_export_set_node = node; | | |
| 3638 | // | | |
| 3639 | // AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto; | | |
| 3640 | // if (fn_proto->top_level_decl.visib_mod != VisibModExport) { | | |
| 3641 | // ErrorMsg *msg = add_node_error(g, node, | | |
| 3642 | // buf_sprintf("function must be marked export to set function visibility")); | | |
| 3643 | // add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here")); | | |
| 3644 | // return g->builtin_types.entry_void; | | |
| 3645 | // } | | |
| 3646 | // if (!want_export) { | | |
| 3647 | // fn_proto->top_level_decl.visib_mod = VisibModPub; | | |
| 3648 | // } | | |
| 3649 | // | | |
| 3650 | // return g->builtin_types.entry_void; | | |
| 3651 | //} | | |
| 3652 | // | | |
| 3653 | //static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import, | | |
| 3654 | // BlockContext *parent_context, AstNode *node) | | |
| 3655 | //{ | | |
| 3656 | // AstNode **target_node = &node->data.fn_call_expr.params.at(0); | | |
| 3657 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 3658 | // | | |
| 3659 | // TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node); | | |
| 3660 | // BlockContext *target_context; | | |
| 3661 | // ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val; | | |
| 3662 | // if (target_type->id == TypeTableEntryIdInvalid) { | | |
| 3663 | // return g->builtin_types.entry_invalid; | | |
| 3664 | // } | | |
| 3665 | // if (!const_val->ok) { | | |
| 3666 | // add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression")); | | |
| 3667 | // return g->builtin_types.entry_invalid; | | |
| 3668 | // } | | |
| 3669 | // if (target_type->id == TypeTableEntryIdBlock) { | | |
| 3670 | // target_context = const_val->data.x_block; | | |
| 3671 | // } else if (target_type->id == TypeTableEntryIdFn) { | | |
| 3672 | // target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context; | | |
| 3673 | // } else if (target_type->id == TypeTableEntryIdMetaType) { | | |
| 3674 | // TypeTableEntry *type_arg = const_val->data.x_type; | | |
| 3675 | // if (type_arg->id == TypeTableEntryIdStruct) { | | |
| 3676 | // target_context = type_arg->data.structure.block_context; | | |
| 3677 | // } else if (type_arg->id == TypeTableEntryIdEnum) { | | |
| 3678 | // target_context = type_arg->data.enumeration.block_context; | | |
| 3679 | // } else if (type_arg->id == TypeTableEntryIdUnion) { | | |
| 3680 | // target_context = type_arg->data.unionation.block_context; | | |
| 3681 | // } else { | | |
| 3682 | // add_node_error(g, *target_node, | | |
| 3683 | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name))); | | |
| 3684 | // return g->builtin_types.entry_invalid; | | |
| 3685 | // } | | |
| 3686 | // } else { | | |
| 3687 | // add_node_error(g, *target_node, | | |
| 3688 | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name))); | | |
| 3689 | // return g->builtin_types.entry_invalid; | | |
| 3690 | // } | | |
| 3691 | // | | |
| 3692 | // bool want_debug_safety; | | |
| 3693 | // bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety); | | |
| 3694 | // if (!ok) { | | |
| 3695 | // return g->builtin_types.entry_invalid; | | |
| 3696 | // } | | |
| 3697 | // | | |
| 3698 | // if (target_context->safety_set_node) { | | |
| 3699 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice")); | | |
| 3700 | // add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here")); | | |
| 3701 | // return g->builtin_types.entry_invalid; | | |
| 3702 | // } | | |
| 3703 | // target_context->safety_set_node = node; | | |
| 3704 | // | | |
| 3705 | // target_context->safety_off = !want_debug_safety; | | |
| 3706 | // | | |
| 3707 | // return g->builtin_types.entry_void; | | |
| 3708 | //} | | |
| 3709 | | | |
| 3710 | | | |
| 3711 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 3712 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 3713 | //{ | | |
| 3714 | // | | |
| 3715 | // switch (builtin_fn->id) { | | |
| 3716 | // case BuiltinFnIdInvalid: | | |
| 3717 | // zig_unreachable(); | | |
| 3718 | // case BuiltinFnIdAddWithOverflow: | | |
| 3719 | // case BuiltinFnIdSubWithOverflow: | | |
| 3720 | // case BuiltinFnIdMulWithOverflow: | | |
| 3721 | // case BuiltinFnIdShlWithOverflow: | | |
| 3722 | // { | | |
| 3723 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3724 | // TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); | | |
| 3725 | // if (int_type->id == TypeTableEntryIdInvalid) { | | |
| 3726 | // return g->builtin_types.entry_bool; | | |
| 3727 | // } else if (int_type->id == TypeTableEntryIdInt) { | | |
| 3728 | // AstNode *op1_node = node->data.fn_call_expr.params.at(1); | | |
| 3729 | // AstNode *op2_node = node->data.fn_call_expr.params.at(2); | | |
| 3730 | // AstNode *result_node = node->data.fn_call_expr.params.at(3); | | |
| 3731 | // | | |
| 3732 | // analyze_expression(g, import, context, int_type, op1_node); | | |
| 3733 | // analyze_expression(g, import, context, int_type, op2_node); | | |
| 3734 | // analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false), | | |
| 3735 | // result_node); | | |
| 3736 | // } else { | | |
| 3737 | // add_node_error(g, type_node, | | |
| 3738 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); | | |
| 3739 | // } | | |
| 3740 | // | | |
| 3741 | // // TODO constant expression evaluation | | |
| 3742 | // | | |
| 3743 | // return g->builtin_types.entry_bool; | | |
| 3744 | // } | | |
| 3745 | // case BuiltinFnIdMemcpy: | | |
| 3746 | // { | | |
| 3747 | // AstNode *dest_node = node->data.fn_call_expr.params.at(0); | | |
| 3748 | // AstNode *src_node = node->data.fn_call_expr.params.at(1); | | |
| 3749 | // AstNode *len_node = node->data.fn_call_expr.params.at(2); | | |
| 3750 | // TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); | | |
| 3751 | // TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node); | | |
| 3752 | // analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); | | |
| 3753 | // | | |
| 3754 | // if (dest_type->id != TypeTableEntryIdInvalid && | | |
| 3755 | // dest_type->id != TypeTableEntryIdPointer) | | |
| 3756 | // { | | |
| 3757 | // add_node_error(g, dest_node, | | |
| 3758 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); | | |
| 3759 | // } | | |
| 3760 | // | | |
| 3761 | // if (src_type->id != TypeTableEntryIdInvalid && | | |
| 3762 | // src_type->id != TypeTableEntryIdPointer) | | |
| 3763 | // { | | |
| 3764 | // add_node_error(g, src_node, | | |
| 3765 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name))); | | |
| 3766 | // } | | |
| 3767 | // | | |
| 3768 | // if (dest_type->id == TypeTableEntryIdPointer && | | |
| 3769 | // src_type->id == TypeTableEntryIdPointer) | | |
| 3770 | // { | | |
| 3771 | // uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type); | | |
| 3772 | // uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type); | | |
| 3773 | // if (dest_align != src_align) { | | |
| 3774 | // add_node_error(g, dest_node, buf_sprintf( | | |
| 3775 | // "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64, | | |
| 3776 | // buf_ptr(&dest_type->name), dest_align, | | |
| 3777 | // buf_ptr(&src_type->name), src_align)); | | |
| 3778 | // } | | |
| 3779 | // } | | |
| 3780 | // | | |
| 3781 | // return builtin_fn->return_type; | | |
| 3782 | // } | | |
| 3783 | // case BuiltinFnIdMemset: | | |
| 3784 | // { | | |
| 3785 | // AstNode *dest_node = node->data.fn_call_expr.params.at(0); | | |
| 3786 | // AstNode *char_node = node->data.fn_call_expr.params.at(1); | | |
| 3787 | // AstNode *len_node = node->data.fn_call_expr.params.at(2); | | |
| 3788 | // TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); | | |
| 3789 | // analyze_expression(g, import, context, builtin_fn->param_types[1], char_node); | | |
| 3790 | // analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); | | |
| 3791 | // | | |
| 3792 | // if (dest_type->id != TypeTableEntryIdInvalid && | | |
| 3793 | // dest_type->id != TypeTableEntryIdPointer) | | |
| 3794 | // { | | |
| 3795 | // add_node_error(g, dest_node, | | |
| 3796 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); | | |
| 3797 | // } | | |
| 3798 | // | | |
| 3799 | // return builtin_fn->return_type; | | |
| 3800 | // } | | |
| 3801 | // case BuiltinFnIdSizeof: | | |
| 3802 | // { | | |
| 3803 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3804 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 3805 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 3806 | // return g->builtin_types.entry_invalid; | | |
| 3807 | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { | | |
| 3808 | // add_node_error(g, first_executing_node(type_node), | | |
| 3809 | // buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); | | |
| 3810 | // return g->builtin_types.entry_invalid; | | |
| 3811 | // } else { | | |
| 3812 | // uint64_t size_in_bytes = type_size(g, type_entry); | | |
| 3813 | // bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize || | | |
| 3814 | // type_entry == g->builtin_types.entry_isize); | | |
| 3815 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 3816 | // size_in_bytes, depends_on_compile_var); | | |
| 3817 | // } | | |
| 3818 | // } | | |
| 3819 | // case BuiltinFnIdAlignof: | | |
| 3820 | // { | | |
| 3821 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3822 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 3823 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 3824 | // return g->builtin_types.entry_invalid; | | |
| 3825 | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { | | |
| 3826 | // add_node_error(g, first_executing_node(type_node), | | |
| 3827 | // buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); | | |
| 3828 | // return g->builtin_types.entry_invalid; | | |
| 3829 | // } else { | | |
| 3830 | // uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); | | |
| 3831 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 3832 | // align_in_bytes, false); | | |
| 3833 | // } | | |
| 3834 | // } | | |
| 3835 | // case BuiltinFnIdMaxValue: | | |
| 3836 | // return analyze_min_max_value(g, import, context, node, | | |
| 3837 | // "no max value available for type '%s'", true); | | |
| 3838 | // case BuiltinFnIdMinValue: | | |
| 3839 | // return analyze_min_max_value(g, import, context, node, | | |
| 3840 | // "no min value available for type '%s'", false); | | |
| 3841 | // case BuiltinFnIdMemberCount: | | |
| 3842 | // { | | |
| 3843 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3844 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 3845 | // | | |
| 3846 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 3847 | // return type_entry; | | |
| 3848 | // } else if (type_entry->id == TypeTableEntryIdEnum) { | | |
| 3849 | // uint64_t value_count = type_entry->data.enumeration.src_field_count; | | |
| 3850 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 3851 | // value_count, false); | | |
| 3852 | // } else { | | |
| 3853 | // add_node_error(g, node, | | |
| 3854 | // buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name))); | | |
| 3855 | // return g->builtin_types.entry_invalid; | | |
| 3856 | // } | | |
| 3857 | // } | | |
| 3858 | // case BuiltinFnIdCInclude: | | |
| 3859 | // { | | |
| 3860 | // if (!context->c_import_buf) { | | |
| 3861 | // add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks")); | | |
| 3862 | // return g->builtin_types.entry_invalid; | | |
| 3863 | // } | | |
| 3864 | // | | |
| 3865 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | | |
| 3866 | // TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | | |
| 3867 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); | | |
| 3868 | // | | |
| 3869 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 3870 | // return resolved_type; | | |
| 3871 | // } | | |
| 3872 | // | | |
| 3873 | // ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; | | |
| 3874 | // | | |
| 3875 | // if (!const_str_val->ok) { | | |
| 3876 | // add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression")); | | |
| 3877 | // return g->builtin_types.entry_void; | | |
| 3878 | // } | | |
| 3879 | // | | |
| 3880 | // buf_appendf(context->c_import_buf, "#include <"); | | |
| 3881 | // ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; | | |
| 3882 | // uint64_t len = ptr_field->data.x_ptr.len; | | |
| 3883 | // for (uint64_t i = 0; i < len; i += 1) { | | |
| 3884 | // ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; | | |
| 3885 | // uint64_t big_c = char_val->data.x_bignum.data.x_uint; | | |
| 3886 | // assert(big_c <= UINT8_MAX); | | |
| 3887 | // uint8_t c = big_c; | | |
| 3888 | // buf_append_char(context->c_import_buf, c); | | |
| 3889 | // } | | |
| 3890 | // buf_appendf(context->c_import_buf, ">\n"); | | |
| 3891 | // | | |
| 3892 | // return g->builtin_types.entry_void; | | |
| 3893 | // } | | |
| 3894 | // case BuiltinFnIdCDefine: | | |
| 3895 | // zig_panic("TODO"); | | |
| 3896 | // case BuiltinFnIdCUndef: | | |
| 3897 | // zig_panic("TODO"); | | |
| 3898 | // | | |
| 3899 | // case BuiltinFnIdCompileVar: | | |
| 3900 | // { | | |
| 3901 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | | |
| 3902 | // | | |
| 3903 | // Buf *var_name = resolve_const_expr_str(g, import, context, str_node); | | |
| 3904 | // if (!var_name) { | | |
| 3905 | // return g->builtin_types.entry_invalid; | | |
| 3906 | // } | | |
| 3907 | // | | |
| 3908 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 3909 | // const_val->ok = true; | | |
| 3910 | // const_val->depends_on_compile_var = true; | | |
| 3911 | // | | |
| 3912 | // if (buf_eql_str(var_name, "is_big_endian")) { | | |
| 3913 | // return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true); | | |
| 3914 | // } else if (buf_eql_str(var_name, "is_release")) { | | |
| 3915 | // return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true); | | |
| 3916 | // } else if (buf_eql_str(var_name, "is_test")) { | | |
| 3917 | // return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true); | | |
| 3918 | // } else if (buf_eql_str(var_name, "os")) { | | |
| 3919 | // const_val->data.x_enum.tag = g->target_os_index; | | |
| 3920 | // return g->builtin_types.entry_os_enum; | | |
| 3921 | // } else if (buf_eql_str(var_name, "arch")) { | | |
| 3922 | // const_val->data.x_enum.tag = g->target_arch_index; | | |
| 3923 | // return g->builtin_types.entry_arch_enum; | | |
| 3924 | // } else if (buf_eql_str(var_name, "environ")) { | | |
| 3925 | // const_val->data.x_enum.tag = g->target_environ_index; | | |
| 3926 | // return g->builtin_types.entry_environ_enum; | | |
| 3927 | // } else if (buf_eql_str(var_name, "object_format")) { | | |
| 3928 | // const_val->data.x_enum.tag = g->target_oformat_index; | | |
| 3929 | // return g->builtin_types.entry_oformat_enum; | | |
| 3930 | // } else { | | |
| 3931 | // add_node_error(g, *str_node, | | |
| 3932 | // buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); | | |
| 3933 | // return g->builtin_types.entry_invalid; | | |
| 3934 | // } | | |
| 3935 | // } | | |
| 3936 | // case BuiltinFnIdConstEval: | | |
| 3937 | // { | | |
| 3938 | // AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; | | |
| 3939 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node); | | |
| 3940 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 3941 | // return resolved_type; | | |
| 3942 | // } | | |
| 3943 | // | | |
| 3944 | // ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val; | | |
| 3945 | // | | |
| 3946 | // if (!const_expr_val->ok) { | | |
| 3947 | // add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression")); | | |
| 3948 | // return g->builtin_types.entry_invalid; | | |
| 3949 | // } | | |
| 3950 | // | | |
| 3951 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 3952 | // *const_val = *const_expr_val; | | |
| 3953 | // | | |
| 3954 | // return resolved_type; | | |
| 3955 | // } | | |
| 3956 | // case BuiltinFnIdCtz: | | |
| 3957 | // case BuiltinFnIdClz: | | |
| 3958 | // { | | |
| 3959 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 3960 | // TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); | | |
| 3961 | // if (int_type->id == TypeTableEntryIdInvalid) { | | |
| 3962 | // return int_type; | | |
| 3963 | // } else if (int_type->id == TypeTableEntryIdInt) { | | |
| 3964 | // AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field; | | |
| 3965 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node); | | |
| 3966 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 3967 | // return resolved_type; | | |
| 3968 | // } | | |
| 3969 | // | | |
| 3970 | // // TODO const expr eval | | |
| 3971 | // | | |
| 3972 | // return resolved_type; | | |
| 3973 | // } else { | | |
| 3974 | // add_node_error(g, type_node, | | |
| 3975 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); | | |
| 3976 | // return g->builtin_types.entry_invalid; | | |
| 3977 | // } | | |
| 3978 | // } | | |
| 3979 | // case BuiltinFnIdImport: | | |
| 3980 | // return analyze_import(g, import, context, node); | | |
| 3981 | // case BuiltinFnIdCImport: | | |
| 3982 | // return analyze_c_import(g, import, context, node); | | |
| 3983 | // case BuiltinFnIdErrName: | | |
| 3984 | // return analyze_err_name(g, import, context, node); | | |
| 3985 | // case BuiltinFnIdBreakpoint: | | |
| 3986 | // mark_impure_fn(g, context, node); | | |
| 3987 | // return g->builtin_types.entry_void; | | |
| 3988 | // case BuiltinFnIdReturnAddress: | | |
| 3989 | // case BuiltinFnIdFrameAddress: | | |
| 3990 | // mark_impure_fn(g, context, node); | | |
| 3991 | // return builtin_fn->return_type; | | |
| 3992 | // case BuiltinFnIdEmbedFile: | | |
| 3993 | // return analyze_embed_file(g, import, context, node); | | |
| 3994 | // case BuiltinFnIdCmpExchange: | | |
| 3995 | // return analyze_cmpxchg(g, import, context, node); | | |
| 3996 | // case BuiltinFnIdFence: | | |
| 3997 | // return analyze_fence(g, import, context, node); | | |
| 3998 | // case BuiltinFnIdDivExact: | | |
| 3999 | // return analyze_div_exact(g, import, context, node); | | |
| 4000 | // case BuiltinFnIdTruncate: | | |
| 4001 | // return analyze_truncate(g, import, context, node); | | |
| 4002 | // case BuiltinFnIdCompileErr: | | |
| 4003 | // return analyze_compile_err(g, import, context, node); | | |
| 4004 | // case BuiltinFnIdIntType: | | |
| 4005 | // return analyze_int_type(g, import, context, node); | | |
| 4006 | // case BuiltinFnIdSetFnTest: | | |
| 4007 | // return analyze_set_fn_test(g, import, context, node); | | |
| 4008 | // case BuiltinFnIdSetFnNoInline: | | |
| 4009 | // return analyze_set_fn_no_inline(g, import, context, node); | | |
| 4010 | // case BuiltinFnIdSetFnStaticEval: | | |
| 4011 | // return analyze_set_fn_static_eval(g, import, context, node); | | |
| 4012 | // case BuiltinFnIdSetFnVisible: | | |
| 4013 | // return analyze_set_fn_visible(g, import, context, node); | | |
| 4014 | // case BuiltinFnIdSetDebugSafety: | | |
| 4015 | // return analyze_set_debug_safety(g, import, context, node); | | |
| 4016 | // } | | |
| 4017 | // zig_unreachable(); | | |
| 4018 | //} | | |
| 4019 | | | |
| 4020 | //static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import, | | |
| 4021 | // BlockContext *context, AstNode *node) | | |
| 4022 | //{ | | |
| 4023 | // assert(node->type == NodeTypeContainerInitExpr); | | |
| 4024 | // | | |
| 4025 | // AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; | | |
| 4026 | // | | |
| 4027 | // ContainerInitKind kind = container_init_expr->kind; | | |
| 4028 | // | | |
| 4029 | // if (container_init_expr->type->type == NodeTypeFieldAccessExpr) { | | |
| 4030 | // container_init_expr->type->data.field_access_expr.container_init_expr_node = node; | | |
| 4031 | // } | | |
| 4032 | // | | |
| 4033 | // TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr, | | |
| 4034 | // container_init_expr->type); | | |
| 4035 | // | | |
| 4036 | // if (container_meta_type->id == TypeTableEntryIdInvalid) { | | |
| 4037 | // return g->builtin_types.entry_invalid; | | |
| 4038 | // } | | |
| 4039 | // | | |
| 4040 | // if (node->data.container_init_expr.enum_type) { | | |
| 4041 | // get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val; | | |
| 4042 | // return node->data.container_init_expr.enum_type; | | |
| 4043 | // } | | |
| 4044 | // | | |
| 4045 | // TypeTableEntry *container_type = resolve_type(g, container_init_expr->type); | | |
| 4046 | // | | |
| 4047 | // if (container_type->id == TypeTableEntryIdInvalid) { | | |
| 4048 | // return container_type; | | |
| 4049 | // } else if (container_type->id == TypeTableEntryIdStruct && | | |
| 4050 | // !container_type->data.structure.is_slice && | | |
| 4051 | // (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray && | | |
| 4052 | // container_init_expr->entries.length == 0))) | | |
| 4053 | // { | | |
| 4054 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; | | |
| 4055 | // codegen->type_entry = container_type; | | |
| 4056 | // codegen->source_node = node; | | |
| 4057 | // | | |
| 4058 | // | | |
| 4059 | // size_t expr_field_count = container_init_expr->entries.length; | | |
| 4060 | // size_t actual_field_count = container_type->data.structure.src_field_count; | | |
| 4061 | // | | |
| 4062 | // AstNode *non_const_expr_culprit = nullptr; | | |
| 4063 | // | | |
| 4064 | // size_t *field_use_counts = allocate<size_t>(actual_field_count); | | |
| 4065 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 4066 | // const_val->ok = true; | | |
| 4067 | // const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count); | | |
| 4068 | // for (size_t i = 0; i < expr_field_count; i += 1) { | | |
| 4069 | // AstNode *val_field_node = container_init_expr->entries.at(i); | | |
| 4070 | // assert(val_field_node->type == NodeTypeStructValueField); | | |
| 4071 | // | | |
| 4072 | // val_field_node->block_context = context; | | |
| 4073 | // | | |
| 4074 | // TypeStructField *type_field = find_struct_type_field(container_type, | | |
| 4075 | // val_field_node->data.struct_val_field.name); | | |
| 4076 | // | | |
| 4077 | // if (!type_field) { | | |
| 4078 | // add_node_error(g, val_field_node, | | |
| 4079 | // buf_sprintf("no member named '%s' in '%s'", | | |
| 4080 | // buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name))); | | |
| 4081 | // continue; | | |
| 4082 | // } | | |
| 4083 | // | | |
| 4084 | // if (type_field->type_entry->id == TypeTableEntryIdInvalid) { | | |
| 4085 | // return g->builtin_types.entry_invalid; | | |
| 4086 | // } | | |
| 4087 | // | | |
| 4088 | // size_t field_index = type_field->src_index; | | |
| 4089 | // field_use_counts[field_index] += 1; | | |
| 4090 | // if (field_use_counts[field_index] > 1) { | | |
| 4091 | // add_node_error(g, val_field_node, buf_sprintf("duplicate field")); | | |
| 4092 | // continue; | | |
| 4093 | // } | | |
| 4094 | // | | |
| 4095 | // val_field_node->data.struct_val_field.type_struct_field = type_field; | | |
| 4096 | // | | |
| 4097 | // analyze_expression(g, import, context, type_field->type_entry, | | |
| 4098 | // val_field_node->data.struct_val_field.expr); | | |
| 4099 | // | | |
| 4100 | // if (const_val->ok) { | | |
| 4101 | // ConstExprValue *field_val = | | |
| 4102 | // &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val; | | |
| 4103 | // if (field_val->ok) { | | |
| 4104 | // const_val->data.x_struct.fields[field_index] = field_val; | | |
| 4105 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var; | | |
| 4106 | // } else { | | |
| 4107 | // const_val->ok = false; | | |
| 4108 | // non_const_expr_culprit = val_field_node->data.struct_val_field.expr; | | |
| 4109 | // } | | |
| 4110 | // } | | |
| 4111 | // } | | |
| 4112 | // if (!const_val->ok) { | | |
| 4113 | // assert(non_const_expr_culprit); | | |
| 4114 | // if (context->fn_entry) { | | |
| 4115 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); | | |
| 4116 | // } else { | | |
| 4117 | // add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression")); | | |
| 4118 | // } | | |
| 4119 | // } | | |
| 4120 | // | | |
| 4121 | // for (size_t i = 0; i < actual_field_count; i += 1) { | | |
| 4122 | // if (field_use_counts[i] == 0) { | | |
| 4123 | // add_node_error(g, node, | | |
| 4124 | // buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); | | |
| 4125 | // } | | |
| 4126 | // } | | |
| 4127 | // return container_type; | | |
| 4128 | // } else if (container_type->id == TypeTableEntryIdStruct && | | |
| 4129 | // container_type->data.structure.is_slice && | | |
| 4130 | // kind == ContainerInitKindArray) | | |
| 4131 | // { | | |
| 4132 | // size_t elem_count = container_init_expr->entries.length; | | |
| 4133 | // | | |
| 4134 | // TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry; | | |
| 4135 | // assert(pointer_type->id == TypeTableEntryIdPointer); | | |
| 4136 | // TypeTableEntry *child_type = pointer_type->data.pointer.child_type; | | |
| 4137 | // | | |
| 4138 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 4139 | // const_val->ok = true; | | |
| 4140 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count); | | |
| 4141 | // | | |
| 4142 | // for (size_t i = 0; i < elem_count; i += 1) { | | |
| 4143 | // AstNode **elem_node = &container_init_expr->entries.at(i); | | |
| 4144 | // analyze_expression(g, import, context, child_type, *elem_node); | | |
| 4145 | // | | |
| 4146 | // if (const_val->ok) { | | |
| 4147 | // ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val; | | |
| 4148 | // if (elem_const_val->ok) { | | |
| 4149 | // const_val->data.x_array.fields[i] = elem_const_val; | | |
| 4150 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || | | |
| 4151 | // elem_const_val->depends_on_compile_var; | | |
| 4152 | // } else { | | |
| 4153 | // const_val->ok = false; | | |
| 4154 | // } | | |
| 4155 | // } | | |
| 4156 | // } | | |
| 4157 | // | | |
| 4158 | // TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count); | | |
| 4159 | // | | |
| 4160 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; | | |
| 4161 | // codegen->type_entry = fixed_size_array_type; | | |
| 4162 | // codegen->source_node = node; | | |
| 4163 | // if (!const_val->ok) { | | |
| 4164 | // if (!context->fn_entry) { | | |
| 4165 | // add_node_error(g, node, | | |
| 4166 | // buf_sprintf("unable to evaluate constant expression")); | | |
| 4167 | // } else { | | |
| 4168 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); | | |
| 4169 | // } | | |
| 4170 | // } | | |
| 4171 | // | | |
| 4172 | // return fixed_size_array_type; | | |
| 4173 | // } else if (container_type->id == TypeTableEntryIdArray) { | | |
| 4174 | // zig_panic("TODO array container init"); | | |
| 4175 | // return container_type; | | |
| 4176 | // } else if (container_type->id == TypeTableEntryIdVoid) { | | |
| 4177 | // if (container_init_expr->entries.length != 0) { | | |
| 4178 | // add_node_error(g, node, buf_sprintf("void expression expects no arguments")); | | |
| 4179 | // return g->builtin_types.entry_invalid; | | |
| 4180 | // } else { | | |
| 4181 | // return resolve_expr_const_val_as_void(g, node); | | |
| 4182 | // } | | |
| 4183 | // } else { | | |
| 4184 | // add_node_error(g, node, | | |
| 4185 | // buf_sprintf("type '%s' does not support %s initialization syntax", | | |
| 4186 | // buf_ptr(&container_type->name), err_container_init_syntax_name(kind))); | | |
| 4187 | // return g->builtin_types.entry_invalid; | | |
| 4188 | // } | | |
| 4189 | //} | | |
| 4190 | | | |
| 4191 | static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { | | |
| 4192 | IrBasicBlock *old_dest_block = br_instruction->dest_block; | | |
| 4193 | | 3174 | |
| 4194 | // TODO detect backward jumps | 3175 | // TODO detect backward jumps |
| 4195 | | 3176 | |
| ... | @@ -4235,55 +3216,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct | ... | @@ -4235,55 +3216,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct |
| 4235 | return ira->codegen->builtin_types.entry_unreachable; | 3216 | return ira->codegen->builtin_types.entry_unreachable; |
| 4236 | } | 3217 | } |
| 4237 | | 3218 | |
| 4238 | static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, | | |
| 4239 | IrInstructionBuiltinCall *builtin_call_instruction) | | |
| 4240 | { | | |
| 4241 | switch (builtin_call_instruction->fn->id) { | | |
| 4242 | case BuiltinFnIdInvalid: | | |
| 4243 | case BuiltinFnIdUnreachable: | | |
| 4244 | case BuiltinFnIdTypeof: | | |
| 4245 | zig_unreachable(); | | |
| 4246 | case BuiltinFnIdMemcpy: | | |
| 4247 | case BuiltinFnIdMemset: | | |
| 4248 | case BuiltinFnIdSizeof: | | |
| 4249 | case BuiltinFnIdAlignof: | | |
| 4250 | case BuiltinFnIdMaxValue: | | |
| 4251 | case BuiltinFnIdMinValue: | | |
| 4252 | case BuiltinFnIdMemberCount: | | |
| 4253 | case BuiltinFnIdAddWithOverflow: | | |
| 4254 | case BuiltinFnIdSubWithOverflow: | | |
| 4255 | case BuiltinFnIdMulWithOverflow: | | |
| 4256 | case BuiltinFnIdShlWithOverflow: | | |
| 4257 | case BuiltinFnIdCInclude: | | |
| 4258 | case BuiltinFnIdCDefine: | | |
| 4259 | case BuiltinFnIdCUndef: | | |
| 4260 | case BuiltinFnIdCompileVar: | | |
| 4261 | case BuiltinFnIdCompileErr: | | |
| 4262 | case BuiltinFnIdConstEval: | | |
| 4263 | case BuiltinFnIdCtz: | | |
| 4264 | case BuiltinFnIdClz: | | |
| 4265 | case BuiltinFnIdImport: | | |
| 4266 | case BuiltinFnIdCImport: | | |
| 4267 | case BuiltinFnIdErrName: | | |
| 4268 | case BuiltinFnIdBreakpoint: | | |
| 4269 | case BuiltinFnIdReturnAddress: | | |
| 4270 | case BuiltinFnIdFrameAddress: | | |
| 4271 | case BuiltinFnIdEmbedFile: | | |
| 4272 | case BuiltinFnIdCmpExchange: | | |
| 4273 | case BuiltinFnIdFence: | | |
| 4274 | case BuiltinFnIdDivExact: | | |
| 4275 | case BuiltinFnIdTruncate: | | |
| 4276 | case BuiltinFnIdIntType: | | |
| 4277 | case BuiltinFnIdSetFnTest: | | |
| 4278 | case BuiltinFnIdSetFnVisible: | | |
| 4279 | case BuiltinFnIdSetFnStaticEval: | | |
| 4280 | case BuiltinFnIdSetFnNoInline: | | |
| 4281 | case BuiltinFnIdSetDebugSafety: | | |
| 4282 | zig_panic("TODO analyze more builtin functions"); | | |
| 4283 | } | | |
| 4284 | zig_unreachable(); | | |
| 4285 | } | | |
| 4286 | | | |
| 4287 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, | 3219 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, |
| 4288 | IrInstructionUnreachable *unreachable_instruction) | 3220 | IrInstructionUnreachable *unreachable_instruction) |
| 4289 | { | 3221 | { |
| ... | @@ -4731,6 +3663,34 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, | ... | @@ -4731,6 +3663,34 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 4731 | return ira->codegen->builtin_types.entry_type; | 3663 | return ira->codegen->builtin_types.entry_type; |
| 4732 | } | 3664 | } |
| 4733 | | 3665 | |
| | 3666 | static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira, |
| | 3667 | IrInstructionSetFnTest *set_fn_test_instruction) |
| | 3668 | { |
| | 3669 | IrInstruction *fn_value = set_fn_test_instruction->fn_value->other; |
| | 3670 | IrInstruction *is_test_value = set_fn_test_instruction->is_test->other; |
| | 3671 | |
| | 3672 | FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value); |
| | 3673 | if (!fn_entry) |
| | 3674 | return ira->codegen->builtin_types.entry_invalid; |
| | 3675 | |
| | 3676 | if (!ir_resolve_bool(ira, is_test_value, &fn_entry->is_test)) |
| | 3677 | return ira->codegen->builtin_types.entry_invalid; |
| | 3678 | |
| | 3679 | AstNode *source_node = set_fn_test_instruction->base.source_node; |
| | 3680 | if (fn_entry->fn_test_set_node) { |
| | 3681 | ErrorMsg *msg = add_node_error(ira->codegen, source_node, |
| | 3682 | buf_sprintf("function test attribute set twice")); |
| | 3683 | add_error_note(ira->codegen, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here")); |
| | 3684 | return ira->codegen->builtin_types.entry_invalid; |
| | 3685 | } |
| | 3686 | fn_entry->fn_test_set_node = source_node; |
| | 3687 | |
| | 3688 | ira->codegen->test_fn_count += 1; |
| | 3689 | |
| | 3690 | ir_build_const_from(ira, &set_fn_test_instruction->base, false); |
| | 3691 | return ira->codegen->builtin_types.entry_void; |
| | 3692 | } |
| | 3693 | |
| 4734 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 3694 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 4735 | switch (instruction->id) { | 3695 | switch (instruction->id) { |
| 4736 | case IrInstructionIdInvalid: | 3696 | case IrInstructionIdInvalid: |
| ... | @@ -4763,8 +3723,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4763,8 +3723,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4763 | return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction); | 3723 | return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction); |
| 4764 | case IrInstructionIdCondBr: | 3724 | case IrInstructionIdCondBr: |
| 4765 | return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction); | 3725 | return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction); |
| 4766 | case IrInstructionIdBuiltinCall: | | |
| 4767 | return ir_analyze_instruction_builtin_call(ira, (IrInstructionBuiltinCall *)instruction); | | |
| 4768 | case IrInstructionIdUnreachable: | 3726 | case IrInstructionIdUnreachable: |
| 4769 | return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction); | 3727 | return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction); |
| 4770 | case IrInstructionIdPhi: | 3728 | case IrInstructionIdPhi: |
| ... | @@ -4775,175 +3733,3488 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4775,175 +3733,3488 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4775 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); | 3733 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 4776 | case IrInstructionIdPtrTypeChild: | 3734 | case IrInstructionIdPtrTypeChild: |
| 4777 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); | 3735 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| | 3736 | case IrInstructionIdSetFnTest: |
| | 3737 | return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); |
| | 3738 | case IrInstructionIdSwitchBr: |
| | 3739 | case IrInstructionIdCast: |
| | 3740 | case IrInstructionIdContainerInitList: |
| | 3741 | case IrInstructionIdContainerInitFields: |
| | 3742 | case IrInstructionIdStructFieldPtr: |
| | 3743 | zig_panic("TODO analyze more instructions"); |
| | 3744 | } |
| | 3745 | zig_unreachable(); |
| | 3746 | } |
| | 3747 | |
| | 3748 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { |
| | 3749 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| | 3750 | instruction->type_entry = instruction_type; |
| | 3751 | if (instruction->other) { |
| | 3752 | instruction->other->type_entry = instruction_type; |
| | 3753 | } else { |
| | 3754 | assert(instruction_type->id == TypeTableEntryIdInvalid || |
| | 3755 | instruction_type->id == TypeTableEntryIdUnreachable); |
| | 3756 | instruction->other = instruction; |
| | 3757 | } |
| | 3758 | return instruction_type; |
| | 3759 | } |
| | 3760 | |
| | 3761 | // This function attempts to evaluate IR code while doing type checking and other analysis. |
| | 3762 | // It emits a new IrExecutable which is partially evaluated IR code. |
| | 3763 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, |
| | 3764 | TypeTableEntry *expected_type, AstNode *expected_type_source_node) |
| | 3765 | { |
| | 3766 | IrAnalyze ir_analyze_data = {}; |
| | 3767 | IrAnalyze *ira = &ir_analyze_data; |
| | 3768 | ira->codegen = codegen; |
| | 3769 | ira->explicit_return_type = expected_type; |
| | 3770 | |
| | 3771 | ira->old_irb.codegen = codegen; |
| | 3772 | ira->old_irb.exec = old_exec; |
| | 3773 | |
| | 3774 | ira->new_irb.codegen = codegen; |
| | 3775 | ira->new_irb.exec = new_exec; |
| | 3776 | |
| | 3777 | ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count; |
| | 3778 | ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count); |
| | 3779 | |
| | 3780 | IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); |
| | 3781 | IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb); |
| | 3782 | ir_ref_bb(new_entry_bb); |
| | 3783 | ira->old_irb.current_basic_block = old_entry_bb; |
| | 3784 | ira->new_irb.current_basic_block = new_entry_bb; |
| | 3785 | ira->block_queue_index = 0; |
| | 3786 | ira->instruction_index = 0; |
| | 3787 | |
| | 3788 | while (ira->block_queue_index < ira->old_bb_queue.length) { |
| | 3789 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| | 3790 | |
| | 3791 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { |
| | 3792 | ira->instruction_index += 1; |
| | 3793 | continue; |
| | 3794 | } |
| | 3795 | |
| | 3796 | TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction); |
| | 3797 | |
| | 3798 | // unreachable instructions do their own control flow. |
| | 3799 | if (return_type->id == TypeTableEntryIdUnreachable) |
| | 3800 | continue; |
| | 3801 | |
| | 3802 | ira->instruction_index += 1; |
| | 3803 | } |
| | 3804 | |
| | 3805 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items, |
| | 3806 | ira->implicit_return_type_list.length); |
| | 3807 | } |
| | 3808 | |
| | 3809 | bool ir_has_side_effects(IrInstruction *instruction) { |
| | 3810 | switch (instruction->id) { |
| | 3811 | case IrInstructionIdInvalid: |
| | 3812 | zig_unreachable(); |
| | 3813 | case IrInstructionIdBr: |
| | 3814 | case IrInstructionIdCondBr: |
| 4778 | case IrInstructionIdSwitchBr: | 3815 | case IrInstructionIdSwitchBr: |
| | 3816 | case IrInstructionIdDeclVar: |
| | 3817 | case IrInstructionIdStorePtr: |
| | 3818 | case IrInstructionIdCall: |
| | 3819 | case IrInstructionIdReturn: |
| | 3820 | case IrInstructionIdUnreachable: |
| | 3821 | case IrInstructionIdSetFnTest: |
| | 3822 | return true; |
| | 3823 | case IrInstructionIdPhi: |
| | 3824 | case IrInstructionIdUnOp: |
| | 3825 | case IrInstructionIdBinOp: |
| | 3826 | case IrInstructionIdLoadPtr: |
| | 3827 | case IrInstructionIdConst: |
| 4779 | case IrInstructionIdCast: | 3828 | case IrInstructionIdCast: |
| 4780 | case IrInstructionIdContainerInitList: | 3829 | case IrInstructionIdContainerInitList: |
| 4781 | case IrInstructionIdContainerInitFields: | 3830 | case IrInstructionIdContainerInitFields: |
| | 3831 | case IrInstructionIdFieldPtr: |
| | 3832 | case IrInstructionIdElemPtr: |
| | 3833 | case IrInstructionIdVarPtr: |
| | 3834 | case IrInstructionIdTypeOf: |
| | 3835 | case IrInstructionIdToPtrType: |
| | 3836 | case IrInstructionIdPtrTypeChild: |
| | 3837 | case IrInstructionIdReadField: |
| 4782 | case IrInstructionIdStructFieldPtr: | 3838 | case IrInstructionIdStructFieldPtr: |
| 4783 | zig_panic("TODO analyze more instructions"); | 3839 | return false; |
| 4784 | } | 3840 | } |
| 4785 | zig_unreachable(); | 3841 | zig_unreachable(); |
| 4786 | } | 3842 | } |
| 4787 | | 3843 | |
| 4788 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { | 3844 | IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 4789 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); | 3845 | if (exec->basic_block_list.length != 1) |
| 4790 | instruction->type_entry = instruction_type; | 3846 | return nullptr; |
| 4791 | if (instruction->other) { | | |
| 4792 | instruction->other->type_entry = instruction_type; | | |
| 4793 | } else { | | |
| 4794 | assert(instruction_type->id == TypeTableEntryIdInvalid || | | |
| 4795 | instruction_type->id == TypeTableEntryIdUnreachable); | | |
| 4796 | instruction->other = instruction; | | |
| 4797 | } | | |
| 4798 | return instruction_type; | | |
| 4799 | } | | |
| 4800 | | | |
| 4801 | // This function attempts to evaluate IR code while doing type checking and other analysis. | | |
| 4802 | // It emits a new IrExecutable which is partially evaluated IR code. | | |
| 4803 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, | | |
| 4804 | TypeTableEntry *expected_type, AstNode *expected_type_source_node) | | |
| 4805 | { | | |
| 4806 | IrAnalyze ir_analyze_data = {}; | | |
| 4807 | IrAnalyze *ira = &ir_analyze_data; | | |
| 4808 | ira->codegen = codegen; | | |
| 4809 | ira->explicit_return_type = expected_type; | | |
| 4810 | | 3847 | |
| 4811 | ira->old_irb.codegen = codegen; | 3848 | IrBasicBlock *bb = exec->basic_block_list.at(0); |
| 4812 | ira->old_irb.exec = old_exec; | 3849 | if (bb->instruction_list.length != 1) |
| | 3850 | return nullptr; |
| 4813 | | 3851 | |
| 4814 | ira->new_irb.codegen = codegen; | 3852 | IrInstruction *only_inst = bb->instruction_list.at(0); |
| 4815 | ira->new_irb.exec = new_exec; | 3853 | if (only_inst->id != IrInstructionIdReturn) |
| | 3854 | return nullptr; |
| 4816 | | 3855 | |
| 4817 | ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count; | 3856 | IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst; |
| 4818 | ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count); | 3857 | IrInstruction *value = ret_inst->value; |
| | 3858 | assert(value->static_value.ok); |
| | 3859 | return value; |
| | 3860 | } |
| 4819 | | 3861 | |
| 4820 | IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); | 3862 | //static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4821 | IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb); | 3863 | // AstNode *node, const char *err_format, bool is_max) |
| 4822 | ir_ref_bb(new_entry_bb); | 3864 | //{ |
| 4823 | ira->old_irb.current_basic_block = old_entry_bb; | 3865 | // assert(node->type == NodeTypeFnCallExpr); |
| 4824 | ira->new_irb.current_basic_block = new_entry_bb; | 3866 | // assert(node->data.fn_call_expr.params.length == 1); |
| 4825 | ira->block_queue_index = 0; | 3867 | // |
| 4826 | ira->instruction_index = 0; | 3868 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 3869 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| | 3870 | // |
| | 3871 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 3872 | // return g->builtin_types.entry_invalid; |
| | 3873 | // } else if (type_entry->id == TypeTableEntryIdInt) { |
| | 3874 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); |
| | 3875 | // return g->builtin_types.entry_num_lit_int; |
| | 3876 | // } else if (type_entry->id == TypeTableEntryIdFloat) { |
| | 3877 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); |
| | 3878 | // return g->builtin_types.entry_num_lit_float; |
| | 3879 | // } else if (type_entry->id == TypeTableEntryIdBool) { |
| | 3880 | // eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); |
| | 3881 | // return type_entry; |
| | 3882 | // } else { |
| | 3883 | // add_node_error(g, node, |
| | 3884 | // buf_sprintf(err_format, buf_ptr(&type_entry->name))); |
| | 3885 | // return g->builtin_types.entry_invalid; |
| | 3886 | // } |
| | 3887 | //} |
| 4827 | | 3888 | |
| 4828 | while (ira->block_queue_index < ira->old_bb_queue.length) { | 3889 | //static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4829 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | 3890 | // AstNode *node) |
| | 3891 | //{ |
| | 3892 | // assert(node->type == NodeTypeFnCallExpr); |
| | 3893 | // |
| | 3894 | // if (context->fn_entry) { |
| | 3895 | // add_node_error(g, node, buf_sprintf("@import invalid inside function bodies")); |
| | 3896 | // return g->builtin_types.entry_invalid; |
| | 3897 | // } |
| | 3898 | // |
| | 3899 | // AstNode *first_param_node = node->data.fn_call_expr.params.at(0); |
| | 3900 | // Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field); |
| | 3901 | // if (!import_target_str) { |
| | 3902 | // return g->builtin_types.entry_invalid; |
| | 3903 | // } |
| | 3904 | // |
| | 3905 | // Buf *import_target_path; |
| | 3906 | // Buf *search_dir; |
| | 3907 | // assert(import->package); |
| | 3908 | // PackageTableEntry *target_package; |
| | 3909 | // auto package_entry = import->package->package_table.maybe_get(import_target_str); |
| | 3910 | // if (package_entry) { |
| | 3911 | // target_package = package_entry->value; |
| | 3912 | // import_target_path = &target_package->root_src_path; |
| | 3913 | // search_dir = &target_package->root_src_dir; |
| | 3914 | // } else { |
| | 3915 | // // try it as a filename |
| | 3916 | // target_package = import->package; |
| | 3917 | // import_target_path = import_target_str; |
| | 3918 | // search_dir = &import->package->root_src_dir; |
| | 3919 | // } |
| | 3920 | // |
| | 3921 | // Buf full_path = BUF_INIT; |
| | 3922 | // os_path_join(search_dir, import_target_path, &full_path); |
| | 3923 | // |
| | 3924 | // Buf *import_code = buf_alloc(); |
| | 3925 | // Buf *abs_full_path = buf_alloc(); |
| | 3926 | // int err; |
| | 3927 | // if ((err = os_path_real(&full_path, abs_full_path))) { |
| | 3928 | // if (err == ErrorFileNotFound) { |
| | 3929 | // add_node_error(g, node, |
| | 3930 | // buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); |
| | 3931 | // return g->builtin_types.entry_invalid; |
| | 3932 | // } else { |
| | 3933 | // g->error_during_imports = true; |
| | 3934 | // add_node_error(g, node, |
| | 3935 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); |
| | 3936 | // return g->builtin_types.entry_invalid; |
| | 3937 | // } |
| | 3938 | // } |
| | 3939 | // |
| | 3940 | // auto import_entry = g->import_table.maybe_get(abs_full_path); |
| | 3941 | // if (import_entry) { |
| | 3942 | // return resolve_expr_const_val_as_import(g, node, import_entry->value); |
| | 3943 | // } |
| | 3944 | // |
| | 3945 | // if ((err = os_fetch_file_path(abs_full_path, import_code))) { |
| | 3946 | // if (err == ErrorFileNotFound) { |
| | 3947 | // add_node_error(g, node, |
| | 3948 | // buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); |
| | 3949 | // return g->builtin_types.entry_invalid; |
| | 3950 | // } else { |
| | 3951 | // add_node_error(g, node, |
| | 3952 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); |
| | 3953 | // return g->builtin_types.entry_invalid; |
| | 3954 | // } |
| | 3955 | // } |
| | 3956 | // ImportTableEntry *target_import = add_source_file(g, target_package, |
| | 3957 | // abs_full_path, search_dir, import_target_path, import_code); |
| | 3958 | // |
| | 3959 | // scan_decls(g, target_import, target_import->block_context, target_import->root); |
| | 3960 | // |
| | 3961 | // return resolve_expr_const_val_as_import(g, node, target_import); |
| | 3962 | //} |
| | 3963 | // |
| | 3964 | //static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import, |
| | 3965 | // BlockContext *parent_context, AstNode *node) |
| | 3966 | //{ |
| | 3967 | // assert(node->type == NodeTypeFnCallExpr); |
| | 3968 | // |
| | 3969 | // if (parent_context->fn_entry) { |
| | 3970 | // add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies")); |
| | 3971 | // return g->builtin_types.entry_invalid; |
| | 3972 | // } |
| | 3973 | // |
| | 3974 | // AstNode *block_node = node->data.fn_call_expr.params.at(0); |
| | 3975 | // |
| | 3976 | // BlockContext *child_context = new_block_context(node, parent_context); |
| | 3977 | // child_context->c_import_buf = buf_alloc(); |
| | 3978 | // |
| | 3979 | // TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context, |
| | 3980 | // g->builtin_types.entry_void, block_node); |
| | 3981 | // |
| | 3982 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 3983 | // return resolved_type; |
| | 3984 | // } |
| | 3985 | // |
| | 3986 | // find_libc_include_path(g); |
| | 3987 | // |
| | 3988 | // ImportTableEntry *child_import = allocate<ImportTableEntry>(1); |
| | 3989 | // child_import->c_import_node = node; |
| | 3990 | // |
| | 3991 | // ZigList<ErrorMsg *> errors = {0}; |
| | 3992 | // |
| | 3993 | // int err; |
| | 3994 | // if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) { |
| | 3995 | // zig_panic("unable to parse h file: %s\n", err_str(err)); |
| | 3996 | // } |
| | 3997 | // |
| | 3998 | // if (errors.length > 0) { |
| | 3999 | // ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed")); |
| | 4000 | // for (size_t i = 0; i < errors.length; i += 1) { |
| | 4001 | // ErrorMsg *err_msg = errors.at(i); |
| | 4002 | // err_msg_add_note(parent_err_msg, err_msg); |
| | 4003 | // } |
| | 4004 | // |
| | 4005 | // return g->builtin_types.entry_invalid; |
| | 4006 | // } |
| | 4007 | // |
| | 4008 | // if (g->verbose) { |
| | 4009 | // fprintf(stderr, "\nc_import:\n"); |
| | 4010 | // fprintf(stderr, "-----------\n"); |
| | 4011 | // ast_render(stderr, child_import->root, 4); |
| | 4012 | // } |
| | 4013 | // |
| | 4014 | // child_import->di_file = parent_import->di_file; |
| | 4015 | // child_import->block_context = new_block_context(child_import->root, nullptr); |
| | 4016 | // |
| | 4017 | // scan_decls(g, child_import, child_import->block_context, child_import->root); |
| | 4018 | // return resolve_expr_const_val_as_import(g, node, child_import); |
| | 4019 | //} |
| | 4020 | // |
| | 4021 | //static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import, |
| | 4022 | // BlockContext *context, AstNode *node) |
| | 4023 | //{ |
| | 4024 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4025 | // |
| | 4026 | // AstNode *err_value = node->data.fn_call_expr.params.at(0); |
| | 4027 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, |
| | 4028 | // g->builtin_types.entry_pure_error, err_value); |
| | 4029 | // |
| | 4030 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 4031 | // return resolved_type; |
| | 4032 | // } |
| | 4033 | // |
| | 4034 | // g->generate_error_name_table = true; |
| | 4035 | // |
| | 4036 | // TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); |
| | 4037 | // return str_type; |
| | 4038 | //} |
| | 4039 | // |
| | 4040 | //static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, |
| | 4041 | // BlockContext *context, AstNode *node) |
| | 4042 | //{ |
| | 4043 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4044 | // |
| | 4045 | // AstNode **first_param_node = &node->data.fn_call_expr.params.at(0); |
| | 4046 | // Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node); |
| | 4047 | // if (!rel_file_path) { |
| | 4048 | // return g->builtin_types.entry_invalid; |
| | 4049 | // } |
| | 4050 | // |
| | 4051 | // // figure out absolute path to resource |
| | 4052 | // Buf source_dir_path = BUF_INIT; |
| | 4053 | // os_path_dirname(import->path, &source_dir_path); |
| | 4054 | // |
| | 4055 | // Buf file_path = BUF_INIT; |
| | 4056 | // os_path_resolve(&source_dir_path, rel_file_path, &file_path); |
| | 4057 | // |
| | 4058 | // // load from file system into const expr |
| | 4059 | // Buf file_contents = BUF_INIT; |
| | 4060 | // int err; |
| | 4061 | // if ((err = os_fetch_file_path(&file_path, &file_contents))) { |
| | 4062 | // if (err == ErrorFileNotFound) { |
| | 4063 | // add_node_error(g, node, |
| | 4064 | // buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); |
| | 4065 | // return g->builtin_types.entry_invalid; |
| | 4066 | // } else { |
| | 4067 | // add_node_error(g, node, |
| | 4068 | // buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); |
| | 4069 | // return g->builtin_types.entry_invalid; |
| | 4070 | // } |
| | 4071 | // } |
| | 4072 | // |
| | 4073 | // // TODO add dependency on the file we embedded so that we know if it changes |
| | 4074 | // // we'll have to invalidate the cache |
| | 4075 | // |
| | 4076 | // return resolve_expr_const_val_as_string_lit(g, node, &file_contents); |
| | 4077 | //} |
| | 4078 | // |
| | 4079 | //static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, |
| | 4080 | // BlockContext *context, AstNode *node) |
| | 4081 | //{ |
| | 4082 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4083 | // |
| | 4084 | // AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0); |
| | 4085 | // AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1); |
| | 4086 | // AstNode **new_arg = &node->data.fn_call_expr.params.at(2); |
| | 4087 | // AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3); |
| | 4088 | // AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4); |
| | 4089 | // |
| | 4090 | // TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg); |
| | 4091 | // if (ptr_type->id == TypeTableEntryIdInvalid) { |
| | 4092 | // return g->builtin_types.entry_invalid; |
| | 4093 | // } else if (ptr_type->id != TypeTableEntryIdPointer) { |
| | 4094 | // add_node_error(g, *ptr_arg, |
| | 4095 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name))); |
| | 4096 | // return g->builtin_types.entry_invalid; |
| | 4097 | // } |
| | 4098 | // |
| | 4099 | // TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| | 4100 | // TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg); |
| | 4101 | // TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg); |
| | 4102 | // |
| | 4103 | // TypeTableEntry *success_order_type = analyze_expression(g, import, context, |
| | 4104 | // g->builtin_types.entry_atomic_order_enum, *success_order_arg); |
| | 4105 | // TypeTableEntry *failure_order_type = analyze_expression(g, import, context, |
| | 4106 | // g->builtin_types.entry_atomic_order_enum, *failure_order_arg); |
| | 4107 | // |
| | 4108 | // if (cmp_type->id == TypeTableEntryIdInvalid || |
| | 4109 | // new_type->id == TypeTableEntryIdInvalid || |
| | 4110 | // success_order_type->id == TypeTableEntryIdInvalid || |
| | 4111 | // failure_order_type->id == TypeTableEntryIdInvalid) |
| | 4112 | // { |
| | 4113 | // return g->builtin_types.entry_invalid; |
| | 4114 | // } |
| | 4115 | // |
| | 4116 | // ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val; |
| | 4117 | // ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val; |
| | 4118 | // if (!success_order_val->ok) { |
| | 4119 | // add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression")); |
| | 4120 | // return g->builtin_types.entry_invalid; |
| | 4121 | // } else if (!failure_order_val->ok) { |
| | 4122 | // add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression")); |
| | 4123 | // return g->builtin_types.entry_invalid; |
| | 4124 | // } |
| | 4125 | // |
| | 4126 | // if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) { |
| | 4127 | // add_node_error(g, *success_order_arg, |
| | 4128 | // buf_sprintf("success atomic ordering must be Monotonic or stricter")); |
| | 4129 | // return g->builtin_types.entry_invalid; |
| | 4130 | // } |
| | 4131 | // if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) { |
| | 4132 | // add_node_error(g, *failure_order_arg, |
| | 4133 | // buf_sprintf("failure atomic ordering must be Monotonic or stricter")); |
| | 4134 | // return g->builtin_types.entry_invalid; |
| | 4135 | // } |
| | 4136 | // if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) { |
| | 4137 | // add_node_error(g, *failure_order_arg, |
| | 4138 | // buf_sprintf("failure atomic ordering must be no stricter than success")); |
| | 4139 | // return g->builtin_types.entry_invalid; |
| | 4140 | // } |
| | 4141 | // if (failure_order_val->data.x_enum.tag == AtomicOrderRelease || |
| | 4142 | // failure_order_val->data.x_enum.tag == AtomicOrderAcqRel) |
| | 4143 | // { |
| | 4144 | // add_node_error(g, *failure_order_arg, |
| | 4145 | // buf_sprintf("failure atomic ordering must not be Release or AcqRel")); |
| | 4146 | // return g->builtin_types.entry_invalid; |
| | 4147 | // } |
| | 4148 | // |
| | 4149 | // return g->builtin_types.entry_bool; |
| | 4150 | //} |
| | 4151 | // |
| | 4152 | //static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import, |
| | 4153 | // BlockContext *context, AstNode *node) |
| | 4154 | //{ |
| | 4155 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4156 | // |
| | 4157 | // AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0); |
| | 4158 | // TypeTableEntry *atomic_order_type = analyze_expression(g, import, context, |
| | 4159 | // g->builtin_types.entry_atomic_order_enum, *atomic_order_arg); |
| | 4160 | // |
| | 4161 | // if (atomic_order_type->id == TypeTableEntryIdInvalid) { |
| | 4162 | // return g->builtin_types.entry_invalid; |
| | 4163 | // } |
| | 4164 | // |
| | 4165 | // ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val; |
| | 4166 | // |
| | 4167 | // if (!atomic_order_val->ok) { |
| | 4168 | // add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression")); |
| | 4169 | // return g->builtin_types.entry_invalid; |
| | 4170 | // } |
| | 4171 | // |
| | 4172 | // return g->builtin_types.entry_void; |
| | 4173 | //} |
| | 4174 | // |
| | 4175 | //static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import, |
| | 4176 | // BlockContext *context, AstNode *node) |
| | 4177 | //{ |
| | 4178 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4179 | // |
| | 4180 | // AstNode **op1 = &node->data.fn_call_expr.params.at(0); |
| | 4181 | // AstNode **op2 = &node->data.fn_call_expr.params.at(1); |
| | 4182 | // |
| | 4183 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); |
| | 4184 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 4185 | // |
| | 4186 | // AstNode *op_nodes[] = {*op1, *op2}; |
| | 4187 | // TypeTableEntry *op_types[] = {op1_type, op2_type}; |
| | 4188 | // TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node, |
| | 4189 | // op_nodes, op_types, 2); |
| | 4190 | // |
| | 4191 | // if (result_type->id == TypeTableEntryIdInvalid) { |
| | 4192 | // return g->builtin_types.entry_invalid; |
| | 4193 | // } else if (result_type->id == TypeTableEntryIdInt) { |
| | 4194 | // return result_type; |
| | 4195 | // } else if (result_type->id == TypeTableEntryIdNumLitInt) { |
| | 4196 | // // check for division by zero |
| | 4197 | // // check for non exact division |
| | 4198 | // zig_panic("TODO"); |
| | 4199 | // } else { |
| | 4200 | // add_node_error(g, node, |
| | 4201 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name))); |
| | 4202 | // return g->builtin_types.entry_invalid; |
| | 4203 | // } |
| | 4204 | //} |
| | 4205 | // |
| | 4206 | //static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import, |
| | 4207 | // BlockContext *context, AstNode *node) |
| | 4208 | //{ |
| | 4209 | // assert(node->type == NodeTypeFnCallExpr); |
| | 4210 | // |
| | 4211 | // AstNode **op1 = &node->data.fn_call_expr.params.at(0); |
| | 4212 | // AstNode **op2 = &node->data.fn_call_expr.params.at(1); |
| | 4213 | // |
| | 4214 | // TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1); |
| | 4215 | // TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 4216 | // |
| | 4217 | // if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) { |
| | 4218 | // return g->builtin_types.entry_invalid; |
| | 4219 | // } else if (dest_type->id != TypeTableEntryIdInt) { |
| | 4220 | // add_node_error(g, *op1, |
| | 4221 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name))); |
| | 4222 | // return g->builtin_types.entry_invalid; |
| | 4223 | // } else if (src_type->id != TypeTableEntryIdInt) { |
| | 4224 | // add_node_error(g, *op2, |
| | 4225 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name))); |
| | 4226 | // return g->builtin_types.entry_invalid; |
| | 4227 | // } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { |
| | 4228 | // const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; |
| | 4229 | // add_node_error(g, *op2, |
| | 4230 | // buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name))); |
| | 4231 | // return g->builtin_types.entry_invalid; |
| | 4232 | // } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) { |
| | 4233 | // add_node_error(g, *op2, |
| | 4234 | // buf_sprintf("type '%s' has same or fewer bits than destination type '%s'", |
| | 4235 | // buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); |
| | 4236 | // return g->builtin_types.entry_invalid; |
| | 4237 | // } |
| | 4238 | // |
| | 4239 | // // TODO const expr eval |
| | 4240 | // |
| | 4241 | // return dest_type; |
| | 4242 | //} |
| | 4243 | // |
| | 4244 | //static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import, |
| | 4245 | // BlockContext *context, AstNode *node) |
| | 4246 | //{ |
| | 4247 | // AstNode *first_param_node = node->data.fn_call_expr.params.at(0); |
| | 4248 | // Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field); |
| | 4249 | // if (!err_msg) { |
| | 4250 | // return g->builtin_types.entry_invalid; |
| | 4251 | // } |
| | 4252 | // |
| | 4253 | // add_node_error(g, node, err_msg); |
| | 4254 | // |
| | 4255 | // return g->builtin_types.entry_invalid; |
| | 4256 | //} |
| | 4257 | // |
| | 4258 | //static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, |
| | 4259 | // BlockContext *context, AstNode *node) |
| | 4260 | //{ |
| | 4261 | // AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); |
| | 4262 | // AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); |
| | 4263 | // |
| | 4264 | // TypeTableEntry *bool_type = g->builtin_types.entry_bool; |
| | 4265 | // TypeTableEntry *usize_type = g->builtin_types.entry_usize; |
| | 4266 | // TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); |
| | 4267 | // TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); |
| | 4268 | // |
| | 4269 | // if (is_signed_type->id == TypeTableEntryIdInvalid || |
| | 4270 | // bit_count_type->id == TypeTableEntryIdInvalid) |
| | 4271 | // { |
| | 4272 | // return g->builtin_types.entry_invalid; |
| | 4273 | // } |
| | 4274 | // |
| | 4275 | // ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; |
| | 4276 | // ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; |
| | 4277 | // |
| | 4278 | // AstNode *bad_node = nullptr; |
| | 4279 | // if (!is_signed_val->ok) { |
| | 4280 | // bad_node = *is_signed_node; |
| | 4281 | // } else if (!bit_count_val->ok) { |
| | 4282 | // bad_node = *bit_count_node; |
| | 4283 | // } |
| | 4284 | // if (bad_node) { |
| | 4285 | // add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); |
| | 4286 | // return g->builtin_types.entry_invalid; |
| | 4287 | // } |
| | 4288 | // |
| | 4289 | // bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var; |
| | 4290 | // |
| | 4291 | // TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, |
| | 4292 | // bit_count_val->data.x_bignum.data.x_uint); |
| | 4293 | // return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); |
| | 4294 | // |
| | 4295 | //} |
| | 4296 | // |
| | 4297 | //static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import, |
| | 4298 | // BlockContext *context, AstNode *node) |
| | 4299 | //{ |
| | 4300 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); |
| | 4301 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); |
| | 4302 | // |
| | 4303 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); |
| | 4304 | // if (!fn_entry) { |
| | 4305 | // return g->builtin_types.entry_invalid; |
| | 4306 | // } |
| | 4307 | // |
| | 4308 | // bool is_noinline; |
| | 4309 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline); |
| | 4310 | // if (!ok) { |
| | 4311 | // return g->builtin_types.entry_invalid; |
| | 4312 | // } |
| | 4313 | // |
| | 4314 | // if (fn_entry->fn_no_inline_set_node) { |
| | 4315 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice")); |
| | 4316 | // add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here")); |
| | 4317 | // return g->builtin_types.entry_invalid; |
| | 4318 | // } |
| | 4319 | // fn_entry->fn_no_inline_set_node = node; |
| | 4320 | // |
| | 4321 | // if (fn_entry->fn_inline == FnInlineAlways) { |
| | 4322 | // add_node_error(g, node, buf_sprintf("function is both inline and noinline")); |
| | 4323 | // fn_entry->proto_node->data.fn_proto.skip = true; |
| | 4324 | // return g->builtin_types.entry_invalid; |
| | 4325 | // } else if (is_noinline) { |
| | 4326 | // fn_entry->fn_inline = FnInlineNever; |
| | 4327 | // } |
| | 4328 | // |
| | 4329 | // return g->builtin_types.entry_void; |
| | 4330 | //} |
| | 4331 | // |
| | 4332 | //static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import, |
| | 4333 | // BlockContext *context, AstNode *node) |
| | 4334 | //{ |
| | 4335 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); |
| | 4336 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); |
| | 4337 | // |
| | 4338 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); |
| | 4339 | // if (!fn_entry) { |
| | 4340 | // return g->builtin_types.entry_invalid; |
| | 4341 | // } |
| | 4342 | // |
| | 4343 | // bool want_static_eval; |
| | 4344 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval); |
| | 4345 | // if (!ok) { |
| | 4346 | // return g->builtin_types.entry_invalid; |
| | 4347 | // } |
| | 4348 | // |
| | 4349 | // if (fn_entry->fn_static_eval_set_node) { |
| | 4350 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice")); |
| | 4351 | // add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here")); |
| | 4352 | // return g->builtin_types.entry_invalid; |
| | 4353 | // } |
| | 4354 | // fn_entry->fn_static_eval_set_node = node; |
| | 4355 | // |
| | 4356 | // if (want_static_eval && !context->fn_entry->is_pure) { |
| | 4357 | // add_node_error(g, node, buf_sprintf("attribute appears too late within function")); |
| | 4358 | // return g->builtin_types.entry_invalid; |
| | 4359 | // } |
| | 4360 | // |
| | 4361 | // if (want_static_eval) { |
| | 4362 | // fn_entry->want_pure = WantPureTrue; |
| | 4363 | // fn_entry->want_pure_attr_node = node; |
| | 4364 | // } else { |
| | 4365 | // fn_entry->want_pure = WantPureFalse; |
| | 4366 | // fn_entry->is_pure = false; |
| | 4367 | // } |
| | 4368 | // |
| | 4369 | // return g->builtin_types.entry_void; |
| | 4370 | //} |
| | 4371 | // |
| | 4372 | //static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import, |
| | 4373 | // BlockContext *context, AstNode *node) |
| | 4374 | //{ |
| | 4375 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); |
| | 4376 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); |
| | 4377 | // |
| | 4378 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); |
| | 4379 | // if (!fn_entry) { |
| | 4380 | // return g->builtin_types.entry_invalid; |
| | 4381 | // } |
| | 4382 | // |
| | 4383 | // bool want_export; |
| | 4384 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export); |
| | 4385 | // if (!ok) { |
| | 4386 | // return g->builtin_types.entry_invalid; |
| | 4387 | // } |
| | 4388 | // |
| | 4389 | // if (fn_entry->fn_export_set_node) { |
| | 4390 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice")); |
| | 4391 | // add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here")); |
| | 4392 | // return g->builtin_types.entry_invalid; |
| | 4393 | // } |
| | 4394 | // fn_entry->fn_export_set_node = node; |
| | 4395 | // |
| | 4396 | // AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto; |
| | 4397 | // if (fn_proto->top_level_decl.visib_mod != VisibModExport) { |
| | 4398 | // ErrorMsg *msg = add_node_error(g, node, |
| | 4399 | // buf_sprintf("function must be marked export to set function visibility")); |
| | 4400 | // add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here")); |
| | 4401 | // return g->builtin_types.entry_void; |
| | 4402 | // } |
| | 4403 | // if (!want_export) { |
| | 4404 | // fn_proto->top_level_decl.visib_mod = VisibModPub; |
| | 4405 | // } |
| | 4406 | // |
| | 4407 | // return g->builtin_types.entry_void; |
| | 4408 | //} |
| | 4409 | // |
| | 4410 | //static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import, |
| | 4411 | // BlockContext *parent_context, AstNode *node) |
| | 4412 | //{ |
| | 4413 | // AstNode **target_node = &node->data.fn_call_expr.params.at(0); |
| | 4414 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); |
| | 4415 | // |
| | 4416 | // TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node); |
| | 4417 | // BlockContext *target_context; |
| | 4418 | // ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val; |
| | 4419 | // if (target_type->id == TypeTableEntryIdInvalid) { |
| | 4420 | // return g->builtin_types.entry_invalid; |
| | 4421 | // } |
| | 4422 | // if (!const_val->ok) { |
| | 4423 | // add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression")); |
| | 4424 | // return g->builtin_types.entry_invalid; |
| | 4425 | // } |
| | 4426 | // if (target_type->id == TypeTableEntryIdBlock) { |
| | 4427 | // target_context = const_val->data.x_block; |
| | 4428 | // } else if (target_type->id == TypeTableEntryIdFn) { |
| | 4429 | // target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context; |
| | 4430 | // } else if (target_type->id == TypeTableEntryIdMetaType) { |
| | 4431 | // TypeTableEntry *type_arg = const_val->data.x_type; |
| | 4432 | // if (type_arg->id == TypeTableEntryIdStruct) { |
| | 4433 | // target_context = type_arg->data.structure.block_context; |
| | 4434 | // } else if (type_arg->id == TypeTableEntryIdEnum) { |
| | 4435 | // target_context = type_arg->data.enumeration.block_context; |
| | 4436 | // } else if (type_arg->id == TypeTableEntryIdUnion) { |
| | 4437 | // target_context = type_arg->data.unionation.block_context; |
| | 4438 | // } else { |
| | 4439 | // add_node_error(g, *target_node, |
| | 4440 | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name))); |
| | 4441 | // return g->builtin_types.entry_invalid; |
| | 4442 | // } |
| | 4443 | // } else { |
| | 4444 | // add_node_error(g, *target_node, |
| | 4445 | // buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name))); |
| | 4446 | // return g->builtin_types.entry_invalid; |
| | 4447 | // } |
| | 4448 | // |
| | 4449 | // bool want_debug_safety; |
| | 4450 | // bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety); |
| | 4451 | // if (!ok) { |
| | 4452 | // return g->builtin_types.entry_invalid; |
| | 4453 | // } |
| | 4454 | // |
| | 4455 | // if (target_context->safety_set_node) { |
| | 4456 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice")); |
| | 4457 | // add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here")); |
| | 4458 | // return g->builtin_types.entry_invalid; |
| | 4459 | // } |
| | 4460 | // target_context->safety_set_node = node; |
| | 4461 | // |
| | 4462 | // target_context->safety_off = !want_debug_safety; |
| | 4463 | // |
| | 4464 | // return g->builtin_types.entry_void; |
| | 4465 | //} |
| 4830 | | 4466 | |
| 4831 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { | | |
| 4832 | ira->instruction_index += 1; | | |
| 4833 | continue; | | |
| 4834 | } | | |
| 4835 | | 4467 | |
| 4836 | TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction); | 4468 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 4469 | // TypeTableEntry *expected_type, AstNode *node) |
| | 4470 | //{ |
| | 4471 | // |
| | 4472 | // switch (builtin_fn->id) { |
| | 4473 | // case BuiltinFnIdInvalid: |
| | 4474 | // zig_unreachable(); |
| | 4475 | // case BuiltinFnIdAddWithOverflow: |
| | 4476 | // case BuiltinFnIdSubWithOverflow: |
| | 4477 | // case BuiltinFnIdMulWithOverflow: |
| | 4478 | // case BuiltinFnIdShlWithOverflow: |
| | 4479 | // { |
| | 4480 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 4481 | // TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); |
| | 4482 | // if (int_type->id == TypeTableEntryIdInvalid) { |
| | 4483 | // return g->builtin_types.entry_bool; |
| | 4484 | // } else if (int_type->id == TypeTableEntryIdInt) { |
| | 4485 | // AstNode *op1_node = node->data.fn_call_expr.params.at(1); |
| | 4486 | // AstNode *op2_node = node->data.fn_call_expr.params.at(2); |
| | 4487 | // AstNode *result_node = node->data.fn_call_expr.params.at(3); |
| | 4488 | // |
| | 4489 | // analyze_expression(g, import, context, int_type, op1_node); |
| | 4490 | // analyze_expression(g, import, context, int_type, op2_node); |
| | 4491 | // analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false), |
| | 4492 | // result_node); |
| | 4493 | // } else { |
| | 4494 | // add_node_error(g, type_node, |
| | 4495 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); |
| | 4496 | // } |
| | 4497 | // |
| | 4498 | // // TODO constant expression evaluation |
| | 4499 | // |
| | 4500 | // return g->builtin_types.entry_bool; |
| | 4501 | // } |
| | 4502 | // case BuiltinFnIdMemcpy: |
| | 4503 | // { |
| | 4504 | // AstNode *dest_node = node->data.fn_call_expr.params.at(0); |
| | 4505 | // AstNode *src_node = node->data.fn_call_expr.params.at(1); |
| | 4506 | // AstNode *len_node = node->data.fn_call_expr.params.at(2); |
| | 4507 | // TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); |
| | 4508 | // TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node); |
| | 4509 | // analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); |
| | 4510 | // |
| | 4511 | // if (dest_type->id != TypeTableEntryIdInvalid && |
| | 4512 | // dest_type->id != TypeTableEntryIdPointer) |
| | 4513 | // { |
| | 4514 | // add_node_error(g, dest_node, |
| | 4515 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); |
| | 4516 | // } |
| | 4517 | // |
| | 4518 | // if (src_type->id != TypeTableEntryIdInvalid && |
| | 4519 | // src_type->id != TypeTableEntryIdPointer) |
| | 4520 | // { |
| | 4521 | // add_node_error(g, src_node, |
| | 4522 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name))); |
| | 4523 | // } |
| | 4524 | // |
| | 4525 | // if (dest_type->id == TypeTableEntryIdPointer && |
| | 4526 | // src_type->id == TypeTableEntryIdPointer) |
| | 4527 | // { |
| | 4528 | // uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type); |
| | 4529 | // uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type); |
| | 4530 | // if (dest_align != src_align) { |
| | 4531 | // add_node_error(g, dest_node, buf_sprintf( |
| | 4532 | // "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64, |
| | 4533 | // buf_ptr(&dest_type->name), dest_align, |
| | 4534 | // buf_ptr(&src_type->name), src_align)); |
| | 4535 | // } |
| | 4536 | // } |
| | 4537 | // |
| | 4538 | // return builtin_fn->return_type; |
| | 4539 | // } |
| | 4540 | // case BuiltinFnIdMemset: |
| | 4541 | // { |
| | 4542 | // AstNode *dest_node = node->data.fn_call_expr.params.at(0); |
| | 4543 | // AstNode *char_node = node->data.fn_call_expr.params.at(1); |
| | 4544 | // AstNode *len_node = node->data.fn_call_expr.params.at(2); |
| | 4545 | // TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); |
| | 4546 | // analyze_expression(g, import, context, builtin_fn->param_types[1], char_node); |
| | 4547 | // analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); |
| | 4548 | // |
| | 4549 | // if (dest_type->id != TypeTableEntryIdInvalid && |
| | 4550 | // dest_type->id != TypeTableEntryIdPointer) |
| | 4551 | // { |
| | 4552 | // add_node_error(g, dest_node, |
| | 4553 | // buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); |
| | 4554 | // } |
| | 4555 | // |
| | 4556 | // return builtin_fn->return_type; |
| | 4557 | // } |
| | 4558 | // case BuiltinFnIdSizeof: |
| | 4559 | // { |
| | 4560 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 4561 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| | 4562 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 4563 | // return g->builtin_types.entry_invalid; |
| | 4564 | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { |
| | 4565 | // add_node_error(g, first_executing_node(type_node), |
| | 4566 | // buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); |
| | 4567 | // return g->builtin_types.entry_invalid; |
| | 4568 | // } else { |
| | 4569 | // uint64_t size_in_bytes = type_size(g, type_entry); |
| | 4570 | // bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize || |
| | 4571 | // type_entry == g->builtin_types.entry_isize); |
| | 4572 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| | 4573 | // size_in_bytes, depends_on_compile_var); |
| | 4574 | // } |
| | 4575 | // } |
| | 4576 | // case BuiltinFnIdAlignof: |
| | 4577 | // { |
| | 4578 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 4579 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| | 4580 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 4581 | // return g->builtin_types.entry_invalid; |
| | 4582 | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { |
| | 4583 | // add_node_error(g, first_executing_node(type_node), |
| | 4584 | // buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); |
| | 4585 | // return g->builtin_types.entry_invalid; |
| | 4586 | // } else { |
| | 4587 | // uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); |
| | 4588 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| | 4589 | // align_in_bytes, false); |
| | 4590 | // } |
| | 4591 | // } |
| | 4592 | // case BuiltinFnIdMaxValue: |
| | 4593 | // return analyze_min_max_value(g, import, context, node, |
| | 4594 | // "no max value available for type '%s'", true); |
| | 4595 | // case BuiltinFnIdMinValue: |
| | 4596 | // return analyze_min_max_value(g, import, context, node, |
| | 4597 | // "no min value available for type '%s'", false); |
| | 4598 | // case BuiltinFnIdMemberCount: |
| | 4599 | // { |
| | 4600 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 4601 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| | 4602 | // |
| | 4603 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 4604 | // return type_entry; |
| | 4605 | // } else if (type_entry->id == TypeTableEntryIdEnum) { |
| | 4606 | // uint64_t value_count = type_entry->data.enumeration.src_field_count; |
| | 4607 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| | 4608 | // value_count, false); |
| | 4609 | // } else { |
| | 4610 | // add_node_error(g, node, |
| | 4611 | // buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name))); |
| | 4612 | // return g->builtin_types.entry_invalid; |
| | 4613 | // } |
| | 4614 | // } |
| | 4615 | // case BuiltinFnIdCInclude: |
| | 4616 | // { |
| | 4617 | // if (!context->c_import_buf) { |
| | 4618 | // add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks")); |
| | 4619 | // return g->builtin_types.entry_invalid; |
| | 4620 | // } |
| | 4621 | // |
| | 4622 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; |
| | 4623 | // TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); |
| | 4624 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); |
| | 4625 | // |
| | 4626 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 4627 | // return resolved_type; |
| | 4628 | // } |
| | 4629 | // |
| | 4630 | // ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; |
| | 4631 | // |
| | 4632 | // if (!const_str_val->ok) { |
| | 4633 | // add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression")); |
| | 4634 | // return g->builtin_types.entry_void; |
| | 4635 | // } |
| | 4636 | // |
| | 4637 | // buf_appendf(context->c_import_buf, "#include <"); |
| | 4638 | // ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; |
| | 4639 | // uint64_t len = ptr_field->data.x_ptr.len; |
| | 4640 | // for (uint64_t i = 0; i < len; i += 1) { |
| | 4641 | // ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; |
| | 4642 | // uint64_t big_c = char_val->data.x_bignum.data.x_uint; |
| | 4643 | // assert(big_c <= UINT8_MAX); |
| | 4644 | // uint8_t c = big_c; |
| | 4645 | // buf_append_char(context->c_import_buf, c); |
| | 4646 | // } |
| | 4647 | // buf_appendf(context->c_import_buf, ">\n"); |
| | 4648 | // |
| | 4649 | // return g->builtin_types.entry_void; |
| | 4650 | // } |
| | 4651 | // case BuiltinFnIdCDefine: |
| | 4652 | // zig_panic("TODO"); |
| | 4653 | // case BuiltinFnIdCUndef: |
| | 4654 | // zig_panic("TODO"); |
| | 4655 | // |
| | 4656 | // case BuiltinFnIdCompileVar: |
| | 4657 | // { |
| | 4658 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; |
| | 4659 | // |
| | 4660 | // Buf *var_name = resolve_const_expr_str(g, import, context, str_node); |
| | 4661 | // if (!var_name) { |
| | 4662 | // return g->builtin_types.entry_invalid; |
| | 4663 | // } |
| | 4664 | // |
| | 4665 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 4666 | // const_val->ok = true; |
| | 4667 | // const_val->depends_on_compile_var = true; |
| | 4668 | // |
| | 4669 | // if (buf_eql_str(var_name, "is_big_endian")) { |
| | 4670 | // return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true); |
| | 4671 | // } else if (buf_eql_str(var_name, "is_release")) { |
| | 4672 | // return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true); |
| | 4673 | // } else if (buf_eql_str(var_name, "is_test")) { |
| | 4674 | // return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true); |
| | 4675 | // } else if (buf_eql_str(var_name, "os")) { |
| | 4676 | // const_val->data.x_enum.tag = g->target_os_index; |
| | 4677 | // return g->builtin_types.entry_os_enum; |
| | 4678 | // } else if (buf_eql_str(var_name, "arch")) { |
| | 4679 | // const_val->data.x_enum.tag = g->target_arch_index; |
| | 4680 | // return g->builtin_types.entry_arch_enum; |
| | 4681 | // } else if (buf_eql_str(var_name, "environ")) { |
| | 4682 | // const_val->data.x_enum.tag = g->target_environ_index; |
| | 4683 | // return g->builtin_types.entry_environ_enum; |
| | 4684 | // } else if (buf_eql_str(var_name, "object_format")) { |
| | 4685 | // const_val->data.x_enum.tag = g->target_oformat_index; |
| | 4686 | // return g->builtin_types.entry_oformat_enum; |
| | 4687 | // } else { |
| | 4688 | // add_node_error(g, *str_node, |
| | 4689 | // buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); |
| | 4690 | // return g->builtin_types.entry_invalid; |
| | 4691 | // } |
| | 4692 | // } |
| | 4693 | // case BuiltinFnIdConstEval: |
| | 4694 | // { |
| | 4695 | // AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; |
| | 4696 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node); |
| | 4697 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 4698 | // return resolved_type; |
| | 4699 | // } |
| | 4700 | // |
| | 4701 | // ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val; |
| | 4702 | // |
| | 4703 | // if (!const_expr_val->ok) { |
| | 4704 | // add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression")); |
| | 4705 | // return g->builtin_types.entry_invalid; |
| | 4706 | // } |
| | 4707 | // |
| | 4708 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 4709 | // *const_val = *const_expr_val; |
| | 4710 | // |
| | 4711 | // return resolved_type; |
| | 4712 | // } |
| | 4713 | // case BuiltinFnIdCtz: |
| | 4714 | // case BuiltinFnIdClz: |
| | 4715 | // { |
| | 4716 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 4717 | // TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); |
| | 4718 | // if (int_type->id == TypeTableEntryIdInvalid) { |
| | 4719 | // return int_type; |
| | 4720 | // } else if (int_type->id == TypeTableEntryIdInt) { |
| | 4721 | // AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field; |
| | 4722 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node); |
| | 4723 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 4724 | // return resolved_type; |
| | 4725 | // } |
| | 4726 | // |
| | 4727 | // // TODO const expr eval |
| | 4728 | // |
| | 4729 | // return resolved_type; |
| | 4730 | // } else { |
| | 4731 | // add_node_error(g, type_node, |
| | 4732 | // buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); |
| | 4733 | // return g->builtin_types.entry_invalid; |
| | 4734 | // } |
| | 4735 | // } |
| | 4736 | // case BuiltinFnIdImport: |
| | 4737 | // return analyze_import(g, import, context, node); |
| | 4738 | // case BuiltinFnIdCImport: |
| | 4739 | // return analyze_c_import(g, import, context, node); |
| | 4740 | // case BuiltinFnIdErrName: |
| | 4741 | // return analyze_err_name(g, import, context, node); |
| | 4742 | // case BuiltinFnIdBreakpoint: |
| | 4743 | // mark_impure_fn(g, context, node); |
| | 4744 | // return g->builtin_types.entry_void; |
| | 4745 | // case BuiltinFnIdReturnAddress: |
| | 4746 | // case BuiltinFnIdFrameAddress: |
| | 4747 | // mark_impure_fn(g, context, node); |
| | 4748 | // return builtin_fn->return_type; |
| | 4749 | // case BuiltinFnIdEmbedFile: |
| | 4750 | // return analyze_embed_file(g, import, context, node); |
| | 4751 | // case BuiltinFnIdCmpExchange: |
| | 4752 | // return analyze_cmpxchg(g, import, context, node); |
| | 4753 | // case BuiltinFnIdFence: |
| | 4754 | // return analyze_fence(g, import, context, node); |
| | 4755 | // case BuiltinFnIdDivExact: |
| | 4756 | // return analyze_div_exact(g, import, context, node); |
| | 4757 | // case BuiltinFnIdTruncate: |
| | 4758 | // return analyze_truncate(g, import, context, node); |
| | 4759 | // case BuiltinFnIdCompileErr: |
| | 4760 | // return analyze_compile_err(g, import, context, node); |
| | 4761 | // case BuiltinFnIdIntType: |
| | 4762 | // return analyze_int_type(g, import, context, node); |
| | 4763 | // case BuiltinFnIdSetFnTest: |
| | 4764 | // return analyze_set_fn_test(g, import, context, node); |
| | 4765 | // case BuiltinFnIdSetFnNoInline: |
| | 4766 | // return analyze_set_fn_no_inline(g, import, context, node); |
| | 4767 | // case BuiltinFnIdSetFnStaticEval: |
| | 4768 | // return analyze_set_fn_static_eval(g, import, context, node); |
| | 4769 | // case BuiltinFnIdSetFnVisible: |
| | 4770 | // return analyze_set_fn_visible(g, import, context, node); |
| | 4771 | // case BuiltinFnIdSetDebugSafety: |
| | 4772 | // return analyze_set_debug_safety(g, import, context, node); |
| | 4773 | // } |
| | 4774 | // zig_unreachable(); |
| | 4775 | //} |
| 4837 | | 4776 | |
| 4838 | // unreachable instructions do their own control flow. | 4777 | //static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import, |
| 4839 | if (return_type->id == TypeTableEntryIdUnreachable) | 4778 | // BlockContext *context, AstNode *node) |
| 4840 | continue; | 4779 | //{ |
| | 4780 | // assert(node->type == NodeTypeContainerInitExpr); |
| | 4781 | // |
| | 4782 | // AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; |
| | 4783 | // |
| | 4784 | // ContainerInitKind kind = container_init_expr->kind; |
| | 4785 | // |
| | 4786 | // if (container_init_expr->type->type == NodeTypeFieldAccessExpr) { |
| | 4787 | // container_init_expr->type->data.field_access_expr.container_init_expr_node = node; |
| | 4788 | // } |
| | 4789 | // |
| | 4790 | // TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr, |
| | 4791 | // container_init_expr->type); |
| | 4792 | // |
| | 4793 | // if (container_meta_type->id == TypeTableEntryIdInvalid) { |
| | 4794 | // return g->builtin_types.entry_invalid; |
| | 4795 | // } |
| | 4796 | // |
| | 4797 | // if (node->data.container_init_expr.enum_type) { |
| | 4798 | // get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val; |
| | 4799 | // return node->data.container_init_expr.enum_type; |
| | 4800 | // } |
| | 4801 | // |
| | 4802 | // TypeTableEntry *container_type = resolve_type(g, container_init_expr->type); |
| | 4803 | // |
| | 4804 | // if (container_type->id == TypeTableEntryIdInvalid) { |
| | 4805 | // return container_type; |
| | 4806 | // } else if (container_type->id == TypeTableEntryIdStruct && |
| | 4807 | // !container_type->data.structure.is_slice && |
| | 4808 | // (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray && |
| | 4809 | // container_init_expr->entries.length == 0))) |
| | 4810 | // { |
| | 4811 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; |
| | 4812 | // codegen->type_entry = container_type; |
| | 4813 | // codegen->source_node = node; |
| | 4814 | // |
| | 4815 | // |
| | 4816 | // size_t expr_field_count = container_init_expr->entries.length; |
| | 4817 | // size_t actual_field_count = container_type->data.structure.src_field_count; |
| | 4818 | // |
| | 4819 | // AstNode *non_const_expr_culprit = nullptr; |
| | 4820 | // |
| | 4821 | // size_t *field_use_counts = allocate<size_t>(actual_field_count); |
| | 4822 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 4823 | // const_val->ok = true; |
| | 4824 | // const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count); |
| | 4825 | // for (size_t i = 0; i < expr_field_count; i += 1) { |
| | 4826 | // AstNode *val_field_node = container_init_expr->entries.at(i); |
| | 4827 | // assert(val_field_node->type == NodeTypeStructValueField); |
| | 4828 | // |
| | 4829 | // val_field_node->block_context = context; |
| | 4830 | // |
| | 4831 | // TypeStructField *type_field = find_struct_type_field(container_type, |
| | 4832 | // val_field_node->data.struct_val_field.name); |
| | 4833 | // |
| | 4834 | // if (!type_field) { |
| | 4835 | // add_node_error(g, val_field_node, |
| | 4836 | // buf_sprintf("no member named '%s' in '%s'", |
| | 4837 | // buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name))); |
| | 4838 | // continue; |
| | 4839 | // } |
| | 4840 | // |
| | 4841 | // if (type_field->type_entry->id == TypeTableEntryIdInvalid) { |
| | 4842 | // return g->builtin_types.entry_invalid; |
| | 4843 | // } |
| | 4844 | // |
| | 4845 | // size_t field_index = type_field->src_index; |
| | 4846 | // field_use_counts[field_index] += 1; |
| | 4847 | // if (field_use_counts[field_index] > 1) { |
| | 4848 | // add_node_error(g, val_field_node, buf_sprintf("duplicate field")); |
| | 4849 | // continue; |
| | 4850 | // } |
| | 4851 | // |
| | 4852 | // val_field_node->data.struct_val_field.type_struct_field = type_field; |
| | 4853 | // |
| | 4854 | // analyze_expression(g, import, context, type_field->type_entry, |
| | 4855 | // val_field_node->data.struct_val_field.expr); |
| | 4856 | // |
| | 4857 | // if (const_val->ok) { |
| | 4858 | // ConstExprValue *field_val = |
| | 4859 | // &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val; |
| | 4860 | // if (field_val->ok) { |
| | 4861 | // const_val->data.x_struct.fields[field_index] = field_val; |
| | 4862 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var; |
| | 4863 | // } else { |
| | 4864 | // const_val->ok = false; |
| | 4865 | // non_const_expr_culprit = val_field_node->data.struct_val_field.expr; |
| | 4866 | // } |
| | 4867 | // } |
| | 4868 | // } |
| | 4869 | // if (!const_val->ok) { |
| | 4870 | // assert(non_const_expr_culprit); |
| | 4871 | // if (context->fn_entry) { |
| | 4872 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); |
| | 4873 | // } else { |
| | 4874 | // add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression")); |
| | 4875 | // } |
| | 4876 | // } |
| | 4877 | // |
| | 4878 | // for (size_t i = 0; i < actual_field_count; i += 1) { |
| | 4879 | // if (field_use_counts[i] == 0) { |
| | 4880 | // add_node_error(g, node, |
| | 4881 | // buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); |
| | 4882 | // } |
| | 4883 | // } |
| | 4884 | // return container_type; |
| | 4885 | // } else if (container_type->id == TypeTableEntryIdStruct && |
| | 4886 | // container_type->data.structure.is_slice && |
| | 4887 | // kind == ContainerInitKindArray) |
| | 4888 | // { |
| | 4889 | // size_t elem_count = container_init_expr->entries.length; |
| | 4890 | // |
| | 4891 | // TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry; |
| | 4892 | // assert(pointer_type->id == TypeTableEntryIdPointer); |
| | 4893 | // TypeTableEntry *child_type = pointer_type->data.pointer.child_type; |
| | 4894 | // |
| | 4895 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 4896 | // const_val->ok = true; |
| | 4897 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count); |
| | 4898 | // |
| | 4899 | // for (size_t i = 0; i < elem_count; i += 1) { |
| | 4900 | // AstNode **elem_node = &container_init_expr->entries.at(i); |
| | 4901 | // analyze_expression(g, import, context, child_type, *elem_node); |
| | 4902 | // |
| | 4903 | // if (const_val->ok) { |
| | 4904 | // ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val; |
| | 4905 | // if (elem_const_val->ok) { |
| | 4906 | // const_val->data.x_array.fields[i] = elem_const_val; |
| | 4907 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || |
| | 4908 | // elem_const_val->depends_on_compile_var; |
| | 4909 | // } else { |
| | 4910 | // const_val->ok = false; |
| | 4911 | // } |
| | 4912 | // } |
| | 4913 | // } |
| | 4914 | // |
| | 4915 | // TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count); |
| | 4916 | // |
| | 4917 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; |
| | 4918 | // codegen->type_entry = fixed_size_array_type; |
| | 4919 | // codegen->source_node = node; |
| | 4920 | // if (!const_val->ok) { |
| | 4921 | // if (!context->fn_entry) { |
| | 4922 | // add_node_error(g, node, |
| | 4923 | // buf_sprintf("unable to evaluate constant expression")); |
| | 4924 | // } else { |
| | 4925 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); |
| | 4926 | // } |
| | 4927 | // } |
| | 4928 | // |
| | 4929 | // return fixed_size_array_type; |
| | 4930 | // } else if (container_type->id == TypeTableEntryIdArray) { |
| | 4931 | // zig_panic("TODO array container init"); |
| | 4932 | // return container_type; |
| | 4933 | // } else if (container_type->id == TypeTableEntryIdVoid) { |
| | 4934 | // if (container_init_expr->entries.length != 0) { |
| | 4935 | // add_node_error(g, node, buf_sprintf("void expression expects no arguments")); |
| | 4936 | // return g->builtin_types.entry_invalid; |
| | 4937 | // } else { |
| | 4938 | // return resolve_expr_const_val_as_void(g, node); |
| | 4939 | // } |
| | 4940 | // } else { |
| | 4941 | // add_node_error(g, node, |
| | 4942 | // buf_sprintf("type '%s' does not support %s initialization syntax", |
| | 4943 | // buf_ptr(&container_type->name), err_container_init_syntax_name(kind))); |
| | 4944 | // return g->builtin_types.entry_invalid; |
| | 4945 | // } |
| | 4946 | //} |
| 4841 | | 4947 | |
| 4842 | ira->instruction_index += 1; | | |
| 4843 | } | | |
| 4844 | | 4948 | |
| 4845 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items, | | |
| 4846 | ira->implicit_return_type_list.length); | | |
| 4847 | } | | |
| 4848 | | 4949 | |
| 4849 | static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) { | 4950 | //static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4850 | switch (call_instruction->fn->id) { | 4951 | // TypeTableEntry *expected_type, AstNode *node) |
| 4851 | case BuiltinFnIdInvalid: | 4952 | //{ |
| 4852 | zig_unreachable(); | 4953 | // assert(node->type == NodeTypeFieldAccessExpr); |
| 4853 | case BuiltinFnIdMemcpy: | 4954 | // |
| 4854 | case BuiltinFnIdMemset: | 4955 | // AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr; |
| 4855 | case BuiltinFnIdAddWithOverflow: | 4956 | // TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node); |
| 4856 | case BuiltinFnIdSubWithOverflow: | 4957 | // Buf *field_name = node->data.field_access_expr.field_name; |
| 4857 | case BuiltinFnIdMulWithOverflow: | 4958 | // |
| 4858 | case BuiltinFnIdShlWithOverflow: | 4959 | // if (struct_type->id == TypeTableEntryIdInvalid) { |
| 4859 | case BuiltinFnIdCInclude: | 4960 | // return struct_type; |
| 4860 | case BuiltinFnIdCDefine: | 4961 | // } else if (is_container_ref(struct_type)) { |
| 4861 | case BuiltinFnIdCUndef: | 4962 | // return analyze_container_member_access(g, field_name, node, struct_type); |
| 4862 | case BuiltinFnIdImport: | 4963 | // } else if (struct_type->id == TypeTableEntryIdArray) { |
| 4863 | case BuiltinFnIdCImport: | 4964 | // if (buf_eql_str(field_name, "len")) { |
| 4864 | case BuiltinFnIdBreakpoint: | 4965 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| 4865 | case BuiltinFnIdEmbedFile: | 4966 | // struct_type->data.array.len, false); |
| 4866 | case BuiltinFnIdCmpExchange: | 4967 | // } else { |
| 4867 | case BuiltinFnIdFence: | 4968 | // add_node_error(g, node, |
| 4868 | case BuiltinFnIdUnreachable: | 4969 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| 4869 | case BuiltinFnIdSetFnTest: | 4970 | // buf_ptr(&struct_type->name))); |
| 4870 | case BuiltinFnIdSetFnVisible: | 4971 | // return g->builtin_types.entry_invalid; |
| 4871 | case BuiltinFnIdSetFnStaticEval: | 4972 | // } |
| 4872 | case BuiltinFnIdSetFnNoInline: | 4973 | // } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| 4873 | case BuiltinFnIdSetDebugSafety: | 4974 | // TypeTableEntry *child_type = resolve_type(g, *struct_expr_node); |
| 4874 | return true; | 4975 | // |
| 4875 | case BuiltinFnIdSizeof: | 4976 | // if (child_type->id == TypeTableEntryIdInvalid) { |
| 4876 | case BuiltinFnIdAlignof: | 4977 | // return g->builtin_types.entry_invalid; |
| 4877 | case BuiltinFnIdMaxValue: | 4978 | // } else if (child_type->id == TypeTableEntryIdEnum) { |
| 4878 | case BuiltinFnIdMinValue: | 4979 | // AstNode *container_init_node = node->data.field_access_expr.container_init_expr_node; |
| 4879 | case BuiltinFnIdMemberCount: | 4980 | // AstNode *value_node; |
| 4880 | case BuiltinFnIdTypeof: | 4981 | // if (container_init_node) { |
| 4881 | case BuiltinFnIdCompileVar: | 4982 | // assert(container_init_node->type == NodeTypeContainerInitExpr); |
| 4882 | case BuiltinFnIdCompileErr: | 4983 | // size_t param_count = container_init_node->data.container_init_expr.entries.length; |
| 4883 | case BuiltinFnIdConstEval: | 4984 | // if (param_count > 1) { |
| 4884 | case BuiltinFnIdCtz: | 4985 | // AstNode *first_invalid_node = container_init_node->data.container_init_expr.entries.at(1); |
| 4885 | case BuiltinFnIdClz: | 4986 | // add_node_error(g, first_executing_node(first_invalid_node), |
| 4886 | case BuiltinFnIdErrName: | 4987 | // buf_sprintf("enum values accept only one parameter")); |
| 4887 | case BuiltinFnIdReturnAddress: | 4988 | // return child_type; |
| 4888 | case BuiltinFnIdFrameAddress: | 4989 | // } else { |
| 4889 | case BuiltinFnIdDivExact: | 4990 | // if (param_count == 1) { |
| 4890 | case BuiltinFnIdTruncate: | 4991 | // value_node = container_init_node->data.container_init_expr.entries.at(0); |
| 4891 | case BuiltinFnIdIntType: | 4992 | // } else { |
| 4892 | return false; | 4993 | // value_node = nullptr; |
| 4893 | } | 4994 | // } |
| 4894 | zig_unreachable(); | 4995 | // container_init_node->data.container_init_expr.enum_type = child_type; |
| 4895 | } | 4996 | // } |
| | 4997 | // } else { |
| | 4998 | // value_node = nullptr; |
| | 4999 | // } |
| | 5000 | // return analyze_enum_value_expr(g, import, context, node, value_node, child_type, field_name, node); |
| | 5001 | // } else if (child_type->id == TypeTableEntryIdStruct) { |
| | 5002 | // BlockContext *container_block_context = get_container_block_context(child_type); |
| | 5003 | // auto entry = container_block_context->decl_table.maybe_get(field_name); |
| | 5004 | // AstNode *decl_node = entry ? entry->value : nullptr; |
| | 5005 | // if (decl_node) { |
| | 5006 | // bool pointer_only = false; |
| | 5007 | // return analyze_decl_ref(g, node, decl_node, pointer_only, context, false); |
| | 5008 | // } else { |
| | 5009 | // add_node_error(g, node, |
| | 5010 | // buf_sprintf("container '%s' has no member called '%s'", |
| | 5011 | // buf_ptr(&child_type->name), buf_ptr(field_name))); |
| | 5012 | // return g->builtin_types.entry_invalid; |
| | 5013 | // } |
| | 5014 | // } else if (child_type->id == TypeTableEntryIdPureError) { |
| | 5015 | // return analyze_error_literal_expr(g, import, context, node, field_name); |
| | 5016 | // } else if (child_type->id == TypeTableEntryIdInt) { |
| | 5017 | // bool depends_on_compile_var = |
| | 5018 | // get_resolved_expr(*struct_expr_node)->const_val.depends_on_compile_var; |
| | 5019 | // if (buf_eql_str(field_name, "bit_count")) { |
| | 5020 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| | 5021 | // child_type->data.integral.bit_count, depends_on_compile_var); |
| | 5022 | // } else if (buf_eql_str(field_name, "is_signed")) { |
| | 5023 | // return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed, |
| | 5024 | // depends_on_compile_var); |
| | 5025 | // } else { |
| | 5026 | // add_node_error(g, node, |
| | 5027 | // buf_sprintf("type '%s' has no member called '%s'", |
| | 5028 | // buf_ptr(&child_type->name), buf_ptr(field_name))); |
| | 5029 | // return g->builtin_types.entry_invalid; |
| | 5030 | // } |
| | 5031 | // } else { |
| | 5032 | // add_node_error(g, node, |
| | 5033 | // buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name))); |
| | 5034 | // return g->builtin_types.entry_invalid; |
| | 5035 | // } |
| | 5036 | // } else if (struct_type->id == TypeTableEntryIdNamespace) { |
| | 5037 | // ConstExprValue *const_val = &get_resolved_expr(*struct_expr_node)->const_val; |
| | 5038 | // assert(const_val->ok); |
| | 5039 | // ImportTableEntry *namespace_import = const_val->data.x_import; |
| | 5040 | // AstNode *decl_node = find_decl(namespace_import->block_context, field_name); |
| | 5041 | // if (!decl_node) { |
| | 5042 | // // we must now resolve all the use decls |
| | 5043 | // for (size_t i = 0; i < namespace_import->use_decls.length; i += 1) { |
| | 5044 | // AstNode *use_decl_node = namespace_import->use_decls.at(i); |
| | 5045 | // if (!get_resolved_expr(use_decl_node->data.use.expr)->type_entry) { |
| | 5046 | // preview_use_decl(g, use_decl_node); |
| | 5047 | // } |
| | 5048 | // resolve_use_decl(g, use_decl_node); |
| | 5049 | // } |
| | 5050 | // decl_node = find_decl(namespace_import->block_context, field_name); |
| | 5051 | // } |
| | 5052 | // if (decl_node) { |
| | 5053 | // TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| | 5054 | // if (tld->visib_mod == VisibModPrivate && decl_node->owner != import) { |
| | 5055 | // ErrorMsg *msg = add_node_error(g, node, |
| | 5056 | // buf_sprintf("'%s' is private", buf_ptr(field_name))); |
| | 5057 | // add_error_note(g, msg, decl_node, buf_sprintf("declared here")); |
| | 5058 | // } |
| | 5059 | // bool pointer_only = false; |
| | 5060 | // return analyze_decl_ref(g, node, decl_node, pointer_only, context, |
| | 5061 | // const_val->depends_on_compile_var); |
| | 5062 | // } else { |
| | 5063 | // const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)"; |
| | 5064 | // add_node_error(g, node, |
| | 5065 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), import_name)); |
| | 5066 | // return g->builtin_types.entry_invalid; |
| | 5067 | // } |
| | 5068 | // } else { |
| | 5069 | // add_node_error(g, node, |
| | 5070 | // buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name))); |
| | 5071 | // return g->builtin_types.entry_invalid; |
| | 5072 | // } |
| | 5073 | //} |
| | 5074 | // |
| 4896 | | 5075 | |
| 4897 | bool ir_has_side_effects(IrInstruction *instruction) { | 5076 | //static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context, |
| 4898 | switch (instruction->id) { | 5077 | // AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const) |
| 4899 | case IrInstructionIdInvalid: | 5078 | //{ |
| 4900 | zig_unreachable(); | 5079 | // TypeTableEntry *expected_rhs_type = nullptr; |
| 4901 | case IrInstructionIdBr: | 5080 | // lhs_node->block_context = block_context; |
| 4902 | case IrInstructionIdCondBr: | 5081 | // if (lhs_node->type == NodeTypeSymbol) { |
| 4903 | case IrInstructionIdSwitchBr: | 5082 | // bool pointer_only = purpose == LValPurposeAddressOf; |
| 4904 | case IrInstructionIdDeclVar: | 5083 | // expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only); |
| 4905 | case IrInstructionIdStorePtr: | 5084 | // if (expected_rhs_type->id == TypeTableEntryIdInvalid) { |
| 4906 | case IrInstructionIdCall: | 5085 | // return g->builtin_types.entry_invalid; |
| 4907 | case IrInstructionIdReturn: | 5086 | // } |
| 4908 | case IrInstructionIdUnreachable: | 5087 | // if (purpose != LValPurposeAddressOf) { |
| 4909 | return true; | 5088 | // Buf *name = lhs_node->data.symbol_expr.symbol; |
| 4910 | case IrInstructionIdPhi: | 5089 | // VariableTableEntry *var = find_variable(g, block_context, name); |
| 4911 | case IrInstructionIdUnOp: | 5090 | // if (var) { |
| 4912 | case IrInstructionIdBinOp: | 5091 | // if (var->src_is_const) { |
| 4913 | case IrInstructionIdLoadPtr: | 5092 | // add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant")); |
| 4914 | case IrInstructionIdConst: | 5093 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| 4915 | case IrInstructionIdCast: | 5094 | // } else { |
| 4916 | case IrInstructionIdContainerInitList: | 5095 | // expected_rhs_type = var->type; |
| 4917 | case IrInstructionIdContainerInitFields: | 5096 | // get_resolved_expr(lhs_node)->variable = var; |
| 4918 | case IrInstructionIdFieldPtr: | 5097 | // } |
| 4919 | case IrInstructionIdElemPtr: | 5098 | // } else { |
| 4920 | case IrInstructionIdVarPtr: | 5099 | // add_node_error(g, lhs_node, |
| 4921 | case IrInstructionIdTypeOf: | 5100 | // buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name))); |
| 4922 | case IrInstructionIdToPtrType: | 5101 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| 4923 | case IrInstructionIdPtrTypeChild: | 5102 | // } |
| 4924 | case IrInstructionIdReadField: | 5103 | // } |
| 4925 | case IrInstructionIdStructFieldPtr: | 5104 | // } else if (lhs_node->type == NodeTypeArrayAccessExpr) { |
| 4926 | return false; | 5105 | // expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node, purpose); |
| 4927 | case IrInstructionIdBuiltinCall: | 5106 | // } else if (lhs_node->type == NodeTypeFieldAccessExpr) { |
| 4928 | return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction); | 5107 | // expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node); |
| 4929 | } | 5108 | // } else if (lhs_node->type == NodeTypePrefixOpExpr && |
| 4930 | zig_unreachable(); | 5109 | // lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference) |
| 4931 | } | 5110 | // { |
| | 5111 | // assert(purpose == LValPurposeAssign); |
| | 5112 | // AstNode *target_node = lhs_node->data.prefix_op_expr.primary_expr; |
| | 5113 | // TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, target_node); |
| | 5114 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 5115 | // expected_rhs_type = type_entry; |
| | 5116 | // } else if (type_entry->id == TypeTableEntryIdPointer) { |
| | 5117 | // expected_rhs_type = type_entry->data.pointer.child_type; |
| | 5118 | // } else { |
| | 5119 | // add_node_error(g, target_node, |
| | 5120 | // buf_sprintf("indirection requires pointer operand ('%s' invalid)", |
| | 5121 | // buf_ptr(&type_entry->name))); |
| | 5122 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| | 5123 | // } |
| | 5124 | // } else { |
| | 5125 | // if (purpose == LValPurposeAssign) { |
| | 5126 | // add_node_error(g, lhs_node, buf_sprintf("invalid assignment target")); |
| | 5127 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| | 5128 | // } else if (purpose == LValPurposeAddressOf) { |
| | 5129 | // TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, lhs_node); |
| | 5130 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 5131 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| | 5132 | // } else if (type_entry->id == TypeTableEntryIdMetaType) { |
| | 5133 | // expected_rhs_type = type_entry; |
| | 5134 | // } else { |
| | 5135 | // add_node_error(g, lhs_node, buf_sprintf("invalid addressof target")); |
| | 5136 | // expected_rhs_type = g->builtin_types.entry_invalid; |
| | 5137 | // } |
| | 5138 | // } |
| | 5139 | // } |
| | 5140 | // assert(expected_rhs_type); |
| | 5141 | // return expected_rhs_type; |
| | 5142 | //} |
| 4932 | | 5143 | |
| 4933 | IrInstruction *ir_exec_const_result(IrExecutable *exec) { | | |
| 4934 | if (exec->basic_block_list.length != 1) | | |
| 4935 | return nullptr; | | |
| 4936 | | 5144 | |
| 4937 | IrBasicBlock *bb = exec->basic_block_list.at(0); | | |
| 4938 | if (bb->instruction_list.length != 1) | | |
| 4939 | return nullptr; | | |
| 4940 | | 5145 | |
| 4941 | IrInstruction *only_inst = bb->instruction_list.at(0); | 5146 | //static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4942 | if (only_inst->id != IrInstructionIdReturn) | 5147 | // TypeTableEntry *expected_type, AstNode *node) |
| 4943 | return nullptr; | 5148 | //{ |
| | 5149 | // assert(node->type == NodeTypeBinOpExpr); |
| | 5150 | // BinOpType bin_op_type = node->data.bin_op_expr.bin_op; |
| | 5151 | // switch (bin_op_type) { |
| | 5152 | // case BinOpTypeAssign: |
| | 5153 | // case BinOpTypeAssignTimes: |
| | 5154 | // case BinOpTypeAssignTimesWrap: |
| | 5155 | // case BinOpTypeAssignDiv: |
| | 5156 | // case BinOpTypeAssignMod: |
| | 5157 | // case BinOpTypeAssignPlus: |
| | 5158 | // case BinOpTypeAssignPlusWrap: |
| | 5159 | // case BinOpTypeAssignMinus: |
| | 5160 | // case BinOpTypeAssignMinusWrap: |
| | 5161 | // case BinOpTypeAssignBitShiftLeft: |
| | 5162 | // case BinOpTypeAssignBitShiftLeftWrap: |
| | 5163 | // case BinOpTypeAssignBitShiftRight: |
| | 5164 | // case BinOpTypeAssignBitAnd: |
| | 5165 | // case BinOpTypeAssignBitXor: |
| | 5166 | // case BinOpTypeAssignBitOr: |
| | 5167 | // case BinOpTypeAssignBoolAnd: |
| | 5168 | // case BinOpTypeAssignBoolOr: |
| | 5169 | // { |
| | 5170 | // AstNode *lhs_node = node->data.bin_op_expr.op1; |
| | 5171 | // |
| | 5172 | // TypeTableEntry *expected_rhs_type = analyze_lvalue(g, import, context, lhs_node, |
| | 5173 | // LValPurposeAssign, false); |
| | 5174 | // if (expected_rhs_type->id == TypeTableEntryIdInvalid) { |
| | 5175 | // return g->builtin_types.entry_invalid; |
| | 5176 | // } else if (!is_op_allowed(expected_rhs_type, node->data.bin_op_expr.bin_op)) { |
| | 5177 | // if (expected_rhs_type->id != TypeTableEntryIdInvalid) { |
| | 5178 | // add_node_error(g, lhs_node, |
| | 5179 | // buf_sprintf("operator not allowed for type '%s'", |
| | 5180 | // buf_ptr(&expected_rhs_type->name))); |
| | 5181 | // } |
| | 5182 | // } |
| | 5183 | // |
| | 5184 | // analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2); |
| | 5185 | // // not const ok because expression has side effects |
| | 5186 | // return g->builtin_types.entry_void; |
| | 5187 | // } |
| | 5188 | // case BinOpTypeBoolOr: |
| | 5189 | // case BinOpTypeBoolAnd: |
| | 5190 | // return analyze_logic_bin_op_expr(g, import, context, node); |
| | 5191 | // case BinOpTypeCmpEq: |
| | 5192 | // case BinOpTypeCmpNotEq: |
| | 5193 | // case BinOpTypeCmpLessThan: |
| | 5194 | // case BinOpTypeCmpGreaterThan: |
| | 5195 | // case BinOpTypeCmpLessOrEq: |
| | 5196 | // case BinOpTypeCmpGreaterOrEq: |
| | 5197 | // return analyze_bool_bin_op_expr(g, import, context, node); |
| | 5198 | // case BinOpTypeBinOr: |
| | 5199 | // case BinOpTypeBinXor: |
| | 5200 | // case BinOpTypeBinAnd: |
| | 5201 | // case BinOpTypeBitShiftLeft: |
| | 5202 | // case BinOpTypeBitShiftLeftWrap: |
| | 5203 | // case BinOpTypeBitShiftRight: |
| | 5204 | // case BinOpTypeAdd: |
| | 5205 | // case BinOpTypeAddWrap: |
| | 5206 | // case BinOpTypeSub: |
| | 5207 | // case BinOpTypeSubWrap: |
| | 5208 | // case BinOpTypeMult: |
| | 5209 | // case BinOpTypeMultWrap: |
| | 5210 | // case BinOpTypeDiv: |
| | 5211 | // case BinOpTypeMod: |
| | 5212 | // { |
| | 5213 | // AstNode **op1 = node->data.bin_op_expr.op1->parent_field; |
| | 5214 | // AstNode **op2 = node->data.bin_op_expr.op2->parent_field; |
| | 5215 | // TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, *op1); |
| | 5216 | // TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 5217 | // |
| | 5218 | // AstNode *op_nodes[] = {*op1, *op2}; |
| | 5219 | // TypeTableEntry *op_types[] = {lhs_type, rhs_type}; |
| | 5220 | // |
| | 5221 | // TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node, |
| | 5222 | // op_nodes, op_types, 2); |
| | 5223 | // |
| | 5224 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 5225 | // return resolved_type; |
| | 5226 | // } |
| | 5227 | // |
| | 5228 | // if (resolved_type->id == TypeTableEntryIdInt || |
| | 5229 | // resolved_type->id == TypeTableEntryIdNumLitInt) |
| | 5230 | // { |
| | 5231 | // // int |
| | 5232 | // } else if ((resolved_type->id == TypeTableEntryIdFloat || |
| | 5233 | // resolved_type->id == TypeTableEntryIdNumLitFloat) && |
| | 5234 | // (bin_op_type == BinOpTypeAdd || |
| | 5235 | // bin_op_type == BinOpTypeSub || |
| | 5236 | // bin_op_type == BinOpTypeMult || |
| | 5237 | // bin_op_type == BinOpTypeDiv || |
| | 5238 | // bin_op_type == BinOpTypeMod)) |
| | 5239 | // { |
| | 5240 | // // float |
| | 5241 | // } else { |
| | 5242 | // add_node_error(g, node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'", |
| | 5243 | // buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name))); |
| | 5244 | // return g->builtin_types.entry_invalid; |
| | 5245 | // } |
| | 5246 | // |
| | 5247 | // ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; |
| | 5248 | // ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; |
| | 5249 | // if (!op1_val->ok || !op2_val->ok) { |
| | 5250 | // return resolved_type; |
| | 5251 | // } |
| | 5252 | // |
| | 5253 | // ConstExprValue *out_val = &get_resolved_expr(node)->const_val; |
| | 5254 | // int err; |
| | 5255 | // if ((err = eval_const_expr_bin_op(op1_val, resolved_type, bin_op_type, |
| | 5256 | // op2_val, resolved_type, out_val))) |
| | 5257 | // { |
| | 5258 | // if (err == ErrorDivByZero) { |
| | 5259 | // add_node_error(g, node, buf_sprintf("division by zero is undefined")); |
| | 5260 | // return g->builtin_types.entry_invalid; |
| | 5261 | // } else if (err == ErrorOverflow) { |
| | 5262 | // add_node_error(g, node, buf_sprintf("value cannot be represented in any integer type")); |
| | 5263 | // return g->builtin_types.entry_invalid; |
| | 5264 | // } |
| | 5265 | // return g->builtin_types.entry_invalid; |
| | 5266 | // } |
| | 5267 | // |
| | 5268 | // num_lit_fits_in_other_type(g, node, resolved_type); |
| | 5269 | // return resolved_type; |
| | 5270 | // } |
| | 5271 | // case BinOpTypeUnwrapMaybe: |
| | 5272 | // { |
| | 5273 | // AstNode *op1 = node->data.bin_op_expr.op1; |
| | 5274 | // AstNode *op2 = node->data.bin_op_expr.op2; |
| | 5275 | // TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1); |
| | 5276 | // |
| | 5277 | // if (lhs_type->id == TypeTableEntryIdInvalid) { |
| | 5278 | // return lhs_type; |
| | 5279 | // } else if (lhs_type->id == TypeTableEntryIdMaybe) { |
| | 5280 | // TypeTableEntry *child_type = lhs_type->data.maybe.child_type; |
| | 5281 | // analyze_expression(g, import, context, child_type, op2); |
| | 5282 | // return child_type; |
| | 5283 | // } else { |
| | 5284 | // add_node_error(g, op1, |
| | 5285 | // buf_sprintf("expected maybe type, got '%s'", |
| | 5286 | // buf_ptr(&lhs_type->name))); |
| | 5287 | // return g->builtin_types.entry_invalid; |
| | 5288 | // } |
| | 5289 | // } |
| | 5290 | // case BinOpTypeArrayCat: |
| | 5291 | // { |
| | 5292 | // AstNode **op1 = node->data.bin_op_expr.op1->parent_field; |
| | 5293 | // AstNode **op2 = node->data.bin_op_expr.op2->parent_field; |
| | 5294 | // |
| | 5295 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); |
| | 5296 | // TypeTableEntry *child_type; |
| | 5297 | // if (op1_type->id == TypeTableEntryIdInvalid) { |
| | 5298 | // return g->builtin_types.entry_invalid; |
| | 5299 | // } else if (op1_type->id == TypeTableEntryIdArray) { |
| | 5300 | // child_type = op1_type->data.array.child_type; |
| | 5301 | // } else if (op1_type->id == TypeTableEntryIdPointer && |
| | 5302 | // op1_type->data.pointer.child_type == g->builtin_types.entry_u8) { |
| | 5303 | // child_type = op1_type->data.pointer.child_type; |
| | 5304 | // } else { |
| | 5305 | // add_node_error(g, *op1, buf_sprintf("expected array or C string literal, got '%s'", |
| | 5306 | // buf_ptr(&op1_type->name))); |
| | 5307 | // return g->builtin_types.entry_invalid; |
| | 5308 | // } |
| | 5309 | // |
| | 5310 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 5311 | // |
| | 5312 | // if (op2_type->id == TypeTableEntryIdInvalid) { |
| | 5313 | // return g->builtin_types.entry_invalid; |
| | 5314 | // } else if (op2_type->id == TypeTableEntryIdArray) { |
| | 5315 | // if (op2_type->data.array.child_type != child_type) { |
| | 5316 | // add_node_error(g, *op2, buf_sprintf("expected array of type '%s', got '%s'", |
| | 5317 | // buf_ptr(&child_type->name), |
| | 5318 | // buf_ptr(&op2_type->name))); |
| | 5319 | // return g->builtin_types.entry_invalid; |
| | 5320 | // } |
| | 5321 | // } else if (op2_type->id == TypeTableEntryIdPointer && |
| | 5322 | // op2_type->data.pointer.child_type == g->builtin_types.entry_u8) { |
| | 5323 | // } else { |
| | 5324 | // add_node_error(g, *op2, buf_sprintf("expected array or C string literal, got '%s'", |
| | 5325 | // buf_ptr(&op2_type->name))); |
| | 5326 | // return g->builtin_types.entry_invalid; |
| | 5327 | // } |
| | 5328 | // |
| | 5329 | // ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; |
| | 5330 | // ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; |
| | 5331 | // |
| | 5332 | // AstNode *bad_node; |
| | 5333 | // if (!op1_val->ok) { |
| | 5334 | // bad_node = *op1; |
| | 5335 | // } else if (!op2_val->ok) { |
| | 5336 | // bad_node = *op2; |
| | 5337 | // } else { |
| | 5338 | // bad_node = nullptr; |
| | 5339 | // } |
| | 5340 | // if (bad_node) { |
| | 5341 | // add_node_error(g, bad_node, buf_sprintf("array concatenation requires constant expression")); |
| | 5342 | // return g->builtin_types.entry_invalid; |
| | 5343 | // } |
| | 5344 | // |
| | 5345 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 5346 | // const_val->ok = true; |
| | 5347 | // const_val->depends_on_compile_var = op1_val->depends_on_compile_var || |
| | 5348 | // op2_val->depends_on_compile_var; |
| | 5349 | // |
| | 5350 | // if (op1_type->id == TypeTableEntryIdArray) { |
| | 5351 | // uint64_t new_len = op1_type->data.array.len + op2_type->data.array.len; |
| | 5352 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(new_len); |
| | 5353 | // uint64_t next_index = 0; |
| | 5354 | // for (uint64_t i = 0; i < op1_type->data.array.len; i += 1, next_index += 1) { |
| | 5355 | // const_val->data.x_array.fields[next_index] = op1_val->data.x_array.fields[i]; |
| | 5356 | // } |
| | 5357 | // for (uint64_t i = 0; i < op2_type->data.array.len; i += 1, next_index += 1) { |
| | 5358 | // const_val->data.x_array.fields[next_index] = op2_val->data.x_array.fields[i]; |
| | 5359 | // } |
| | 5360 | // return get_array_type(g, child_type, new_len); |
| | 5361 | // } else if (op1_type->id == TypeTableEntryIdPointer) { |
| | 5362 | // if (!op1_val->data.x_ptr.is_c_str) { |
| | 5363 | // add_node_error(g, *op1, |
| | 5364 | // buf_sprintf("expected array or C string literal, got '%s'", |
| | 5365 | // buf_ptr(&op1_type->name))); |
| | 5366 | // return g->builtin_types.entry_invalid; |
| | 5367 | // } else if (!op2_val->data.x_ptr.is_c_str) { |
| | 5368 | // add_node_error(g, *op2, |
| | 5369 | // buf_sprintf("expected array or C string literal, got '%s'", |
| | 5370 | // buf_ptr(&op2_type->name))); |
| | 5371 | // return g->builtin_types.entry_invalid; |
| | 5372 | // } |
| | 5373 | // const_val->data.x_ptr.is_c_str = true; |
| | 5374 | // const_val->data.x_ptr.len = op1_val->data.x_ptr.len + op2_val->data.x_ptr.len - 1; |
| | 5375 | // const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(const_val->data.x_ptr.len); |
| | 5376 | // uint64_t next_index = 0; |
| | 5377 | // for (uint64_t i = 0; i < op1_val->data.x_ptr.len - 1; i += 1, next_index += 1) { |
| | 5378 | // const_val->data.x_ptr.ptr[next_index] = op1_val->data.x_ptr.ptr[i]; |
| | 5379 | // } |
| | 5380 | // for (uint64_t i = 0; i < op2_val->data.x_ptr.len; i += 1, next_index += 1) { |
| | 5381 | // const_val->data.x_ptr.ptr[next_index] = op2_val->data.x_ptr.ptr[i]; |
| | 5382 | // } |
| | 5383 | // return op1_type; |
| | 5384 | // } else { |
| | 5385 | // zig_unreachable(); |
| | 5386 | // } |
| | 5387 | // } |
| | 5388 | // case BinOpTypeArrayMult: |
| | 5389 | // return analyze_array_mult(g, import, context, expected_type, node); |
| | 5390 | // case BinOpTypeInvalid: |
| | 5391 | // zig_unreachable(); |
| | 5392 | // } |
| | 5393 | // zig_unreachable(); |
| | 5394 | //} |
| 4944 | | 5395 | |
| 4945 | IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst; | 5396 | |
| 4946 | IrInstruction *value = ret_inst->value; | 5397 | //static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4947 | assert(value->static_value.ok); | 5398 | // AstNode *node) |
| 4948 | return value; | 5399 | //{ |
| 4949 | } | 5400 | // assert(node->type == NodeTypeBinOpExpr); |
| | 5401 | // BinOpType bin_op_type = node->data.bin_op_expr.bin_op; |
| | 5402 | // |
| | 5403 | // AstNode **op1 = &node->data.bin_op_expr.op1; |
| | 5404 | // AstNode **op2 = &node->data.bin_op_expr.op2; |
| | 5405 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); |
| | 5406 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 5407 | // |
| | 5408 | // AstNode *op_nodes[] = {*op1, *op2}; |
| | 5409 | // TypeTableEntry *op_types[] = {op1_type, op2_type}; |
| | 5410 | // |
| | 5411 | // TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node, |
| | 5412 | // op_nodes, op_types, 2); |
| | 5413 | // |
| | 5414 | // bool is_equality_cmp = (bin_op_type == BinOpTypeCmpEq || bin_op_type == BinOpTypeCmpNotEq); |
| | 5415 | // |
| | 5416 | // switch (resolved_type->id) { |
| | 5417 | // case TypeTableEntryIdInvalid: |
| | 5418 | // return g->builtin_types.entry_invalid; |
| | 5419 | // |
| | 5420 | // case TypeTableEntryIdNumLitFloat: |
| | 5421 | // case TypeTableEntryIdNumLitInt: |
| | 5422 | // case TypeTableEntryIdInt: |
| | 5423 | // case TypeTableEntryIdFloat: |
| | 5424 | // break; |
| | 5425 | // |
| | 5426 | // case TypeTableEntryIdBool: |
| | 5427 | // case TypeTableEntryIdMetaType: |
| | 5428 | // case TypeTableEntryIdVoid: |
| | 5429 | // case TypeTableEntryIdPointer: |
| | 5430 | // case TypeTableEntryIdPureError: |
| | 5431 | // case TypeTableEntryIdFn: |
| | 5432 | // case TypeTableEntryIdTypeDecl: |
| | 5433 | // case TypeTableEntryIdNamespace: |
| | 5434 | // case TypeTableEntryIdBlock: |
| | 5435 | // case TypeTableEntryIdGenericFn: |
| | 5436 | // if (!is_equality_cmp) { |
| | 5437 | // add_node_error(g, node, |
| | 5438 | // buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| | 5439 | // return g->builtin_types.entry_invalid; |
| | 5440 | // } |
| | 5441 | // break; |
| | 5442 | // |
| | 5443 | // case TypeTableEntryIdEnum: |
| | 5444 | // if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) { |
| | 5445 | // add_node_error(g, node, |
| | 5446 | // buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| | 5447 | // return g->builtin_types.entry_invalid; |
| | 5448 | // } |
| | 5449 | // break; |
| | 5450 | // |
| | 5451 | // case TypeTableEntryIdUnreachable: |
| | 5452 | // case TypeTableEntryIdArray: |
| | 5453 | // case TypeTableEntryIdStruct: |
| | 5454 | // case TypeTableEntryIdUndefLit: |
| | 5455 | // case TypeTableEntryIdNullLit: |
| | 5456 | // case TypeTableEntryIdMaybe: |
| | 5457 | // case TypeTableEntryIdErrorUnion: |
| | 5458 | // case TypeTableEntryIdUnion: |
| | 5459 | // add_node_error(g, node, |
| | 5460 | // buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| | 5461 | // return g->builtin_types.entry_invalid; |
| | 5462 | // |
| | 5463 | // case TypeTableEntryIdVar: |
| | 5464 | // zig_unreachable(); |
| | 5465 | // } |
| | 5466 | // |
| | 5467 | // ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; |
| | 5468 | // ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; |
| | 5469 | // if (!op1_val->ok || !op2_val->ok) { |
| | 5470 | // return g->builtin_types.entry_bool; |
| | 5471 | // } |
| | 5472 | // |
| | 5473 | // |
| | 5474 | // ConstExprValue *out_val = &get_resolved_expr(node)->const_val; |
| | 5475 | // eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val); |
| | 5476 | // return g->builtin_types.entry_bool; |
| | 5477 | // |
| | 5478 | //} |
| | 5479 | // |
| | 5480 | //// |
| | 5481 | //static TypeTableEntry *analyze_if(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| | 5482 | // TypeTableEntry *expected_type, AstNode *node, |
| | 5483 | // AstNode **then_node, AstNode **else_node, bool cond_is_const, bool cond_bool_val) |
| | 5484 | //{ |
| | 5485 | // if (!*else_node) { |
| | 5486 | // *else_node = create_ast_void_node(g, import, node); |
| | 5487 | // normalize_parent_ptrs(node); |
| | 5488 | // } |
| | 5489 | // |
| | 5490 | // BlockContext *then_context; |
| | 5491 | // BlockContext *else_context; |
| | 5492 | // if (cond_is_const) { |
| | 5493 | // if (cond_bool_val) { |
| | 5494 | // then_context = parent_context; |
| | 5495 | // else_context = new_block_context(node, parent_context); |
| | 5496 | // |
| | 5497 | // else_context->codegen_excluded = true; |
| | 5498 | // } else { |
| | 5499 | // then_context = new_block_context(node, parent_context); |
| | 5500 | // else_context = parent_context; |
| | 5501 | // |
| | 5502 | // then_context->codegen_excluded = true; |
| | 5503 | // } |
| | 5504 | // } else { |
| | 5505 | // then_context = parent_context; |
| | 5506 | // else_context = parent_context; |
| | 5507 | // } |
| | 5508 | // |
| | 5509 | // TypeTableEntry *then_type = nullptr; |
| | 5510 | // TypeTableEntry *else_type = nullptr; |
| | 5511 | // |
| | 5512 | // if (!then_context->codegen_excluded) { |
| | 5513 | // then_type = analyze_expression(g, import, then_context, expected_type, *then_node); |
| | 5514 | // if (then_type->id == TypeTableEntryIdInvalid) { |
| | 5515 | // return g->builtin_types.entry_invalid; |
| | 5516 | // } |
| | 5517 | // } |
| | 5518 | // if (!else_context->codegen_excluded) { |
| | 5519 | // else_type = analyze_expression(g, import, else_context, expected_type, *else_node); |
| | 5520 | // if (else_type->id == TypeTableEntryIdInvalid) { |
| | 5521 | // return g->builtin_types.entry_invalid; |
| | 5522 | // } |
| | 5523 | // } |
| | 5524 | // |
| | 5525 | // TypeTableEntry *result_type; |
| | 5526 | // if (then_context->codegen_excluded) { |
| | 5527 | // result_type = else_type; |
| | 5528 | // } else if (else_context->codegen_excluded) { |
| | 5529 | // result_type = then_type; |
| | 5530 | // } else if (expected_type) { |
| | 5531 | // result_type = (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; |
| | 5532 | // } else { |
| | 5533 | // AstNode *op_nodes[] = {*then_node, *else_node}; |
| | 5534 | // TypeTableEntry *op_types[] = {then_type, else_type}; |
| | 5535 | // result_type = resolve_peer_type_compatibility(g, import, parent_context, node, op_nodes, op_types, 2); |
| | 5536 | // } |
| | 5537 | // |
| | 5538 | // if (!cond_is_const) { |
| | 5539 | // return add_error_if_type_is_num_lit(g, result_type, node); |
| | 5540 | // } |
| | 5541 | // |
| | 5542 | // ConstExprValue *other_const_val; |
| | 5543 | // if (cond_bool_val) { |
| | 5544 | // other_const_val = &get_resolved_expr(*then_node)->const_val; |
| | 5545 | // } else { |
| | 5546 | // other_const_val = &get_resolved_expr(*else_node)->const_val; |
| | 5547 | // } |
| | 5548 | // if (!other_const_val->ok) { |
| | 5549 | // return add_error_if_type_is_num_lit(g, result_type, node); |
| | 5550 | // } |
| | 5551 | // |
| | 5552 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 5553 | // *const_val = *other_const_val; |
| | 5554 | // // the condition depends on a compile var, so the entire if statement does too |
| | 5555 | // const_val->depends_on_compile_var = true; |
| | 5556 | // return result_type; |
| | 5557 | //} |
| | 5558 | // |
| | 5559 | //static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| | 5560 | // TypeTableEntry *expected_type, AstNode *node) |
| | 5561 | //{ |
| | 5562 | // assert(node->type == NodeTypeIfVarExpr); |
| | 5563 | // |
| | 5564 | // BlockContext *child_context = new_block_context(node, parent_context); |
| | 5565 | // |
| | 5566 | // analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true, |
| | 5567 | // nullptr, node->data.if_var_expr.var_is_ptr); |
| | 5568 | // VariableTableEntry *var = node->data.if_var_expr.var_decl.variable; |
| | 5569 | // if (var->type->id == TypeTableEntryIdInvalid) { |
| | 5570 | // return g->builtin_types.entry_invalid; |
| | 5571 | // } |
| | 5572 | // AstNode *var_expr_node = node->data.if_var_expr.var_decl.expr; |
| | 5573 | // ConstExprValue *var_const_val = &get_resolved_expr(var_expr_node)->const_val; |
| | 5574 | // bool cond_is_const = var_const_val->ok; |
| | 5575 | // bool cond_bool_val = cond_is_const ? (var_const_val->data.x_maybe != nullptr) : false; |
| | 5576 | // |
| | 5577 | // |
| | 5578 | // AstNode **then_node = &node->data.if_var_expr.then_block; |
| | 5579 | // AstNode **else_node = &node->data.if_var_expr.else_node; |
| | 5580 | // |
| | 5581 | // return analyze_if(g, import, child_context, expected_type, |
| | 5582 | // node, then_node, else_node, cond_is_const, cond_bool_val); |
| | 5583 | //} |
| | 5584 | // |
| | 5585 | //static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type, |
| | 5586 | // TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry) |
| | 5587 | //{ |
| | 5588 | // ErrorMsg *msg = add_node_error(g, node, |
| | 5589 | // buf_sprintf("function called as method of '%s', but first parameter is of type '%s'", |
| | 5590 | // buf_ptr(&container_type->name), |
| | 5591 | // buf_ptr(&expected_param_type->name))); |
| | 5592 | // if (fn_table_entry) { |
| | 5593 | // add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here")); |
| | 5594 | // } |
| | 5595 | // return g->builtin_types.entry_invalid; |
| | 5596 | //} |
| | 5597 | // |
| | 5598 | //// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known |
| | 5599 | //// at compile time. Otherwise this is a function pointer call. |
| | 5600 | //static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 5601 | // TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type, |
| | 5602 | // AstNode *struct_node) |
| | 5603 | //{ |
| | 5604 | // assert(node->type == NodeTypeFnCallExpr); |
| | 5605 | // |
| | 5606 | // if (fn_type->id == TypeTableEntryIdInvalid) { |
| | 5607 | // return fn_type; |
| | 5608 | // } |
| | 5609 | // |
| | 5610 | // // The function call might include inline parameters which we need to ignore according to the |
| | 5611 | // // fn_type. |
| | 5612 | // FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry; |
| | 5613 | // AstNode *generic_proto_node = fn_table_entry ? |
| | 5614 | // fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr; |
| | 5615 | // |
| | 5616 | // // count parameters |
| | 5617 | // size_t struct_node_1_or_0 = struct_node ? 1 : 0; |
| | 5618 | // size_t src_param_count = fn_type->data.fn.fn_type_id.param_count + |
| | 5619 | // (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0); |
| | 5620 | // size_t call_param_count = node->data.fn_call_expr.params.length; |
| | 5621 | // size_t expect_arg_count = src_param_count - struct_node_1_or_0; |
| | 5622 | // |
| | 5623 | // bool ok_invocation = true; |
| | 5624 | // |
| | 5625 | // if (fn_type->data.fn.fn_type_id.is_var_args) { |
| | 5626 | // if (call_param_count < expect_arg_count) { |
| | 5627 | // ok_invocation = false; |
| | 5628 | // add_node_error(g, node, |
| | 5629 | // buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count)); |
| | 5630 | // } |
| | 5631 | // } else if (expect_arg_count != call_param_count) { |
| | 5632 | // ok_invocation = false; |
| | 5633 | // add_node_error(g, node, |
| | 5634 | // buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count)); |
| | 5635 | // } |
| | 5636 | // |
| | 5637 | // bool all_args_const_expr = true; |
| | 5638 | // |
| | 5639 | // if (struct_node) { |
| | 5640 | // Expr *struct_expr = get_resolved_expr(struct_node); |
| | 5641 | // ConstExprValue *struct_const_val = &struct_expr->const_val; |
| | 5642 | // if (!struct_const_val->ok) { |
| | 5643 | // all_args_const_expr = false; |
| | 5644 | // } |
| | 5645 | // |
| | 5646 | // FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0]; |
| | 5647 | // TypeTableEntry *expected_param_type = param_info->type; |
| | 5648 | // TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry); |
| | 5649 | // if (is_container_ref(expected_param_type)) { |
| | 5650 | // TypeTableEntry *param_bare_type = container_ref_type(expected_param_type); |
| | 5651 | // if (param_bare_type != container_bare_type) { |
| | 5652 | // return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry); |
| | 5653 | // } |
| | 5654 | // } else { |
| | 5655 | // return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry); |
| | 5656 | // } |
| | 5657 | // } |
| | 5658 | // |
| | 5659 | // // analyze each parameter. in the case of a method, we already analyzed the |
| | 5660 | // // first parameter in order to figure out which struct we were calling a method on. |
| | 5661 | // size_t next_type_i = struct_node_1_or_0; |
| | 5662 | // for (size_t call_i = 0; call_i < call_param_count; call_i += 1) { |
| | 5663 | // size_t proto_i = call_i + struct_node_1_or_0; |
| | 5664 | // AstNode **param_node = &node->data.fn_call_expr.params.at(call_i); |
| | 5665 | // // determine the expected type for each parameter |
| | 5666 | // TypeTableEntry *expected_param_type = nullptr; |
| | 5667 | // if (proto_i < src_param_count) { |
| | 5668 | // if (generic_proto_node && |
| | 5669 | // generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline) |
| | 5670 | // { |
| | 5671 | // continue; |
| | 5672 | // } |
| | 5673 | // |
| | 5674 | // FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i]; |
| | 5675 | // next_type_i += 1; |
| | 5676 | // |
| | 5677 | // expected_param_type = param_info->type; |
| | 5678 | // } |
| | 5679 | // TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node); |
| | 5680 | // if (param_type->id == TypeTableEntryIdInvalid) { |
| | 5681 | // return param_type; |
| | 5682 | // } |
| | 5683 | // |
| | 5684 | // ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val; |
| | 5685 | // if (!const_arg_val->ok) { |
| | 5686 | // all_args_const_expr = false; |
| | 5687 | // } |
| | 5688 | // } |
| | 5689 | // |
| | 5690 | // TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| | 5691 | // |
| | 5692 | // if (return_type->id == TypeTableEntryIdInvalid) { |
| | 5693 | // return return_type; |
| | 5694 | // } |
| | 5695 | // |
| | 5696 | // ConstExprValue *result_val = &get_resolved_expr(node)->const_val; |
| | 5697 | // if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) { |
| | 5698 | // if (fn_table_entry->anal_state == FnAnalStateReady) { |
| | 5699 | // analyze_fn_body(g, fn_table_entry); |
| | 5700 | // if (fn_table_entry->proto_node->data.fn_proto.skip) { |
| | 5701 | // return g->builtin_types.entry_invalid; |
| | 5702 | // } |
| | 5703 | // } |
| | 5704 | // if (all_args_const_expr) { |
| | 5705 | // if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) { |
| | 5706 | // if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) { |
| | 5707 | // // function evaluation generated an error |
| | 5708 | // return g->builtin_types.entry_invalid; |
| | 5709 | // } |
| | 5710 | // return return_type; |
| | 5711 | // } |
| | 5712 | // } |
| | 5713 | // } |
| | 5714 | // if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) { |
| | 5715 | // // calling an impure fn is impure |
| | 5716 | // mark_impure_fn(g, context, node); |
| | 5717 | // if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) { |
| | 5718 | // return g->builtin_types.entry_invalid; |
| | 5719 | // } |
| | 5720 | // } |
| | 5721 | // |
| | 5722 | // // TODO |
| | 5723 | // //if (handle_is_ptr(return_type)) { |
| | 5724 | // // if (context->fn_entry) { |
| | 5725 | // // context->fn_entry->cast_alloca_list.append(node); |
| | 5726 | // // } else if (!result_val->ok) { |
| | 5727 | // // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression")); |
| | 5728 | // // } |
| | 5729 | // //} |
| | 5730 | // |
| | 5731 | // return return_type; |
| | 5732 | //} |
| | 5733 | // |
| | 5734 | //static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import, |
| | 5735 | // BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node, |
| | 5736 | // FnTableEntry *fn_table_entry, AstNode *struct_node) |
| | 5737 | //{ |
| | 5738 | // assert(call_node->type == NodeTypeFnCallExpr); |
| | 5739 | // assert(fn_table_entry); |
| | 5740 | // |
| | 5741 | // AstNode *decl_node = fn_table_entry->proto_node; |
| | 5742 | // |
| | 5743 | // // count parameters |
| | 5744 | // size_t struct_node_1_or_0 = (struct_node ? 1 : 0); |
| | 5745 | // size_t src_param_count = decl_node->data.fn_proto.params.length; |
| | 5746 | // size_t call_param_count = call_node->data.fn_call_expr.params.length; |
| | 5747 | // |
| | 5748 | // if (src_param_count != call_param_count + struct_node_1_or_0) { |
| | 5749 | // add_node_error(g, call_node, |
| | 5750 | // buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count)); |
| | 5751 | // return g->builtin_types.entry_invalid; |
| | 5752 | // } |
| | 5753 | // |
| | 5754 | // size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count; |
| | 5755 | // assert(inline_or_var_type_arg_count > 0); |
| | 5756 | // |
| | 5757 | // BlockContext *child_context = decl_node->owner->block_context; |
| | 5758 | // size_t next_generic_param_index = 0; |
| | 5759 | // |
| | 5760 | // GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1); |
| | 5761 | // generic_fn_type_id->decl_node = decl_node; |
| | 5762 | // generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count; |
| | 5763 | // generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count); |
| | 5764 | // |
| | 5765 | // size_t next_impl_i = 0; |
| | 5766 | // for (size_t call_i = 0; call_i < call_param_count; call_i += 1) { |
| | 5767 | // size_t proto_i = call_i + struct_node_1_or_0; |
| | 5768 | // AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i); |
| | 5769 | // assert(generic_param_decl_node->type == NodeTypeParamDecl); |
| | 5770 | // |
| | 5771 | // AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; |
| | 5772 | // TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context, |
| | 5773 | // *generic_param_type_node); |
| | 5774 | // if (expected_param_type->id == TypeTableEntryIdInvalid) { |
| | 5775 | // return expected_param_type; |
| | 5776 | // } |
| | 5777 | // |
| | 5778 | // bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar); |
| | 5779 | // bool is_inline = generic_param_decl_node->data.param_decl.is_inline; |
| | 5780 | // if (!is_inline && !is_var_type) { |
| | 5781 | // next_impl_i += 1; |
| | 5782 | // continue; |
| | 5783 | // } |
| | 5784 | // |
| | 5785 | // |
| | 5786 | // AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i); |
| | 5787 | // TypeTableEntry *param_type = analyze_expression(g, import, parent_context, |
| | 5788 | // is_var_type ? nullptr : expected_param_type, *param_node); |
| | 5789 | // if (param_type->id == TypeTableEntryIdInvalid) { |
| | 5790 | // return param_type; |
| | 5791 | // } |
| | 5792 | // |
| | 5793 | // // set child_context so that the previous param is in scope |
| | 5794 | // child_context = new_block_context(generic_param_decl_node, child_context); |
| | 5795 | // |
| | 5796 | // ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val; |
| | 5797 | // if (is_inline && !const_val->ok) { |
| | 5798 | // add_node_error(g, *param_node, |
| | 5799 | // buf_sprintf("unable to evaluate constant expression for inline parameter")); |
| | 5800 | // |
| | 5801 | // return g->builtin_types.entry_invalid; |
| | 5802 | // } |
| | 5803 | // |
| | 5804 | // VariableTableEntry *var = add_local_var_shadowable(g, generic_param_decl_node, decl_node->owner, child_context, |
| | 5805 | // generic_param_decl_node->data.param_decl.name, param_type, true, *param_node, true); |
| | 5806 | // // This generic function instance could be called with anything, so when this variable is read it |
| | 5807 | // // needs to know that it depends on compile time variable data. |
| | 5808 | // var->force_depends_on_compile_var = true; |
| | 5809 | // |
| | 5810 | // GenericParamValue *generic_param_value = |
| | 5811 | // &generic_fn_type_id->generic_params[next_generic_param_index]; |
| | 5812 | // generic_param_value->type = param_type; |
| | 5813 | // generic_param_value->node = is_inline ? *param_node : nullptr; |
| | 5814 | // generic_param_value->impl_index = next_impl_i; |
| | 5815 | // next_generic_param_index += 1; |
| | 5816 | // |
| | 5817 | // if (!is_inline) { |
| | 5818 | // next_impl_i += 1; |
| | 5819 | // } |
| | 5820 | // } |
| | 5821 | // |
| | 5822 | // assert(next_generic_param_index == inline_or_var_type_arg_count); |
| | 5823 | // |
| | 5824 | // auto entry = g->generic_table.maybe_get(generic_fn_type_id); |
| | 5825 | // FnTableEntry *impl_fn; |
| | 5826 | // if (entry) { |
| | 5827 | // AstNode *impl_decl_node = entry->value; |
| | 5828 | // assert(impl_decl_node->type == NodeTypeFnProto); |
| | 5829 | // impl_fn = impl_decl_node->data.fn_proto.fn_table_entry; |
| | 5830 | // } else { |
| | 5831 | // AstNode *decl_node = generic_fn_type_id->decl_node; |
| | 5832 | // AstNode *impl_fn_def_node = ast_clone_subtree_special(decl_node->data.fn_proto.fn_def_node, |
| | 5833 | // &g->next_node_index, AstCloneSpecialOmitInlineParams); |
| | 5834 | // AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto; |
| | 5835 | // impl_decl_node->data.fn_proto.inline_arg_count = 0; |
| | 5836 | // impl_decl_node->data.fn_proto.inline_or_var_type_arg_count = 0; |
| | 5837 | // impl_decl_node->data.fn_proto.generic_proto_node = decl_node; |
| | 5838 | // |
| | 5839 | // // replace var arg types with actual types |
| | 5840 | // for (size_t generic_arg_i = 0; generic_arg_i < inline_or_var_type_arg_count; generic_arg_i += 1) { |
| | 5841 | // GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[generic_arg_i]; |
| | 5842 | // if (!generic_param_value->node) { |
| | 5843 | // size_t impl_i = generic_param_value->impl_index; |
| | 5844 | // AstNode *impl_param_decl_node = impl_decl_node->data.fn_proto.params.at(impl_i); |
| | 5845 | // assert(impl_param_decl_node->type == NodeTypeParamDecl); |
| | 5846 | // |
| | 5847 | // impl_param_decl_node->data.param_decl.type = create_ast_type_node(g, import, |
| | 5848 | // generic_param_value->type, impl_param_decl_node); |
| | 5849 | // normalize_parent_ptrs(impl_param_decl_node); |
| | 5850 | // } |
| | 5851 | // } |
| | 5852 | // |
| | 5853 | // preview_fn_proto_instance(g, import, impl_decl_node, child_context); |
| | 5854 | // g->generic_table.put(generic_fn_type_id, impl_decl_node); |
| | 5855 | // impl_fn = impl_decl_node->data.fn_proto.fn_table_entry; |
| | 5856 | // } |
| | 5857 | // |
| | 5858 | // call_node->data.fn_call_expr.fn_entry = impl_fn; |
| | 5859 | // return analyze_fn_call_ptr(g, import, parent_context, expected_type, call_node, |
| | 5860 | // impl_fn->type_entry, struct_node); |
| | 5861 | //} |
| | 5862 | // |
| | 5863 | //static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| | 5864 | // TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *generic_fn_type) |
| | 5865 | //{ |
| | 5866 | // assert(node->type == NodeTypeFnCallExpr); |
| | 5867 | // assert(generic_fn_type->id == TypeTableEntryIdGenericFn); |
| | 5868 | // |
| | 5869 | // AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node; |
| | 5870 | // assert(decl_node->type == NodeTypeContainerDecl); |
| | 5871 | // ZigList<AstNode *> *generic_params = &decl_node->data.struct_decl.generic_params; |
| | 5872 | // |
| | 5873 | // size_t expected_param_count = generic_params->length; |
| | 5874 | // size_t actual_param_count = node->data.fn_call_expr.params.length; |
| | 5875 | // |
| | 5876 | // if (actual_param_count != expected_param_count) { |
| | 5877 | // add_node_error(g, first_executing_node(node), |
| | 5878 | // buf_sprintf("expected %zu arguments, got %zu", expected_param_count, actual_param_count)); |
| | 5879 | // return g->builtin_types.entry_invalid; |
| | 5880 | // } |
| | 5881 | // |
| | 5882 | // GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1); |
| | 5883 | // generic_fn_type_id->decl_node = decl_node; |
| | 5884 | // generic_fn_type_id->generic_param_count = actual_param_count; |
| | 5885 | // generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count); |
| | 5886 | // |
| | 5887 | // BlockContext *child_context = decl_node->owner->block_context; |
| | 5888 | // for (size_t i = 0; i < actual_param_count; i += 1) { |
| | 5889 | // AstNode *generic_param_decl_node = generic_params->at(i); |
| | 5890 | // assert(generic_param_decl_node->type == NodeTypeParamDecl); |
| | 5891 | // |
| | 5892 | // AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; |
| | 5893 | // |
| | 5894 | // TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, |
| | 5895 | // child_context, *generic_param_type_node); |
| | 5896 | // if (expected_param_type->id == TypeTableEntryIdInvalid) { |
| | 5897 | // return expected_param_type; |
| | 5898 | // } |
| | 5899 | // |
| | 5900 | // |
| | 5901 | // |
| | 5902 | // AstNode **param_node = &node->data.fn_call_expr.params.at(i); |
| | 5903 | // |
| | 5904 | // TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type, |
| | 5905 | // *param_node); |
| | 5906 | // if (param_type->id == TypeTableEntryIdInvalid) { |
| | 5907 | // return param_type; |
| | 5908 | // } |
| | 5909 | // |
| | 5910 | // // set child_context so that the previous param is in scope |
| | 5911 | // child_context = new_block_context(generic_param_decl_node, child_context); |
| | 5912 | // |
| | 5913 | // ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val; |
| | 5914 | // if (const_val->ok) { |
| | 5915 | // VariableTableEntry *var = add_local_var(g, generic_param_decl_node, decl_node->owner, child_context, |
| | 5916 | // generic_param_decl_node->data.param_decl.name, param_type, true, *param_node); |
| | 5917 | // var->force_depends_on_compile_var = true; |
| | 5918 | // } else { |
| | 5919 | // add_node_error(g, *param_node, buf_sprintf("unable to evaluate constant expression")); |
| | 5920 | // |
| | 5921 | // return g->builtin_types.entry_invalid; |
| | 5922 | // } |
| | 5923 | // |
| | 5924 | // GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[i]; |
| | 5925 | // generic_param_value->type = param_type; |
| | 5926 | // generic_param_value->node = *param_node; |
| | 5927 | // } |
| | 5928 | // |
| | 5929 | // auto entry = g->generic_table.maybe_get(generic_fn_type_id); |
| | 5930 | // if (entry) { |
| | 5931 | // AstNode *impl_decl_node = entry->value; |
| | 5932 | // assert(impl_decl_node->type == NodeTypeContainerDecl); |
| | 5933 | // TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; |
| | 5934 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); |
| | 5935 | // } |
| | 5936 | // |
| | 5937 | // // make a type from the generic parameters supplied |
| | 5938 | // assert(decl_node->type == NodeTypeContainerDecl); |
| | 5939 | // AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index); |
| | 5940 | // g->generic_table.put(generic_fn_type_id, impl_decl_node); |
| | 5941 | // scan_struct_decl(g, import, child_context, impl_decl_node); |
| | 5942 | // TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; |
| | 5943 | // resolve_struct_type(g, import, type_entry); |
| | 5944 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); |
| | 5945 | //} |
| | 5946 | // |
| | 5947 | //static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 5948 | // TypeTableEntry *expected_type, AstNode *node) |
| | 5949 | //{ |
| | 5950 | // AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| | 5951 | // |
| | 5952 | // if (node->data.fn_call_expr.is_builtin) { |
| | 5953 | // zig_panic("moved builtin fn call code to ir.cpp"); |
| | 5954 | // } |
| | 5955 | // |
| | 5956 | // TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); |
| | 5957 | // if (invoke_type_entry->id == TypeTableEntryIdInvalid) { |
| | 5958 | // return g->builtin_types.entry_invalid; |
| | 5959 | // } |
| | 5960 | // |
| | 5961 | // // use constant expression evaluator to figure out the function at compile time. |
| | 5962 | // // otherwise we treat this as a function pointer. |
| | 5963 | // ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val; |
| | 5964 | // |
| | 5965 | // if (const_val->ok) { |
| | 5966 | // if (invoke_type_entry->id == TypeTableEntryIdMetaType) { |
| | 5967 | // zig_unreachable(); |
| | 5968 | // } else if (invoke_type_entry->id == TypeTableEntryIdFn) { |
| | 5969 | // AstNode *struct_node; |
| | 5970 | // if (fn_ref_expr->type == NodeTypeFieldAccessExpr && |
| | 5971 | // fn_ref_expr->data.field_access_expr.is_member_fn) |
| | 5972 | // { |
| | 5973 | // struct_node = fn_ref_expr->data.field_access_expr.struct_expr; |
| | 5974 | // } else { |
| | 5975 | // struct_node = nullptr; |
| | 5976 | // } |
| | 5977 | // |
| | 5978 | // FnTableEntry *fn_table_entry = const_val->data.x_fn; |
| | 5979 | // node->data.fn_call_expr.fn_entry = fn_table_entry; |
| | 5980 | // return analyze_fn_call_ptr(g, import, context, expected_type, node, |
| | 5981 | // fn_table_entry->type_entry, struct_node); |
| | 5982 | // } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) { |
| | 5983 | // TypeTableEntry *generic_fn_type = const_val->data.x_type; |
| | 5984 | // AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node; |
| | 5985 | // if (decl_node->type == NodeTypeFnProto) { |
| | 5986 | // AstNode *struct_node; |
| | 5987 | // if (fn_ref_expr->type == NodeTypeFieldAccessExpr && |
| | 5988 | // fn_ref_expr->data.field_access_expr.is_member_fn) |
| | 5989 | // { |
| | 5990 | // struct_node = fn_ref_expr->data.field_access_expr.struct_expr; |
| | 5991 | // } else { |
| | 5992 | // struct_node = nullptr; |
| | 5993 | // } |
| | 5994 | // |
| | 5995 | // FnTableEntry *fn_table_entry = decl_node->data.fn_proto.fn_table_entry; |
| | 5996 | // if (fn_table_entry->proto_node->data.fn_proto.skip) { |
| | 5997 | // return g->builtin_types.entry_invalid; |
| | 5998 | // } |
| | 5999 | // return analyze_fn_call_with_inline_args(g, import, context, expected_type, node, |
| | 6000 | // fn_table_entry, struct_node); |
| | 6001 | // } else { |
| | 6002 | // return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type); |
| | 6003 | // } |
| | 6004 | // } else { |
| | 6005 | // add_node_error(g, fn_ref_expr, |
| | 6006 | // buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); |
| | 6007 | // return g->builtin_types.entry_invalid; |
| | 6008 | // } |
| | 6009 | // } |
| | 6010 | // |
| | 6011 | // // function pointer |
| | 6012 | // if (invoke_type_entry->id == TypeTableEntryIdFn) { |
| | 6013 | // return analyze_fn_call_ptr(g, import, context, expected_type, node, invoke_type_entry, nullptr); |
| | 6014 | // } else { |
| | 6015 | // add_node_error(g, fn_ref_expr, |
| | 6016 | // buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); |
| | 6017 | // return g->builtin_types.entry_invalid; |
| | 6018 | // } |
| | 6019 | //} |
| | 6020 | //static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6021 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6022 | //{ |
| | 6023 | // AstNode **expr_node = &node->data.switch_expr.expr; |
| | 6024 | // TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); |
| | 6025 | // ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val; |
| | 6026 | // if (expr_val->ok && !expr_val->depends_on_compile_var) { |
| | 6027 | // add_node_error(g, first_executing_node(*expr_node), |
| | 6028 | // buf_sprintf("value is constant; unnecessary switch statement")); |
| | 6029 | // } |
| | 6030 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 6031 | // |
| | 6032 | // |
| | 6033 | // size_t prong_count = node->data.switch_expr.prongs.length; |
| | 6034 | // AstNode **peer_nodes = allocate<AstNode*>(prong_count); |
| | 6035 | // TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count); |
| | 6036 | // |
| | 6037 | // bool any_errors = false; |
| | 6038 | // if (expr_type->id == TypeTableEntryIdInvalid) { |
| | 6039 | // return expr_type; |
| | 6040 | // } else if (expr_type->id == TypeTableEntryIdUnreachable) { |
| | 6041 | // add_node_error(g, first_executing_node(*expr_node), |
| | 6042 | // buf_sprintf("switch on unreachable expression not allowed")); |
| | 6043 | // return g->builtin_types.entry_invalid; |
| | 6044 | // } |
| | 6045 | // |
| | 6046 | // |
| | 6047 | // size_t *field_use_counts = nullptr; |
| | 6048 | // HashMap<int, AstNode *, int_hash, int_eq> err_use_nodes = {}; |
| | 6049 | // if (expr_type->id == TypeTableEntryIdEnum) { |
| | 6050 | // field_use_counts = allocate<size_t>(expr_type->data.enumeration.src_field_count); |
| | 6051 | // } else if (expr_type->id == TypeTableEntryIdErrorUnion) { |
| | 6052 | // err_use_nodes.init(10); |
| | 6053 | // } |
| | 6054 | // |
| | 6055 | // size_t *const_chosen_prong_index = &node->data.switch_expr.const_chosen_prong_index; |
| | 6056 | // *const_chosen_prong_index = SIZE_MAX; |
| | 6057 | // AstNode *else_prong = nullptr; |
| | 6058 | // for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| | 6059 | // AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| | 6060 | // |
| | 6061 | // TypeTableEntry *var_type; |
| | 6062 | // bool var_is_target_expr; |
| | 6063 | // if (prong_node->data.switch_prong.items.length == 0) { |
| | 6064 | // if (else_prong) { |
| | 6065 | // add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression")); |
| | 6066 | // any_errors = true; |
| | 6067 | // } else { |
| | 6068 | // else_prong = prong_node; |
| | 6069 | // } |
| | 6070 | // var_type = expr_type; |
| | 6071 | // var_is_target_expr = true; |
| | 6072 | // if (*const_chosen_prong_index == SIZE_MAX && expr_val->ok) { |
| | 6073 | // *const_chosen_prong_index = prong_i; |
| | 6074 | // } |
| | 6075 | // } else { |
| | 6076 | // bool all_agree_on_var_type = true; |
| | 6077 | // var_type = nullptr; |
| | 6078 | // |
| | 6079 | // for (size_t item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) { |
| | 6080 | // AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); |
| | 6081 | // if (item_node->type == NodeTypeSwitchRange) { |
| | 6082 | // zig_panic("TODO range in switch statement"); |
| | 6083 | // } |
| | 6084 | // |
| | 6085 | // if (expr_type->id == TypeTableEntryIdEnum) { |
| | 6086 | // if (item_node->type == NodeTypeSymbol) { |
| | 6087 | // Buf *field_name = item_node->data.symbol_expr.symbol; |
| | 6088 | // TypeEnumField *type_enum_field = find_enum_type_field(expr_type, field_name); |
| | 6089 | // if (type_enum_field) { |
| | 6090 | // item_node->data.symbol_expr.enum_field = type_enum_field; |
| | 6091 | // if (!var_type) { |
| | 6092 | // var_type = type_enum_field->type_entry; |
| | 6093 | // } |
| | 6094 | // if (type_enum_field->type_entry != var_type) { |
| | 6095 | // all_agree_on_var_type = false; |
| | 6096 | // } |
| | 6097 | // uint32_t field_index = type_enum_field->value; |
| | 6098 | // assert(field_use_counts); |
| | 6099 | // field_use_counts[field_index] += 1; |
| | 6100 | // if (field_use_counts[field_index] > 1) { |
| | 6101 | // add_node_error(g, item_node, |
| | 6102 | // buf_sprintf("duplicate switch value: '%s'", |
| | 6103 | // buf_ptr(type_enum_field->name))); |
| | 6104 | // any_errors = true; |
| | 6105 | // } |
| | 6106 | // if (!any_errors && expr_val->ok) { |
| | 6107 | // if (expr_val->data.x_enum.tag == type_enum_field->value) { |
| | 6108 | // *const_chosen_prong_index = prong_i; |
| | 6109 | // } |
| | 6110 | // } |
| | 6111 | // } else { |
| | 6112 | // add_node_error(g, item_node, |
| | 6113 | // buf_sprintf("enum '%s' has no field '%s'", |
| | 6114 | // buf_ptr(&expr_type->name), buf_ptr(field_name))); |
| | 6115 | // any_errors = true; |
| | 6116 | // } |
| | 6117 | // } else { |
| | 6118 | // add_node_error(g, item_node, buf_sprintf("expected enum tag name")); |
| | 6119 | // any_errors = true; |
| | 6120 | // } |
| | 6121 | // } else if (expr_type->id == TypeTableEntryIdErrorUnion) { |
| | 6122 | // if (item_node->type == NodeTypeSymbol) { |
| | 6123 | // Buf *err_name = item_node->data.symbol_expr.symbol; |
| | 6124 | // bool is_ok_case = buf_eql_str(err_name, "Ok"); |
| | 6125 | // auto err_table_entry = is_ok_case ? nullptr: g->error_table.maybe_get(err_name); |
| | 6126 | // if (is_ok_case || err_table_entry) { |
| | 6127 | // uint32_t err_value = is_ok_case ? 0 : err_table_entry->value->value; |
| | 6128 | // item_node->data.symbol_expr.err_value = err_value; |
| | 6129 | // TypeTableEntry *this_var_type; |
| | 6130 | // if (is_ok_case) { |
| | 6131 | // this_var_type = expr_type->data.error.child_type; |
| | 6132 | // } else { |
| | 6133 | // this_var_type = g->builtin_types.entry_pure_error; |
| | 6134 | // } |
| | 6135 | // if (!var_type) { |
| | 6136 | // var_type = this_var_type; |
| | 6137 | // } |
| | 6138 | // if (this_var_type != var_type) { |
| | 6139 | // all_agree_on_var_type = false; |
| | 6140 | // } |
| | 6141 | // |
| | 6142 | // // detect duplicate switch values |
| | 6143 | // auto existing_entry = err_use_nodes.maybe_get(err_value); |
| | 6144 | // if (existing_entry) { |
| | 6145 | // add_node_error(g, existing_entry->value, |
| | 6146 | // buf_sprintf("duplicate switch value: '%s'", buf_ptr(err_name))); |
| | 6147 | // any_errors = true; |
| | 6148 | // } else { |
| | 6149 | // err_use_nodes.put(err_value, item_node); |
| | 6150 | // } |
| | 6151 | // |
| | 6152 | // if (!any_errors && expr_val->ok) { |
| | 6153 | // if (expr_val->data.x_err.err->value == err_value) { |
| | 6154 | // *const_chosen_prong_index = prong_i; |
| | 6155 | // } |
| | 6156 | // } |
| | 6157 | // } else { |
| | 6158 | // add_node_error(g, item_node, |
| | 6159 | // buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name))); |
| | 6160 | // any_errors = true; |
| | 6161 | // } |
| | 6162 | // } else { |
| | 6163 | // add_node_error(g, item_node, buf_sprintf("expected error value name")); |
| | 6164 | // any_errors = true; |
| | 6165 | // } |
| | 6166 | // } else { |
| | 6167 | // if (!any_errors && expr_val->ok) { |
| | 6168 | // // note: there is now a function in eval.cpp for doing const expr comparison |
| | 6169 | // zig_panic("TODO determine if const exprs are equal"); |
| | 6170 | // } |
| | 6171 | // TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node); |
| | 6172 | // if (item_type->id != TypeTableEntryIdInvalid) { |
| | 6173 | // ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val; |
| | 6174 | // if (!const_val->ok) { |
| | 6175 | // add_node_error(g, item_node, |
| | 6176 | // buf_sprintf("unable to evaluate constant expression")); |
| | 6177 | // any_errors = true; |
| | 6178 | // } |
| | 6179 | // } |
| | 6180 | // } |
| | 6181 | // } |
| | 6182 | // if (!var_type || !all_agree_on_var_type) { |
| | 6183 | // var_type = expr_type; |
| | 6184 | // var_is_target_expr = true; |
| | 6185 | // } else { |
| | 6186 | // var_is_target_expr = false; |
| | 6187 | // } |
| | 6188 | // } |
| | 6189 | // |
| | 6190 | // BlockContext *child_context = new_block_context(node, context); |
| | 6191 | // prong_node->data.switch_prong.block_context = child_context; |
| | 6192 | // AstNode *var_node = prong_node->data.switch_prong.var_symbol; |
| | 6193 | // if (var_node) { |
| | 6194 | // assert(var_node->type == NodeTypeSymbol); |
| | 6195 | // Buf *var_name = var_node->data.symbol_expr.symbol; |
| | 6196 | // var_node->block_context = child_context; |
| | 6197 | // prong_node->data.switch_prong.var = add_local_var(g, var_node, import, |
| | 6198 | // child_context, var_name, var_type, true, nullptr); |
| | 6199 | // prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr; |
| | 6200 | // } |
| | 6201 | // } |
| | 6202 | // |
| | 6203 | // for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| | 6204 | // AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| | 6205 | // BlockContext *child_context = prong_node->data.switch_prong.block_context; |
| | 6206 | // child_context->codegen_excluded = expr_val->ok && (*const_chosen_prong_index != prong_i); |
| | 6207 | // |
| | 6208 | // if (child_context->codegen_excluded) { |
| | 6209 | // peer_types[prong_i] = g->builtin_types.entry_unreachable; |
| | 6210 | // } else { |
| | 6211 | // peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type, |
| | 6212 | // prong_node->data.switch_prong.expr); |
| | 6213 | // } |
| | 6214 | // // This must go after the analyze_expression for |
| | 6215 | // // prong_node->data.switch_prong.expr because of AST rewriting. |
| | 6216 | // peer_nodes[prong_i] = prong_node->data.switch_prong.expr; |
| | 6217 | // } |
| | 6218 | // |
| | 6219 | // if (expr_type->id == TypeTableEntryIdEnum && !else_prong) { |
| | 6220 | // for (uint32_t i = 0; i < expr_type->data.enumeration.src_field_count; i += 1) { |
| | 6221 | // if (field_use_counts[i] == 0) { |
| | 6222 | // add_node_error(g, node, |
| | 6223 | // buf_sprintf("enumeration value '%s' not handled in switch", |
| | 6224 | // buf_ptr(expr_type->data.enumeration.fields[i].name))); |
| | 6225 | // any_errors = true; |
| | 6226 | // } |
| | 6227 | // } |
| | 6228 | // } |
| | 6229 | // |
| | 6230 | // if (any_errors) { |
| | 6231 | // return g->builtin_types.entry_invalid; |
| | 6232 | // } |
| | 6233 | // |
| | 6234 | // if (prong_count == 0) { |
| | 6235 | // add_node_error(g, node, buf_sprintf("switch statement has no prongs")); |
| | 6236 | // return g->builtin_types.entry_invalid; |
| | 6237 | // } |
| | 6238 | // |
| | 6239 | // TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node, |
| | 6240 | // peer_nodes, peer_types, prong_count); |
| | 6241 | // |
| | 6242 | // if (expr_val->ok) { |
| | 6243 | // assert(*const_chosen_prong_index != SIZE_MAX); |
| | 6244 | // |
| | 6245 | // *const_val = get_resolved_expr(peer_nodes[*const_chosen_prong_index])->const_val; |
| | 6246 | // // the target expr depends on a compile var because we have an error on unnecessary |
| | 6247 | // // switch statement, so the entire switch statement does too |
| | 6248 | // const_val->depends_on_compile_var = true; |
| | 6249 | // |
| | 6250 | // if (!const_val->ok) { |
| | 6251 | // return add_error_if_type_is_num_lit(g, result_type, node); |
| | 6252 | // } |
| | 6253 | // } else { |
| | 6254 | // return add_error_if_type_is_num_lit(g, result_type, node); |
| | 6255 | // } |
| | 6256 | // |
| | 6257 | // return result_type; |
| | 6258 | //} |
| | 6259 | // |
| | 6260 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6261 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6262 | //{ |
| | 6263 | // if (!node->data.return_expr.expr) { |
| | 6264 | // node->data.return_expr.expr = create_ast_void_node(g, import, node); |
| | 6265 | // normalize_parent_ptrs(node); |
| | 6266 | // } |
| | 6267 | // |
| | 6268 | // TypeTableEntry *expected_return_type = get_return_type(context); |
| | 6269 | // |
| | 6270 | // switch (node->data.return_expr.kind) { |
| | 6271 | // case ReturnKindUnconditional: |
| | 6272 | // zig_panic("TODO moved to ir.cpp"); |
| | 6273 | // case ReturnKindError: |
| | 6274 | // { |
| | 6275 | // TypeTableEntry *expected_err_type; |
| | 6276 | // if (expected_type) { |
| | 6277 | // expected_err_type = get_error_type(g, expected_type); |
| | 6278 | // } else { |
| | 6279 | // expected_err_type = nullptr; |
| | 6280 | // } |
| | 6281 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_err_type, |
| | 6282 | // node->data.return_expr.expr); |
| | 6283 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 6284 | // return resolved_type; |
| | 6285 | // } else if (resolved_type->id == TypeTableEntryIdErrorUnion) { |
| | 6286 | // if (expected_return_type->id != TypeTableEntryIdErrorUnion && |
| | 6287 | // expected_return_type->id != TypeTableEntryIdPureError) |
| | 6288 | // { |
| | 6289 | // ErrorMsg *msg = add_node_error(g, node, |
| | 6290 | // buf_sprintf("%%return statement in function with return type '%s'", |
| | 6291 | // buf_ptr(&expected_return_type->name))); |
| | 6292 | // AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type; |
| | 6293 | // add_error_note(g, msg, return_type_node, buf_sprintf("function return type here")); |
| | 6294 | // } |
| | 6295 | // |
| | 6296 | // return resolved_type->data.error.child_type; |
| | 6297 | // } else { |
| | 6298 | // add_node_error(g, node->data.return_expr.expr, |
| | 6299 | // buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name))); |
| | 6300 | // return g->builtin_types.entry_invalid; |
| | 6301 | // } |
| | 6302 | // } |
| | 6303 | // case ReturnKindMaybe: |
| | 6304 | // { |
| | 6305 | // TypeTableEntry *expected_maybe_type; |
| | 6306 | // if (expected_type) { |
| | 6307 | // expected_maybe_type = get_maybe_type(g, expected_type); |
| | 6308 | // } else { |
| | 6309 | // expected_maybe_type = nullptr; |
| | 6310 | // } |
| | 6311 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_maybe_type, |
| | 6312 | // node->data.return_expr.expr); |
| | 6313 | // if (resolved_type->id == TypeTableEntryIdInvalid) { |
| | 6314 | // return resolved_type; |
| | 6315 | // } else if (resolved_type->id == TypeTableEntryIdMaybe) { |
| | 6316 | // if (expected_return_type->id != TypeTableEntryIdMaybe) { |
| | 6317 | // ErrorMsg *msg = add_node_error(g, node, |
| | 6318 | // buf_sprintf("?return statement in function with return type '%s'", |
| | 6319 | // buf_ptr(&expected_return_type->name))); |
| | 6320 | // AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type; |
| | 6321 | // add_error_note(g, msg, return_type_node, buf_sprintf("function return type here")); |
| | 6322 | // } |
| | 6323 | // |
| | 6324 | // return resolved_type->data.maybe.child_type; |
| | 6325 | // } else { |
| | 6326 | // add_node_error(g, node->data.return_expr.expr, |
| | 6327 | // buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name))); |
| | 6328 | // return g->builtin_types.entry_invalid; |
| | 6329 | // } |
| | 6330 | // } |
| | 6331 | // } |
| | 6332 | // zig_unreachable(); |
| | 6333 | //} |
| | 6334 | //static TypeTableEntry *analyze_goto_pass1(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6335 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6336 | //{ |
| | 6337 | // assert(node->type == NodeTypeGoto); |
| | 6338 | // |
| | 6339 | // FnTableEntry *fn_table_entry = context->fn_entry; |
| | 6340 | // assert(fn_table_entry); |
| | 6341 | // |
| | 6342 | // fn_table_entry->goto_list.append(node); |
| | 6343 | // |
| | 6344 | // return g->builtin_types.entry_unreachable; |
| | 6345 | //} |
| | 6346 | // |
| | 6347 | //static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6348 | // AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name, |
| | 6349 | // AstNode *out_node) |
| | 6350 | //{ |
| | 6351 | // assert(field_access_node->type == NodeTypeFieldAccessExpr); |
| | 6352 | // |
| | 6353 | // TypeEnumField *type_enum_field = find_enum_type_field(enum_type, field_name); |
| | 6354 | // if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) { |
| | 6355 | // return g->builtin_types.entry_invalid; |
| | 6356 | // } |
| | 6357 | // |
| | 6358 | // field_access_node->data.field_access_expr.type_enum_field = type_enum_field; |
| | 6359 | // |
| | 6360 | // if (type_enum_field) { |
| | 6361 | // if (value_node) { |
| | 6362 | // AstNode **value_node_ptr = value_node->parent_field; |
| | 6363 | // TypeTableEntry *value_type = analyze_expression(g, import, context, |
| | 6364 | // type_enum_field->type_entry, value_node); |
| | 6365 | // |
| | 6366 | // if (value_type->id == TypeTableEntryIdInvalid) { |
| | 6367 | // return g->builtin_types.entry_invalid; |
| | 6368 | // } |
| | 6369 | // |
| | 6370 | // StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr; |
| | 6371 | // codegen->type_entry = enum_type; |
| | 6372 | // codegen->source_node = field_access_node; |
| | 6373 | // |
| | 6374 | // ConstExprValue *value_const_val = &get_resolved_expr(*value_node_ptr)->const_val; |
| | 6375 | // if (value_const_val->ok) { |
| | 6376 | // ConstExprValue *const_val = &get_resolved_expr(out_node)->const_val; |
| | 6377 | // const_val->ok = true; |
| | 6378 | // const_val->data.x_enum.tag = type_enum_field->value; |
| | 6379 | // const_val->data.x_enum.payload = value_const_val; |
| | 6380 | // } else { |
| | 6381 | // if (context->fn_entry) { |
| | 6382 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); |
| | 6383 | // } else { |
| | 6384 | // add_node_error(g, *value_node_ptr, buf_sprintf("unable to evaluate constant expression")); |
| | 6385 | // return g->builtin_types.entry_invalid; |
| | 6386 | // } |
| | 6387 | // } |
| | 6388 | // } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) { |
| | 6389 | // add_node_error(g, field_access_node, |
| | 6390 | // buf_sprintf("enum value '%s.%s' requires parameter of type '%s'", |
| | 6391 | // buf_ptr(&enum_type->name), |
| | 6392 | // buf_ptr(field_name), |
| | 6393 | // buf_ptr(&type_enum_field->type_entry->name))); |
| | 6394 | // } else { |
| | 6395 | // Expr *expr = get_resolved_expr(out_node); |
| | 6396 | // expr->const_val.ok = true; |
| | 6397 | // expr->const_val.data.x_enum.tag = type_enum_field->value; |
| | 6398 | // expr->const_val.data.x_enum.payload = nullptr; |
| | 6399 | // } |
| | 6400 | // } else { |
| | 6401 | // add_node_error(g, field_access_node, |
| | 6402 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| | 6403 | // buf_ptr(&enum_type->name))); |
| | 6404 | // } |
| | 6405 | // return enum_type; |
| | 6406 | //} |
| | 6407 | // |
| | 6408 | //static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g, |
| | 6409 | // TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| | 6410 | //{ |
| | 6411 | // assert(node->type == NodeTypeFieldAccessExpr); |
| | 6412 | // if (!is_slice(bare_struct_type)) { |
| | 6413 | // BlockContext *container_block_context = get_container_block_context(bare_struct_type); |
| | 6414 | // assert(container_block_context); |
| | 6415 | // auto entry = container_block_context->decl_table.maybe_get(field_name); |
| | 6416 | // AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| | 6417 | // if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| | 6418 | // resolve_top_level_decl(g, fn_decl_node, false); |
| | 6419 | // TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node); |
| | 6420 | // if (tld->resolution == TldResolutionInvalid) { |
| | 6421 | // return g->builtin_types.entry_invalid; |
| | 6422 | // } |
| | 6423 | // |
| | 6424 | // node->data.field_access_expr.is_member_fn = true; |
| | 6425 | // FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry; |
| | 6426 | // if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { |
| | 6427 | // return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false); |
| | 6428 | // } else { |
| | 6429 | // return resolve_expr_const_val_as_fn(g, node, fn_entry, false); |
| | 6430 | // } |
| | 6431 | // } |
| | 6432 | // } |
| | 6433 | // add_node_error(g, node, |
| | 6434 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| | 6435 | // return g->builtin_types.entry_invalid; |
| | 6436 | //} |
| | 6437 | // |
| | 6438 | //static TypeTableEntry *analyze_container_member_access(CodeGen *g, |
| | 6439 | // Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| | 6440 | //{ |
| | 6441 | // TypeTableEntry *bare_type = container_ref_type(struct_type); |
| | 6442 | // if (!type_is_complete(bare_type)) { |
| | 6443 | // resolve_container_type(g, bare_type); |
| | 6444 | // } |
| | 6445 | // |
| | 6446 | // node->data.field_access_expr.bare_container_type = bare_type; |
| | 6447 | // |
| | 6448 | // if (bare_type->id == TypeTableEntryIdStruct) { |
| | 6449 | // node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name); |
| | 6450 | // if (node->data.field_access_expr.type_struct_field) { |
| | 6451 | // return node->data.field_access_expr.type_struct_field->type_entry; |
| | 6452 | // } else { |
| | 6453 | // return analyze_container_member_access_inner(g, bare_type, field_name, |
| | 6454 | // node, struct_type); |
| | 6455 | // } |
| | 6456 | // } else if (bare_type->id == TypeTableEntryIdEnum) { |
| | 6457 | // node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name); |
| | 6458 | // if (node->data.field_access_expr.type_enum_field) { |
| | 6459 | // return node->data.field_access_expr.type_enum_field->type_entry; |
| | 6460 | // } else { |
| | 6461 | // return analyze_container_member_access_inner(g, bare_type, field_name, |
| | 6462 | // node, struct_type); |
| | 6463 | // } |
| | 6464 | // } else if (bare_type->id == TypeTableEntryIdUnion) { |
| | 6465 | // zig_panic("TODO"); |
| | 6466 | // } else { |
| | 6467 | // zig_unreachable(); |
| | 6468 | // } |
| | 6469 | //} |
| | 6470 | // |
| | 6471 | //static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6472 | // AstNode *node) |
| | 6473 | //{ |
| | 6474 | // assert(node->type == NodeTypeSliceExpr); |
| | 6475 | // |
| | 6476 | // TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, |
| | 6477 | // node->data.slice_expr.array_ref_expr); |
| | 6478 | // |
| | 6479 | // TypeTableEntry *return_type; |
| | 6480 | // |
| | 6481 | // if (array_type->id == TypeTableEntryIdInvalid) { |
| | 6482 | // return_type = g->builtin_types.entry_invalid; |
| | 6483 | // } else if (array_type->id == TypeTableEntryIdArray) { |
| | 6484 | // return_type = get_slice_type(g, array_type->data.array.child_type, |
| | 6485 | // node->data.slice_expr.is_const); |
| | 6486 | // } else if (array_type->id == TypeTableEntryIdPointer) { |
| | 6487 | // return_type = get_slice_type(g, array_type->data.pointer.child_type, |
| | 6488 | // node->data.slice_expr.is_const); |
| | 6489 | // } else if (array_type->id == TypeTableEntryIdStruct && |
| | 6490 | // array_type->data.structure.is_slice) |
| | 6491 | // { |
| | 6492 | // return_type = get_slice_type(g, |
| | 6493 | // array_type->data.structure.fields[0].type_entry->data.pointer.child_type, |
| | 6494 | // node->data.slice_expr.is_const); |
| | 6495 | // } else { |
| | 6496 | // add_node_error(g, node, |
| | 6497 | // buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); |
| | 6498 | // return_type = g->builtin_types.entry_invalid; |
| | 6499 | // } |
| | 6500 | // |
| | 6501 | // if (return_type->id != TypeTableEntryIdInvalid) { |
| | 6502 | // node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type; |
| | 6503 | // node->data.slice_expr.resolved_struct_val_expr.source_node = node; |
| | 6504 | // context->fn_entry->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr); |
| | 6505 | // } |
| | 6506 | // |
| | 6507 | // analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start); |
| | 6508 | // |
| | 6509 | // if (node->data.slice_expr.end) { |
| | 6510 | // analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.end); |
| | 6511 | // } |
| | 6512 | // |
| | 6513 | // return return_type; |
| | 6514 | //} |
| | 6515 | // |
| | 6516 | //static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6517 | // AstNode *node, LValPurpose purpose) |
| | 6518 | //{ |
| | 6519 | // TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, |
| | 6520 | // node->data.array_access_expr.array_ref_expr); |
| | 6521 | // |
| | 6522 | // TypeTableEntry *return_type; |
| | 6523 | // |
| | 6524 | // if (array_type->id == TypeTableEntryIdInvalid) { |
| | 6525 | // return_type = g->builtin_types.entry_invalid; |
| | 6526 | // } else if (array_type->id == TypeTableEntryIdArray) { |
| | 6527 | // if (array_type->data.array.len == 0) { |
| | 6528 | // add_node_error(g, node, buf_sprintf("out of bounds array access")); |
| | 6529 | // } |
| | 6530 | // return_type = array_type->data.array.child_type; |
| | 6531 | // } else if (array_type->id == TypeTableEntryIdPointer) { |
| | 6532 | // if (array_type->data.pointer.is_const && purpose == LValPurposeAssign) { |
| | 6533 | // add_node_error(g, node, buf_sprintf("cannot assign to constant")); |
| | 6534 | // return g->builtin_types.entry_invalid; |
| | 6535 | // } |
| | 6536 | // return_type = array_type->data.pointer.child_type; |
| | 6537 | // } else if (array_type->id == TypeTableEntryIdStruct && |
| | 6538 | // array_type->data.structure.is_slice) |
| | 6539 | // { |
| | 6540 | // TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry; |
| | 6541 | // if (pointer_type->data.pointer.is_const && purpose == LValPurposeAssign) { |
| | 6542 | // add_node_error(g, node, buf_sprintf("cannot assign to constant")); |
| | 6543 | // return g->builtin_types.entry_invalid; |
| | 6544 | // } |
| | 6545 | // return_type = pointer_type->data.pointer.child_type; |
| | 6546 | // } else { |
| | 6547 | // add_node_error(g, node, |
| | 6548 | // buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); |
| | 6549 | // return_type = g->builtin_types.entry_invalid; |
| | 6550 | // } |
| | 6551 | // |
| | 6552 | // analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.array_access_expr.subscript); |
| | 6553 | // |
| | 6554 | // return return_type; |
| | 6555 | //} |
| | 6556 | // |
| | 6557 | //static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6558 | // AstNode *node) |
| | 6559 | //{ |
| | 6560 | // assert(node->type == NodeTypeBinOpExpr); |
| | 6561 | // BinOpType bin_op_type = node->data.bin_op_expr.bin_op; |
| | 6562 | // |
| | 6563 | // AstNode *op1 = node->data.bin_op_expr.op1; |
| | 6564 | // AstNode *op2 = node->data.bin_op_expr.op2; |
| | 6565 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op1); |
| | 6566 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op2); |
| | 6567 | // |
| | 6568 | // if (op1_type->id == TypeTableEntryIdInvalid || |
| | 6569 | // op2_type->id == TypeTableEntryIdInvalid) |
| | 6570 | // { |
| | 6571 | // return g->builtin_types.entry_invalid; |
| | 6572 | // } |
| | 6573 | // |
| | 6574 | // ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val; |
| | 6575 | // ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val; |
| | 6576 | // if (!op1_val->ok || !op2_val->ok) { |
| | 6577 | // return g->builtin_types.entry_bool; |
| | 6578 | // } |
| | 6579 | // |
| | 6580 | // ConstExprValue *out_val = &get_resolved_expr(node)->const_val; |
| | 6581 | // eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val); |
| | 6582 | // return g->builtin_types.entry_bool; |
| | 6583 | //} |
| | 6584 | // |
| | 6585 | //static TypeTableEntry *analyze_array_mult(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6586 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6587 | //{ |
| | 6588 | // assert(node->type == NodeTypeBinOpExpr); |
| | 6589 | // assert(node->data.bin_op_expr.bin_op == BinOpTypeArrayMult); |
| | 6590 | // |
| | 6591 | // AstNode **op1 = node->data.bin_op_expr.op1->parent_field; |
| | 6592 | // AstNode **op2 = node->data.bin_op_expr.op2->parent_field; |
| | 6593 | // |
| | 6594 | // TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); |
| | 6595 | // TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); |
| | 6596 | // |
| | 6597 | // if (op1_type->id == TypeTableEntryIdInvalid || |
| | 6598 | // op2_type->id == TypeTableEntryIdInvalid) |
| | 6599 | // { |
| | 6600 | // return g->builtin_types.entry_invalid; |
| | 6601 | // } |
| | 6602 | // |
| | 6603 | // ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val; |
| | 6604 | // ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val; |
| | 6605 | // |
| | 6606 | // AstNode *bad_node; |
| | 6607 | // if (!op1_val->ok) { |
| | 6608 | // bad_node = *op1; |
| | 6609 | // } else if (!op2_val->ok) { |
| | 6610 | // bad_node = *op2; |
| | 6611 | // } else { |
| | 6612 | // bad_node = nullptr; |
| | 6613 | // } |
| | 6614 | // if (bad_node) { |
| | 6615 | // add_node_error(g, bad_node, buf_sprintf("array multiplication requires constant expression")); |
| | 6616 | // return g->builtin_types.entry_invalid; |
| | 6617 | // } |
| | 6618 | // |
| | 6619 | // if (op1_type->id != TypeTableEntryIdArray) { |
| | 6620 | // add_node_error(g, *op1, |
| | 6621 | // buf_sprintf("expected array type, got '%s'", buf_ptr(&op1_type->name))); |
| | 6622 | // return g->builtin_types.entry_invalid; |
| | 6623 | // } |
| | 6624 | // |
| | 6625 | // if (op2_type->id != TypeTableEntryIdNumLitInt && |
| | 6626 | // op2_type->id != TypeTableEntryIdInt) |
| | 6627 | // { |
| | 6628 | // add_node_error(g, *op2, buf_sprintf("expected integer type, got '%s'", buf_ptr(&op2_type->name))); |
| | 6629 | // return g->builtin_types.entry_invalid; |
| | 6630 | // } |
| | 6631 | // |
| | 6632 | // if (op2_val->data.x_bignum.is_negative) { |
| | 6633 | // add_node_error(g, *op2, buf_sprintf("expected positive number")); |
| | 6634 | // return g->builtin_types.entry_invalid; |
| | 6635 | // } |
| | 6636 | // |
| | 6637 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 6638 | // const_val->ok = true; |
| | 6639 | // const_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| | 6640 | // |
| | 6641 | // TypeTableEntry *child_type = op1_type->data.array.child_type; |
| | 6642 | // BigNum old_array_len; |
| | 6643 | // bignum_init_unsigned(&old_array_len, op1_type->data.array.len); |
| | 6644 | // |
| | 6645 | // BigNum new_array_len; |
| | 6646 | // if (bignum_mul(&new_array_len, &old_array_len, &op2_val->data.x_bignum)) { |
| | 6647 | // add_node_error(g, node, buf_sprintf("operation results in overflow")); |
| | 6648 | // return g->builtin_types.entry_invalid; |
| | 6649 | // } |
| | 6650 | // |
| | 6651 | // uint64_t old_array_len_bare = op1_type->data.array.len; |
| | 6652 | // uint64_t operand_amt = op2_val->data.x_bignum.data.x_uint; |
| | 6653 | // |
| | 6654 | // uint64_t new_array_len_bare = new_array_len.data.x_uint; |
| | 6655 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(new_array_len_bare); |
| | 6656 | // |
| | 6657 | // uint64_t i = 0; |
| | 6658 | // for (uint64_t x = 0; x < operand_amt; x += 1) { |
| | 6659 | // for (uint64_t y = 0; y < old_array_len_bare; y += 1) { |
| | 6660 | // const_val->data.x_array.fields[i] = op1_val->data.x_array.fields[y]; |
| | 6661 | // i += 1; |
| | 6662 | // } |
| | 6663 | // } |
| | 6664 | // |
| | 6665 | // return get_array_type(g, child_type, new_array_len_bare); |
| | 6666 | //} |
| | 6667 | // |
| | 6668 | //static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import, |
| | 6669 | // BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node) |
| | 6670 | //{ |
| | 6671 | // AstNode *op1 = node->data.unwrap_err_expr.op1; |
| | 6672 | // AstNode *op2 = node->data.unwrap_err_expr.op2; |
| | 6673 | // AstNode *var_node = node->data.unwrap_err_expr.symbol; |
| | 6674 | // |
| | 6675 | // TypeTableEntry *lhs_type = analyze_expression(g, import, parent_context, nullptr, op1); |
| | 6676 | // if (lhs_type->id == TypeTableEntryIdInvalid) { |
| | 6677 | // return lhs_type; |
| | 6678 | // } else if (lhs_type->id == TypeTableEntryIdErrorUnion) { |
| | 6679 | // TypeTableEntry *child_type = lhs_type->data.error.child_type; |
| | 6680 | // BlockContext *child_context; |
| | 6681 | // if (var_node) { |
| | 6682 | // child_context = new_block_context(node, parent_context); |
| | 6683 | // var_node->block_context = child_context; |
| | 6684 | // Buf *var_name = var_node->data.symbol_expr.symbol; |
| | 6685 | // node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name, |
| | 6686 | // g->builtin_types.entry_pure_error, true, nullptr); |
| | 6687 | // } else { |
| | 6688 | // child_context = parent_context; |
| | 6689 | // } |
| | 6690 | // |
| | 6691 | // analyze_expression(g, import, child_context, child_type, op2); |
| | 6692 | // return child_type; |
| | 6693 | // } else { |
| | 6694 | // add_node_error(g, op1, |
| | 6695 | // buf_sprintf("expected error type, got '%s'", buf_ptr(&lhs_type->name))); |
| | 6696 | // return g->builtin_types.entry_invalid; |
| | 6697 | // } |
| | 6698 | //} |
| | 6699 | // |
| | 6700 | // |
| | 6701 | //static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import, |
| | 6702 | // BlockContext *context, AstNode *source_node, |
| | 6703 | // AstNodeVariableDeclaration *variable_declaration, |
| | 6704 | // bool expr_is_maybe, AstNode *decl_node, bool var_is_ptr) |
| | 6705 | //{ |
| | 6706 | // bool is_const = variable_declaration->is_const; |
| | 6707 | // bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport); |
| | 6708 | // bool is_extern = variable_declaration->is_extern; |
| | 6709 | // |
| | 6710 | // TypeTableEntry *explicit_type = nullptr; |
| | 6711 | // if (variable_declaration->type != nullptr) { |
| | 6712 | // explicit_type = analyze_type_expr(g, import, context, variable_declaration->type); |
| | 6713 | // if (explicit_type->id == TypeTableEntryIdUnreachable) { |
| | 6714 | // add_node_error(g, variable_declaration->type, |
| | 6715 | // buf_sprintf("variable of type 'unreachable' not allowed")); |
| | 6716 | // explicit_type = g->builtin_types.entry_invalid; |
| | 6717 | // } |
| | 6718 | // } |
| | 6719 | // |
| | 6720 | // TypeTableEntry *implicit_type = nullptr; |
| | 6721 | // if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) { |
| | 6722 | // implicit_type = explicit_type; |
| | 6723 | // } else if (variable_declaration->expr) { |
| | 6724 | // implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr); |
| | 6725 | // if (implicit_type->id == TypeTableEntryIdInvalid) { |
| | 6726 | // // ignore the poison value |
| | 6727 | // } else if (expr_is_maybe) { |
| | 6728 | // if (implicit_type->id == TypeTableEntryIdMaybe) { |
| | 6729 | // if (var_is_ptr) { |
| | 6730 | // // TODO if the expression is constant, can't get pointer to it |
| | 6731 | // implicit_type = get_pointer_to_type(g, implicit_type->data.maybe.child_type, false); |
| | 6732 | // } else { |
| | 6733 | // implicit_type = implicit_type->data.maybe.child_type; |
| | 6734 | // } |
| | 6735 | // } else { |
| | 6736 | // add_node_error(g, variable_declaration->expr, buf_sprintf("expected maybe type")); |
| | 6737 | // implicit_type = g->builtin_types.entry_invalid; |
| | 6738 | // } |
| | 6739 | // } else if (implicit_type->id == TypeTableEntryIdUnreachable) { |
| | 6740 | // add_node_error(g, source_node, |
| | 6741 | // buf_sprintf("variable initialization is unreachable")); |
| | 6742 | // implicit_type = g->builtin_types.entry_invalid; |
| | 6743 | // } else if ((!is_const || is_export) && |
| | 6744 | // (implicit_type->id == TypeTableEntryIdNumLitFloat || |
| | 6745 | // implicit_type->id == TypeTableEntryIdNumLitInt)) |
| | 6746 | // { |
| | 6747 | // add_node_error(g, source_node, buf_sprintf("unable to infer variable type")); |
| | 6748 | // implicit_type = g->builtin_types.entry_invalid; |
| | 6749 | // } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) { |
| | 6750 | // add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); |
| | 6751 | // implicit_type = g->builtin_types.entry_invalid; |
| | 6752 | // } |
| | 6753 | // if (implicit_type->id != TypeTableEntryIdInvalid && !context->fn_entry) { |
| | 6754 | // ConstExprValue *const_val = &get_resolved_expr(variable_declaration->expr)->const_val; |
| | 6755 | // if (!const_val->ok) { |
| | 6756 | // add_node_error(g, first_executing_node(variable_declaration->expr), |
| | 6757 | // buf_sprintf("global variable initializer requires constant expression")); |
| | 6758 | // } |
| | 6759 | // } |
| | 6760 | // } else if (!is_extern) { |
| | 6761 | // add_node_error(g, source_node, buf_sprintf("variables must be initialized")); |
| | 6762 | // implicit_type = g->builtin_types.entry_invalid; |
| | 6763 | // } |
| | 6764 | // |
| | 6765 | // TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type; |
| | 6766 | // assert(type != nullptr); // should have been caught by the parser |
| | 6767 | // |
| | 6768 | // VariableTableEntry *var = add_local_var(g, source_node, import, context, |
| | 6769 | // variable_declaration->symbol, type, is_const, |
| | 6770 | // expr_is_maybe ? nullptr : variable_declaration->expr); |
| | 6771 | // |
| | 6772 | // variable_declaration->variable = var; |
| | 6773 | // |
| | 6774 | // return var; |
| | 6775 | //} |
| | 6776 | // |
| | 6777 | //static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| | 6778 | // BlockContext *context, TypeTableEntry *expected_type, AstNode *node) |
| | 6779 | //{ |
| | 6780 | // AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; |
| | 6781 | // return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, |
| | 6782 | // false, nullptr, false); |
| | 6783 | //} |
| | 6784 | // |
| | 6785 | //static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6786 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6787 | //{ |
| | 6788 | // AstNode *size_node = node->data.array_type.size; |
| | 6789 | // |
| | 6790 | // TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context, |
| | 6791 | // node->data.array_type.child_type, true); |
| | 6792 | // |
| | 6793 | // if (child_type->id == TypeTableEntryIdUnreachable) { |
| | 6794 | // add_node_error(g, node, buf_create_from_str("array of unreachable not allowed")); |
| | 6795 | // return g->builtin_types.entry_invalid; |
| | 6796 | // } else if (child_type->id == TypeTableEntryIdInvalid) { |
| | 6797 | // return g->builtin_types.entry_invalid; |
| | 6798 | // } |
| | 6799 | // |
| | 6800 | // if (size_node) { |
| | 6801 | // child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); |
| | 6802 | // TypeTableEntry *size_type = analyze_expression(g, import, context, |
| | 6803 | // g->builtin_types.entry_usize, size_node); |
| | 6804 | // if (size_type->id == TypeTableEntryIdInvalid) { |
| | 6805 | // return g->builtin_types.entry_invalid; |
| | 6806 | // } |
| | 6807 | // |
| | 6808 | // ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| | 6809 | // if (const_val->ok) { |
| | 6810 | // if (const_val->data.x_bignum.is_negative) { |
| | 6811 | // add_node_error(g, size_node, |
| | 6812 | // buf_sprintf("array size %s is negative", |
| | 6813 | // buf_ptr(bignum_to_buf(&const_val->data.x_bignum)))); |
| | 6814 | // return g->builtin_types.entry_invalid; |
| | 6815 | // } else { |
| | 6816 | // return resolve_expr_const_val_as_type(g, node, |
| | 6817 | // get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false); |
| | 6818 | // } |
| | 6819 | // } else if (context->fn_entry) { |
| | 6820 | // return resolve_expr_const_val_as_type(g, node, |
| | 6821 | // get_slice_type(g, child_type, node->data.array_type.is_const), false); |
| | 6822 | // } else { |
| | 6823 | // add_node_error(g, first_executing_node(size_node), |
| | 6824 | // buf_sprintf("unable to evaluate constant expression")); |
| | 6825 | // return g->builtin_types.entry_invalid; |
| | 6826 | // } |
| | 6827 | // } else { |
| | 6828 | // TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const); |
| | 6829 | // return resolve_expr_const_val_as_type(g, node, slice_type, false); |
| | 6830 | // } |
| | 6831 | //} |
| | 6832 | // |
| | 6833 | //static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6834 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6835 | //{ |
| | 6836 | // assert(node->type == NodeTypeWhileExpr); |
| | 6837 | // |
| | 6838 | // AstNode **condition_node = &node->data.while_expr.condition; |
| | 6839 | // AstNode *while_body_node = node->data.while_expr.body; |
| | 6840 | // AstNode **continue_expr_node = &node->data.while_expr.continue_expr; |
| | 6841 | // |
| | 6842 | // TypeTableEntry *condition_type = analyze_expression(g, import, context, |
| | 6843 | // g->builtin_types.entry_bool, *condition_node); |
| | 6844 | // |
| | 6845 | // if (*continue_expr_node) { |
| | 6846 | // analyze_expression(g, import, context, g->builtin_types.entry_void, *continue_expr_node); |
| | 6847 | // } |
| | 6848 | // |
| | 6849 | // BlockContext *child_context = new_block_context(node, context); |
| | 6850 | // child_context->parent_loop_node = node; |
| | 6851 | // |
| | 6852 | // analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node); |
| | 6853 | // |
| | 6854 | // |
| | 6855 | // TypeTableEntry *expr_return_type = g->builtin_types.entry_void; |
| | 6856 | // |
| | 6857 | // if (condition_type->id == TypeTableEntryIdInvalid) { |
| | 6858 | // expr_return_type = g->builtin_types.entry_invalid; |
| | 6859 | // } else { |
| | 6860 | // // if the condition is a simple constant expression and there are no break statements |
| | 6861 | // // then the return type is unreachable |
| | 6862 | // ConstExprValue *const_val = &get_resolved_expr(*condition_node)->const_val; |
| | 6863 | // if (const_val->ok) { |
| | 6864 | // if (const_val->data.x_bool) { |
| | 6865 | // node->data.while_expr.condition_always_true = true; |
| | 6866 | // if (!node->data.while_expr.contains_break) { |
| | 6867 | // expr_return_type = g->builtin_types.entry_unreachable; |
| | 6868 | // } |
| | 6869 | // } |
| | 6870 | // } |
| | 6871 | // } |
| | 6872 | // |
| | 6873 | // return expr_return_type; |
| | 6874 | //} |
| | 6875 | // |
| | 6876 | //static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6877 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6878 | //{ |
| | 6879 | // assert(node->type == NodeTypeBreak); |
| | 6880 | // |
| | 6881 | // AstNode *loop_node = context->parent_loop_node; |
| | 6882 | // if (loop_node) { |
| | 6883 | // if (loop_node->type == NodeTypeWhileExpr) { |
| | 6884 | // loop_node->data.while_expr.contains_break = true; |
| | 6885 | // } else if (loop_node->type == NodeTypeForExpr) { |
| | 6886 | // loop_node->data.for_expr.contains_break = true; |
| | 6887 | // } else { |
| | 6888 | // zig_unreachable(); |
| | 6889 | // } |
| | 6890 | // } else { |
| | 6891 | // add_node_error(g, node, buf_sprintf("'break' expression outside loop")); |
| | 6892 | // } |
| | 6893 | // return g->builtin_types.entry_unreachable; |
| | 6894 | //} |
| | 6895 | // |
| | 6896 | //static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6897 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6898 | //{ |
| | 6899 | // AstNode *loop_node = context->parent_loop_node; |
| | 6900 | // if (loop_node) { |
| | 6901 | // if (loop_node->type == NodeTypeWhileExpr) { |
| | 6902 | // loop_node->data.while_expr.contains_continue = true; |
| | 6903 | // } else if (loop_node->type == NodeTypeForExpr) { |
| | 6904 | // loop_node->data.for_expr.contains_continue = true; |
| | 6905 | // } else { |
| | 6906 | // zig_unreachable(); |
| | 6907 | // } |
| | 6908 | // } else { |
| | 6909 | // add_node_error(g, node, buf_sprintf("'continue' expression outside loop")); |
| | 6910 | // } |
| | 6911 | // return g->builtin_types.entry_unreachable; |
| | 6912 | //} |
| | 6913 | // |
| | 6914 | //static TypeTableEntry *analyze_defer(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| | 6915 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6916 | //{ |
| | 6917 | // if (!parent_context->fn_entry) { |
| | 6918 | // add_node_error(g, node, buf_sprintf("defer expression outside function definition")); |
| | 6919 | // return g->builtin_types.entry_invalid; |
| | 6920 | // } |
| | 6921 | // |
| | 6922 | // if (!node->data.defer.expr) { |
| | 6923 | // add_node_error(g, node, buf_sprintf("defer expects an expression")); |
| | 6924 | // return g->builtin_types.entry_void; |
| | 6925 | // } |
| | 6926 | // |
| | 6927 | // node->data.defer.child_block = new_block_context(node, parent_context); |
| | 6928 | // |
| | 6929 | // TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr, |
| | 6930 | // node->data.defer.expr); |
| | 6931 | // validate_voided_expr(g, node->data.defer.expr, resolved_type); |
| | 6932 | // |
| | 6933 | // return g->builtin_types.entry_void; |
| | 6934 | //} |
| | 6935 | // |
| | 6936 | //static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 6937 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6938 | //{ |
| | 6939 | // if (node->data.string_literal.c) { |
| | 6940 | // return resolve_expr_const_val_as_c_string_lit(g, node, node->data.string_literal.buf); |
| | 6941 | // } else { |
| | 6942 | // return resolve_expr_const_val_as_string_lit(g, node, node->data.string_literal.buf); |
| | 6943 | // } |
| | 6944 | //} |
| | 6945 | // |
| | 6946 | //static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, |
| | 6947 | // TypeTableEntry *expected_type, AstNode *node) |
| | 6948 | //{ |
| | 6949 | // BlockContext *child_context = new_block_context(node, parent_context); |
| | 6950 | // node->data.block.child_block = child_context; |
| | 6951 | // TypeTableEntry *return_type = g->builtin_types.entry_void; |
| | 6952 | // |
| | 6953 | // for (size_t i = 0; i < node->data.block.statements.length; i += 1) { |
| | 6954 | // AstNode *child = node->data.block.statements.at(i); |
| | 6955 | // if (child->type == NodeTypeLabel) { |
| | 6956 | // FnTableEntry *fn_table_entry = child_context->fn_entry; |
| | 6957 | // assert(fn_table_entry); |
| | 6958 | // |
| | 6959 | // LabelTableEntry *label = allocate<LabelTableEntry>(1); |
| | 6960 | // label->decl_node = child; |
| | 6961 | // label->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable); |
| | 6962 | // |
| | 6963 | // child->block_context = child_context; |
| | 6964 | // child->data.label.label_entry = label; |
| | 6965 | // fn_table_entry->all_labels.append(label); |
| | 6966 | // |
| | 6967 | // child_context->label_table.put(child->data.label.name, label); |
| | 6968 | // |
| | 6969 | // return_type = g->builtin_types.entry_void; |
| | 6970 | // continue; |
| | 6971 | // } |
| | 6972 | // if (return_type->id == TypeTableEntryIdUnreachable) { |
| | 6973 | // if (is_node_void_expr(child)) { |
| | 6974 | // // {unreachable;void;void} is allowed. |
| | 6975 | // // ignore void statements once we enter unreachable land. |
| | 6976 | // analyze_expression(g, import, child_context, g->builtin_types.entry_void, child); |
| | 6977 | // continue; |
| | 6978 | // } |
| | 6979 | // add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code")); |
| | 6980 | // break; |
| | 6981 | // } |
| | 6982 | // bool is_last = (i == node->data.block.statements.length - 1); |
| | 6983 | // TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr; |
| | 6984 | // return_type = analyze_expression(g, import, child_context, passed_expected_type, child); |
| | 6985 | // if (child->type == NodeTypeDefer && return_type->id != TypeTableEntryIdInvalid) { |
| | 6986 | // // defer starts a new block context |
| | 6987 | // child_context = child->data.defer.child_block; |
| | 6988 | // assert(child_context); |
| | 6989 | // } |
| | 6990 | // if (!is_last) { |
| | 6991 | // validate_voided_expr(g, child, return_type); |
| | 6992 | // } |
| | 6993 | // } |
| | 6994 | // node->data.block.nested_block = child_context; |
| | 6995 | // |
| | 6996 | // ConstExprValue *const_val = &node->data.block.resolved_expr.const_val; |
| | 6997 | // if (node->data.block.statements.length == 0) { |
| | 6998 | // const_val->ok = true; |
| | 6999 | // } else if (node->data.block.statements.length == 1) { |
| | 7000 | // AstNode *only_node = node->data.block.statements.at(0); |
| | 7001 | // ConstExprValue *other_const_val = &get_resolved_expr(only_node)->const_val; |
| | 7002 | // if (other_const_val->ok) { |
| | 7003 | // *const_val = *other_const_val; |
| | 7004 | // } |
| | 7005 | // } |
| | 7006 | // |
| | 7007 | // return return_type; |
| | 7008 | //} |
| | 7009 | // |
| | 7010 | //static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 7011 | // TypeTableEntry *expected_type, AstNode *node) |
| | 7012 | //{ |
| | 7013 | // mark_impure_fn(g, context, node); |
| | 7014 | // |
| | 7015 | // node->data.asm_expr.return_count = 0; |
| | 7016 | // TypeTableEntry *return_type = g->builtin_types.entry_void; |
| | 7017 | // for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1) { |
| | 7018 | // AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| | 7019 | // if (asm_output->return_type) { |
| | 7020 | // node->data.asm_expr.return_count += 1; |
| | 7021 | // return_type = analyze_type_expr(g, import, context, asm_output->return_type); |
| | 7022 | // if (node->data.asm_expr.return_count > 1) { |
| | 7023 | // add_node_error(g, node, |
| | 7024 | // buf_sprintf("inline assembly allows up to one output value")); |
| | 7025 | // break; |
| | 7026 | // } |
| | 7027 | // } else { |
| | 7028 | // Buf *variable_name = asm_output->variable_name; |
| | 7029 | // VariableTableEntry *var = find_variable(g, context, variable_name); |
| | 7030 | // if (var) { |
| | 7031 | // asm_output->variable = var; |
| | 7032 | // return var->type; |
| | 7033 | // } else { |
| | 7034 | // add_node_error(g, node, |
| | 7035 | // buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| | 7036 | // return g->builtin_types.entry_invalid; |
| | 7037 | // } |
| | 7038 | // } |
| | 7039 | // } |
| | 7040 | // for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) { |
| | 7041 | // AsmInput *asm_input = node->data.asm_expr.input_list.at(i); |
| | 7042 | // analyze_expression(g, import, context, nullptr, asm_input->expr); |
| | 7043 | // } |
| | 7044 | // |
| | 7045 | // return return_type; |
| | 7046 | //} |
| | 7047 | // |
| | 7048 | //static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, |
| | 7049 | // BlockContext *context, AstNode *node, Buf *err_name) |
| | 7050 | //{ |
| | 7051 | // auto err_table_entry = g->error_table.maybe_get(err_name); |
| | 7052 | // |
| | 7053 | // if (err_table_entry) { |
| | 7054 | // return resolve_expr_const_val_as_err(g, node, err_table_entry->value); |
| | 7055 | // } |
| | 7056 | // |
| | 7057 | // add_node_error(g, node, |
| | 7058 | // buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name))); |
| | 7059 | // |
| | 7060 | // return g->builtin_types.entry_invalid; |
| | 7061 | //} |
| | 7062 | // |
| | 7063 | //static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 7064 | // TypeTableEntry *expected_type, AstNode *node, bool pointer_only) |
| | 7065 | //{ |
| | 7066 | // Buf *variable_name = node->data.symbol_expr.symbol; |
| | 7067 | // |
| | 7068 | // auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name); |
| | 7069 | // if (primitive_table_entry) { |
| | 7070 | // return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value, false); |
| | 7071 | // } |
| | 7072 | // |
| | 7073 | // VariableTableEntry *var = find_variable(g, context, variable_name); |
| | 7074 | // if (var) { |
| | 7075 | // TypeTableEntry *var_type = analyze_var_ref(g, node, var, context, false); |
| | 7076 | // return var_type; |
| | 7077 | // } |
| | 7078 | // |
| | 7079 | // AstNode *decl_node = find_decl(context, variable_name); |
| | 7080 | // if (decl_node) { |
| | 7081 | // return analyze_decl_ref(g, node, decl_node, pointer_only, context, false); |
| | 7082 | // } |
| | 7083 | // |
| | 7084 | // if (import->any_imports_failed) { |
| | 7085 | // // skip the error message since we had a failing import in this file |
| | 7086 | // // if an import breaks we don't need 9999 undeclared identifier errors |
| | 7087 | // return g->builtin_types.entry_invalid; |
| | 7088 | // } |
| | 7089 | // |
| | 7090 | // mark_impure_fn(g, context, node); |
| | 7091 | // add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| | 7092 | // return g->builtin_types.entry_invalid; |
| | 7093 | //} |
| | 7094 | // |
| | 7095 | //static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node, |
| | 7096 | // bool pointer_only, BlockContext *block_context, bool depends_on_compile_var) |
| | 7097 | //{ |
| | 7098 | // resolve_top_level_decl(g, decl_node, pointer_only); |
| | 7099 | // TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| | 7100 | // if (tld->resolution == TldResolutionInvalid) { |
| | 7101 | // return g->builtin_types.entry_invalid; |
| | 7102 | // } |
| | 7103 | // |
| | 7104 | // if (decl_node->type == NodeTypeVariableDeclaration) { |
| | 7105 | // VariableTableEntry *var = decl_node->data.variable_declaration.variable; |
| | 7106 | // return analyze_var_ref(g, source_node, var, block_context, depends_on_compile_var); |
| | 7107 | // } else if (decl_node->type == NodeTypeFnProto) { |
| | 7108 | // FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry; |
| | 7109 | // assert(fn_entry->type_entry); |
| | 7110 | // if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { |
| | 7111 | // return resolve_expr_const_val_as_generic_fn(g, source_node, fn_entry->type_entry, depends_on_compile_var); |
| | 7112 | // } else { |
| | 7113 | // return resolve_expr_const_val_as_fn(g, source_node, fn_entry, depends_on_compile_var); |
| | 7114 | // } |
| | 7115 | // } else if (decl_node->type == NodeTypeContainerDecl) { |
| | 7116 | // if (decl_node->data.struct_decl.generic_params.length > 0) { |
| | 7117 | // TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type; |
| | 7118 | // assert(type_entry); |
| | 7119 | // return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry, depends_on_compile_var); |
| | 7120 | // } else { |
| | 7121 | // return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry, |
| | 7122 | // depends_on_compile_var); |
| | 7123 | // } |
| | 7124 | // } else if (decl_node->type == NodeTypeTypeDecl) { |
| | 7125 | // return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry, |
| | 7126 | // depends_on_compile_var); |
| | 7127 | // } else { |
| | 7128 | // zig_unreachable(); |
| | 7129 | // } |
| | 7130 | //} |
| | 7131 | // |
| | 7132 | //static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var, |
| | 7133 | // BlockContext *context, bool depends_on_compile_var) |
| | 7134 | //{ |
| | 7135 | // get_resolved_expr(source_node)->variable = var; |
| | 7136 | // if (!var_is_pure(var, context)) { |
| | 7137 | // mark_impure_fn(g, context, source_node); |
| | 7138 | // } |
| | 7139 | // if (var->src_is_const && var->val_node) { |
| | 7140 | // ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val; |
| | 7141 | // if (other_const_val->ok) { |
| | 7142 | // return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node, |
| | 7143 | // depends_on_compile_var || var->force_depends_on_compile_var); |
| | 7144 | // } |
| | 7145 | // } |
| | 7146 | // return var->type; |
| | 7147 | //} |
| | 7148 | // |
| | 7149 | //static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import, |
| | 7150 | // BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) |
| | 7151 | //{ |
| | 7152 | // assert(node->type == NodeTypeNullLiteral); |
| | 7153 | // |
| | 7154 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 7155 | // const_val->ok = true; |
| | 7156 | // |
| | 7157 | // return g->builtin_types.entry_null; |
| | 7158 | //} |
| | 7159 | // |
| | 7160 | //static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 7161 | // TypeTableEntry *expected_type, AstNode *node) |
| | 7162 | //{ |
| | 7163 | // assert(node->type == NodeTypeUndefinedLiteral); |
| | 7164 | // |
| | 7165 | // Expr *expr = get_resolved_expr(node); |
| | 7166 | // ConstExprValue *const_val = &expr->const_val; |
| | 7167 | // |
| | 7168 | // const_val->ok = true; |
| | 7169 | // const_val->special = ConstValSpecialUndef; |
| | 7170 | // |
| | 7171 | // return expected_type ? expected_type : g->builtin_types.entry_undef; |
| | 7172 | //} |
| | 7173 | // |
| | 7174 | //static TypeTableEntry *analyze_zeroes_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 7175 | // TypeTableEntry *expected_type, AstNode *node) |
| | 7176 | //{ |
| | 7177 | // Expr *expr = get_resolved_expr(node); |
| | 7178 | // ConstExprValue *const_val = &expr->const_val; |
| | 7179 | // |
| | 7180 | // const_val->ok = true; |
| | 7181 | // const_val->special = ConstValSpecialZeroes; |
| | 7182 | // |
| | 7183 | // return expected_type ? expected_type : g->builtin_types.entry_undef; |
| | 7184 | //} |
| | 7185 | // |
| | 7186 | //static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, |
| | 7187 | // BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) |
| | 7188 | //{ |
| | 7189 | // return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false); |
| | 7190 | //} |
| | 7191 | // |
| | 7192 | //static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| | 7193 | // TypeTableEntry *expected_type, AstNode *node) |
| | 7194 | //{ |
| | 7195 | // TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node, |
| | 7196 | // false, false, nullptr); |
| | 7197 | // |
| | 7198 | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 7199 | // return type_entry; |
| | 7200 | // } |
| | 7201 | // |
| | 7202 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); |
| | 7203 | //} |
| | 7204 | // |
| | 7205 | //static bool var_is_pure(VariableTableEntry *var, BlockContext *context) { |
| | 7206 | // if (var->block_context->fn_entry == context->fn_entry) { |
| | 7207 | // // variable was declared in the current function, so it's OK. |
| | 7208 | // return true; |
| | 7209 | // } |
| | 7210 | // return var->src_is_const && var->type->deep_const; |
| | 7211 | //} |
| | 7212 | // |
| | 7213 | //static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) { |
| | 7214 | // if (type_entry->id == TypeTableEntryIdMetaType) { |
| | 7215 | // add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type")); |
| | 7216 | // } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| | 7217 | // add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value")); |
| | 7218 | // } |
| | 7219 | //} |
| | 7220 | // |