Commit 114049a220
Changed files (4)
src/analyze.cpp
@@ -3575,6 +3575,7 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_
variable_entry->block_context = context;
variable_entry->import = import;
variable_entry->shadowable = shadowable;
+ variable_entry->mem_slot_index = SIZE_MAX;
if (name) {
buf_init_from_buf(&variable_entry->name, name);
src/codegen.cpp
@@ -1539,79 +1539,44 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
}
-static LLVMIntPredicate cmp_op_to_int_predicate(BinOpType cmp_op, bool is_signed) {
+static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) {
switch (cmp_op) {
- case BinOpTypeCmpEq:
+ case IrBinOpCmpEq:
return LLVMIntEQ;
- case BinOpTypeCmpNotEq:
+ case IrBinOpCmpNotEq:
return LLVMIntNE;
- case BinOpTypeCmpLessThan:
+ case IrBinOpCmpLessThan:
return is_signed ? LLVMIntSLT : LLVMIntULT;
- case BinOpTypeCmpGreaterThan:
+ case IrBinOpCmpGreaterThan:
return is_signed ? LLVMIntSGT : LLVMIntUGT;
- case BinOpTypeCmpLessOrEq:
+ case IrBinOpCmpLessOrEq:
return is_signed ? LLVMIntSLE : LLVMIntULE;
- case BinOpTypeCmpGreaterOrEq:
+ case IrBinOpCmpGreaterOrEq:
return is_signed ? LLVMIntSGE : LLVMIntUGE;
default:
zig_unreachable();
}
}
-static LLVMRealPredicate cmp_op_to_real_predicate(BinOpType cmp_op) {
+static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
switch (cmp_op) {
- case BinOpTypeCmpEq:
+ case IrBinOpCmpEq:
return LLVMRealOEQ;
- case BinOpTypeCmpNotEq:
+ case IrBinOpCmpNotEq:
return LLVMRealONE;
- case BinOpTypeCmpLessThan:
+ case IrBinOpCmpLessThan:
return LLVMRealOLT;
- case BinOpTypeCmpGreaterThan:
+ case IrBinOpCmpGreaterThan:
return LLVMRealOGT;
- case BinOpTypeCmpLessOrEq:
+ case IrBinOpCmpLessOrEq:
return LLVMRealOLE;
- case BinOpTypeCmpGreaterOrEq:
+ case IrBinOpCmpGreaterOrEq:
return LLVMRealOGE;
default:
zig_unreachable();
}
}
-static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) {
- assert(node->type == NodeTypeBinOpExpr);
-
- LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
- LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
-
- TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
- TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
- assert(op1_type == op2_type);
-
- if (op1_type->id == TypeTableEntryIdFloat) {
- LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op);
- return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
- } else if (op1_type->id == TypeTableEntryIdInt) {
- LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op,
- op1_type->data.integral.is_signed);
- return LLVMBuildICmp(g->builder, pred, val1, val2, "");
- } else if (op1_type->id == TypeTableEntryIdEnum) {
- if (op1_type->data.enumeration.gen_field_count == 0) {
- LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, false);
- return LLVMBuildICmp(g->builder, pred, val1, val2, "");
- } else {
- zig_unreachable();
- }
- } else if (op1_type->id == TypeTableEntryIdPureError ||
- op1_type->id == TypeTableEntryIdPointer ||
- op1_type->id == TypeTableEntryIdBool)
- {
- LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, false);
- return LLVMBuildICmp(g->builder, pred, val1, val2, "");
- } else {
- zig_unreachable();
- }
-}
-
static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeBinOpExpr);
@@ -1844,7 +1809,7 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
case BinOpTypeCmpGreaterThan:
case BinOpTypeCmpLessOrEq:
case BinOpTypeCmpGreaterOrEq:
- return gen_cmp_expr(g, node);
+ zig_panic("moved to ir_render");
case BinOpTypeUnwrapMaybe:
return gen_unwrap_maybe_expr(g, node);
case BinOpTypeBinOr:
@@ -2341,6 +2306,41 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
}
}
+static LLVMValueRef ir_render_bin_op_cmp(CodeGen *g, IrExecutable *executable,
+ IrInstructionBinOp *bin_op_instruction)
+{
+ IrBinOp op_id = bin_op_instruction->op_id;
+ LLVMValueRef val1 = ir_llvm_value(g, bin_op_instruction->op1);
+ LLVMValueRef val2 = ir_llvm_value(g, bin_op_instruction->op2);
+
+ TypeTableEntry *op1_type = bin_op_instruction->op1->type_entry;
+ TypeTableEntry *op2_type = bin_op_instruction->op2->type_entry;
+ assert(op1_type == op2_type);
+
+ if (op1_type->id == TypeTableEntryIdFloat) {
+ LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
+ return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
+ } else if (op1_type->id == TypeTableEntryIdInt) {
+ LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1_type->data.integral.is_signed);
+ return LLVMBuildICmp(g->builder, pred, val1, val2, "");
+ } else if (op1_type->id == TypeTableEntryIdEnum) {
+ if (op1_type->data.enumeration.gen_field_count == 0) {
+ LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
+ return LLVMBuildICmp(g->builder, pred, val1, val2, "");
+ } else {
+ zig_unreachable();
+ }
+ } else if (op1_type->id == TypeTableEntryIdPureError ||
+ op1_type->id == TypeTableEntryIdPointer ||
+ op1_type->id == TypeTableEntryIdBool)
+ {
+ LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
+ return LLVMBuildICmp(g->builder, pred, val1, val2, "");
+ } else {
+ zig_unreachable();
+ }
+}
+
static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
IrInstructionBinOp *bin_op_instruction)
{
@@ -2389,7 +2389,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpCmpGreaterThan:
case IrBinOpCmpLessOrEq:
case IrBinOpCmpGreaterOrEq:
- zig_panic("TODO bin op cmp");
+ return ir_render_bin_op_cmp(g, executable, bin_op_instruction);
case IrBinOpAdd:
case IrBinOpAddWrap:
return ir_render_bin_op_add(g, executable, bin_op_instruction);
@@ -2860,6 +2860,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), "");
}
+static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
+ LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
+ LLVMValueRef value = ir_llvm_value(g, instruction->value);
+ LLVMBuildStore(g->builder, value, ptr);
+ return nullptr;
+}
+
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
return instruction->var->value_ref;
}
@@ -2931,13 +2938,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
case IrInstructionIdLoadPtr:
return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
+ case IrInstructionIdStorePtr:
+ return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
case IrInstructionIdVarPtr:
return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
case IrInstructionIdCall:
return ir_render_call(g, executable, (IrInstructionCall *)instruction);
case IrInstructionIdSwitchBr:
case IrInstructionIdPhi:
- case IrInstructionIdStorePtr:
case IrInstructionIdBuiltinCall:
case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields:
src/ir.cpp
@@ -21,7 +21,7 @@ struct IrAnalyze {
IrBuilder old_irb;
IrBuilder new_irb;
IrExecContext exec_context;
- ZigList<IrBasicBlock *> block_queue;
+ ZigList<IrBasicBlock *> old_bb_queue;
size_t block_queue_index;
size_t instruction_index;
TypeTableEntry *explicit_return_type;
@@ -1609,15 +1609,15 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
if (old_bb->other)
return old_bb->other;
IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);
- ira->block_queue.append(new_bb);
+ ira->old_bb_queue.append(old_bb);
return new_bb;
}
static void ir_finish_bb(IrAnalyze *ira) {
ira->block_queue_index += 1;
- if (ira->block_queue_index < ira->block_queue.length) {
- IrBasicBlock *old_bb = ira->block_queue.at(ira->block_queue_index);
+ if (ira->block_queue_index < ira->old_bb_queue.length) {
+ IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index);
ira->instruction_index = 0;
ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);
ira->old_irb.current_basic_block = old_bb;
@@ -2260,9 +2260,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
return ira->codegen->builtin_types.entry_invalid;
}
- if (op1->static_value.ok && op2->static_value.ok) {
- ConstExprValue *op1_val = &op1->static_value;
- ConstExprValue *op2_val = &op2->static_value;
+ IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, resolved_type);
+ if (casted_op1 == ira->codegen->invalid_instruction)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, resolved_type);
+ if (casted_op2 == ira->codegen->invalid_instruction)
+ return ira->codegen->builtin_types.entry_invalid;
+
+
+ if (casted_op1->static_value.ok && casted_op2->static_value.ok) {
+ ConstExprValue *op1_val = &casted_op1->static_value;
+ ConstExprValue *op2_val = &casted_op2->static_value;
ConstExprValue *out_val = &bin_op_instruction->base.static_value;
bin_op_instruction->base.other = &bin_op_instruction->base;
@@ -2286,8 +2295,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, op2);
-
+ ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2);
return resolved_type;
}
@@ -4006,17 +4014,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
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) {
- ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base);
-
- out_val->ok = true;
- out_val->data.x_ptr.len = 1;
- out_val->data.x_ptr.is_c_str = false;
- out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
- out_val->data.x_ptr.ptr[0] = mem_slot;
- return ptr_type;
+ // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing.
+ if (var->mem_slot_index != SIZE_MAX) {
+ ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
+ if (mem_slot->ok) {
+ ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base);
+
+ out_val->ok = true;
+ out_val->data.x_ptr.len = 1;
+ out_val->data.x_ptr.is_c_str = false;
+ out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
+ out_val->data.x_ptr.ptr[0] = mem_slot;
+ return ptr_type;
+ }
}
ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var);
@@ -4065,6 +4076,30 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
}
}
+ if (ptr->static_value.ok) {
+ // This memory location is transforming from known at compile time to known at runtime.
+ // We must emit our own var ptr instruction.
+ ptr->static_value.ok = false;
+ IrInstruction *new_ptr_inst;
+ if (ptr->id == IrInstructionIdVarPtr) {
+ IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr;
+ VariableTableEntry *var = var_ptr_inst->var;
+ new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var);
+ assert(var->mem_slot_index != SIZE_MAX);
+ ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
+ mem_slot->ok = false;
+ } else if (ptr->id == IrInstructionIdFieldPtr) {
+ zig_panic("TODO");
+ } else if (ptr->id == IrInstructionIdElemPtr) {
+ zig_panic("TODO");
+ } else {
+ zig_unreachable();
+ }
+ new_ptr_inst->type_entry = ptr->type_entry;
+ ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, new_ptr_inst, casted_value);
+ return ira->codegen->builtin_types.entry_void;
+ }
+
ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value);
return ira->codegen->builtin_types.entry_void;
}
@@ -4153,7 +4188,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
ira->block_queue_index = 0;
ira->instruction_index = 0;
- while (ira->block_queue_index < ira->block_queue.length) {
+ while (ira->block_queue_index < ira->old_bb_queue.length) {
IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
ira->instruction_index += 1;
src/ir_print.cpp
@@ -93,11 +93,15 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction)
ir_print_const_value(irp, type_entry, const_val);
}
+static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
+ fprintf(irp->f, "#%zu", instruction->debug_id);
+}
+
static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
if (instruction->static_value.ok) {
ir_print_const_instruction(irp, instruction);
} else {
- fprintf(irp->f, "#%zu", instruction->debug_id);
+ ir_print_var_instruction(irp, instruction);
}
}
@@ -333,7 +337,7 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
fprintf(irp->f, "*");
- ir_print_other_instruction(irp, instruction->ptr);
+ ir_print_var_instruction(irp, instruction->ptr);
fprintf(irp->f, " = ");
ir_print_other_instruction(irp, instruction->value);
}