IR: introduce concept of lvalues
This commit is contained in:
289
src/codegen.cpp
289
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
|
||||
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");
|
||||
}
|
||||
//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);
|
||||
//set_debug_source_node(g, node);
|
||||
//LLVMBuildBr(g->builder, body_block);
|
||||
|
||||
if (continue_expr_node) {
|
||||
LLVMPositionBuilderAtEnd(g->builder, continue_block);
|
||||
//if (continue_expr_node) {
|
||||
// LLVMPositionBuilderAtEnd(g->builder, continue_block);
|
||||
|
||||
gen_expr(g, continue_expr_node);
|
||||
// gen_expr(g, continue_expr_node);
|
||||
|
||||
set_debug_source_node(g, node);
|
||||
LLVMBuildBr(g->builder, body_block);
|
||||
}
|
||||
// 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();
|
||||
//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 (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);
|
||||
}
|
||||
//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);
|
||||
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);
|
||||
//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);
|
||||
//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");
|
||||
//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);
|
||||
//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);
|
||||
//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);
|
||||
//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, 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);
|
||||
//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);
|
||||
}
|
||||
//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, 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;
|
||||
//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();
|
||||
//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);
|
||||
//}
|
||||
|
||||
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_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:
|
||||
|
||||
Reference in New Issue
Block a user