authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 21:14:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 21:14:56-04:00
log2c11acf807b2f52d076e3e35399d9cd5d038759a
tree5f33d7a73f4d577d3c1164b616ded7a28bc4a025
parentc12bc8652ed45dd143932ef0d3a2540c0ef057a4

ir: analyze fieldptr instruction


3 files changed, 137 insertions(+), 35 deletions(-)

src-self-hosted/ir.zig+34-1
...@@ -382,7 +382,7 @@ const Analyze = struct {...@@ -382,7 +382,7 @@ const Analyze = struct {
382 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);382 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);
383 },383 },
384 .ptrtoint => return self.analyzeInstPtrToInt(func, old_inst.cast(text.Inst.PtrToInt).?),384 .ptrtoint => return self.analyzeInstPtrToInt(func, old_inst.cast(text.Inst.PtrToInt).?),
385 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),385 .fieldptr => return self.analyzeInstFieldPtr(func, old_inst.cast(text.Inst.FieldPtr).?),
386 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),386 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
387 .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),387 .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),
388 .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),388 .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
...@@ -470,6 +470,39 @@ const Analyze = struct {...@@ -470,6 +470,39 @@ const Analyze = struct {
470 return self.addNewInstArgs(f, ptrtoint.base.src, ty, Inst.PtrToInt, Inst.Args(Inst.PtrToInt){ .ptr = ptr });470 return self.addNewInstArgs(f, ptrtoint.base.src, ty, Inst.PtrToInt, Inst.Args(Inst.PtrToInt){ .ptr = ptr });
471 }471 }
472472
473 fn analyzeInstFieldPtr(self: *Analyze, func: ?*Fn, fieldptr: *text.Inst.FieldPtr) InnerError!*Inst {
474 const object_ptr = try self.resolveInst(func, fieldptr.positionals.object_ptr);
475 const field_name = try self.resolveConstString(func, fieldptr.positionals.field_name);
476
477 const elem_ty = switch (object_ptr.ty.zigTypeTag()) {
478 .Pointer => object_ptr.ty.elemType(),
479 else => return self.fail(fieldptr.base.src, "expected pointer, found '{}'", .{object_ptr.ty}),
480 };
481 switch (elem_ty.zigTypeTag()) {
482 .Array => {
483 if (mem.eql(u8, field_name, "len")) {
484 const len_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
485 len_payload.* = .{ .int = elem_ty.arrayLen() };
486
487 const ref_payload = try self.arena.allocator.create(Value.Payload.RefVal);
488 ref_payload.* = .{ .val = Value.initPayload(&len_payload.base) };
489
490 return self.constInst(fieldptr.base.src, .{
491 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
492 .val = Value.initPayload(&ref_payload.base),
493 });
494 } else {
495 return self.fail(
496 fieldptr.positionals.field_name.src,
497 "no member named '{}' in '{}'",
498 .{ field_name, elem_ty },
499 );
500 }
501 },
502 else => return self.fail(fieldptr.base.src, "type '{}' does not support field access", .{elem_ty}),
503 }
504 }
505
473 fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst {506 fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst {
474 const dest_type = try self.resolveType(func, intcast.positionals.dest_type);507 const dest_type = try self.resolveType(func, intcast.positionals.dest_type);
475 const new_inst = try self.resolveInst(func, intcast.positionals.value);508 const new_inst = try self.resolveInst(func, intcast.positionals.value);
src-self-hosted/type.zig+79-28
...@@ -54,6 +54,7 @@ pub const Type = extern union {...@@ -54,6 +54,7 @@ pub const Type = extern union {
5454
55 .array, .array_u8_sentinel_0 => return .Array,55 .array, .array_u8_sentinel_0 => return .Array,
56 .single_const_pointer => return .Pointer,56 .single_const_pointer => return .Pointer,
57 .single_const_pointer_to_comptime_int => return .Pointer,
57 .const_slice_u8 => return .Pointer,58 .const_slice_u8 => return .Pointer,
58 }59 }
59 }60 }
...@@ -127,6 +128,7 @@ pub const Type = extern union {...@@ -127,6 +128,7 @@ pub const Type = extern union {
127128
128 .const_slice_u8 => return out_stream.writeAll("[]const u8"),129 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
129 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),130 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
131 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
130132
131 .array_u8_sentinel_0 => {133 .array_u8_sentinel_0 => {
132 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);134 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);
...@@ -177,6 +179,7 @@ pub const Type = extern union {...@@ -177,6 +179,7 @@ pub const Type = extern union {
177 .@"comptime_float" => return Value.initTag(.comptime_float_type),179 .@"comptime_float" => return Value.initTag(.comptime_float_type),
178 .@"noreturn" => return Value.initTag(.noreturn_type),180 .@"noreturn" => return Value.initTag(.noreturn_type),
179 .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),181 .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),
182 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
180 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),183 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
181 else => {184 else => {
182 const ty_payload = try allocator.create(Value.Payload.Ty);185 const ty_payload = try allocator.create(Value.Payload.Ty);
...@@ -219,7 +222,9 @@ pub const Type = extern union {...@@ -219,7 +222,9 @@ pub const Type = extern union {
219 .fn_naked_noreturn_no_args,222 .fn_naked_noreturn_no_args,
220 => false,223 => false,
221224
222 .single_const_pointer => true,225 .single_const_pointer,
226 .single_const_pointer_to_comptime_int,
227 => true,
223 };228 };
224 }229 }
225230
...@@ -253,6 +258,7 @@ pub const Type = extern union {...@@ -253,6 +258,7 @@ pub const Type = extern union {
253 .array,258 .array,
254 .array_u8_sentinel_0,259 .array_u8_sentinel_0,
255 .single_const_pointer,260 .single_const_pointer,
261 .single_const_pointer_to_comptime_int,
256 .fn_naked_noreturn_no_args,262 .fn_naked_noreturn_no_args,
257 => false,263 => false,
258264
...@@ -293,7 +299,10 @@ pub const Type = extern union {...@@ -293,7 +299,10 @@ pub const Type = extern union {
293 .fn_naked_noreturn_no_args,299 .fn_naked_noreturn_no_args,
294 => unreachable,300 => unreachable,
295301
296 .single_const_pointer, .const_slice_u8 => true,302 .single_const_pointer,
303 .single_const_pointer_to_comptime_int,
304 .const_slice_u8,
305 => true,
297 };306 };
298 }307 }
299308
...@@ -330,7 +339,47 @@ pub const Type = extern union {...@@ -330,7 +339,47 @@ pub const Type = extern union {
330339
331 .array => self.cast(Payload.Array).?.elem_type,340 .array => self.cast(Payload.Array).?.elem_type,
332 .single_const_pointer => self.cast(Payload.SingleConstPointer).?.pointee_type,341 .single_const_pointer => self.cast(Payload.SingleConstPointer).?.pointee_type,
333 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.@"u8"),342 .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
343 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
344 };
345 }
346
347 /// Asserts the type is an array.
348 pub fn arrayLen(self: Type) u64 {
349 return switch (self.tag()) {
350 .u8,
351 .i8,
352 .isize,
353 .usize,
354 .c_short,
355 .c_ushort,
356 .c_int,
357 .c_uint,
358 .c_long,
359 .c_ulong,
360 .c_longlong,
361 .c_ulonglong,
362 .c_longdouble,
363 .f16,
364 .f32,
365 .f64,
366 .f128,
367 .c_void,
368 .bool,
369 .void,
370 .type,
371 .anyerror,
372 .comptime_int,
373 .comptime_float,
374 .noreturn,
375 .fn_naked_noreturn_no_args,
376 .single_const_pointer,
377 .single_const_pointer_to_comptime_int,
378 .const_slice_u8,
379 => unreachable,
380
381 .array => self.cast(Payload.Array).?.len,
382 .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len,
334 };383 };
335 }384 }
336385
...@@ -353,6 +402,7 @@ pub const Type = extern union {...@@ -353,6 +402,7 @@ pub const Type = extern union {
353 .fn_naked_noreturn_no_args,402 .fn_naked_noreturn_no_args,
354 .array,403 .array,
355 .single_const_pointer,404 .single_const_pointer,
405 .single_const_pointer_to_comptime_int,
356 .array_u8_sentinel_0,406 .array_u8_sentinel_0,
357 .const_slice_u8,407 .const_slice_u8,
358 => unreachable,408 => unreachable,
...@@ -380,32 +430,33 @@ pub const Type = extern union {...@@ -380,32 +430,33 @@ pub const Type = extern union {
380 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.430 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
381 pub const Tag = enum {431 pub const Tag = enum {
382 // The first section of this enum are tags that require no payload.432 // The first section of this enum are tags that require no payload.
383 @"u8",433 u8,
384 @"i8",434 i8,
385 @"isize",435 isize,
386 @"usize",436 usize,
387 @"c_short",437 c_short,
388 @"c_ushort",438 c_ushort,
389 @"c_int",439 c_int,
390 @"c_uint",440 c_uint,
391 @"c_long",441 c_long,
392 @"c_ulong",442 c_ulong,
393 @"c_longlong",443 c_longlong,
394 @"c_ulonglong",444 c_ulonglong,
395 @"c_longdouble",445 c_longdouble,
396 @"c_void",446 c_void,
397 @"f16",447 f16,
398 @"f32",448 f32,
399 @"f64",449 f64,
400 @"f128",450 f128,
401 @"bool",451 bool,
402 @"void",452 void,
403 @"type",453 type,
404 @"anyerror",454 anyerror,
405 @"comptime_int",455 comptime_int,
406 @"comptime_float",456 comptime_float,
407 @"noreturn",457 noreturn,
408 fn_naked_noreturn_no_args,458 fn_naked_noreturn_no_args,
459 single_const_pointer_to_comptime_int,
409 const_slice_u8, // See last_no_payload_tag below.460 const_slice_u8, // See last_no_payload_tag below.
410 // After this, the tag requires a payload.461 // After this, the tag requires a payload.
411462
src-self-hosted/value.zig+24-6
...@@ -44,6 +44,7 @@ pub const Value = extern union {...@@ -44,6 +44,7 @@ pub const Value = extern union {
44 comptime_float_type,44 comptime_float_type,
45 noreturn_type,45 noreturn_type,
46 fn_naked_noreturn_no_args_type,46 fn_naked_noreturn_no_args_type,
47 single_const_pointer_to_comptime_int_type,
47 const_slice_u8_type,48 const_slice_u8_type,
4849
49 void_value,50 void_value,
...@@ -58,6 +59,7 @@ pub const Value = extern union {...@@ -58,6 +59,7 @@ pub const Value = extern union {
58 int_big,59 int_big,
59 function,60 function,
60 ref,61 ref,
62 ref_val,
61 bytes,63 bytes,
6264
63 pub const last_no_payload_tag = Tag.bool_false;65 pub const last_no_payload_tag = Tag.bool_false;
...@@ -100,7 +102,8 @@ pub const Value = extern union {...@@ -100,7 +102,8 @@ pub const Value = extern union {
100 out_stream: var,102 out_stream: var,
101 ) !void {103 ) !void {
102 comptime assert(fmt.len == 0);104 comptime assert(fmt.len == 0);
103 switch (self.tag()) {105 var val = self;
106 while (true) switch (val.tag()) {
104 .u8_type => return out_stream.writeAll("u8"),107 .u8_type => return out_stream.writeAll("u8"),
105 .i8_type => return out_stream.writeAll("i8"),108 .i8_type => return out_stream.writeAll("i8"),
106 .isize_type => return out_stream.writeAll("isize"),109 .isize_type => return out_stream.writeAll("isize"),
...@@ -127,20 +130,26 @@ pub const Value = extern union {...@@ -127,20 +130,26 @@ pub const Value = extern union {
127 .comptime_float_type => return out_stream.writeAll("comptime_float"),130 .comptime_float_type => return out_stream.writeAll("comptime_float"),
128 .noreturn_type => return out_stream.writeAll("noreturn"),131 .noreturn_type => return out_stream.writeAll("noreturn"),
129 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),132 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
133 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
130 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),134 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
131135
132 .void_value => return out_stream.writeAll("{}"),136 .void_value => return out_stream.writeAll("{}"),
133 .noreturn_value => return out_stream.writeAll("unreachable"),137 .noreturn_value => return out_stream.writeAll("unreachable"),
134 .bool_true => return out_stream.writeAll("true"),138 .bool_true => return out_stream.writeAll("true"),
135 .bool_false => return out_stream.writeAll("false"),139 .bool_false => return out_stream.writeAll("false"),
136 .ty => return self.cast(Payload.Ty).?.ty.format("", options, out_stream),140 .ty => return val.cast(Payload.Ty).?.ty.format("", options, out_stream),
137 .int_u64 => return std.fmt.formatIntValue(self.cast(Payload.Int_u64).?.int, "", options, out_stream),141 .int_u64 => return std.fmt.formatIntValue(val.cast(Payload.Int_u64).?.int, "", options, out_stream),
138 .int_i64 => return std.fmt.formatIntValue(self.cast(Payload.Int_i64).?.int, "", options, out_stream),142 .int_i64 => return std.fmt.formatIntValue(val.cast(Payload.Int_i64).?.int, "", options, out_stream),
139 .int_big => return out_stream.print("{}", .{self.cast(Payload.IntBig).?.big_int}),143 .int_big => return out_stream.print("{}", .{val.cast(Payload.IntBig).?.big_int}),
140 .function => return out_stream.writeAll("(function)"),144 .function => return out_stream.writeAll("(function)"),
141 .ref => return out_stream.writeAll("(ref)"),145 .ref => return out_stream.writeAll("(ref)"),
146 .ref_val => {
147 try out_stream.writeAll("*const ");
148 val = val.cast(Payload.RefVal).?.val;
149 continue;
150 },
142 .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),151 .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),
143 }152 };
144 }153 }
145154
146 /// Asserts that the value is representable as an array of bytes.155 /// Asserts that the value is representable as an array of bytes.
...@@ -183,6 +192,7 @@ pub const Value = extern union {...@@ -183,6 +192,7 @@ pub const Value = extern union {
183 .comptime_float_type => Type.initTag(.@"comptime_float"),192 .comptime_float_type => Type.initTag(.@"comptime_float"),
184 .noreturn_type => Type.initTag(.@"noreturn"),193 .noreturn_type => Type.initTag(.@"noreturn"),
185 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),194 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
195 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
186 .const_slice_u8_type => Type.initTag(.const_slice_u8),196 .const_slice_u8_type => Type.initTag(.const_slice_u8),
187197
188 .void_value,198 .void_value,
...@@ -194,6 +204,7 @@ pub const Value = extern union {...@@ -194,6 +204,7 @@ pub const Value = extern union {
194 .int_big,204 .int_big,
195 .function,205 .function,
196 .ref,206 .ref,
207 .ref_val,
197 .bytes,208 .bytes,
198 => unreachable,209 => unreachable,
199 };210 };
...@@ -229,6 +240,7 @@ pub const Value = extern union {...@@ -229,6 +240,7 @@ pub const Value = extern union {
229 .comptime_float_type,240 .comptime_float_type,
230 .noreturn_type,241 .noreturn_type,
231 .fn_naked_noreturn_no_args_type,242 .fn_naked_noreturn_no_args_type,
243 .single_const_pointer_to_comptime_int_type,
232 .const_slice_u8_type,244 .const_slice_u8_type,
233 .void_value,245 .void_value,
234 .noreturn_value,246 .noreturn_value,
...@@ -236,6 +248,7 @@ pub const Value = extern union {...@@ -236,6 +248,7 @@ pub const Value = extern union {
236 .bool_false,248 .bool_false,
237 .function,249 .function,
238 .ref,250 .ref,
251 .ref_val,
239 .bytes,252 .bytes,
240 => unreachable,253 => unreachable,
241254
...@@ -311,6 +324,11 @@ pub const Value = extern union {...@@ -311,6 +324,11 @@ pub const Value = extern union {
311 pointee: *MemoryCell,324 pointee: *MemoryCell,
312 };325 };
313326
327 pub const RefVal = struct {
328 base: Payload = Payload{ .tag = .ref_val },
329 val: Value,
330 };
331
314 pub const Bytes = struct {332 pub const Bytes = struct {
315 base: Payload = Payload{ .tag = .bytes },333 base: Payload = Payload{ .tag = .bytes },
316 data: []const u8,334 data: []const u8,