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 {...@@ -90,6 +90,11 @@ enum ConstPtrSpecial {
90 // This means that the pointer points to inline memory, so attempting90 // This means that the pointer points to inline memory, so attempting
91 // to write a non-compile-time known value is an error91 // to write a non-compile-time known value is an error
92 ConstPtrSpecialInline,92 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,
93};98};
9499
95struct ConstPtrValue {100struct ConstPtrValue {
...@@ -427,8 +432,6 @@ struct AstNodeUnwrapErrorExpr {...@@ -427,8 +432,6 @@ struct AstNodeUnwrapErrorExpr {
427enum CastOp {432enum CastOp {
428 CastOpNoCast, // signifies the function call expression is not a cast433 CastOpNoCast, // signifies the function call expression is not a cast
429 CastOpNoop, // fn call expr is a cast, but does nothing434 CastOpNoop, // fn call expr is a cast, but does nothing
430 CastOpPtrToInt,
431 CastOpIntToPtr,
432 CastOpErrToInt,435 CastOpErrToInt,
433 CastOpIntToFloat,436 CastOpIntToFloat,
434 CastOpFloatToInt,437 CastOpFloatToInt,
...@@ -1453,6 +1456,8 @@ enum IrInstructionId {...@@ -1453,6 +1456,8 @@ enum IrInstructionId {
1453 IrInstructionIdInitEnum,1456 IrInstructionIdInitEnum,
1454 IrInstructionIdPointerReinterpret,1457 IrInstructionIdPointerReinterpret,
1455 IrInstructionIdWidenOrShorten,1458 IrInstructionIdWidenOrShorten,
1459 IrInstructionIdIntToPtr,
1460 IrInstructionIdPtrToInt,
1456};1461};
14571462
1458struct IrInstruction {1463struct IrInstruction {
...@@ -2101,6 +2106,18 @@ struct IrInstructionWidenOrShorten {...@@ -2101,6 +2106,18 @@ struct IrInstructionWidenOrShorten {
2101 IrInstruction *target;2106 IrInstruction *target;
2102};2107};
21032108
2109struct IrInstructionPtrToInt {
2110 IrInstruction base;
2111
2112 IrInstruction *target;
2113};
2114
2115struct IrInstructionIntToPtr {
2116 IrInstruction base;
2117
2118 IrInstruction *target;
2119};
2120
2104enum LValPurpose {2121enum LValPurpose {
2105 LValPurposeNone,2122 LValPurposeNone,
2106 LValPurposeAssign,2123 LValPurposeAssign,
src/codegen.cpp+16-4
...@@ -969,10 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -969,10 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
969 } else {969 } else {
970 zig_panic("TODO");970 zig_panic("TODO");
971 }971 }
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, "");
976 case CastOpResizeSlice:972 case CastOpResizeSlice:
977 {973 {
978 assert(cast_instruction->tmp_ptr);974 assert(cast_instruction->tmp_ptr);
...@@ -1114,6 +1110,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa...@@ -1114,6 +1110,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
1114 instruction->base.value.type, target_val);1110 instruction->base.value.type, target_val);
1115}1111}
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
1117static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,1125static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
1118 IrInstructionUnreachable *unreachable_instruction)1126 IrInstructionUnreachable *unreachable_instruction)
1119{1127{
...@@ -2347,6 +2355,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2347,6 +2355,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2347 return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);2355 return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
2348 case IrInstructionIdWidenOrShorten:2356 case IrInstructionIdWidenOrShorten:
2349 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);2357 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);
2350 case IrInstructionIdContainerInitList:2362 case IrInstructionIdContainerInitList:
2351 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);2363 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
2352 case IrInstructionIdSwitchVar:2364 case IrInstructionIdSwitchVar:
src/ir.cpp+84-4
...@@ -52,6 +52,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ...@@ -52,6 +52,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
5252
53ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {53ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
54 assert(const_val->special == ConstValSpecialStatic);54 assert(const_val->special == ConstValSpecialStatic);
55 assert(const_val->data.x_ptr.special != ConstPtrSpecialRuntime);
55 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;56 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
56 size_t index = const_val->data.x_ptr.index;57 size_t index = const_val->data.x_ptr.index;
5758
...@@ -459,6 +460,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *...@@ -459,6 +460,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *
459 return IrInstructionIdWidenOrShorten;460 return IrInstructionIdWidenOrShorten;
460}461}
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
462template<typename T>471template<typename T>
463static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {472static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
464 T *special_instruction = allocate<T>(1);473 T *special_instruction = allocate<T>(1);
...@@ -1899,6 +1908,30 @@ static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, As...@@ -1899,6 +1908,30 @@ static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, As
1899 return &instruction->base;1908 return &instruction->base;
1900}1909}
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
1902static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1935static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
1903 results[ReturnKindUnconditional] = 0;1936 results[ReturnKindUnconditional] = 0;
1904 results[ReturnKindError] = 0;1937 results[ReturnKindError] = 0;
...@@ -4657,8 +4690,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -4657,8 +4690,6 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
4657 *const_val = *other_val;4690 *const_val = *other_val;
4658 const_val->type = new_type;4691 const_val->type = new_type;
4659 break;4692 break;
4660 case CastOpPtrToInt:
4661 case CastOpIntToPtr:
4662 case CastOpResizeSlice:4693 case CastOpResizeSlice:
4663 case CastOpBytesToSlice:4694 case CastOpBytesToSlice:
4664 // can't do it4695 // can't do it
...@@ -5234,6 +5265,51 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -5234,6 +5265,51 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
5234 return result;5265 return result;
5235}5266}
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
5238static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,5314static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
5239 TypeTableEntry *wanted_type, IrInstruction *value)5315 TypeTableEntry *wanted_type, IrInstruction *value)
...@@ -5270,7 +5346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -5270,7 +5346,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
5270 if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) &&5346 if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) &&
5271 type_is_codegen_pointer(actual_type_canon))5347 type_is_codegen_pointer(actual_type_canon))
5272 {5348 {
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);
5274 }5350 }
52755351
52765352
...@@ -5278,7 +5354,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -5278,7 +5354,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
5278 if (wanted_type_canon->id == TypeTableEntryIdPointer &&5354 if (wanted_type_canon->id == TypeTableEntryIdPointer &&
5279 (actual_type_canon == isize_type || actual_type_canon == usize_type))5355 (actual_type_canon == isize_type || actual_type_canon == usize_type))
5280 {5356 {
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);
5282 }5358 }
52835359
5284 // explicit widening or shortening cast5360 // explicit widening or shortening cast
...@@ -9937,6 +10013,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -9937,6 +10013,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
9937 case IrInstructionIdInvalid:10013 case IrInstructionIdInvalid:
9938 case IrInstructionIdPointerReinterpret:10014 case IrInstructionIdPointerReinterpret:
9939 case IrInstructionIdWidenOrShorten:10015 case IrInstructionIdWidenOrShorten:
10016 case IrInstructionIdIntToPtr:
10017 case IrInstructionIdPtrToInt:
9940 case IrInstructionIdStructInit:10018 case IrInstructionIdStructInit:
9941 case IrInstructionIdStructFieldPtr:10019 case IrInstructionIdStructFieldPtr:
9942 case IrInstructionIdEnumFieldPtr:10020 case IrInstructionIdEnumFieldPtr:
...@@ -10244,6 +10322,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -10244,6 +10322,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
10244 case IrInstructionIdInitEnum:10322 case IrInstructionIdInitEnum:
10245 case IrInstructionIdPointerReinterpret:10323 case IrInstructionIdPointerReinterpret:
10246 case IrInstructionIdWidenOrShorten:10324 case IrInstructionIdWidenOrShorten:
10325 case IrInstructionIdPtrToInt:
10326 case IrInstructionIdIntToPtr:
10247 return false;10327 return false;
10248 case IrInstructionIdAsm:10328 case IrInstructionIdAsm:
10249 {10329 {
src/ir_print.cpp+23-1
...@@ -98,7 +98,11 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {...@@ -98,7 +98,11 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
98 }98 }
99 case TypeTableEntryIdPointer:99 case TypeTableEntryIdPointer:
100 fprintf(irp->f, "&");100 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 }
102 return;106 return;
103 case TypeTableEntryIdFn:107 case TypeTableEntryIdFn:
104 {108 {
...@@ -934,6 +938,18 @@ static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten...@@ -934,6 +938,18 @@ static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten
934 fprintf(irp->f, ")");938 fprintf(irp->f, ")");
935}939}
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
937static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {953static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
938 ir_print_prefix(irp, instruction);954 ir_print_prefix(irp, instruction);
939 switch (instruction->id) {955 switch (instruction->id) {
...@@ -1179,6 +1195,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1179,6 +1195,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1179 case IrInstructionIdWidenOrShorten:1195 case IrInstructionIdWidenOrShorten:
1180 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);1196 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
1181 break;1197 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;
1182 }1204 }
1183 fprintf(irp->f, "\n");1205 fprintf(irp->f, "\n");
1184}1206}
src/parseh.cpp+1-1
...@@ -1203,7 +1203,7 @@ static void process_symbol_macros(Context *c) {...@@ -1203,7 +1203,7 @@ static void process_symbol_macros(Context *c) {
1203 if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {1203 if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {
1204 TypeTableEntry *child_type = var_type->data.maybe.child_type;1204 TypeTableEntry *child_type = var_type->data.maybe.child_type;
1205 if (child_type->id == TypeTableEntryIdFn) {1205 if (child_type->id == TypeTableEntryIdFn) {
1206 zig_panic("TODO");1206 zig_panic("TODO macro alias of function pointer in .h file");
1207 //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var);1207 //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var);
1208 //c->macro_table.put(ms.name, fn_tld);1208 //c->macro_table.put(ms.name, fn_tld);
1209 continue;1209 continue;
test/cases/misc.zig+8
...@@ -414,6 +414,14 @@ fn testTakeAddressOfParameter(f: f32) {...@@ -414,6 +414,14 @@ fn testTakeAddressOfParameter(f: f32) {
414}414}
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 {...@@ -11,16 +11,6 @@ fn getFirstByte(inline T: type, mem: []T) -> u8 {
11}11}
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
24// TODO not passing14// TODO not passing
25fn pointerToVoidReturnType() {15fn pointerToVoidReturnType() {
26 @setFnTest(this);16 @setFnTest(this);