authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-23 00:21:29-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-23 00:21:29-04:00
logd7a2b05a813a7badf0606726c9a4b1423befd437
treeb4f1f0caa664d10b26a0ca4be31d1aeb125c802b
parenta9a6f77a1f0a6e173d85fee42aec0a8d5e22a64d

IR: introduce concept of lvalues


6 files changed, 522 insertions(+), 280 deletions(-)

CMakeLists.txt+1-1
......@@ -38,6 +38,7 @@ include_directories(
3838)
3939
4040set(ZIG_SOURCES
41 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
4142 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
4243 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
4344 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
......@@ -47,7 +48,6 @@ set(ZIG_SOURCES
4748 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
4849 "${CMAKE_SOURCE_DIR}/src/error.cpp"
4950 "${CMAKE_SOURCE_DIR}/src/eval.cpp"
50 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
5151 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
5252 "${CMAKE_SOURCE_DIR}/src/link.cpp"
5353 "${CMAKE_SOURCE_DIR}/src/main.cpp"
src/all_types.hpp+30-7
......@@ -34,7 +34,7 @@ struct IrBasicBlock;
3434
3535struct IrExecutable {
3636 ZigList<IrBasicBlock *> basic_block_list;
37 size_t var_slot_count;
37 size_t mem_slot_count;
3838 size_t next_debug_id;
3939};
4040
......@@ -1349,7 +1349,7 @@ struct VariableTableEntry {
13491349 bool force_depends_on_compile_var;
13501350 ImportTableEntry *import;
13511351 bool shadowable;
1352 size_t slot_index;
1352 size_t mem_slot_index;
13531353 size_t ref_count;
13541354};
13551355
......@@ -1425,8 +1425,11 @@ enum IrInstructionId {
14251425 IrInstructionIdUnOp,
14261426 IrInstructionIdBinOp,
14271427 IrInstructionIdDeclVar,
1428 IrInstructionIdLoadVar,
1429 IrInstructionIdStoreVar,
1428 IrInstructionIdLoadPtr,
1429 IrInstructionIdStorePtr,
1430 IrInstructionIdFieldPtr,
1431 IrInstructionIdElemPtr,
1432 IrInstructionIdVarPtr,
14301433 IrInstructionIdCall,
14311434 IrInstructionIdBuiltinCall,
14321435 IrInstructionIdConst,
......@@ -1554,16 +1557,36 @@ struct IrInstructionDeclVar {
15541557 IrInstruction *init_value;
15551558};
15561559
1557struct IrInstructionLoadVar {
1560struct IrInstructionLoadPtr {
15581561 IrInstruction base;
15591562
1560 VariableTableEntry *var;
1563 IrInstruction *ptr;
15611564};
15621565
1563struct IrInstructionStoreVar {
1566struct IrInstructionStorePtr {
15641567 IrInstruction base;
15651568
1569 IrInstruction *ptr;
15661570 IrInstruction *value;
1571};
1572
1573struct IrInstructionFieldPtr {
1574 IrInstruction base;
1575
1576 IrInstruction *struct_ptr;
1577 Buf field_name;
1578};
1579
1580struct IrInstructionElemPtr {
1581 IrInstruction base;
1582
1583 IrInstruction *array_ptr;
1584 IrInstruction *elem_index;
1585};
1586
1587struct IrInstructionVarPtr {
1588 IrInstruction base;
1589
15671590 VariableTableEntry *var;
15681591};
15691592
src/analyze.cpp+3
......@@ -3615,6 +3615,9 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_
36153615 // TODO replace _anon with @anon and make sure all tests still pass
36163616 buf_init_from_str(&variable_entry->name, "_anon");
36173617 }
3618 if (context->fn_entry) {
3619 context->fn_entry->variable_list.append(variable_entry);
3620 }
36183621
36193622 variable_entry->is_const = is_const;
36203623 variable_entry->decl_node = source_node;
src/codegen.cpp+150-183
......@@ -2326,17 +2326,6 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
23262326 return nullptr;
23272327}
23282328
2329static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
2330 IrInstructionLoadVar *load_var_instruction)
2331{
2332 VariableTableEntry *var = load_var_instruction->var;
2333 if (!type_has_bits(var->type))
2334 return nullptr;
2335
2336 assert(var->value_ref);
2337 return get_handle_value(g, var->value_ref, var->type);
2338}
2339
23402329static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
23412330 IrInstructionBinOp *bin_op_instruction)
23422331{
......@@ -2864,6 +2853,14 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
28642853 return nullptr;
28652854}
28662855
2856static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {
2857 return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), "");
2858}
2859
2860static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
2861 return instruction->var->value_ref;
2862}
2863
28672864static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
28682865 set_debug_source_node(g, instruction->source_node);
28692866
......@@ -2875,8 +2872,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
28752872 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
28762873 case IrInstructionIdDeclVar:
28772874 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
2878 case IrInstructionIdLoadVar:
2879 return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
28802875 case IrInstructionIdBinOp:
28812876 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
28822877 case IrInstructionIdCast:
......@@ -2889,13 +2884,19 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
28892884 return ir_render_br(g, executable, (IrInstructionBr *)instruction);
28902885 case IrInstructionIdUnOp:
28912886 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
2887 case IrInstructionIdLoadPtr:
2888 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
2889 case IrInstructionIdVarPtr:
2890 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
28922891 case IrInstructionIdSwitchBr:
28932892 case IrInstructionIdPhi:
2894 case IrInstructionIdStoreVar:
2893 case IrInstructionIdStorePtr:
28952894 case IrInstructionIdCall:
28962895 case IrInstructionIdBuiltinCall:
28972896 case IrInstructionIdContainerInitList:
28982897 case IrInstructionIdContainerInitFields:
2898 case IrInstructionIdFieldPtr:
2899 case IrInstructionIdElemPtr:
28992900 zig_panic("TODO render more IR instructions to LLVM");
29002901 }
29012902 zig_unreachable();
......@@ -3152,86 +3153,51 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
31523153 assert(node->data.while_expr.condition);
31533154 assert(node->data.while_expr.body);
31543155
3155 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
3156 //AstNode *continue_expr_node = node->data.while_expr.continue_expr;
31563157
31573158 bool condition_always_true = node->data.while_expr.condition_always_true;
3158 bool contains_break = node->data.while_expr.contains_break;
3159 //bool contains_break = node->data.while_expr.contains_break;
31593160 if (condition_always_true) {
31603161 // generate a forever loop
3161
3162 LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
3163 LLVMBasicBlockRef continue_block = continue_expr_node ?
3164 LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
3165 LLVMBasicBlockRef end_block = nullptr;
3166 if (contains_break) {
3167 end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
3168 }
3169
3170 set_debug_source_node(g, node);
3171 LLVMBuildBr(g->builder, body_block);
3172
3173 if (continue_expr_node) {
3174 LLVMPositionBuilderAtEnd(g->builder, continue_block);
3175
3176 gen_expr(g, continue_expr_node);
3177
3178 set_debug_source_node(g, node);
3179 LLVMBuildBr(g->builder, body_block);
3180 }
3181
3182 LLVMPositionBuilderAtEnd(g->builder, body_block);
3183 g->break_block_stack.append(end_block);
3184 g->continue_block_stack.append(continue_block);
3185 gen_expr(g, node->data.while_expr.body);
3186 g->break_block_stack.pop();
3187 g->continue_block_stack.pop();
3188
3189 if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
3190 set_debug_source_node(g, node);
3191 LLVMBuildBr(g->builder, continue_block);
3192 }
3193
3194 if (contains_break) {
3195 LLVMPositionBuilderAtEnd(g->builder, end_block);
3196 }
3162 zig_panic("TODO IR");
3163
3164 //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
3165 //LLVMBasicBlockRef continue_block = continue_expr_node ?
3166 // LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
3167 //LLVMBasicBlockRef end_block = nullptr;
3168 //if (contains_break) {
3169 // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
3170 //}
3171
3172 //set_debug_source_node(g, node);
3173 //LLVMBuildBr(g->builder, body_block);
3174
3175 //if (continue_expr_node) {
3176 // LLVMPositionBuilderAtEnd(g->builder, continue_block);
3177
3178 // gen_expr(g, continue_expr_node);
3179
3180 // set_debug_source_node(g, node);
3181 // LLVMBuildBr(g->builder, body_block);
3182 //}
3183
3184 //LLVMPositionBuilderAtEnd(g->builder, body_block);
3185 //g->break_block_stack.append(end_block);
3186 //g->continue_block_stack.append(continue_block);
3187 //gen_expr(g, node->data.while_expr.body);
3188 //g->break_block_stack.pop();
3189 //g->continue_block_stack.pop();
3190
3191 //if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
3192 // set_debug_source_node(g, node);
3193 // LLVMBuildBr(g->builder, continue_block);
3194 //}
3195
3196 //if (contains_break) {
3197 // LLVMPositionBuilderAtEnd(g->builder, end_block);
3198 //}
31973199 } else {
3198 // generate a normal while loop
3199
3200 LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileCond");
3201 LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
3202 LLVMBasicBlockRef continue_block = continue_expr_node ?
3203 LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : cond_block;
3204 LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
3205
3206 set_debug_source_node(g, node);
3207 LLVMBuildBr(g->builder, cond_block);
3208
3209 if (continue_expr_node) {
3210 LLVMPositionBuilderAtEnd(g->builder, continue_block);
3211
3212 gen_expr(g, continue_expr_node);
3213
3214 set_debug_source_node(g, node);
3215 LLVMBuildBr(g->builder, cond_block);
3216 }
3217
3218 LLVMPositionBuilderAtEnd(g->builder, cond_block);
3219 LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
3220 set_debug_source_node(g, node->data.while_expr.condition);
3221 LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
3222
3223 LLVMPositionBuilderAtEnd(g->builder, body_block);
3224 g->break_block_stack.append(end_block);
3225 g->continue_block_stack.append(continue_block);
3226 gen_expr(g, node->data.while_expr.body);
3227 g->break_block_stack.pop();
3228 g->continue_block_stack.pop();
3229 if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
3230 set_debug_source_node(g, node);
3231 LLVMBuildBr(g->builder, continue_block);
3232 }
3233
3234 LLVMPositionBuilderAtEnd(g->builder, end_block);
3200 zig_panic("moved to ir.cpp");
32353201 }
32363202
32373203 return nullptr;
......@@ -3242,98 +3208,99 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
32423208 assert(node->data.for_expr.array_expr);
32433209 assert(node->data.for_expr.body);
32443210
3245 VariableTableEntry *elem_var = node->data.for_expr.elem_var;
3246 assert(elem_var);
3247
3248 TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
3249
3250 VariableTableEntry *index_var = node->data.for_expr.index_var;
3251 assert(index_var);
3252 LLVMValueRef index_ptr = index_var->value_ref;
3253 LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false);
3254
3255 LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
3256 LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
3257 LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
3258 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
3259
3260 LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
3261 set_debug_source_node(g, node);
3262 LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
3263
3264 gen_var_debug_decl(g, index_var);
3265
3266 LLVMValueRef len_val;
3267 TypeTableEntry *child_type;
3268 if (array_type->id == TypeTableEntryIdArray) {
3269 len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
3270 array_type->data.array.len, false);
3271 child_type = array_type->data.array.child_type;
3272 } else if (array_type->id == TypeTableEntryIdStruct) {
3273 assert(array_type->data.structure.is_slice);
3274 TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
3275 assert(child_ptr_type->id == TypeTableEntryIdPointer);
3276 child_type = child_ptr_type->data.pointer.child_type;
3277 size_t len_index = array_type->data.structure.fields[1].gen_index;
3278 assert(len_index != SIZE_MAX);
3279 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
3280 len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
3281 } else {
3282 zig_unreachable();
3283 }
3284 LLVMBuildBr(g->builder, cond_block);
3285
3286 LLVMPositionBuilderAtEnd(g->builder, cond_block);
3287 LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
3288 LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
3289 LLVMBuildCondBr(g->builder, cond, body_block, end_block);
3290
3291 LLVMPositionBuilderAtEnd(g->builder, body_block);
3292 LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
3293
3294 LLVMValueRef elem_val;
3295 if (node->data.for_expr.elem_is_ptr) {
3296 elem_val = elem_ptr;
3297 } else {
3298 elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
3299 }
3300 gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
3301 gen_var_debug_decl(g, elem_var);
3302 g->break_block_stack.append(end_block);
3303 g->continue_block_stack.append(continue_block);
3304 gen_expr(g, node->data.for_expr.body);
3305 g->break_block_stack.pop();
3306 g->continue_block_stack.pop();
3307 if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
3308 set_debug_source_node(g, node);
3309 LLVMBuildBr(g->builder, continue_block);
3310 }
3311
3312 LLVMPositionBuilderAtEnd(g->builder, continue_block);
3313 set_debug_source_node(g, node);
3314 LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
3315 LLVMBuildStore(g->builder, new_index_val, index_ptr);
3316 LLVMBuildBr(g->builder, cond_block);
3317
3318 LLVMPositionBuilderAtEnd(g->builder, end_block);
3319 return nullptr;
3320}
3321
3322static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
3323 assert(node->type == NodeTypeBreak);
3324 LLVMBasicBlockRef dest_block = g->break_block_stack.last();
3325
3326 set_debug_source_node(g, node);
3327 return LLVMBuildBr(g->builder, dest_block);
3328}
3329
3330static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
3331 assert(node->type == NodeTypeContinue);
3332 LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
3333
3334 set_debug_source_node(g, node);
3335 return LLVMBuildBr(g->builder, dest_block);
3336}
3211 zig_panic("TODO IR for loop");
3212 //VariableTableEntry *elem_var = node->data.for_expr.elem_var;
3213 //assert(elem_var);
3214
3215 //TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
3216
3217 //VariableTableEntry *index_var = node->data.for_expr.index_var;
3218 //assert(index_var);
3219 //LLVMValueRef index_ptr = index_var->value_ref;
3220 //LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false);
3221
3222 //LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
3223 //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
3224 //LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
3225 //LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
3226
3227 //LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
3228 //set_debug_source_node(g, node);
3229 //LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
3230
3231 //gen_var_debug_decl(g, index_var);
3232
3233 //LLVMValueRef len_val;
3234 //TypeTableEntry *child_type;
3235 //if (array_type->id == TypeTableEntryIdArray) {
3236 // len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
3237 // array_type->data.array.len, false);
3238 // child_type = array_type->data.array.child_type;
3239 //} else if (array_type->id == TypeTableEntryIdStruct) {
3240 // assert(array_type->data.structure.is_slice);
3241 // TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
3242 // assert(child_ptr_type->id == TypeTableEntryIdPointer);
3243 // child_type = child_ptr_type->data.pointer.child_type;
3244 // size_t len_index = array_type->data.structure.fields[1].gen_index;
3245 // assert(len_index != SIZE_MAX);
3246 // LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
3247 // len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
3248 //} else {
3249 // zig_unreachable();
3250 //}
3251 //LLVMBuildBr(g->builder, cond_block);
3252
3253 //LLVMPositionBuilderAtEnd(g->builder, cond_block);
3254 //LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
3255 //LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
3256 //LLVMBuildCondBr(g->builder, cond, body_block, end_block);
3257
3258 //LLVMPositionBuilderAtEnd(g->builder, body_block);
3259 //LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
3260
3261 //LLVMValueRef elem_val;
3262 //if (node->data.for_expr.elem_is_ptr) {
3263 // elem_val = elem_ptr;
3264 //} else {
3265 // elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
3266 //}
3267 //gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
3268 //gen_var_debug_decl(g, elem_var);
3269 //g->break_block_stack.append(end_block);
3270 //g->continue_block_stack.append(continue_block);
3271 //gen_expr(g, node->data.for_expr.body);
3272 //g->break_block_stack.pop();
3273 //g->continue_block_stack.pop();
3274 //if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
3275 // set_debug_source_node(g, node);
3276 // LLVMBuildBr(g->builder, continue_block);
3277 //}
3278
3279 //LLVMPositionBuilderAtEnd(g->builder, continue_block);
3280 //set_debug_source_node(g, node);
3281 //LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
3282 //LLVMBuildStore(g->builder, new_index_val, index_ptr);
3283 //LLVMBuildBr(g->builder, cond_block);
3284
3285 //LLVMPositionBuilderAtEnd(g->builder, end_block);
3286 //return nullptr;
3287}
3288
3289//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
3290// assert(node->type == NodeTypeBreak);
3291// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
3292//
3293// set_debug_source_node(g, node);
3294// return LLVMBuildBr(g->builder, dest_block);
3295//}
3296
3297//static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
3298// assert(node->type == NodeTypeContinue);
3299// LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
3300//
3301// set_debug_source_node(g, node);
3302// return LLVMBuildBr(g->builder, dest_block);
3303//}
33373304
33383305static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
33393306 bool unwrap_maybe, LLVMValueRef *init_value, TypeTableEntry **expr_type, bool var_is_ptr)
......@@ -3735,9 +3702,9 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
37353702 case NodeTypeGoto:
37363703 return gen_goto(g, node);
37373704 case NodeTypeBreak:
3738 return gen_break(g, node);
3705 zig_panic("TODO IR");
37393706 case NodeTypeContinue:
3740 return gen_continue(g, node);
3707 zig_panic("TODO IR");
37413708 case NodeTypeLabel:
37423709 return gen_label(g, node);
37433710 case NodeTypeContainerInitExpr:
src/ir.cpp+293-69
......@@ -3,20 +3,17 @@
33#include "eval.hpp"
44#include "ir.hpp"
55
6struct IrVarSlot {
7 ConstExprValue value;
8 bool runtime;
9};
10
116struct IrExecContext {
12 IrVarSlot *var_slot_list;
13 size_t var_slot_count;
7 ConstExprValue *mem_slot_list;
8 size_t mem_slot_count;
149};
1510
1611struct IrBuilder {
1712 CodeGen *codegen;
1813 IrExecutable *exec;
1914 IrBasicBlock *current_basic_block;
15 ZigList<IrBasicBlock *> break_block_stack;
16 ZigList<IrBasicBlock *> continue_block_stack;
2017};
2118
2219struct IrAnalyze {
......@@ -27,6 +24,7 @@ struct IrAnalyze {
2724};
2825
2926static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
27static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope);
3028
3129static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
3230 assert(basic_block);
......@@ -40,9 +38,9 @@ static size_t exec_next_debug_id(IrExecutable *exec) {
4038 return result;
4139}
4240
43static size_t exec_next_var_slot(IrExecutable *exec) {
44 size_t result = exec->var_slot_count;
45 exec->var_slot_count += 1;
41static size_t exec_next_mem_slot(IrExecutable *exec) {
42 size_t result = exec->mem_slot_count;
43 exec->mem_slot_count += 1;
4644 return result;
4745}
4846
......@@ -115,12 +113,24 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
115113 return IrInstructionIdDeclVar;
116114}
117115
118static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadVar *) {
119 return IrInstructionIdLoadVar;
116static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {
117 return IrInstructionIdLoadPtr;
120118}
121119
122static constexpr IrInstructionId ir_instruction_id(IrInstructionStoreVar *) {
123 return IrInstructionIdStoreVar;
120static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
121 return IrInstructionIdStorePtr;
122}
123
124static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
125 return IrInstructionIdFieldPtr;
126}
127
128static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) {
129 return IrInstructionIdElemPtr;
130}
131
132static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {
133 return IrInstructionIdVarPtr;
124134}
125135
126136static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
......@@ -283,6 +293,37 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
283293 return &const_instruction->base;
284294}
285295
296static IrInstruction *ir_build_const_ptr(IrBuilder *irb, AstNode *source_node, ConstExprValue *pointee) {
297 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
298 const_instruction->base.static_value.ok = true;
299 const_instruction->base.static_value.data.x_ptr.len = 1;
300 const_instruction->base.static_value.data.x_ptr.is_c_str = false;
301 const_instruction->base.static_value.data.x_ptr.ptr = allocate<ConstExprValue *>(1);
302 const_instruction->base.static_value.data.x_ptr.ptr[0] = pointee;
303 return &const_instruction->base;
304}
305
306static IrInstruction *ir_build_const_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
307 ConstExprValue *pointee)
308{
309 IrInstruction *new_instruction = ir_build_const_ptr(irb, old_instruction->source_node, pointee);
310 ir_link_new_instruction(new_instruction, old_instruction);
311 return new_instruction;
312}
313
314static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, ConstExprValue *value) {
315 IrInstructionConst *instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
316 instruction->base.static_value = *value;
317 instruction->base.static_value.ok = true;
318 return &instruction->base;
319}
320
321static IrInstruction *ir_build_const_from(IrBuilder *irb, IrInstruction *old_instruction, ConstExprValue *value) {
322 IrInstruction *new_instruction = ir_build_const(irb, old_instruction->source_node, value);
323 ir_link_new_instruction(new_instruction, old_instruction);
324 return new_instruction;
325}
326
286327static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id,
287328 IrInstruction *op1, IrInstruction *op2)
288329{
......@@ -305,20 +346,19 @@ static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_in
305346 return new_instruction;
306347}
307348
308static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
309 IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node);
310 load_var_instruction->base.type_entry = var->type;
311 load_var_instruction->var = var;
349static IrInstruction *ir_build_var_ptr(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
350 IrInstructionVarPtr *instruction = ir_build_instruction<IrInstructionVarPtr>(irb, source_node);
351 instruction->var = var;
312352
313353 ir_ref_var(var);
314354
315 return &load_var_instruction->base;
355 return &instruction->base;
316356}
317357
318static IrInstruction *ir_build_load_var_from(IrBuilder *irb, IrInstruction *old_instruction,
358static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
319359 VariableTableEntry *var)
320360{
321 IrInstruction *new_instruction = ir_build_load_var(irb, old_instruction->source_node, var);
361 IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->source_node, var);
322362 ir_link_new_instruction(new_instruction, old_instruction);
323363 return new_instruction;
324364
......@@ -460,16 +500,20 @@ static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *o
460500 return new_instruction;
461501}
462502
463//static IrInstruction *ir_build_store(IrBuilder *irb, AstNode *source_node,
464// VariableTableEntry *var, IrInstruction *value)
465//{
466// IrInstructionStoreVar *store_instruction = ir_build_instruction<IrInstructionStoreVar>(irb, source_node);
467// store_instruction->base.static_value.ok = true;
468// store_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
469// store_instruction->var = var;
470// store_instruction->value = value;
471// return &store_instruction->base;
472//}
503static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
504 IrInstruction *ptr, IrInstruction *value)
505{
506 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);
507 instruction->base.static_value.ok = true;
508 instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
509 instruction->ptr = ptr;
510 instruction->value = value;
511
512 ir_ref_instruction(ptr);
513 ir_ref_instruction(value);
514
515 return &instruction->base;
516}
473517
474518static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
475519 VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
......@@ -480,6 +524,10 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
480524 decl_var_instruction->var = var;
481525 decl_var_instruction->var_type = var_type;
482526 decl_var_instruction->init_value = init_value;
527
528 ir_ref_instruction(var_type);
529 ir_ref_instruction(init_value);
530
483531 return &decl_var_instruction->base;
484532}
485533
......@@ -491,6 +539,21 @@ static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_
491539 return new_instruction;
492540}
493541
542static IrInstruction *ir_build_load_ptr(IrBuilder *irb, AstNode *source_node, IrInstruction *ptr) {
543 IrInstructionLoadPtr *instruction = ir_build_instruction<IrInstructionLoadPtr>(irb, source_node);
544 instruction->ptr = ptr;
545
546 ir_ref_instruction(ptr);
547
548 return &instruction->base;
549}
550
551static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *ptr) {
552 IrInstruction *new_instruction = ir_build_load_ptr(irb, old_instruction->source_node, ptr);
553 ir_link_new_instruction(new_instruction, old_instruction);
554 return new_instruction;
555}
556
494557//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
495558// size_t result = 0;
496559// while (inner_block != outer_block) {
......@@ -552,7 +615,7 @@ static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Buf *
552615 variable_entry->block_context = node->block_context;
553616 variable_entry->import = node->owner;
554617 variable_entry->shadowable = is_shadowable;
555 variable_entry->slot_index = exec_next_var_slot(irb->exec);
618 variable_entry->mem_slot_index = exec_next_mem_slot(irb->exec);
556619
557620 if (name) {
558621 buf_init_from_buf(&variable_entry->name, name);
......@@ -625,6 +688,19 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op
625688 return ir_build_bin_op(irb, node, op_id, op1, op2);
626689}
627690
691static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) {
692 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context);
693 if (lvalue == irb->codegen->invalid_instruction)
694 return lvalue;
695 IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue);
696 IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context);
697 if (op2 == irb->codegen->invalid_instruction)
698 return op2;
699 IrInstruction *result = ir_build_bin_op(irb, node, op_id, op1, op2);
700 ir_build_store_ptr(irb, node, lvalue, result);
701 return ir_build_const_void(irb, node);
702}
703
628704static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
629705 assert(node->type == NodeTypeBinOpExpr);
630706
......@@ -633,23 +709,39 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
633709 case BinOpTypeInvalid:
634710 zig_unreachable();
635711 case BinOpTypeAssign:
712 zig_panic("TODO gen IR for assignment");
636713 case BinOpTypeAssignTimes:
714 return ir_gen_assign_op(irb, node, IrBinOpMult);
637715 case BinOpTypeAssignTimesWrap:
716 return ir_gen_assign_op(irb, node, IrBinOpMultWrap);
638717 case BinOpTypeAssignDiv:
718 return ir_gen_assign_op(irb, node, IrBinOpDiv);
639719 case BinOpTypeAssignMod:
720 return ir_gen_assign_op(irb, node, IrBinOpMod);
640721 case BinOpTypeAssignPlus:
722 return ir_gen_assign_op(irb, node, IrBinOpAdd);
641723 case BinOpTypeAssignPlusWrap:
724 return ir_gen_assign_op(irb, node, IrBinOpAddWrap);
642725 case BinOpTypeAssignMinus:
726 return ir_gen_assign_op(irb, node, IrBinOpSub);
643727 case BinOpTypeAssignMinusWrap:
728 return ir_gen_assign_op(irb, node, IrBinOpSubWrap);
644729 case BinOpTypeAssignBitShiftLeft:
730 return ir_gen_assign_op(irb, node, IrBinOpBitShiftLeft);
645731 case BinOpTypeAssignBitShiftLeftWrap:
732 return ir_gen_assign_op(irb, node, IrBinOpBitShiftLeftWrap);
646733 case BinOpTypeAssignBitShiftRight:
734 return ir_gen_assign_op(irb, node, IrBinOpBitShiftRight);
647735 case BinOpTypeAssignBitAnd:
736 return ir_gen_assign_op(irb, node, IrBinOpBinAnd);
648737 case BinOpTypeAssignBitXor:
738 return ir_gen_assign_op(irb, node, IrBinOpBinXor);
649739 case BinOpTypeAssignBitOr:
740 return ir_gen_assign_op(irb, node, IrBinOpBinOr);
650741 case BinOpTypeAssignBoolAnd:
742 return ir_gen_assign_op(irb, node, IrBinOpBoolAnd);
651743 case BinOpTypeAssignBoolOr:
652 zig_panic("TODO gen IR for assignment");
744 return ir_gen_assign_op(irb, node, IrBinOpBoolOr);
653745 case BinOpTypeBoolOr:
654746 case BinOpTypeBoolAnd:
655747 // note: this is not a direct mapping to IrBinOpBoolOr/And
......@@ -726,7 +818,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN
726818
727819 if (decl_node->type == NodeTypeVariableDeclaration) {
728820 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
729 return ir_build_load_var(irb, source_node, var);
821 IrInstruction *var_ptr = ir_build_var_ptr(irb, source_node, var);
822 return ir_build_load_ptr(irb, source_node, var_ptr);
730823 } else if (decl_node->type == NodeTypeFnProto) {
731824 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
732825 assert(fn_entry->type_entry);
......@@ -763,8 +856,10 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_
763856 return ir_build_const_type(irb, node, primitive_table_entry->value);
764857
765858 VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name);
766 if (var)
767 return ir_build_load_var(irb, node, var);
859 if (var) {
860 IrInstruction *var_ptr = ir_build_var_ptr(irb, node, var);
861 return ir_build_load_ptr(irb, node, var_ptr);
862 }
768863
769864 AstNode *decl_node = find_decl(node->block_context, variable_name);
770865 if (decl_node)
......@@ -1011,6 +1106,44 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) {
10111106 return ir_build_var_decl(irb, node, var, type_instruction, init_value);
10121107}
10131108
1109static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
1110 assert(node->type == NodeTypeWhileExpr);
1111
1112 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
1113
1114 IrBasicBlock *cond_block = ir_build_basic_block(irb, "WhileCond");
1115 IrBasicBlock *body_block = ir_build_basic_block(irb, "WhileBody");
1116 IrBasicBlock *continue_block = continue_expr_node ?
1117 ir_build_basic_block(irb, "WhileContinue") : cond_block;
1118 IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd");
1119
1120 ir_build_br(irb, node, cond_block);
1121
1122 if (continue_expr_node) {
1123 ir_set_cursor_at_end(irb, continue_block);
1124 ir_gen_node(irb, continue_expr_node, node->block_context);
1125 ir_build_br(irb, node, cond_block);
1126
1127 }
1128
1129 ir_set_cursor_at_end(irb, cond_block);
1130 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, node->block_context);
1131 ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block);
1132
1133 ir_set_cursor_at_end(irb, body_block);
1134
1135 irb->break_block_stack.append(end_block);
1136 irb->continue_block_stack.append(continue_block);
1137 ir_gen_node(irb, node->data.while_expr.body, node->block_context);
1138 irb->break_block_stack.pop();
1139 irb->continue_block_stack.pop();
1140
1141 ir_build_br(irb, node, continue_block);
1142 ir_set_cursor_at_end(irb, end_block);
1143
1144 return ir_build_const_void(irb, node);
1145}
1146
10141147static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
10151148 bool pointer_only)
10161149{
......@@ -1036,6 +1169,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
10361169 return ir_gen_container_init_expr(irb, node);
10371170 case NodeTypeVariableDeclaration:
10381171 return ir_gen_var_decl(irb, node);
1172 case NodeTypeWhileExpr:
1173 return ir_gen_while_expr(irb, node);
10391174 case NodeTypeUnwrapErrorExpr:
10401175 case NodeTypeReturnExpr:
10411176 case NodeTypeDefer:
......@@ -1043,7 +1178,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
10431178 case NodeTypeSliceExpr:
10441179 case NodeTypeFieldAccessExpr:
10451180 case NodeTypeIfVarExpr:
1046 case NodeTypeWhileExpr:
10471181 case NodeTypeForExpr:
10481182 case NodeTypeAsmExpr:
10491183 case NodeTypeGoto:
......@@ -1085,6 +1219,67 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *s
10851219 return ir_gen_node_extra(irb, node, scope, pointer_only_no);
10861220}
10871221
1222static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope) {
1223 assert(scope);
1224 node->block_context = scope;
1225 switch (node->type) {
1226 case NodeTypeSymbol:
1227 zig_panic("TODO symbol lvalue");
1228 case NodeTypeArrayAccessExpr:
1229 zig_panic("TODO array access lvalue");
1230 case NodeTypeFieldAccessExpr:
1231 zig_panic("TODO field access lvalue");
1232 case NodeTypePrefixOpExpr:
1233 zig_panic("TODO prefix op lvalue");
1234 case NodeTypeBlock:
1235 case NodeTypeBinOpExpr:
1236 case NodeTypeNumberLiteral:
1237 case NodeTypeFnCallExpr:
1238 case NodeTypeIfBoolExpr:
1239 case NodeTypeContainerInitExpr:
1240 case NodeTypeVariableDeclaration:
1241 case NodeTypeWhileExpr:
1242 case NodeTypeUnwrapErrorExpr:
1243 case NodeTypeReturnExpr:
1244 case NodeTypeDefer:
1245 case NodeTypeSliceExpr:
1246 case NodeTypeIfVarExpr:
1247 case NodeTypeForExpr:
1248 case NodeTypeAsmExpr:
1249 case NodeTypeGoto:
1250 case NodeTypeBreak:
1251 case NodeTypeContinue:
1252 case NodeTypeLabel:
1253 case NodeTypeSwitchExpr:
1254 case NodeTypeBoolLiteral:
1255 case NodeTypeStringLiteral:
1256 case NodeTypeCharLiteral:
1257 case NodeTypeNullLiteral:
1258 case NodeTypeUndefinedLiteral:
1259 case NodeTypeZeroesLiteral:
1260 case NodeTypeThisLiteral:
1261 case NodeTypeErrorType:
1262 case NodeTypeTypeLiteral:
1263 case NodeTypeArrayType:
1264 case NodeTypeVarLiteral:
1265 case NodeTypeRoot:
1266 case NodeTypeFnProto:
1267 case NodeTypeFnDef:
1268 case NodeTypeFnDecl:
1269 case NodeTypeParamDecl:
1270 case NodeTypeUse:
1271 case NodeTypeContainerDecl:
1272 case NodeTypeStructField:
1273 case NodeTypeStructValueField:
1274 case NodeTypeSwitchProng:
1275 case NodeTypeSwitchRange:
1276 case NodeTypeErrorValueDecl:
1277 case NodeTypeTypeDecl:
1278 zig_unreachable();
1279 }
1280 zig_unreachable();
1281}
1282
10881283static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,
10891284 IrExecutable *ir_executable, bool add_return, bool pointer_only)
10901285{
......@@ -1965,8 +2160,8 @@ static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
19652160}
19662161
19672162static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
1968 IrInstruction *op1 = bin_op_instruction->op1;
1969 IrInstruction *op2 = bin_op_instruction->op2;
2163 IrInstruction *op1 = bin_op_instruction->op1->other;
2164 IrInstruction *op2 = bin_op_instruction->op2->other;
19702165 IrInstruction *instructions[] = {op1, op2};
19712166 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);
19722167 if (resolved_type->id == TypeTableEntryIdInvalid)
......@@ -2021,7 +2216,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
20212216
20222217 }
20232218
2024 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
2219 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1, op2);
20252220
20262221 return resolved_type;
20272222}
......@@ -2169,9 +2364,9 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
21692364 var->type = result_type;
21702365 assert(var->type != nullptr); // should have been caught by the parser
21712366
2172 if (casted_init_value->static_value.ok) {
2173 // TODO set the variable in the IrVarSlot
2174 }
2367 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
2368 *mem_slot = casted_init_value->static_value;
2369
21752370 ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value);
21762371
21772372 BlockContext *scope = decl_var_instruction->base.source_node->block_context;
......@@ -2181,11 +2376,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
21812376 return ira->codegen->builtin_types.entry_void;
21822377}
21832378
2184static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {
2185 ir_build_load_var_from(&ira->new_irb, &load_var_instruction->base, load_var_instruction->var);
2186 return load_var_instruction->var->type;
2187}
2188
21892379static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
21902380 IrInstruction *fn_ref = call_instruction->fn->other;
21912381 if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
......@@ -2345,20 +2535,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
23452535 // }
23462536 //}
23472537 case IrUnOpDereference:
2348 zig_panic("TODO analyze PrefixOpDereference");
2349 //{
2350 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
2351 // if (type_entry->id == TypeTableEntryIdInvalid) {
2352 // return type_entry;
2353 // } else if (type_entry->id == TypeTableEntryIdPointer) {
2354 // return type_entry->data.pointer.child_type;
2355 // } else {
2356 // add_node_error(g, *expr_node,
2357 // buf_sprintf("indirection requires pointer operand ('%s' invalid)",
2358 // buf_ptr(&type_entry->name)));
2359 // return g->builtin_types.entry_invalid;
2360 // }
2361 //}
2538 zig_panic("TODO remove this IrUnOp item");
23622539 case IrUnOpMaybe:
23632540 zig_panic("TODO analyze PrefixOpMaybe");
23642541 //{
......@@ -3727,6 +3904,43 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
37273904 return resolved_type;
37283905}
37293906
3907static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) {
3908 VariableTableEntry *var = var_ptr_instruction->var;
3909 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
3910 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false);
3911 if (mem_slot->ok) {
3912 ir_build_const_ptr_from(&ira->new_irb, &var_ptr_instruction->base, mem_slot);
3913 return ptr_type;
3914 }
3915
3916 ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);
3917 return ptr_type;
3918}
3919
3920static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
3921 IrInstruction *ptr = load_ptr_instruction->ptr->other;
3922 TypeTableEntry *type_entry = ptr->type_entry;
3923 if (type_entry->id == TypeTableEntryIdInvalid) {
3924 return type_entry;
3925 } else if (type_entry->id == TypeTableEntryIdPointer) {
3926 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
3927 if (ptr->static_value.ok) {
3928 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
3929 if (pointee->ok) {
3930 ir_build_const_from(&ira->new_irb, &load_ptr_instruction->base, pointee);
3931 return child_type;
3932 }
3933 }
3934 ir_build_load_ptr_from(&ira->new_irb, &load_ptr_instruction->base, ptr);
3935 return child_type;
3936 } else {
3937 add_node_error(ira->codegen, load_ptr_instruction->base.source_node,
3938 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
3939 buf_ptr(&type_entry->name)));
3940 return ira->codegen->builtin_types.entry_invalid;
3941 }
3942}
3943
37303944static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
37313945 switch (instruction->id) {
37323946 case IrInstructionIdInvalid:
......@@ -3741,8 +3955,16 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
37413955 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
37423956 case IrInstructionIdDeclVar:
37433957 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
3744 case IrInstructionIdLoadVar:
3745 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
3958 case IrInstructionIdLoadPtr:
3959 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
3960 case IrInstructionIdStorePtr:
3961 zig_panic("TODO store ptr");
3962 case IrInstructionIdFieldPtr:
3963 zig_panic("TODO field ptr");
3964 case IrInstructionIdElemPtr:
3965 zig_panic("TODO elem ptr");
3966 case IrInstructionIdVarPtr:
3967 return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
37463968 case IrInstructionIdCall:
37473969 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
37483970 case IrInstructionIdBr:
......@@ -3756,7 +3978,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
37563978 case IrInstructionIdPhi:
37573979 return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
37583980 case IrInstructionIdSwitchBr:
3759 case IrInstructionIdStoreVar:
37603981 case IrInstructionIdCast:
37613982 case IrInstructionIdContainerInitList:
37623983 case IrInstructionIdContainerInitFields:
......@@ -3792,8 +4013,8 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
37924013 ira->new_irb.codegen = codegen;
37934014 ira->new_irb.exec = new_exec;
37944015
3795 ira->exec_context.var_slot_count = ira->old_irb.exec->var_slot_count;
3796 ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count);
4016 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;
4017 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);
37974018
37984019 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
37994020 for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) {
......@@ -3881,7 +4102,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
38814102 case IrInstructionIdCondBr:
38824103 case IrInstructionIdSwitchBr:
38834104 case IrInstructionIdDeclVar:
3884 case IrInstructionIdStoreVar:
4105 case IrInstructionIdStorePtr:
38854106 case IrInstructionIdCall:
38864107 case IrInstructionIdReturn:
38874108 case IrInstructionIdUnreachable:
......@@ -3889,11 +4110,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {
38894110 case IrInstructionIdPhi:
38904111 case IrInstructionIdUnOp:
38914112 case IrInstructionIdBinOp:
3892 case IrInstructionIdLoadVar:
4113 case IrInstructionIdLoadPtr:
38934114 case IrInstructionIdConst:
38944115 case IrInstructionIdCast:
38954116 case IrInstructionIdContainerInitList:
38964117 case IrInstructionIdContainerInitFields:
4118 case IrInstructionIdFieldPtr:
4119 case IrInstructionIdElemPtr:
4120 case IrInstructionIdVarPtr:
38974121 return false;
38984122 case IrInstructionIdBuiltinCall:
38994123 return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction);
src/ir_print.cpp+45-20
......@@ -21,8 +21,7 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
2121 fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);
2222}
2323
24static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
25 TypeTableEntry *type_entry = instruction->type_entry;
24static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
2625 switch (type_entry->id) {
2726 case TypeTableEntryIdInvalid:
2827 zig_unreachable();
......@@ -30,21 +29,21 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
3029 fprintf(irp->f, "{}");
3130 break;
3231 case TypeTableEntryIdNumLitFloat:
33 fprintf(irp->f, "%f", instruction->static_value.data.x_bignum.data.x_float);
32 fprintf(irp->f, "%f", const_val->data.x_bignum.data.x_float);
3433 break;
3534 case TypeTableEntryIdNumLitInt:
3635 {
37 BigNum *bignum = &instruction->static_value.data.x_bignum;
36 BigNum *bignum = &const_val->data.x_bignum;
3837 const char *negative_str = bignum->is_negative ? "-" : "";
3938 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
4039 break;
4140 }
4241 case TypeTableEntryIdMetaType:
43 fprintf(irp->f, "%s", buf_ptr(&instruction->static_value.data.x_type->name));
42 fprintf(irp->f, "%s", buf_ptr(&const_val->data.x_type->name));
4443 break;
4544 case TypeTableEntryIdInt:
4645 {
47 BigNum *bignum = &instruction->static_value.data.x_bignum;
46 BigNum *bignum = &const_val->data.x_bignum;
4847 assert(bignum->kind == BigNumKindInt);
4948 const char *negative_str = bignum->is_negative ? "-" : "";
5049 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
......@@ -53,10 +52,18 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
5352 case TypeTableEntryIdUnreachable:
5453 fprintf(irp->f, "@unreachable()");
5554 break;
56 case TypeTableEntryIdVar:
5755 case TypeTableEntryIdBool:
58 case TypeTableEntryIdFloat:
56 {
57 const char *value = const_val->data.x_bool ? "true" : "false";
58 fprintf(irp->f, "%s", value);
59 break;
60 }
5961 case TypeTableEntryIdPointer:
62 fprintf(irp->f, "&");
63 ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);
64 break;
65 case TypeTableEntryIdVar:
66 case TypeTableEntryIdFloat:
6067 case TypeTableEntryIdArray:
6168 case TypeTableEntryIdStruct:
6269 case TypeTableEntryIdUndefLit:
......@@ -75,6 +82,12 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
7582 }
7683}
7784
85static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
86 TypeTableEntry *type_entry = instruction->type_entry;
87 ConstExprValue *const_val = &instruction->static_value;
88 ir_print_const_value(irp, type_entry, const_val);
89}
90
7891static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
7992 if (instruction->static_value.ok) {
8093 ir_print_const_instruction(irp, instruction);
......@@ -211,10 +224,6 @@ static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instr
211224 ir_print_other_instruction(irp, decl_var_instruction->init_value);
212225}
213226
214static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
215 fprintf(irp->f, "%s", buf_ptr(&load_var_instruction->var->name));
216}
217
218227static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
219228 fprintf(irp->f, "cast ");
220229 ir_print_other_instruction(irp, cast_instruction->value);
......@@ -301,9 +310,20 @@ static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruc
301310 fprintf(irp->f, "unreachable");
302311}
303312
304static void ir_print_store(IrPrint *irp, IrInstructionStoreVar *store_instruction) {
305 fprintf(irp->f, "%s = ", buf_ptr(&store_instruction->var->name));
306 ir_print_other_instruction(irp, store_instruction->value);
313static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {
314 ir_print_other_instruction(irp, instruction->array_ptr);
315 fprintf(irp->f, "[");
316 ir_print_other_instruction(irp, instruction->elem_index);
317 fprintf(irp->f, "]");
318}
319
320static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
321 fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
322}
323
324static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
325 fprintf(irp->f, "*");
326 ir_print_other_instruction(irp, instruction->ptr);
307327}
308328
309329static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
......@@ -323,9 +343,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
323343 case IrInstructionIdDeclVar:
324344 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
325345 break;
326 case IrInstructionIdLoadVar:
327 ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);
328 break;
329346 case IrInstructionIdCast:
330347 ir_print_cast(irp, (IrInstructionCast *)instruction);
331348 break;
......@@ -356,10 +373,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
356373 case IrInstructionIdUnreachable:
357374 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
358375 break;
359 case IrInstructionIdStoreVar:
360 ir_print_store(irp, (IrInstructionStoreVar *)instruction);
376 case IrInstructionIdElemPtr:
377 ir_print_elem_ptr(irp, (IrInstructionElemPtr *)instruction);
378 break;
379 case IrInstructionIdVarPtr:
380 ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
381 break;
382 case IrInstructionIdLoadPtr:
383 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
361384 break;
362385 case IrInstructionIdSwitchBr:
386 case IrInstructionIdStorePtr:
387 case IrInstructionIdFieldPtr:
363388 zig_panic("TODO print more IR instructions");
364389 }
365390 fprintf(irp->f, "\n");