aboutsummaryrefslogtreecommitdiff
path: root/src-self-hosted/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-07-14 18:27:51 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-07-14 18:27:51 -0400
commit4d920cee6e8be2f2ae2cfd9067358c65b977568a (patch)
tree2c04de6151b7448dec9958d0a91234ea0ba9a15d /src-self-hosted/value.zig
parentda3acacc14331a6be33445c3bfd204e2cccabddd (diff)
parent28c3d4809bc6d497ac81892bc7eb03b95d8c2b32 (diff)
downloadzig-4d920cee6e8be2f2ae2cfd9067358c65b977568a.tar.gz
zig-4d920cee6e8be2f2ae2cfd9067358c65b977568a.zip
Merge remote-tracking branch 'origin/master' into llvm7
Diffstat (limited to 'src-self-hosted/value.zig')
-rw-r--r--src-self-hosted/value.zig154
1 files changed, 154 insertions, 0 deletions
diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig
new file mode 100644
index 0000000000..8c047b1513
--- /dev/null
+++ b/src-self-hosted/value.zig
@@ -0,0 +1,154 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const Scope = @import("scope.zig").Scope;
+const Compilation = @import("compilation.zig").Compilation;
+
+/// Values are ref-counted, heap-allocated, and copy-on-write
+/// If there is only 1 ref then write need not copy
+pub const Value = struct {
+ id: Id,
+ typeof: *Type,
+ ref_count: std.atomic.Int(usize),
+
+ /// Thread-safe
+ pub fn ref(base: *Value) void {
+ _ = base.ref_count.incr();
+ }
+
+ /// Thread-safe
+ pub fn deref(base: *Value, comp: *Compilation) void {
+ if (base.ref_count.decr() == 1) {
+ base.typeof.base.deref(comp);
+ switch (base.id) {
+ Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
+ Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
+ Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
+ Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
+ Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
+ Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
+ }
+ }
+ }
+
+ pub fn getRef(base: *Value) *Value {
+ base.ref();
+ return base;
+ }
+
+ pub fn dump(base: *const Value) void {
+ std.debug.warn("{}", @tagName(base.id));
+ }
+
+ pub const Id = enum {
+ Type,
+ Fn,
+ Void,
+ Bool,
+ NoReturn,
+ Ptr,
+ };
+
+ pub const Type = @import("type.zig").Type;
+
+ pub const Fn = struct {
+ base: Value,
+
+ /// The main external name that is used in the .o file.
+ /// TODO https://github.com/ziglang/zig/issues/265
+ symbol_name: std.Buffer,
+
+ /// parent should be the top level decls or container decls
+ fndef_scope: *Scope.FnDef,
+
+ /// parent is scope for last parameter
+ child_scope: *Scope,
+
+ /// parent is child_scope
+ block_scope: *Scope.Block,
+
+ /// Creates a Fn value with 1 ref
+ /// Takes ownership of symbol_name
+ pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
+ const self = try comp.a().create(Fn{
+ .base = Value{
+ .id = Value.Id.Fn,
+ .typeof = &fn_type.base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .fndef_scope = fndef_scope,
+ .child_scope = &fndef_scope.base,
+ .block_scope = undefined,
+ .symbol_name = symbol_name,
+ });
+ fn_type.base.base.ref();
+ fndef_scope.fn_val = self;
+ fndef_scope.base.ref();
+ return self;
+ }
+
+ pub fn destroy(self: *Fn, comp: *Compilation) void {
+ self.fndef_scope.base.deref(comp);
+ self.symbol_name.deinit();
+ comp.a().destroy(self);
+ }
+ };
+
+ pub const Void = struct {
+ base: Value,
+
+ pub fn get(comp: *Compilation) *Void {
+ comp.void_value.base.ref();
+ return comp.void_value;
+ }
+
+ pub fn destroy(self: *Void, comp: *Compilation) void {
+ comp.a().destroy(self);
+ }
+ };
+
+ pub const Bool = struct {
+ base: Value,
+ x: bool,
+
+ pub fn get(comp: *Compilation, x: bool) *Bool {
+ if (x) {
+ comp.true_value.base.ref();
+ return comp.true_value;
+ } else {
+ comp.false_value.base.ref();
+ return comp.false_value;
+ }
+ }
+
+ pub fn destroy(self: *Bool, comp: *Compilation) void {
+ comp.a().destroy(self);
+ }
+ };
+
+ pub const NoReturn = struct {
+ base: Value,
+
+ pub fn get(comp: *Compilation) *NoReturn {
+ comp.noreturn_value.base.ref();
+ return comp.noreturn_value;
+ }
+
+ pub fn destroy(self: *NoReturn, comp: *Compilation) void {
+ comp.a().destroy(self);
+ }
+ };
+
+ pub const Ptr = struct {
+ base: Value,
+
+ pub const Mut = enum {
+ CompTimeConst,
+ CompTimeVar,
+ RunTime,
+ };
+
+ pub fn destroy(self: *Ptr, comp: *Compilation) void {
+ comp.a().destroy(self);
+ }
+ };
+};