Commit 0d2f2b79ea

Andrew Kelley <superjoe30@gmail.com>
2016-12-18 07:54:27
IR: basic support for implicit casting to const pointer
1 parent 69cf0ea
Changed files (3)
src/codegen.cpp
@@ -1677,6 +1677,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru
     if (handle_is_ptr(instruction->value->type_entry)) {
         return value;
     } else {
+        assert(instruction->tmp_ptr);
         LLVMBuildStore(g->builder, value, instruction->tmp_ptr);
         return instruction->tmp_ptr;
     }
@@ -2843,6 +2844,7 @@ static void do_code_gen(CodeGen *g) {
         for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {
             IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
             LLVMValueRef *slot;
+            TypeTableEntry *slot_type = instruction->type_entry;
             if (instruction->id == IrInstructionIdCast) {
                 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
                 slot = &cast_instruction->tmp_ptr;
@@ -2876,7 +2878,7 @@ static void do_code_gen(CodeGen *g) {
             } else {
                 zig_unreachable();
             }
-            *slot = LLVMBuildAlloca(g->builder, instruction->type_entry->type_ref, "");
+            *slot = LLVMBuildAlloca(g->builder, slot_type->type_ref, "");
         }
 
         ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
src/ir.cpp
@@ -4230,6 +4230,13 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
         return ImplicitCastMatchResultYes;
     }
 
+    // implicitly take a const pointer to something
+    {
+        TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
+        if (types_match_const_cast_only(expected_type, const_ptr_actual)) {
+            return ImplicitCastMatchResultYes;
+        }
+    }
 
     return ImplicitCastMatchResultNo;
 }
@@ -4721,6 +4728,30 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
     return result;
 }
 
+static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
+    if (instr_is_comptime(value)) {
+        ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+        if (!val)
+            return ira->codegen->invalid_instruction;
+
+        IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
+                source_instr->scope, source_instr->source_node);
+        const_instruction->base.type_entry = wanted_type;
+        const_instruction->base.static_value.special = ConstValSpecialStatic;
+        const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var;
+        const_instruction->base.static_value.data.x_ptr.base_ptr = val;
+        const_instruction->base.static_value.data.x_ptr.index = SIZE_MAX;
+        return &const_instruction->base;
+    }
+
+    if (value->id == IrInstructionIdLoadPtr) {
+        IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;
+        return load_ptr_inst->ptr;
+    } else {
+        zig_panic("TODO more ways to cast to const pointer");
+    }
+}
+
 static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
     assert(wanted_type->id == TypeTableEntryIdMaybe);
     assert(instr_is_comptime(value));
@@ -4974,6 +5005,14 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
     }
 
+    // explicit cast from something to const pointer of it
+    {
+        TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
+        if (types_match_const_cast_only(wanted_type, const_ptr_actual)) {
+            return ir_analyze_cast_ref(ira, source_instr, value, wanted_type);
+        }
+    }
+
     add_node_error(ira->codegen, source_instr->source_node,
         buf_sprintf("invalid cast from type '%s' to '%s'",
             buf_ptr(&actual_type->name),
std/io.zig
@@ -82,7 +82,7 @@ pub struct OutStream {
 
     pub fn write(self: &OutStream, bytes: []const u8) -> %usize {
         var src_bytes_left = bytes.len;
-        var src_index: @typeOf(bytes.len) = 0;
+        var src_index: usize = 0;
         const dest_space_left = self.buffer.len - self.index;
 
         while (src_bytes_left > 0) {