diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-05 17:41:03 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-06 08:42:14 +0100 |
| commit | 556f0ce5bfb962764bb68d9d9c16765cf9e1b9ba (patch) | |
| tree | e3ddbc2240c99a089906a10c4c40dcc83a883f17 /src/Module.zig | |
| parent | 04f379dd414184a42412f4497b0573d7612d6730 (diff) | |
| download | zig-556f0ce5bfb962764bb68d9d9c16765cf9e1b9ba.tar.gz zig-556f0ce5bfb962764bb68d9d9c16765cf9e1b9ba.zip | |
stage2: add new Decl subtype, ExternFn
`ExternFn` will contain a maybe-lib-name if it was defined with
the `extern` keyword like so
```zig
extern "c" fn write(usize, usize, usize) usize;
```
`lib_name` will live as long as `ExternFn` decl does.
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/src/Module.zig b/src/Module.zig index e2e2505927..4fd3ee5c01 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -501,6 +501,10 @@ pub const Decl = struct { } pub fn clearValues(decl: *Decl, gpa: Allocator) void { + if (decl.getExternFn()) |extern_fn| { + extern_fn.deinit(gpa); + gpa.destroy(extern_fn); + } if (decl.getFunction()) |func| { func.deinit(gpa); gpa.destroy(func); @@ -690,6 +694,13 @@ pub const Decl = struct { return func; } + pub fn getExternFn(decl: *const Decl) ?*ExternFn { + if (!decl.owns_tv) return null; + const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data; + assert(extern_fn.owner_decl == decl); + return extern_fn; + } + pub fn getVariable(decl: *Decl) ?*Var { if (!decl.owns_tv) return null; const variable = (decl.val.castTag(.variable) orelse return null).data; @@ -1320,9 +1331,26 @@ pub const Opaque = struct { } }; +/// Some extern function struct memory is owned by the Decl's TypedValue.Managed +/// arena allocator. +pub const ExternFn = struct { + /// The Decl that corresponds to the function itself. + owner_decl: *Decl, + /// Library name if specified. + /// For example `extern "c" fn write(...) usize` would have 'c' as library name. + /// Allocated with Module's allocator; outlives the ZIR code. + lib_name: ?[*:0]const u8, + + pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void { + if (extern_fn.lib_name) |lib_name| { + gpa.free(mem.sliceTo(lib_name, 0)); + } + } +}; + /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. -/// Extern functions do not have this data structure; they are represented by -/// the `Decl` only, with a `Value` tag of `extern_fn`. +/// Extern functions do not have this data structure; they are represented by `ExternFn` +/// instead. pub const Fn = struct { /// The Decl that corresponds to the function itself. owner_decl: *Decl, @@ -3768,8 +3796,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { } }, .extern_fn => { - const owner_decl = decl_tv.val.castTag(.extern_fn).?.data; - if (decl == owner_decl) { + const extern_fn = decl_tv.val.castTag(.extern_fn).?.data; + if (extern_fn.owner_decl == decl) { decl.owns_tv = true; queue_linker_work = true; is_extern = true; |
