Skip to content

Commit

Permalink
Build tests to run against linked library.
Browse files Browse the repository at this point in the history
  • Loading branch information
fubark committed Mar 8, 2024
1 parent 8299b5f commit c437dfd
Show file tree
Hide file tree
Showing 33 changed files with 1,262 additions and 1,305 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/latest-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ jobs:

- name: Run tests.
if: env.BUILD_TARGET != 'wasm32-freestanding' && env.BUILD_CMD == 'lib'
run: zig build test-lib ${{ env.ZIG_TARGET_FLAG }}
run: |
zig build build-link-test ${{ env.ZIG_TARGET_FLAG }}
./zig-out/bin/test
- name: Run tests.
if: env.BUILD_TARGET == 'wasm32-freestanding' || env.BUILD_TARGET == 'wasm32-wasi'
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ jobs:

- name: Run tests.
if: env.BUILD_TARGET != 'wasm32-freestanding' && env.BUILD_CMD == 'lib'
run: zig build test-lib ${{ env.ZIG_TARGET_FLAG }}
run: |
zig build build-link-test ${{ env.ZIG_TARGET_FLAG }}
./zig-out/bin/test
- name: Run tests.
if: env.BUILD_TARGET == 'wasm32-freestanding' || env.BUILD_TARGET == 'wasm32-wasi'
Expand Down
105 changes: 62 additions & 43 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,38 +133,7 @@ pub fn build(b: *std.build.Builder) !void {
opts.cli = false;
opts.applyOverrides();

var lib: *std.build.Step.Compile = undefined;
if (opts.static) {
lib = b.addStaticLibrary(.{
.name = "cyber",
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
});
} else {
lib = b.addSharedLibrary(.{
.name = "cyber",
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
});
}
if (lib.optimize != .Debug) {
lib.strip = true;
}
lib.addIncludePath(.{. path = thisDir() ++ "/src" });

if (target.getCpuArch().isWasm()) {
// Export table so non-exported functions can still be invoked from:
// `instance.exports.__indirect_function_table`
lib.export_table = true;
}

// Allow exported symbols to be visible to dlopen.
// Also needed to export symbols in wasm lib.
lib.rdynamic = true;

try buildAndLinkDeps(lib, opts);
const lib = try buildLib(b, opts);
step.dependOn(&lib.step);
step.dependOn(&b.addInstallArtifact(lib, .{}).step);
}
Expand Down Expand Up @@ -209,8 +178,7 @@ pub fn build(b: *std.build.Builder) !void {
opts.applyOverrides();

var step = b.addTest(.{
// Lib test includes main tests.
.root_source_file = .{ .path = "./test/lib_test.zig" },
.root_source_file = .{ .path = "./test/main_test.zig" },
.target = target,
.optimize = optimize,
.filter = testFilter,
Expand All @@ -227,14 +195,17 @@ pub fn build(b: *std.build.Builder) !void {
}

{
const mainStep = b.step("test", "Run tests.");
const mainStep = b.step("build-link-test", "Build link test.");

var opts = getDefaultOptions(target, optimize);
opts.trackGlobalRc = true;
opts.ffi = false;
opts.link_test = true;
opts.applyOverrides();

var step = b.addTest(.{
.root_source_file = .{ .path = "./test/main_test.zig" },
// Lib test includes main tests.
.root_source_file = .{ .path = "./test/behavior_test.zig" },
.target = target,
.optimize = optimize,
.filter = testFilter,
Expand All @@ -243,22 +214,29 @@ pub fn build(b: *std.build.Builder) !void {
step.addIncludePath(.{ .path = thisDir() ++ "/src" });
step.rdynamic = true;

try buildAndLinkDeps(step, opts);
mainStep.dependOn(&b.addRunArtifact(step).step);
try addBuildOptions(b, step, opts);
step.addModule("stdx", stdx);
step.addAnonymousModule("tcc", .{
.source_file = .{ .path = thisDir() ++ "/src/nopkg.zig" },
});

step = try addTraceTest(b, opts);
mainStep.dependOn(&b.addRunArtifact(step).step);
opts = getDefaultOptions(target, optimize);
opts.cli = true;
opts.applyOverrides();
const lib = try buildLib(b, opts);
step.linkLibrary(lib);
mainStep.dependOn(&b.addInstallArtifact(step, .{}).step);
}

{
const mainStep = b.step("test-lib", "Run tests.");
const mainStep = b.step("test", "Run tests.");

var opts = getDefaultOptions(target, optimize);
opts.trackGlobalRc = true;
opts.applyOverrides();

var step = b.addTest(.{
.root_source_file = .{ .path = "./test/lib_test.zig" },
.root_source_file = .{ .path = "./test/main_test.zig" },
.target = target,
.optimize = optimize,
.filter = testFilter,
Expand Down Expand Up @@ -344,6 +322,7 @@ pub const Options = struct {
cli: bool,
jit: bool,
rt: config.Runtime,
link_test: bool,

fn applyOverrides(self: *Options) void {
if (optMalloc) |malloc| {
Expand Down Expand Up @@ -390,6 +369,7 @@ fn getDefaultOptions(target: std.zig.CrossTarget, optimize: std.builtin.Optimize
.cli = !target.getCpuArch().isWasm(),
.jit = false,
.rt = .vm,
.link_test = false,
};
}

Expand Down Expand Up @@ -423,6 +403,7 @@ fn createBuildOptions(b: *std.build.Builder, opts: Options) !*std.build.Step.Opt
build_options.addOption(bool, "jit", opts.jit);
build_options.addOption(config.TestBackend, "testBackend", testBackend);
build_options.addOption(config.Runtime, "rt", opts.rt);
build_options.addOption(bool, "link_test", opts.link_test);
build_options.addOption([]const u8, "full_version", b.fmt("Cyber {s} build-{s}-{s}", .{Version, buildTag, commitTag}));
return build_options;
}
Expand All @@ -446,7 +427,9 @@ fn addTraceTest(b: *std.build.Builder, opts: Options) !*std.build.LibExeObjStep
var newOpts = opts;
newOpts.trace = true;
newOpts.applyOverrides();
try buildAndLinkDeps(step, newOpts);

// Include all deps since it contains tests that depend on Zig source.
try buildAndLinkDeps(step, opts);
return step;
}

Expand Down Expand Up @@ -536,3 +519,39 @@ pub fn buildCVM(b: *std.Build, opts: Options) !*std.build.Step.Compile {
});
return lib;
}

fn buildLib(b: *std.Build, opts: Options) !*std.build.Step.Compile {
var lib: *std.build.Step.Compile = undefined;
if (opts.static) {
lib = b.addStaticLibrary(.{
.name = "cyber",
.root_source_file = .{ .path = "src/lib.zig" },
.target = opts.target,
.optimize = opts.optimize,
});
} else {
lib = b.addSharedLibrary(.{
.name = "cyber",
.root_source_file = .{ .path = "src/lib.zig" },
.target = opts.target,
.optimize = opts.optimize,
});
}
if (lib.optimize != .Debug) {
lib.strip = true;
}
lib.addIncludePath(.{. path = thisDir() ++ "/src" });

if (opts.target.getCpuArch().isWasm()) {
// Export table so non-exported functions can still be invoked from:
// `instance.exports.__indirect_function_table`
lib.export_table = true;
}

// Allow exported symbols to be visible to dlopen.
// Also needed to export symbols in wasm lib.
lib.rdynamic = true;

try buildAndLinkDeps(lib, opts);
return lib;
}
32 changes: 9 additions & 23 deletions src/arc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const builtin = @import("builtin");
const stdx = @import("stdx");
pub const log = cy.log.scoped(.arc);
const cy = @import("cyber.zig");
const cc = @import("capi.zig");
const c = @import("capi.zig");
const vmc = cy.vmc;
const rt = cy.rt;
const bt = cy.types.BuiltinTypes;
Expand Down Expand Up @@ -214,11 +214,6 @@ pub fn getGlobalRC(self: *const cy.VM) usize {
}
}

const GCResult = struct {
numCycFreed: u32,
numObjFreed: u32,
};

/// Mark-sweep leveraging refcounts and deals only with cyclable objects.
/// 1. Looks at all root nodes from the stack and globals.
/// Traverse the children and sets the mark flag to true.
Expand All @@ -230,7 +225,7 @@ const GCResult = struct {
/// If the mark flag is set, reset the flag for the next gc run.
/// TODO: Allocate using separate pages for cyclable and non-cyclable objects,
/// so only cyclable objects are iterated.
pub fn performGC(vm: *cy.VM) !GCResult {
pub fn performGC(vm: *cy.VM) !c.GCResult {
log.tracev("Run gc.", .{});
try performMark(vm);

Expand All @@ -252,7 +247,7 @@ fn performMark(vm: *cy.VM) !void {
}
}

fn performSweep(vm: *cy.VM) !GCResult {
fn performSweep(vm: *cy.VM) !c.GCResult {
log.tracev("Perform sweep.", .{});
// Collect cyc nodes and release their children (child cyc nodes are skipped).
if (cy.Trace) {
Expand Down Expand Up @@ -319,7 +314,7 @@ fn performSweep(vm: *cy.VM) !GCResult {
vm.numFreed += @intCast(cycObjs.items.len);
}

const res = GCResult{
const res = c.GCResult{
.numCycFreed = @intCast(cycObjs.items.len),
.numObjFreed = if (cy.Trace) vm.numFreed else 0,
};
Expand Down Expand Up @@ -444,7 +439,7 @@ fn markValue(vm: *cy.VM, v: cy.Value) void {
// Custom object type.
if (entry.sym.cast(.custom_object_t).getChildrenFn) |getChildren| {
const children = getChildren(@ptrCast(vm), @ptrFromInt(@intFromPtr(obj) + 8));
for (cc.valueSlice(children)) |child| {
for (cy.Value.fromSliceC(children)) |child| {
if (child.isCycPointer()) {
markValue(vm, child);
}
Expand Down Expand Up @@ -486,18 +481,9 @@ pub fn countObjects(vm: *cy.VM) usize {

pub fn checkGlobalRC(vm: *cy.VM) !void {
const rc = getGlobalRC(vm);
if (rc != vm.expGlobalRC) {
std.debug.print("unreleased refcount: {}, expected: {}\n", .{rc, vm.expGlobalRC});

if (cy.Trace) {
var iter = vm.objectTraceMap.iterator();
while (iter.next()) |it| {
const trace = it.value_ptr.*;
if (trace.freePc == cy.NullId) {
try dumpObjectAllocTrace(vm, it.key_ptr.*, trace.allocPc);
}
}
}
if (rc != 0) {
std.debug.print("unreleased refcount: {}\n", .{rc});
c.traceDumpLiveObjects(@ptrCast(vm));

// var iter = cy.vm.traceObjRetains.iterator();
// while (iter.next()) |e| {
Expand All @@ -509,7 +495,7 @@ pub fn checkGlobalRC(vm: *cy.VM) !void {
}
}

fn dumpObjectAllocTrace(vm: *cy.VM, obj: *cy.HeapObject, allocPc: u32) !void {
pub fn dumpObjectAllocTrace(vm: *cy.VM, obj: *cy.HeapObject, allocPc: u32) !void {
var buf: [256]u8 = undefined;
const typeId = obj.getTypeId();
const typeName = vm.getTypeName(typeId);
Expand Down
17 changes: 9 additions & 8 deletions src/bc_gen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const log = cy.log.scoped(.bc_gen);
const ir = cy.ir;
const rt = cy.rt;
const sema = cy.sema;
const cc = @import("capi.zig");
const types = cy.types;
const bt = types.BuiltinTypes;
const v = cy.fmt.v;
Expand Down Expand Up @@ -240,7 +241,7 @@ fn genStmt(c: *Chunk, idx: u32) anyerror!void {
c.curNodeId = nodeId;
if (cy.Trace) {
const contextStr = try c.encoder.formatNode(nodeId, &cy.tempBuf);
if (cy.verbose) {
if (cc.verbose()) {
rt.logFmt("{}| {}: `{}` unw={} ntmp={}", &.{
cy.fmt.repeat(' ', c.indent * 4), v(@tagName(code)), v(contextStr),
v(c.unwindTempIndexStack.items.len), v(c.rega.nextTemp),
Expand Down Expand Up @@ -299,7 +300,7 @@ fn genStmt(c: *Chunk, idx: u32) anyerror!void {
}

if (cy.Trace) {
if (cy.verbose) {
if (cc.verbose()) {
rt.logFmt("{}| end {} unw={} ntmp={}", &.{
cy.fmt.repeat(' ', c.indent * 4), v(@tagName(code)),
v(c.unwindTempIndexStack.items.len), v(c.rega.nextTemp),
Expand Down Expand Up @@ -359,7 +360,7 @@ fn genExpr(c: *Chunk, idx: usize, cstr: Cstr) anyerror!GenValue {
if (cy.Trace) {
c.indent += 1;
const contextStr = try c.encoder.formatNode(nodeId, &cy.tempBuf);
if (cy.verbose) {
if (cc.verbose()) {
rt.logFmt("{}( {}: `{}` {} unw={} ntmp={}", &.{
cy.fmt.repeat(' ', c.indent * 4), v(@tagName(code)), v(contextStr), v(@tagName(cstr.type)),
v(c.unwindTempIndexStack.items.len), v(c.rega.nextTemp),
Expand Down Expand Up @@ -417,7 +418,7 @@ fn genExpr(c: *Chunk, idx: usize, cstr: Cstr) anyerror!GenValue {
}
};
if (cy.Trace) {
if (cy.verbose) {
if (cc.verbose()) {
rt.logFmt("{}) end {} unw={} ntmp={}", &.{
cy.fmt.repeat(' ', c.indent * 4), v(@tagName(code)),
v(c.unwindTempIndexStack.items.len), v(c.rega.nextTemp),
Expand Down Expand Up @@ -2736,7 +2737,7 @@ fn forRangeStmt(c: *Chunk, idx: usize, nodeId: cy.NodeId) !void {
fn verbose(c: *cy.Chunk, idx: usize, nodeId: cy.NodeId) !void {
_ = nodeId;
const data = c.ir.getStmtData(idx, .verbose);
cy.verbose = data.verbose;
cc.setVerbose(data.verbose);
}

fn tryStmt(c: *cy.Chunk, idx: usize, nodeId: cy.NodeId) !void {
Expand Down Expand Up @@ -3246,7 +3247,7 @@ fn pushFuncBlockCommon(c: *Chunk, maxIrLocals: u8, numParamCopies: u8, params: [

c.curBlock.frameLoc = nodeId;

if (c.compiler.config.genDebugFuncMarkers) {
if (c.compiler.config.gen_debug_func_markers) {
try c.compiler.buf.pushDebugFuncStart(func, c.id);
}

Expand Down Expand Up @@ -3282,7 +3283,7 @@ pub fn popFuncBlockCommon(c: *Chunk, func: *cy.Func) !void {
// Pop the null boundary index.
try popUnwind(c, cy.NullU8);

if (c.compiler.config.genDebugFuncMarkers) {
if (c.compiler.config.gen_debug_func_markers) {
try c.compiler.buf.pushDebugFuncEnd(func, c.id);
}

Expand Down Expand Up @@ -3338,7 +3339,7 @@ fn genLambda(c: *Chunk, idx: usize, cstr: Cstr, nodeId: cy.NodeId) !GenValue {
}

pub fn shouldGenMainScopeReleaseOps(c: *cy.Compiler) bool {
return !c.vm.config.singleRun;
return !c.vm.config.single_run;
}

fn genBlock(c: *Chunk, idx: usize, nodeId: cy.NodeId) !void {
Expand Down
Loading

0 comments on commit c437dfd

Please sign in to comment.