stage2: progress towards basic structs

Introduce `ResultLoc.none_or_ref` which is used by field access
expressions to avoid unnecessary loads when the field access itself
will do the load. This turns:

```zig
p.y - p.x - p.x
```

from

```zir
  %14 = load(%4) node_offset:8:12
  %15 = field_val(%14, "y") node_offset:8:13
  %16 = load(%4) node_offset:8:18
  %17 = field_val(%16, "x") node_offset:8:19
  %18 = sub(%15, %17) node_offset:8:16
  %19 = load(%4) node_offset:8:24
  %20 = field_val(%19, "x") node_offset:8:25
```

to

```zir
  %14 = field_val(%4, "y") node_offset:8:13
  %15 = field_val(%4, "x") node_offset:8:19
  %16 = sub(%14, %15) node_offset:8:16
  %17 = field_val(%4, "x") node_offset:8:25
```

Much more compact. This requires `Sema.zirFieldVal` to support both
pointers and non-pointers.

C backend: Implement typedefs for struct types, as well as the following
TZIR instructions:
 * mul
 * mulwrap
 * addwrap
 * subwrap
 * ref
 * struct_field_ptr

Note that add, addwrap, sub, subwrap, mul, mulwrap instructions are all
incorrect currently and need to be updated to properly handle wrapping
and non wrapping for signed and unsigned.

C backend: change indentation delta to 1, to make the output smaller and
to process fewer bytes.

I promise I will add a test case as soon as I fix those warnings that
are being printed for my test case.
This commit is contained in:
Andrew Kelley
2021-04-02 19:11:51 -07:00
parent 43d364afef
commit 97d7fddfb7
6 changed files with 152 additions and 33 deletions

View File

@@ -373,6 +373,11 @@ pub const Struct = struct {
/// Uses `unreachable_value` to indicate no default.
default_val: Value,
};
pub fn getFullyQualifiedName(struct_obj: *Struct, gpa: *Allocator) ![]u8 {
// TODO this should return e.g. "std.fs.Dir.OpenOptions"
return gpa.dupe(u8, mem.spanZ(struct_obj.owner_decl.name));
}
};
/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
@@ -1048,6 +1053,9 @@ pub const Scope = struct {
gz.rl_ty_inst = ty_inst;
gz.break_result_loc = parent_rl;
},
.none_or_ref => {
gz.break_result_loc = .ref;
},
.discard, .none, .ptr, .ref => {
gz.break_result_loc = parent_rl;
},