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.
This commit is contained in:
Jakub Konka
2022-02-05 17:41:03 +01:00
parent 04f379dd41
commit 556f0ce5bf
8 changed files with 90 additions and 27 deletions

View File

@@ -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;