authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 15:45:50-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-26 15:45:50-05:00
log735cdbfdaca6405d1465ea859032412499c658d8
treea3b6655d26985adafbf71903c5d5bb7049a45454
parentaee7ad3de2e3c334ec5aac2d355e4eed086f1cdf

IR: pass intToPtrCast test


7 files changed, 151 insertions(+), 22 deletions(-)

src/all_types.hpp+19-2
......@@ -90,6 +90,11 @@ enum ConstPtrSpecial {
9090 // This means that the pointer points to inline memory, so attempting
9191 // to write a non-compile-time known value is an error
9292 ConstPtrSpecialInline,
93 // This means that we did a compile-time pointer reinterpret and we cannot
94 // understand the value of pointee at compile time. However, we will still
95 // emit a binary with a compile time known address.
96 // In this case index is the numeric address value.
97 ConstPtrSpecialRuntime,
9398};
9499
95100struct ConstPtrValue {
......@@ -427,8 +432,6 @@ struct AstNodeUnwrapErrorExpr {
427432enum CastOp {
428433 CastOpNoCast, // signifies the function call expression is not a cast
429434 CastOpNoop, // fn call expr is a cast, but does nothing
430 CastOpPtrToInt,
431 CastOpIntToPtr,
432435 CastOpErrToInt,
433436 CastOpIntToFloat,
434437 CastOpFloatToInt,
......@@ -1453,6 +1456,8 @@ enum IrInstructionId {
14531456 IrInstructionIdInitEnum,
14541457 IrInstructionIdPointerReinterpret,
14551458 IrInstructionIdWidenOrShorten,
1459 IrInstructionIdIntToPtr,
1460 IrInstructionIdPtrToInt,
14561461};
14571462
14581463struct IrInstruction {
......@@ -2101,6 +2106,18 @@ struct IrInstructionWidenOrShorten {
21012106 IrInstruction *target;
21022107};
21032108
2109struct IrInstructionPtrToInt {
2110 IrInstruction base;
2111
2112 IrInstruction *target;
2113};
2114
2115struct IrInstructionIntToPtr {
2116 IrInstruction base;
2117
2118 IrInstruction *target;
2119};
2120
21042121enum LValPurpose {
21052122 LValPurposeNone,
21062123 LValPurposeAssign,
src/codegen.cpp+16-4
......@@ -969,10 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
969969 } else {
970970 zig_panic("TODO");
971971 }
972 case CastOpPtrToInt:
973 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
974 case CastOpIntToPtr:
975 return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
976972 case CastOpResizeSlice:
977973 {
978974 assert(cast_instruction->tmp_ptr);
......@@ -1114,6 +1110,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
11141110 instruction->base.value.type, target_val);
11151111}
11161112
1113static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {
1114 TypeTableEntry *wanted_type = instruction->base.value.type;
1115 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
1116 return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, "");
1117}
1118
1119static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) {
1120 TypeTableEntry *wanted_type = instruction->base.value.type;
1121 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
1122 return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, "");
1123}
1124
11171125static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
11181126 IrInstructionUnreachable *unreachable_instruction)
11191127{
......@@ -2347,6 +2355,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
23472355 return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
23482356 case IrInstructionIdWidenOrShorten:
23492357 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
2358 case IrInstructionIdPtrToInt:
2359 return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction);
2360 case IrInstructionIdIntToPtr:
2361 return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction);
23502362 case IrInstructionIdContainerInitList:
23512363 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
23522364 case IrInstructionIdSwitchVar:
src/ir.cpp+84-4
......@@ -52,6 +52,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
5252
5353ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
5454 assert(const_val->special == ConstValSpecialStatic);
55 assert(const_val->data.x_ptr.special != ConstPtrSpecialRuntime);
5556 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
5657 size_t index = const_val->data.x_ptr.index;
5758
......@@ -459,6 +460,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *
459460 return IrInstructionIdWidenOrShorten;
460461}
461462
463static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrToInt *) {
464 return IrInstructionIdPtrToInt;
465}
466
467static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) {
468 return IrInstructionIdIntToPtr;
469}
470
462471template<typename T>
463472static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
464473 T *special_instruction = allocate<T>(1);
......@@ -1899,6 +1908,30 @@ static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, As
18991908 return &instruction->base;
19001909}
19011910
1911static IrInstruction *ir_build_int_to_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1912 IrInstruction *target)
1913{
1914 IrInstructionIntToPtr *instruction = ir_build_instruction<IrInstructionIntToPtr>(
1915 irb, scope, source_node);
1916 instruction->target = target;
1917
1918 ir_ref_instruction(target);
1919
1920 return &instruction->base;
1921}
1922
1923static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node,
1924 IrInstruction *target)
1925{
1926 IrInstructionPtrToInt *instruction = ir_build_instruction<IrInstructionPtrToInt>(
1927 irb, scope, source_node);
1928 instruction->target = target;
1929
1930 ir_ref_instruction(target);
1931
1932 return &instruction->base;
1933}
1934
19021935static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
19031936 results[ReturnKindUnconditional] = 0;
19041937 results[ReturnKindError] = 0;
......@@ -4657,8 +4690,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
46574690 *const_val = *other_val;
46584691 const_val->type = new_type;
46594692 break;
4660 case CastOpPtrToInt:
4661 case CastOpIntToPtr:
46624693 case CastOpResizeSlice:
46634694 case CastOpBytesToSlice:
46644695 // can't do it
......@@ -5234,6 +5265,51 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
52345265 return result;
52355266}
52365267
5268static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *source_instr,
5269 IrInstruction *target, TypeTableEntry *wanted_type)
5270{
5271 assert(wanted_type->id == TypeTableEntryIdInt);
5272
5273 if (instr_is_comptime(target)) {
5274 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
5275 if (!val)
5276 return ira->codegen->invalid_instruction;
5277 if (val->data.x_ptr.special == ConstPtrSpecialRuntime) {
5278 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
5279 source_instr->source_node, wanted_type, val->depends_on_compile_var);
5280 bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.index);
5281 return result;
5282 }
5283 }
5284
5285 IrInstruction *result = ir_build_ptr_to_int(&ira->new_irb, source_instr->scope,
5286 source_instr->source_node, target);
5287 result->value.type = wanted_type;
5288 return result;
5289}
5290
5291static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr,
5292 IrInstruction *target, TypeTableEntry *wanted_type)
5293{
5294 assert(wanted_type->id == TypeTableEntryIdPointer);
5295
5296 if (instr_is_comptime(target)) {
5297 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
5298 if (!val)
5299 return ira->codegen->invalid_instruction;
5300 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
5301 source_instr->source_node, wanted_type, val->depends_on_compile_var);
5302 result->value.data.x_ptr.base_ptr = nullptr;
5303 result->value.data.x_ptr.index = bignum_to_twos_complement(&val->data.x_bignum);
5304 result->value.data.x_ptr.special = ConstPtrSpecialRuntime;
5305 return result;
5306 }
5307
5308 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
5309 source_instr->source_node, target);
5310 result->value.type = wanted_type;
5311 return result;
5312}
52375313
52385314static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
52395315 TypeTableEntry *wanted_type, IrInstruction *value)
......@@ -5270,7 +5346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
52705346 if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) &&
52715347 type_is_codegen_pointer(actual_type_canon))
52725348 {
5273 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPtrToInt, false);
5349 return ir_analyze_ptr_to_int(ira, source_instr, value, wanted_type);
52745350 }
52755351
52765352
......@@ -5278,7 +5354,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
52785354 if (wanted_type_canon->id == TypeTableEntryIdPointer &&
52795355 (actual_type_canon == isize_type || actual_type_canon == usize_type))
52805356 {
5281 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToPtr, false);
5357 return ir_analyze_int_to_ptr(ira, source_instr, value, wanted_type);
52825358 }
52835359
52845360 // explicit widening or shortening cast
......@@ -9937,6 +10013,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
993710013 case IrInstructionIdInvalid:
993810014 case IrInstructionIdPointerReinterpret:
993910015 case IrInstructionIdWidenOrShorten:
10016 case IrInstructionIdIntToPtr:
10017 case IrInstructionIdPtrToInt:
994010018 case IrInstructionIdStructInit:
994110019 case IrInstructionIdStructFieldPtr:
994210020 case IrInstructionIdEnumFieldPtr:
......@@ -10244,6 +10322,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1024410322 case IrInstructionIdInitEnum:
1024510323 case IrInstructionIdPointerReinterpret:
1024610324 case IrInstructionIdWidenOrShorten:
10325 case IrInstructionIdPtrToInt:
10326 case IrInstructionIdIntToPtr:
1024710327 return false;
1024810328 case IrInstructionIdAsm:
1024910329 {
src/ir_print.cpp+23-1
......@@ -98,7 +98,11 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
9898 }
9999 case TypeTableEntryIdPointer:
100100 fprintf(irp->f, "&");
101 ir_print_const_value(irp, const_ptr_pointee(const_val));
101 if (const_val->data.x_ptr.special == ConstPtrSpecialRuntime) {
102 fprintf(irp->f, "(runtime pointer value)");
103 } else {
104 ir_print_const_value(irp, const_ptr_pointee(const_val));
105 }
102106 return;
103107 case TypeTableEntryIdFn:
104108 {
......@@ -934,6 +938,18 @@ static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten
934938 fprintf(irp->f, ")");
935939}
936940
941static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction) {
942 fprintf(irp->f, "@ptrToInt(");
943 ir_print_other_instruction(irp, instruction->target);
944 fprintf(irp->f, ")");
945}
946
947static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) {
948 fprintf(irp->f, "@intToPtr(");
949 ir_print_other_instruction(irp, instruction->target);
950 fprintf(irp->f, ")");
951}
952
937953static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
938954 ir_print_prefix(irp, instruction);
939955 switch (instruction->id) {
......@@ -1179,6 +1195,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11791195 case IrInstructionIdWidenOrShorten:
11801196 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
11811197 break;
1198 case IrInstructionIdPtrToInt:
1199 ir_print_ptr_to_int(irp, (IrInstructionPtrToInt *)instruction);
1200 break;
1201 case IrInstructionIdIntToPtr:
1202 ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction);
1203 break;
11821204 }
11831205 fprintf(irp->f, "\n");
11841206}
src/parseh.cpp+1-1
......@@ -1203,7 +1203,7 @@ static void process_symbol_macros(Context *c) {
12031203 if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {
12041204 TypeTableEntry *child_type = var_type->data.maybe.child_type;
12051205 if (child_type->id == TypeTableEntryIdFn) {
1206 zig_panic("TODO");
1206 zig_panic("TODO macro alias of function pointer in .h file");
12071207 //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var);
12081208 //c->macro_table.put(ms.name, fn_tld);
12091209 continue;
test/cases/misc.zig+8
......@@ -414,6 +414,14 @@ fn testTakeAddressOfParameter(f: f32) {
414414}
415415
416416
417fn intToPtrCast() {
418 @setFnTest(this);
419
420 const x = isize(13);
421 const y = (&u8)(x);
422 const z = usize(y);
423 assert(z == 13);
424}
417425
418426
419427
test/self_hosted.zig-10
......@@ -11,16 +11,6 @@ fn getFirstByte(inline T: type, mem: []T) -> u8 {
1111}
1212
1313
14// TODO not passing
15fn intToPtrCast() {
16 @setFnTest(this);
17
18 const x = isize(13);
19 const y = (&u8)(x);
20 const z = usize(y);
21 assert(z == 13);
22}
23
2414// TODO not passing
2515fn pointerToVoidReturnType() {
2616 @setFnTest(this);