Commit d245fabb80

Andrew Kelley <superjoe30@gmail.com>
2016-12-18 04:00:55
IR: consolidate Ref and PrefixOpAddressOf instructions
1 parent 0f04733
src/all_types.hpp
@@ -1517,8 +1517,6 @@ enum IrUnOp {
     IrUnOpBinNot,
     IrUnOpNegation,
     IrUnOpNegationWrap,
-    IrUnOpAddressOf,
-    IrUnOpConstAddressOf,
     IrUnOpDereference,
     IrUnOpError,
     IrUnOpMaybe,
src/codegen.cpp
@@ -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);
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:
src/ir_print.cpp
@@ -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: