IR: consolidate Ref and PrefixOpAddressOf instructions
This commit is contained in:
parent
0f047337ac
commit
d245fabb80
@ -1517,8 +1517,6 @@ enum IrUnOp {
|
||||
IrUnOpBinNot,
|
||||
IrUnOpNegation,
|
||||
IrUnOpNegationWrap,
|
||||
IrUnOpAddressOf,
|
||||
IrUnOpConstAddressOf,
|
||||
IrUnOpDereference,
|
||||
IrUnOpError,
|
||||
IrUnOpMaybe,
|
||||
|
@ -1175,13 +1175,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
|
||||
}
|
||||
case IrUnOpBinNot:
|
||||
return LLVMBuildNot(g->builder, expr, "");
|
||||
case IrUnOpAddressOf:
|
||||
case IrUnOpConstAddressOf:
|
||||
zig_panic("TODO address of codegen");
|
||||
//{
|
||||
// TypeTableEntry *lvalue_type;
|
||||
// return gen_lvalue(g, node, expr_node, &lvalue_type);
|
||||
//}
|
||||
case IrUnOpDereference:
|
||||
{
|
||||
assert(expr_type->id == TypeTableEntryIdPointer);
|
||||
|
155
src/ir.cpp
155
src/ir.cpp
@ -2368,8 +2368,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
|
||||
auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);
|
||||
if (primitive_table_entry) {
|
||||
IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);
|
||||
if (lval == LValPurposeAddressOf) {
|
||||
return ir_build_un_op(irb, scope, node, IrUnOpAddressOf, value);
|
||||
if (lval != LValPurposeNone) {
|
||||
return ir_build_ref(irb, scope, node, value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
if (lval == LValPurposeAddressOf && (op_id == IrUnOpAddressOf || op_id == IrUnOpConstAddressOf)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return ir_build_un_op(irb, scope, node, op_id, value);
|
||||
}
|
||||
|
||||
@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
|
||||
return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
|
||||
if (lval == LValPurposeNone)
|
||||
return value;
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
// We needed a pointer to a value, but we got a value. So we create
|
||||
// an instruction which just makes a const pointer of it.
|
||||
return ir_build_ref(irb, scope, value->source_node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) {
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
|
||||
IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
|
||||
return ir_lval_wrap(irb, scope, value, lval);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
@ -3002,17 +3021,6 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
|
||||
return ir_build_bool_not(irb, scope, node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
|
||||
if (lval == LValPurposeNone)
|
||||
return value;
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
// We needed a pointer to a value, but we got a value. So we create
|
||||
// an instruction which just makes a const pointer of it.
|
||||
return ir_build_ref(irb, scope, value->source_node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
|
||||
@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
|
||||
case PrefixOpBoolNot:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
|
||||
case PrefixOpBinNot:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval);
|
||||
case PrefixOpNegation:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
|
||||
case PrefixOpNegationWrap:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
|
||||
case PrefixOpAddressOf:
|
||||
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpAddressOf, LValPurposeAddressOf);
|
||||
return ir_gen_address_of(irb, scope, node, false, lval);
|
||||
case PrefixOpConstAddressOf:
|
||||
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpConstAddressOf, LValPurposeAddressOf);
|
||||
return ir_gen_address_of(irb, scope, node, true, lval);
|
||||
case PrefixOpDereference:
|
||||
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
|
||||
case PrefixOpMaybe:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
|
||||
case PrefixOpError:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval);
|
||||
case PrefixOpUnwrapError:
|
||||
return ir_gen_err_assert_ok(irb, scope, node, lval);
|
||||
case PrefixOpUnwrapMaybe:
|
||||
@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
|
||||
ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var,
|
||||
ConstPtrSpecial special, bool ptr_is_const)
|
||||
{
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const);
|
||||
ConstExprValue *const_val = ir_build_const_from(ira, instruction,
|
||||
depends_on_compile_var || pointee->depends_on_compile_var);
|
||||
const_val->data.x_ptr.base_ptr = pointee;
|
||||
const_val->data.x_ptr.index = SIZE_MAX;
|
||||
const_val->data.x_ptr.special = special;
|
||||
return ptr_type;
|
||||
if (pointee_type->id == TypeTableEntryIdMetaType) {
|
||||
TypeTableEntry *type_entry = pointee->data.x_type;
|
||||
ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var || pointee->depends_on_compile_var);
|
||||
const_val->data.x_type = get_pointer_to_type(ira->codegen, type_entry, ptr_is_const);
|
||||
return pointee_type;
|
||||
} else {
|
||||
TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const);
|
||||
ConstExprValue *const_val = ir_build_const_from(ira, instruction,
|
||||
depends_on_compile_var || pointee->depends_on_compile_var);
|
||||
const_val->data.x_ptr.base_ptr = pointee;
|
||||
const_val->data.x_ptr.index = SIZE_MAX;
|
||||
const_val->data.x_ptr.special = special;
|
||||
return ptr_type;
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value,
|
||||
@ -5004,6 +5019,20 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
|
||||
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr);
|
||||
load_ptr_instruction->type_entry = child_type;
|
||||
return load_ptr_instruction;
|
||||
} else if (type_entry->id == TypeTableEntryIdMetaType) {
|
||||
ConstExprValue *ptr_val = ir_resolve_const(ira, ptr);
|
||||
if (!ptr_val)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
TypeTableEntry *ptr_type = ptr_val->data.x_type;
|
||||
if (ptr_type->id == TypeTableEntryIdPointer) {
|
||||
TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
|
||||
return ir_create_const_type(&ira->new_irb, source_instruction->scope, source_instruction->source_node, child_type);
|
||||
} else {
|
||||
ir_add_error(ira, source_instruction,
|
||||
buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
} else {
|
||||
add_node_error(ira->codegen, source_instruction->source_node,
|
||||
buf_sprintf("attempt to dereference non pointer type '%s'",
|
||||
@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
|
||||
return ptr_type;
|
||||
}
|
||||
|
||||
|
||||
static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {
|
||||
if (value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return false;
|
||||
@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction,
|
||||
bool is_const)
|
||||
{
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
if (value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *target_type = value->type_entry;
|
||||
TypeTableEntry *canon_target_type = get_underlying_type(target_type);
|
||||
switch (canon_target_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
// impossible because we look at the canonicalized type
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdInvalid:
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
add_node_error(ira->codegen, un_op_instruction->base.source_node,
|
||||
buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name)));
|
||||
// TODO if type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdMetaType:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
|
||||
value->static_value.depends_on_compile_var);
|
||||
assert(value->static_value.special != ConstValSpecialRuntime);
|
||||
TypeTableEntry *child_type = value->static_value.data.x_type;
|
||||
out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
|
||||
return ira->codegen->builtin_types.entry_type;
|
||||
}
|
||||
case TypeTableEntryIdPointer:
|
||||
{
|
||||
// this instruction is a noop - we solved this in IR gen by passing
|
||||
// LValPurposeAddressOf which caused the loadptr to not do the load.
|
||||
ir_link_new_instruction(value, &un_op_instruction->base);
|
||||
return ir_finish_anal(ira, target_type);
|
||||
}
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
zig_unreachable();
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
|
||||
case IrUnOpNegation:
|
||||
case IrUnOpNegationWrap:
|
||||
return ir_analyze_negation(ira, un_op_instruction);
|
||||
case IrUnOpAddressOf:
|
||||
case IrUnOpConstAddressOf:
|
||||
return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf);
|
||||
case IrUnOpDereference:
|
||||
return ir_analyze_dereference(ira, un_op_instruction);
|
||||
case IrUnOpMaybe:
|
||||
|
@ -285,10 +285,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
|
||||
return "-";
|
||||
case IrUnOpNegationWrap:
|
||||
return "-%";
|
||||
case IrUnOpAddressOf:
|
||||
return "&";
|
||||
case IrUnOpConstAddressOf:
|
||||
return "&const";
|
||||
case IrUnOpDereference:
|
||||
return "*";
|
||||
case IrUnOpMaybe:
|
||||
|
Loading…
x
Reference in New Issue
Block a user