Commit d7a2b05a81
Changed files (6)
src/all_types.hpp
@@ -34,7 +34,7 @@ struct IrBasicBlock;
struct IrExecutable {
ZigList<IrBasicBlock *> basic_block_list;
- size_t var_slot_count;
+ size_t mem_slot_count;
size_t next_debug_id;
};
@@ -1349,7 +1349,7 @@ struct VariableTableEntry {
bool force_depends_on_compile_var;
ImportTableEntry *import;
bool shadowable;
- size_t slot_index;
+ size_t mem_slot_index;
size_t ref_count;
};
@@ -1425,8 +1425,11 @@ enum IrInstructionId {
IrInstructionIdUnOp,
IrInstructionIdBinOp,
IrInstructionIdDeclVar,
- IrInstructionIdLoadVar,
- IrInstructionIdStoreVar,
+ IrInstructionIdLoadPtr,
+ IrInstructionIdStorePtr,
+ IrInstructionIdFieldPtr,
+ IrInstructionIdElemPtr,
+ IrInstructionIdVarPtr,
IrInstructionIdCall,
IrInstructionIdBuiltinCall,
IrInstructionIdConst,
@@ -1554,16 +1557,36 @@ struct IrInstructionDeclVar {
IrInstruction *init_value;
};
-struct IrInstructionLoadVar {
+struct IrInstructionLoadPtr {
IrInstruction base;
- VariableTableEntry *var;
+ IrInstruction *ptr;
};
-struct IrInstructionStoreVar {
+struct IrInstructionStorePtr {
IrInstruction base;
+ IrInstruction *ptr;
IrInstruction *value;
+};
+
+struct IrInstructionFieldPtr {
+ IrInstruction base;
+
+ IrInstruction *struct_ptr;
+ Buf field_name;
+};
+
+struct IrInstructionElemPtr {
+ IrInstruction base;
+
+ IrInstruction *array_ptr;
+ IrInstruction *elem_index;
+};
+
+struct IrInstructionVarPtr {
+ IrInstruction base;
+
VariableTableEntry *var;
};
src/analyze.cpp
@@ -3615,6 +3615,9 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_
// TODO replace _anon with @anon and make sure all tests still pass
buf_init_from_str(&variable_entry->name, "_anon");
}
+ if (context->fn_entry) {
+ context->fn_entry->variable_list.append(variable_entry);
+ }
variable_entry->is_const = is_const;
variable_entry->decl_node = source_node;
src/codegen.cpp
@@ -2326,17 +2326,6 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
return nullptr;
}
-static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
- IrInstructionLoadVar *load_var_instruction)
-{
- VariableTableEntry *var = load_var_instruction->var;
- if (!type_has_bits(var->type))
- return nullptr;
-
- assert(var->value_ref);
- return get_handle_value(g, var->value_ref, var->type);
-}
-
static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
IrInstructionBinOp *bin_op_instruction)
{
@@ -2864,6 +2853,14 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
return nullptr;
}
+static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {
+ return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), "");
+}
+
+static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
+ return instruction->var->value_ref;
+}
+
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
set_debug_source_node(g, instruction->source_node);
@@ -2875,8 +2872,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
case IrInstructionIdDeclVar:
return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
- case IrInstructionIdLoadVar:
- return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
case IrInstructionIdBinOp:
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
case IrInstructionIdCast:
@@ -2889,13 +2884,19 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_br(g, executable, (IrInstructionBr *)instruction);
case IrInstructionIdUnOp:
return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
+ case IrInstructionIdLoadPtr:
+ return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
+ case IrInstructionIdVarPtr:
+ return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
case IrInstructionIdSwitchBr:
case IrInstructionIdPhi:
- case IrInstructionIdStoreVar:
+ case IrInstructionIdStorePtr:
case IrInstructionIdCall:
case IrInstructionIdBuiltinCall:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
+ case IrInstructionIdFieldPtr:
+ case IrInstructionIdElemPtr:
zig_panic("TODO render more IR instructions to LLVM");
}
zig_unreachable();
@@ -3152,86 +3153,51 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
assert(node->data.while_expr.condition);
assert(node->data.while_expr.body);
- AstNode *continue_expr_node = node->data.while_expr.continue_expr;
+ //AstNode *continue_expr_node = node->data.while_expr.continue_expr;
bool condition_always_true = node->data.while_expr.condition_always_true;
- bool contains_break = node->data.while_expr.contains_break;
+ //bool contains_break = node->data.while_expr.contains_break;
if (condition_always_true) {
// generate a forever loop
-
- LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
- LLVMBasicBlockRef continue_block = continue_expr_node ?
- LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
- LLVMBasicBlockRef end_block = nullptr;
- if (contains_break) {
- end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
- }
-
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, body_block);
-
- if (continue_expr_node) {
- LLVMPositionBuilderAtEnd(g->builder, continue_block);
-
- gen_expr(g, continue_expr_node);
-
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, body_block);
- }
-
- LLVMPositionBuilderAtEnd(g->builder, body_block);
- g->break_block_stack.append(end_block);
- g->continue_block_stack.append(continue_block);
- gen_expr(g, node->data.while_expr.body);
- g->break_block_stack.pop();
- g->continue_block_stack.pop();
-
- if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, continue_block);
- }
-
- if (contains_break) {
- LLVMPositionBuilderAtEnd(g->builder, end_block);
- }
+ zig_panic("TODO IR");
+
+ //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
+ //LLVMBasicBlockRef continue_block = continue_expr_node ?
+ // LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
+ //LLVMBasicBlockRef end_block = nullptr;
+ //if (contains_break) {
+ // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
+ //}
+
+ //set_debug_source_node(g, node);
+ //LLVMBuildBr(g->builder, body_block);
+
+ //if (continue_expr_node) {
+ // LLVMPositionBuilderAtEnd(g->builder, continue_block);
+
+ // gen_expr(g, continue_expr_node);
+
+ // set_debug_source_node(g, node);
+ // LLVMBuildBr(g->builder, body_block);
+ //}
+
+ //LLVMPositionBuilderAtEnd(g->builder, body_block);
+ //g->break_block_stack.append(end_block);
+ //g->continue_block_stack.append(continue_block);
+ //gen_expr(g, node->data.while_expr.body);
+ //g->break_block_stack.pop();
+ //g->continue_block_stack.pop();
+
+ //if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
+ // set_debug_source_node(g, node);
+ // LLVMBuildBr(g->builder, continue_block);
+ //}
+
+ //if (contains_break) {
+ // LLVMPositionBuilderAtEnd(g->builder, end_block);
+ //}
} else {
- // generate a normal while loop
-
- LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileCond");
- LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
- LLVMBasicBlockRef continue_block = continue_expr_node ?
- LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : cond_block;
- LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
-
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, cond_block);
-
- if (continue_expr_node) {
- LLVMPositionBuilderAtEnd(g->builder, continue_block);
-
- gen_expr(g, continue_expr_node);
-
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, cond_block);
- }
-
- LLVMPositionBuilderAtEnd(g->builder, cond_block);
- LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
- set_debug_source_node(g, node->data.while_expr.condition);
- LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
-
- LLVMPositionBuilderAtEnd(g->builder, body_block);
- g->break_block_stack.append(end_block);
- g->continue_block_stack.append(continue_block);
- gen_expr(g, node->data.while_expr.body);
- g->break_block_stack.pop();
- g->continue_block_stack.pop();
- if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, continue_block);
- }
-
- LLVMPositionBuilderAtEnd(g->builder, end_block);
+ zig_panic("moved to ir.cpp");
}
return nullptr;
@@ -3242,98 +3208,99 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
assert(node->data.for_expr.array_expr);
assert(node->data.for_expr.body);
- VariableTableEntry *elem_var = node->data.for_expr.elem_var;
- assert(elem_var);
-
- TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
-
- VariableTableEntry *index_var = node->data.for_expr.index_var;
- assert(index_var);
- LLVMValueRef index_ptr = index_var->value_ref;
- LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false);
-
- LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
- LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
- LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
- LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
-
- LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
- set_debug_source_node(g, node);
- LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
-
- gen_var_debug_decl(g, index_var);
-
- LLVMValueRef len_val;
- TypeTableEntry *child_type;
- if (array_type->id == TypeTableEntryIdArray) {
- len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
- array_type->data.array.len, false);
- child_type = array_type->data.array.child_type;
- } else if (array_type->id == TypeTableEntryIdStruct) {
- assert(array_type->data.structure.is_slice);
- TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
- assert(child_ptr_type->id == TypeTableEntryIdPointer);
- child_type = child_ptr_type->data.pointer.child_type;
- size_t len_index = array_type->data.structure.fields[1].gen_index;
- assert(len_index != SIZE_MAX);
- LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
- len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
- } else {
- zig_unreachable();
- }
- LLVMBuildBr(g->builder, cond_block);
-
- LLVMPositionBuilderAtEnd(g->builder, cond_block);
- LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
- LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
- LLVMBuildCondBr(g->builder, cond, body_block, end_block);
-
- LLVMPositionBuilderAtEnd(g->builder, body_block);
- LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
-
- LLVMValueRef elem_val;
- if (node->data.for_expr.elem_is_ptr) {
- elem_val = elem_ptr;
- } else {
- elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
- }
- gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
- gen_var_debug_decl(g, elem_var);
- g->break_block_stack.append(end_block);
- g->continue_block_stack.append(continue_block);
- gen_expr(g, node->data.for_expr.body);
- g->break_block_stack.pop();
- g->continue_block_stack.pop();
- if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
- set_debug_source_node(g, node);
- LLVMBuildBr(g->builder, continue_block);
- }
-
- LLVMPositionBuilderAtEnd(g->builder, continue_block);
- set_debug_source_node(g, node);
- LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
- LLVMBuildStore(g->builder, new_index_val, index_ptr);
- LLVMBuildBr(g->builder, cond_block);
-
- LLVMPositionBuilderAtEnd(g->builder, end_block);
- return nullptr;
-}
-
-static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
- assert(node->type == NodeTypeBreak);
- LLVMBasicBlockRef dest_block = g->break_block_stack.last();
-
- set_debug_source_node(g, node);
- return LLVMBuildBr(g->builder, dest_block);
-}
-
-static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
- assert(node->type == NodeTypeContinue);
- LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
-
- set_debug_source_node(g, node);
- return LLVMBuildBr(g->builder, dest_block);
-}
+ zig_panic("TODO IR for loop");
+ //VariableTableEntry *elem_var = node->data.for_expr.elem_var;
+ //assert(elem_var);
+
+ //TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
+
+ //VariableTableEntry *index_var = node->data.for_expr.index_var;
+ //assert(index_var);
+ //LLVMValueRef index_ptr = index_var->value_ref;
+ //LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false);
+
+ //LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
+ //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
+ //LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
+ //LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
+
+ //LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
+ //set_debug_source_node(g, node);
+ //LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
+
+ //gen_var_debug_decl(g, index_var);
+
+ //LLVMValueRef len_val;
+ //TypeTableEntry *child_type;
+ //if (array_type->id == TypeTableEntryIdArray) {
+ // len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
+ // array_type->data.array.len, false);
+ // child_type = array_type->data.array.child_type;
+ //} else if (array_type->id == TypeTableEntryIdStruct) {
+ // assert(array_type->data.structure.is_slice);
+ // TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
+ // assert(child_ptr_type->id == TypeTableEntryIdPointer);
+ // child_type = child_ptr_type->data.pointer.child_type;
+ // size_t len_index = array_type->data.structure.fields[1].gen_index;
+ // assert(len_index != SIZE_MAX);
+ // LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
+ // len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
+ //} else {
+ // zig_unreachable();
+ //}
+ //LLVMBuildBr(g->builder, cond_block);
+
+ //LLVMPositionBuilderAtEnd(g->builder, cond_block);
+ //LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
+ //LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
+ //LLVMBuildCondBr(g->builder, cond, body_block, end_block);
+
+ //LLVMPositionBuilderAtEnd(g->builder, body_block);
+ //LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
+
+ //LLVMValueRef elem_val;
+ //if (node->data.for_expr.elem_is_ptr) {
+ // elem_val = elem_ptr;
+ //} else {
+ // elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
+ //}
+ //gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
+ //gen_var_debug_decl(g, elem_var);
+ //g->break_block_stack.append(end_block);
+ //g->continue_block_stack.append(continue_block);
+ //gen_expr(g, node->data.for_expr.body);
+ //g->break_block_stack.pop();
+ //g->continue_block_stack.pop();
+ //if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
+ // set_debug_source_node(g, node);
+ // LLVMBuildBr(g->builder, continue_block);
+ //}
+
+ //LLVMPositionBuilderAtEnd(g->builder, continue_block);
+ //set_debug_source_node(g, node);
+ //LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
+ //LLVMBuildStore(g->builder, new_index_val, index_ptr);
+ //LLVMBuildBr(g->builder, cond_block);
+
+ //LLVMPositionBuilderAtEnd(g->builder, end_block);
+ //return nullptr;
+}
+
+//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
+// assert(node->type == NodeTypeBreak);
+// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
+//
+// set_debug_source_node(g, node);
+// return LLVMBuildBr(g->builder, dest_block);
+//}
+
+//static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
+// assert(node->type == NodeTypeContinue);
+// LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
+//
+// set_debug_source_node(g, node);
+// return LLVMBuildBr(g->builder, dest_block);
+//}
static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
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) {
case NodeTypeGoto:
return gen_goto(g, node);
case NodeTypeBreak:
- return gen_break(g, node);
+ zig_panic("TODO IR");
case NodeTypeContinue:
- return gen_continue(g, node);
+ zig_panic("TODO IR");
case NodeTypeLabel:
return gen_label(g, node);
case NodeTypeContainerInitExpr:
src/ir.cpp
@@ -3,20 +3,17 @@
#include "eval.hpp"
#include "ir.hpp"
-struct IrVarSlot {
- ConstExprValue value;
- bool runtime;
-};
-
struct IrExecContext {
- IrVarSlot *var_slot_list;
- size_t var_slot_count;
+ ConstExprValue *mem_slot_list;
+ size_t mem_slot_count;
};
struct IrBuilder {
CodeGen *codegen;
IrExecutable *exec;
IrBasicBlock *current_basic_block;
+ ZigList<IrBasicBlock *> break_block_stack;
+ ZigList<IrBasicBlock *> continue_block_stack;
};
struct IrAnalyze {
@@ -27,6 +24,7 @@ struct IrAnalyze {
};
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
+static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope);
static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
assert(basic_block);
@@ -40,9 +38,9 @@ static size_t exec_next_debug_id(IrExecutable *exec) {
return result;
}
-static size_t exec_next_var_slot(IrExecutable *exec) {
- size_t result = exec->var_slot_count;
- exec->var_slot_count += 1;
+static size_t exec_next_mem_slot(IrExecutable *exec) {
+ size_t result = exec->mem_slot_count;
+ exec->mem_slot_count += 1;
return result;
}
@@ -115,12 +113,24 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
return IrInstructionIdDeclVar;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadVar *) {
- return IrInstructionIdLoadVar;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {
+ return IrInstructionIdLoadPtr;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionStoreVar *) {
- return IrInstructionIdStoreVar;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
+ return IrInstructionIdStorePtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
+ return IrInstructionIdFieldPtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) {
+ return IrInstructionIdElemPtr;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {
+ return IrInstructionIdVarPtr;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
@@ -283,6 +293,37 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
return &const_instruction->base;
}
+static IrInstruction *ir_build_const_ptr(IrBuilder *irb, AstNode *source_node, ConstExprValue *pointee) {
+ IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
+ const_instruction->base.static_value.ok = true;
+ const_instruction->base.static_value.data.x_ptr.len = 1;
+ const_instruction->base.static_value.data.x_ptr.is_c_str = false;
+ const_instruction->base.static_value.data.x_ptr.ptr = allocate<ConstExprValue *>(1);
+ const_instruction->base.static_value.data.x_ptr.ptr[0] = pointee;
+ return &const_instruction->base;
+}
+
+static IrInstruction *ir_build_const_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
+ ConstExprValue *pointee)
+{
+ IrInstruction *new_instruction = ir_build_const_ptr(irb, old_instruction->source_node, pointee);
+ ir_link_new_instruction(new_instruction, old_instruction);
+ return new_instruction;
+}
+
+static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, ConstExprValue *value) {
+ IrInstructionConst *instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
+ instruction->base.static_value = *value;
+ instruction->base.static_value.ok = true;
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_const_from(IrBuilder *irb, IrInstruction *old_instruction, ConstExprValue *value) {
+ IrInstruction *new_instruction = ir_build_const(irb, old_instruction->source_node, value);
+ ir_link_new_instruction(new_instruction, old_instruction);
+ return new_instruction;
+}
+
static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id,
IrInstruction *op1, IrInstruction *op2)
{
@@ -305,20 +346,19 @@ static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_in
return new_instruction;
}
-static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
- IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node);
- load_var_instruction->base.type_entry = var->type;
- load_var_instruction->var = var;
+static IrInstruction *ir_build_var_ptr(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
+ IrInstructionVarPtr *instruction = ir_build_instruction<IrInstructionVarPtr>(irb, source_node);
+ instruction->var = var;
ir_ref_var(var);
- return &load_var_instruction->base;
+ return &instruction->base;
}
-static IrInstruction *ir_build_load_var_from(IrBuilder *irb, IrInstruction *old_instruction,
+static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
VariableTableEntry *var)
{
- IrInstruction *new_instruction = ir_build_load_var(irb, old_instruction->source_node, var);
+ IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->source_node, var);
ir_link_new_instruction(new_instruction, old_instruction);
return new_instruction;
@@ -460,16 +500,20 @@ static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *o
return new_instruction;
}
-//static IrInstruction *ir_build_store(IrBuilder *irb, AstNode *source_node,
-// VariableTableEntry *var, IrInstruction *value)
-//{
-// IrInstructionStoreVar *store_instruction = ir_build_instruction<IrInstructionStoreVar>(irb, source_node);
-// store_instruction->base.static_value.ok = true;
-// store_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
-// store_instruction->var = var;
-// store_instruction->value = value;
-// return &store_instruction->base;
-//}
+static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
+ IrInstruction *ptr, IrInstruction *value)
+{
+ IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, source_node);
+ instruction->base.static_value.ok = true;
+ instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
+ instruction->ptr = ptr;
+ instruction->value = value;
+
+ ir_ref_instruction(ptr);
+ ir_ref_instruction(value);
+
+ return &instruction->base;
+}
static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
@@ -480,6 +524,10 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
decl_var_instruction->var = var;
decl_var_instruction->var_type = var_type;
decl_var_instruction->init_value = init_value;
+
+ ir_ref_instruction(var_type);
+ ir_ref_instruction(init_value);
+
return &decl_var_instruction->base;
}
@@ -491,6 +539,21 @@ static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_
return new_instruction;
}
+static IrInstruction *ir_build_load_ptr(IrBuilder *irb, AstNode *source_node, IrInstruction *ptr) {
+ IrInstructionLoadPtr *instruction = ir_build_instruction<IrInstructionLoadPtr>(irb, source_node);
+ instruction->ptr = ptr;
+
+ ir_ref_instruction(ptr);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *ptr) {
+ IrInstruction *new_instruction = ir_build_load_ptr(irb, old_instruction->source_node, ptr);
+ ir_link_new_instruction(new_instruction, old_instruction);
+ return new_instruction;
+}
+
//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
// size_t result = 0;
// while (inner_block != outer_block) {
@@ -552,7 +615,7 @@ static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Buf *
variable_entry->block_context = node->block_context;
variable_entry->import = node->owner;
variable_entry->shadowable = is_shadowable;
- variable_entry->slot_index = exec_next_var_slot(irb->exec);
+ variable_entry->mem_slot_index = exec_next_mem_slot(irb->exec);
if (name) {
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
return ir_build_bin_op(irb, node, op_id, op1, op2);
}
+static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) {
+ IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context);
+ if (lvalue == irb->codegen->invalid_instruction)
+ return lvalue;
+ IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue);
+ IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context);
+ if (op2 == irb->codegen->invalid_instruction)
+ return op2;
+ IrInstruction *result = ir_build_bin_op(irb, node, op_id, op1, op2);
+ ir_build_store_ptr(irb, node, lvalue, result);
+ return ir_build_const_void(irb, node);
+}
+
static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
assert(node->type == NodeTypeBinOpExpr);
@@ -633,23 +709,39 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
case BinOpTypeInvalid:
zig_unreachable();
case BinOpTypeAssign:
+ zig_panic("TODO gen IR for assignment");
case BinOpTypeAssignTimes:
+ return ir_gen_assign_op(irb, node, IrBinOpMult);
case BinOpTypeAssignTimesWrap:
+ return ir_gen_assign_op(irb, node, IrBinOpMultWrap);
case BinOpTypeAssignDiv:
+ return ir_gen_assign_op(irb, node, IrBinOpDiv);
case BinOpTypeAssignMod:
+ return ir_gen_assign_op(irb, node, IrBinOpMod);
case BinOpTypeAssignPlus:
+ return ir_gen_assign_op(irb, node, IrBinOpAdd);
case BinOpTypeAssignPlusWrap:
+ return ir_gen_assign_op(irb, node, IrBinOpAddWrap);
case BinOpTypeAssignMinus:
+ return ir_gen_assign_op(irb, node, IrBinOpSub);
case BinOpTypeAssignMinusWrap:
+ return ir_gen_assign_op(irb, node, IrBinOpSubWrap);
case BinOpTypeAssignBitShiftLeft:
+ return ir_gen_assign_op(irb, node, IrBinOpBitShiftLeft);
case BinOpTypeAssignBitShiftLeftWrap:
+ return ir_gen_assign_op(irb, node, IrBinOpBitShiftLeftWrap);
case BinOpTypeAssignBitShiftRight:
+ return ir_gen_assign_op(irb, node, IrBinOpBitShiftRight);
case BinOpTypeAssignBitAnd:
+ return ir_gen_assign_op(irb, node, IrBinOpBinAnd);
case BinOpTypeAssignBitXor:
+ return ir_gen_assign_op(irb, node, IrBinOpBinXor);
case BinOpTypeAssignBitOr:
+ return ir_gen_assign_op(irb, node, IrBinOpBinOr);
case BinOpTypeAssignBoolAnd:
+ return ir_gen_assign_op(irb, node, IrBinOpBoolAnd);
case BinOpTypeAssignBoolOr:
- zig_panic("TODO gen IR for assignment");
+ return ir_gen_assign_op(irb, node, IrBinOpBoolOr);
case BinOpTypeBoolOr:
case BinOpTypeBoolAnd:
// 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
if (decl_node->type == NodeTypeVariableDeclaration) {
VariableTableEntry *var = decl_node->data.variable_declaration.variable;
- return ir_build_load_var(irb, source_node, var);
+ IrInstruction *var_ptr = ir_build_var_ptr(irb, source_node, var);
+ return ir_build_load_ptr(irb, source_node, var_ptr);
} else if (decl_node->type == NodeTypeFnProto) {
FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
assert(fn_entry->type_entry);
@@ -763,8 +856,10 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_
return ir_build_const_type(irb, node, primitive_table_entry->value);
VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name);
- if (var)
- return ir_build_load_var(irb, node, var);
+ if (var) {
+ IrInstruction *var_ptr = ir_build_var_ptr(irb, node, var);
+ return ir_build_load_ptr(irb, node, var_ptr);
+ }
AstNode *decl_node = find_decl(node->block_context, variable_name);
if (decl_node)
@@ -1011,6 +1106,44 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) {
return ir_build_var_decl(irb, node, var, type_instruction, init_value);
}
+static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
+ assert(node->type == NodeTypeWhileExpr);
+
+ AstNode *continue_expr_node = node->data.while_expr.continue_expr;
+
+ IrBasicBlock *cond_block = ir_build_basic_block(irb, "WhileCond");
+ IrBasicBlock *body_block = ir_build_basic_block(irb, "WhileBody");
+ IrBasicBlock *continue_block = continue_expr_node ?
+ ir_build_basic_block(irb, "WhileContinue") : cond_block;
+ IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd");
+
+ ir_build_br(irb, node, cond_block);
+
+ if (continue_expr_node) {
+ ir_set_cursor_at_end(irb, continue_block);
+ ir_gen_node(irb, continue_expr_node, node->block_context);
+ ir_build_br(irb, node, cond_block);
+
+ }
+
+ ir_set_cursor_at_end(irb, cond_block);
+ IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, node->block_context);
+ ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block);
+
+ ir_set_cursor_at_end(irb, body_block);
+
+ irb->break_block_stack.append(end_block);
+ irb->continue_block_stack.append(continue_block);
+ ir_gen_node(irb, node->data.while_expr.body, node->block_context);
+ irb->break_block_stack.pop();
+ irb->continue_block_stack.pop();
+
+ ir_build_br(irb, node, continue_block);
+ ir_set_cursor_at_end(irb, end_block);
+
+ return ir_build_const_void(irb, node);
+}
+
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
bool pointer_only)
{
@@ -1036,6 +1169,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
return ir_gen_container_init_expr(irb, node);
case NodeTypeVariableDeclaration:
return ir_gen_var_decl(irb, node);
+ case NodeTypeWhileExpr:
+ return ir_gen_while_expr(irb, node);
case NodeTypeUnwrapErrorExpr:
case NodeTypeReturnExpr:
case NodeTypeDefer:
@@ -1043,7 +1178,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
case NodeTypeSliceExpr:
case NodeTypeFieldAccessExpr:
case NodeTypeIfVarExpr:
- case NodeTypeWhileExpr:
case NodeTypeForExpr:
case NodeTypeAsmExpr:
case NodeTypeGoto:
@@ -1085,6 +1219,67 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *s
return ir_gen_node_extra(irb, node, scope, pointer_only_no);
}
+static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope) {
+ assert(scope);
+ node->block_context = scope;
+ switch (node->type) {
+ case NodeTypeSymbol:
+ zig_panic("TODO symbol lvalue");
+ case NodeTypeArrayAccessExpr:
+ zig_panic("TODO array access lvalue");
+ case NodeTypeFieldAccessExpr:
+ zig_panic("TODO field access lvalue");
+ case NodeTypePrefixOpExpr:
+ zig_panic("TODO prefix op lvalue");
+ case NodeTypeBlock:
+ case NodeTypeBinOpExpr:
+ case NodeTypeNumberLiteral:
+ case NodeTypeFnCallExpr:
+ case NodeTypeIfBoolExpr:
+ case NodeTypeContainerInitExpr:
+ case NodeTypeVariableDeclaration:
+ case NodeTypeWhileExpr:
+ case NodeTypeUnwrapErrorExpr:
+ case NodeTypeReturnExpr:
+ case NodeTypeDefer:
+ case NodeTypeSliceExpr:
+ case NodeTypeIfVarExpr:
+ case NodeTypeForExpr:
+ case NodeTypeAsmExpr:
+ case NodeTypeGoto:
+ case NodeTypeBreak:
+ case NodeTypeContinue:
+ case NodeTypeLabel:
+ case NodeTypeSwitchExpr:
+ case NodeTypeBoolLiteral:
+ case NodeTypeStringLiteral:
+ case NodeTypeCharLiteral:
+ case NodeTypeNullLiteral:
+ case NodeTypeUndefinedLiteral:
+ case NodeTypeZeroesLiteral:
+ case NodeTypeThisLiteral:
+ case NodeTypeErrorType:
+ case NodeTypeTypeLiteral:
+ case NodeTypeArrayType:
+ case NodeTypeVarLiteral:
+ case NodeTypeRoot:
+ case NodeTypeFnProto:
+ case NodeTypeFnDef:
+ case NodeTypeFnDecl:
+ case NodeTypeParamDecl:
+ case NodeTypeUse:
+ case NodeTypeContainerDecl:
+ case NodeTypeStructField:
+ case NodeTypeStructValueField:
+ case NodeTypeSwitchProng:
+ case NodeTypeSwitchRange:
+ case NodeTypeErrorValueDecl:
+ case NodeTypeTypeDecl:
+ zig_unreachable();
+ }
+ zig_unreachable();
+}
+
static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,
IrExecutable *ir_executable, bool add_return, bool pointer_only)
{
@@ -1965,8 +2160,8 @@ static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
}
static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
- IrInstruction *op1 = bin_op_instruction->op1;
- IrInstruction *op2 = bin_op_instruction->op2;
+ IrInstruction *op1 = bin_op_instruction->op1->other;
+ IrInstruction *op2 = bin_op_instruction->op2->other;
IrInstruction *instructions[] = {op1, op2};
TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);
if (resolved_type->id == TypeTableEntryIdInvalid)
@@ -2021,7 +2216,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
}
- ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
+ ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1, op2);
return resolved_type;
}
@@ -2169,9 +2364,9 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
var->type = result_type;
assert(var->type != nullptr); // should have been caught by the parser
- if (casted_init_value->static_value.ok) {
- // TODO set the variable in the IrVarSlot
- }
+ ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
+ *mem_slot = casted_init_value->static_value;
+
ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value);
BlockContext *scope = decl_var_instruction->base.source_node->block_context;
@@ -2181,11 +2376,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
return ira->codegen->builtin_types.entry_void;
}
-static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {
- ir_build_load_var_from(&ira->new_irb, &load_var_instruction->base, load_var_instruction->var);
- return load_var_instruction->var->type;
-}
-
static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
IrInstruction *fn_ref = call_instruction->fn->other;
if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
@@ -2345,20 +2535,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
// }
//}
case IrUnOpDereference:
- zig_panic("TODO analyze PrefixOpDereference");
- //{
- // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
- // if (type_entry->id == TypeTableEntryIdInvalid) {
- // return type_entry;
- // } else if (type_entry->id == TypeTableEntryIdPointer) {
- // return type_entry->data.pointer.child_type;
- // } else {
- // add_node_error(g, *expr_node,
- // buf_sprintf("indirection requires pointer operand ('%s' invalid)",
- // buf_ptr(&type_entry->name)));
- // return g->builtin_types.entry_invalid;
- // }
- //}
+ zig_panic("TODO remove this IrUnOp item");
case IrUnOpMaybe:
zig_panic("TODO analyze PrefixOpMaybe");
//{
@@ -3727,6 +3904,43 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
return resolved_type;
}
+static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) {
+ VariableTableEntry *var = var_ptr_instruction->var;
+ ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
+ TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false);
+ if (mem_slot->ok) {
+ ir_build_const_ptr_from(&ira->new_irb, &var_ptr_instruction->base, mem_slot);
+ return ptr_type;
+ }
+
+ ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);
+ return ptr_type;
+}
+
+static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
+ IrInstruction *ptr = load_ptr_instruction->ptr->other;
+ TypeTableEntry *type_entry = ptr->type_entry;
+ if (type_entry->id == TypeTableEntryIdInvalid) {
+ return type_entry;
+ } else if (type_entry->id == TypeTableEntryIdPointer) {
+ TypeTableEntry *child_type = type_entry->data.pointer.child_type;
+ if (ptr->static_value.ok) {
+ ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
+ if (pointee->ok) {
+ ir_build_const_from(&ira->new_irb, &load_ptr_instruction->base, pointee);
+ return child_type;
+ }
+ }
+ ir_build_load_ptr_from(&ira->new_irb, &load_ptr_instruction->base, ptr);
+ return child_type;
+ } else {
+ add_node_error(ira->codegen, load_ptr_instruction->base.source_node,
+ buf_sprintf("indirection requires pointer operand ('%s' invalid)",
+ buf_ptr(&type_entry->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+}
+
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -3741,8 +3955,16 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
case IrInstructionIdDeclVar:
return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
- case IrInstructionIdLoadVar:
- return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
+ case IrInstructionIdLoadPtr:
+ return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
+ case IrInstructionIdStorePtr:
+ zig_panic("TODO store ptr");
+ case IrInstructionIdFieldPtr:
+ zig_panic("TODO field ptr");
+ case IrInstructionIdElemPtr:
+ zig_panic("TODO elem ptr");
+ case IrInstructionIdVarPtr:
+ return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
case IrInstructionIdCall:
return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
case IrInstructionIdBr:
@@ -3756,7 +3978,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
case IrInstructionIdPhi:
return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
case IrInstructionIdSwitchBr:
- case IrInstructionIdStoreVar:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
@@ -3792,8 +4013,8 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
ira->new_irb.codegen = codegen;
ira->new_irb.exec = new_exec;
- ira->exec_context.var_slot_count = ira->old_irb.exec->var_slot_count;
- ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count);
+ ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;
+ ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);
TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
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) {
case IrInstructionIdCondBr:
case IrInstructionIdSwitchBr:
case IrInstructionIdDeclVar:
- case IrInstructionIdStoreVar:
+ case IrInstructionIdStorePtr:
case IrInstructionIdCall:
case IrInstructionIdReturn:
case IrInstructionIdUnreachable:
@@ -3889,11 +4110,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPhi:
case IrInstructionIdUnOp:
case IrInstructionIdBinOp:
- case IrInstructionIdLoadVar:
+ case IrInstructionIdLoadPtr:
case IrInstructionIdConst:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
+ case IrInstructionIdFieldPtr:
+ case IrInstructionIdElemPtr:
+ case IrInstructionIdVarPtr:
return false;
case IrInstructionIdBuiltinCall:
return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction);
src/ir_print.cpp
@@ -21,8 +21,7 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);
}
-static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
- TypeTableEntry *type_entry = instruction->type_entry;
+static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
zig_unreachable();
@@ -30,21 +29,21 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
fprintf(irp->f, "{}");
break;
case TypeTableEntryIdNumLitFloat:
- fprintf(irp->f, "%f", instruction->static_value.data.x_bignum.data.x_float);
+ fprintf(irp->f, "%f", const_val->data.x_bignum.data.x_float);
break;
case TypeTableEntryIdNumLitInt:
{
- BigNum *bignum = &instruction->static_value.data.x_bignum;
+ BigNum *bignum = &const_val->data.x_bignum;
const char *negative_str = bignum->is_negative ? "-" : "";
fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
break;
}
case TypeTableEntryIdMetaType:
- fprintf(irp->f, "%s", buf_ptr(&instruction->static_value.data.x_type->name));
+ fprintf(irp->f, "%s", buf_ptr(&const_val->data.x_type->name));
break;
case TypeTableEntryIdInt:
{
- BigNum *bignum = &instruction->static_value.data.x_bignum;
+ BigNum *bignum = &const_val->data.x_bignum;
assert(bignum->kind == BigNumKindInt);
const char *negative_str = bignum->is_negative ? "-" : "";
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)
case TypeTableEntryIdUnreachable:
fprintf(irp->f, "@unreachable()");
break;
- case TypeTableEntryIdVar:
case TypeTableEntryIdBool:
- case TypeTableEntryIdFloat:
+ {
+ const char *value = const_val->data.x_bool ? "true" : "false";
+ fprintf(irp->f, "%s", value);
+ break;
+ }
case TypeTableEntryIdPointer:
+ fprintf(irp->f, "&");
+ ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);
+ break;
+ case TypeTableEntryIdVar:
+ case TypeTableEntryIdFloat:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
case TypeTableEntryIdUndefLit:
@@ -75,6 +82,12 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
}
}
+static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
+ TypeTableEntry *type_entry = instruction->type_entry;
+ ConstExprValue *const_val = &instruction->static_value;
+ ir_print_const_value(irp, type_entry, const_val);
+}
+
static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
if (instruction->static_value.ok) {
ir_print_const_instruction(irp, instruction);
@@ -211,10 +224,6 @@ static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instr
ir_print_other_instruction(irp, decl_var_instruction->init_value);
}
-static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
- fprintf(irp->f, "%s", buf_ptr(&load_var_instruction->var->name));
-}
-
static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
fprintf(irp->f, "cast ");
ir_print_other_instruction(irp, cast_instruction->value);
@@ -301,9 +310,20 @@ static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruc
fprintf(irp->f, "unreachable");
}
-static void ir_print_store(IrPrint *irp, IrInstructionStoreVar *store_instruction) {
- fprintf(irp->f, "%s = ", buf_ptr(&store_instruction->var->name));
- ir_print_other_instruction(irp, store_instruction->value);
+static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {
+ ir_print_other_instruction(irp, instruction->array_ptr);
+ fprintf(irp->f, "[");
+ ir_print_other_instruction(irp, instruction->elem_index);
+ fprintf(irp->f, "]");
+}
+
+static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
+ fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
+}
+
+static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
+ fprintf(irp->f, "*");
+ ir_print_other_instruction(irp, instruction->ptr);
}
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
@@ -323,9 +343,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdDeclVar:
ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
break;
- case IrInstructionIdLoadVar:
- ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);
- break;
case IrInstructionIdCast:
ir_print_cast(irp, (IrInstructionCast *)instruction);
break;
@@ -356,10 +373,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdUnreachable:
ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
break;
- case IrInstructionIdStoreVar:
- ir_print_store(irp, (IrInstructionStoreVar *)instruction);
+ case IrInstructionIdElemPtr:
+ ir_print_elem_ptr(irp, (IrInstructionElemPtr *)instruction);
+ break;
+ case IrInstructionIdVarPtr:
+ ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
+ break;
+ case IrInstructionIdLoadPtr:
+ ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
break;
case IrInstructionIdSwitchBr:
+ case IrInstructionIdStorePtr:
+ case IrInstructionIdFieldPtr:
zig_panic("TODO print more IR instructions");
}
fprintf(irp->f, "\n");
CMakeLists.txt
@@ -38,6 +38,7 @@ include_directories(
)
set(ZIG_SOURCES
+ "${CMAKE_SOURCE_DIR}/src/ir.cpp"
"${CMAKE_SOURCE_DIR}/src/analyze.cpp"
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
"${CMAKE_SOURCE_DIR}/src/bignum.cpp"
@@ -47,7 +48,6 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
"${CMAKE_SOURCE_DIR}/src/error.cpp"
"${CMAKE_SOURCE_DIR}/src/eval.cpp"
- "${CMAKE_SOURCE_DIR}/src/ir.cpp"
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
"${CMAKE_SOURCE_DIR}/src/link.cpp"
"${CMAKE_SOURCE_DIR}/src/main.cpp"