diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-12-26 15:45:50 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-12-26 15:45:50 -0500 |
| commit | 735cdbfdaca6405d1465ea859032412499c658d8 (patch) | |
| tree | a3b6655d26985adafbf71903c5d5bb7049a45454 /src | |
| parent | aee7ad3de2e3c334ec5aac2d355e4eed086f1cdf (diff) | |
| download | zig-735cdbfdaca6405d1465ea859032412499c658d8.tar.gz zig-735cdbfdaca6405d1465ea859032412499c658d8.zip | |
IR: pass intToPtrCast test
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 21 | ||||
| -rw-r--r-- | src/codegen.cpp | 20 | ||||
| -rw-r--r-- | src/ir.cpp | 88 | ||||
| -rw-r--r-- | src/ir_print.cpp | 24 | ||||
| -rw-r--r-- | src/parseh.cpp | 2 |
5 files changed, 143 insertions, 12 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 6f4947d436..360ffa3cba 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -90,6 +90,11 @@ enum ConstPtrSpecial { // This means that the pointer points to inline memory, so attempting // to write a non-compile-time known value is an error ConstPtrSpecialInline, + // This means that we did a compile-time pointer reinterpret and we cannot + // understand the value of pointee at compile time. However, we will still + // emit a binary with a compile time known address. + // In this case index is the numeric address value. + ConstPtrSpecialRuntime, }; struct ConstPtrValue { @@ -427,8 +432,6 @@ struct AstNodeUnwrapErrorExpr { enum CastOp { CastOpNoCast, // signifies the function call expression is not a cast CastOpNoop, // fn call expr is a cast, but does nothing - CastOpPtrToInt, - CastOpIntToPtr, CastOpErrToInt, CastOpIntToFloat, CastOpFloatToInt, @@ -1453,6 +1456,8 @@ enum IrInstructionId { IrInstructionIdInitEnum, IrInstructionIdPointerReinterpret, IrInstructionIdWidenOrShorten, + IrInstructionIdIntToPtr, + IrInstructionIdPtrToInt, }; struct IrInstruction { @@ -2101,6 +2106,18 @@ struct IrInstructionWidenOrShorten { IrInstruction *target; }; +struct IrInstructionPtrToInt { + IrInstruction base; + + IrInstruction *target; +}; + +struct IrInstructionIntToPtr { + IrInstruction base; + + IrInstruction *target; +}; + enum LValPurpose { LValPurposeNone, LValPurposeAssign, diff --git a/src/codegen.cpp b/src/codegen.cpp index 6ab14cffe1..cf737fc7c3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -969,10 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, } else { zig_panic("TODO"); } - case CastOpPtrToInt: - return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); - case CastOpIntToPtr: - return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, ""); case CastOpResizeSlice: { assert(cast_instruction->tmp_ptr); @@ -1114,6 +1110,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa instruction->base.value.type, target_val); } +static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) { + TypeTableEntry *wanted_type = instruction->base.value.type; + LLVMValueRef target_val = ir_llvm_value(g, instruction->target); + return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, ""); +} + +static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) { + TypeTableEntry *wanted_type = instruction->base.value.type; + LLVMValueRef target_val = ir_llvm_value(g, instruction->target); + return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, ""); +} + static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable, IrInstructionUnreachable *unreachable_instruction) { @@ -2347,6 +2355,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction); case IrInstructionIdWidenOrShorten: return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction); + case IrInstructionIdPtrToInt: + return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction); + case IrInstructionIdIntToPtr: + return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction); case IrInstructionIdContainerInitList: return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); case IrInstructionIdSwitchVar: diff --git a/src/ir.cpp b/src/ir.cpp index 51a652451b..7eac05def6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -52,6 +52,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { assert(const_val->special == ConstValSpecialStatic); + assert(const_val->data.x_ptr.special != ConstPtrSpecialRuntime); ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; size_t index = const_val->data.x_ptr.index; @@ -459,6 +460,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten * return IrInstructionIdWidenOrShorten; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrToInt *) { + return IrInstructionIdPtrToInt; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) { + return IrInstructionIdIntToPtr; +} + template<typename T> static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { T *special_instruction = allocate<T>(1); @@ -1899,6 +1908,30 @@ static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, As return &instruction->base; } +static IrInstruction *ir_build_int_to_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *target) +{ + IrInstructionIntToPtr *instruction = ir_build_instruction<IrInstructionIntToPtr>( + irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target); + + return &instruction->base; +} + +static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *target) +{ + IrInstructionPtrToInt *instruction = ir_build_instruction<IrInstructionPtrToInt>( + irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target); + + return &instruction->base; +} + static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; @@ -4657,8 +4690,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, *const_val = *other_val; const_val->type = new_type; break; - case CastOpPtrToInt: - case CastOpIntToPtr: case CastOpResizeSlice: case CastOpBytesToSlice: // can't do it @@ -5234,6 +5265,51 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction return result; } +static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *target, TypeTableEntry *wanted_type) +{ + assert(wanted_type->id == TypeTableEntryIdInt); + + if (instr_is_comptime(target)) { + ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); + if (!val) + return ira->codegen->invalid_instruction; + if (val->data.x_ptr.special == ConstPtrSpecialRuntime) { + IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, + source_instr->source_node, wanted_type, val->depends_on_compile_var); + bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.index); + return result; + } + } + + IrInstruction *result = ir_build_ptr_to_int(&ira->new_irb, source_instr->scope, + source_instr->source_node, target); + result->value.type = wanted_type; + return result; +} + +static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *target, TypeTableEntry *wanted_type) +{ + assert(wanted_type->id == TypeTableEntryIdPointer); + + if (instr_is_comptime(target)) { + ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); + if (!val) + return ira->codegen->invalid_instruction; + IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, + source_instr->source_node, wanted_type, val->depends_on_compile_var); + result->value.data.x_ptr.base_ptr = nullptr; + result->value.data.x_ptr.index = bignum_to_twos_complement(&val->data.x_bignum); + result->value.data.x_ptr.special = ConstPtrSpecialRuntime; + return result; + } + + IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope, + source_instr->source_node, target); + result->value.type = wanted_type; + return result; +} static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, TypeTableEntry *wanted_type, IrInstruction *value) @@ -5270,7 +5346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) && type_is_codegen_pointer(actual_type_canon)) { - return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPtrToInt, false); + return ir_analyze_ptr_to_int(ira, source_instr, value, wanted_type); } @@ -5278,7 +5354,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (wanted_type_canon->id == TypeTableEntryIdPointer && (actual_type_canon == isize_type || actual_type_canon == usize_type)) { - return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToPtr, false); + return ir_analyze_int_to_ptr(ira, source_instr, value, wanted_type); } // explicit widening or shortening cast @@ -9937,6 +10013,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi case IrInstructionIdInvalid: case IrInstructionIdPointerReinterpret: case IrInstructionIdWidenOrShorten: + case IrInstructionIdIntToPtr: + case IrInstructionIdPtrToInt: case IrInstructionIdStructInit: case IrInstructionIdStructFieldPtr: case IrInstructionIdEnumFieldPtr: @@ -10244,6 +10322,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdInitEnum: case IrInstructionIdPointerReinterpret: case IrInstructionIdWidenOrShorten: + case IrInstructionIdPtrToInt: + case IrInstructionIdIntToPtr: return false; case IrInstructionIdAsm: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index f0dda04c6d..3db8b32e4f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -98,7 +98,11 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) { } case TypeTableEntryIdPointer: fprintf(irp->f, "&"); - ir_print_const_value(irp, const_ptr_pointee(const_val)); + if (const_val->data.x_ptr.special == ConstPtrSpecialRuntime) { + fprintf(irp->f, "(runtime pointer value)"); + } else { + ir_print_const_value(irp, const_ptr_pointee(const_val)); + } return; case TypeTableEntryIdFn: { @@ -934,6 +938,18 @@ static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten fprintf(irp->f, ")"); } +static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction) { + fprintf(irp->f, "@ptrToInt("); + ir_print_other_instruction(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) { + fprintf(irp->f, "@intToPtr("); + ir_print_other_instruction(irp, instruction->target); + fprintf(irp->f, ")"); +} + static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { @@ -1179,6 +1195,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdWidenOrShorten: ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction); break; + case IrInstructionIdPtrToInt: + ir_print_ptr_to_int(irp, (IrInstructionPtrToInt *)instruction); + break; + case IrInstructionIdIntToPtr: + ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction); + break; } fprintf(irp->f, "\n"); } diff --git a/src/parseh.cpp b/src/parseh.cpp index 9ebe47b44e..f84391aba9 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -1203,7 +1203,7 @@ static void process_symbol_macros(Context *c) { if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) { TypeTableEntry *child_type = var_type->data.maybe.child_type; if (child_type->id == TypeTableEntryIdFn) { - zig_panic("TODO"); + zig_panic("TODO macro alias of function pointer in .h file"); //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var); //c->macro_table.put(ms.name, fn_tld); continue; |
