fibers B1.0b: abi(.pure) emits a real LLVM naked function (green)
Flip the B1.0a emit bail to real emission. The emit_llvm declaration pass now adds LLVM's naked + noinline + nounwind attributes for an is_pure function and skips frame-pointer=all (incompatible with a frameless function); Pass 2 emits the body normally, and the naked attribute makes the backend emit it verbatim (the inline asm + its own ret) with no prologue/epilogue. IR shape verified: ; Function Attrs: naked noinline nounwind define internal i64 @answer() #0 { entry: call void asm sideeffect "...ret...", ""() unreachable } The caller invokes it as an ordinary () -> i64 call (.pure is call_conv == .default). - examples/1800-concurrency-pure-asm.sx: now green, aarch64-pinned (.build macos) -> exit 42 + .ir snapshot. - examples/1801-concurrency-pure-generic.sx (renamed from -bail): the generic .pure now emits a correct naked answer__i64 (exit 42), proving generic.zig produces a naked body, not a framed one. - examples/1802-concurrency-pure-asm-x86.sx: x86_64 cross sibling (.build x86_64-linux, ir-only here); .ir locks naked + movl $42,%eax. - unit test in emit_llvm.test.zig asserts the naked attribute is present and frame-pointer absent on an abi(.pure) function. Suite green (724/0).
This commit is contained in:
@@ -1324,3 +1324,40 @@ test "emit: reflectArgRepr surfaces .unresolved for an unresolvable reflection a
|
||||
try std.testing.expectEqual(LLVMEmitter.ReflectArgRepr.unresolved, emitter.reflectArgRepr(bogus));
|
||||
try std.testing.expect(emitter.reflectArgRepr(bogus) != .bare);
|
||||
}
|
||||
|
||||
test "emit: abi(.pure) function gets the naked attribute (no frame-pointer)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
var b = Builder.init(&module);
|
||||
|
||||
// func answer() -> i64 abi(.pure) { asm volatile { "ret" }; unreachable }
|
||||
// The naked attribute is keyed off Function.is_pure in the declaration pass,
|
||||
// independent of the body — a minimal asm + unreachable body suffices.
|
||||
_ = b.beginFunction(str(&module, "answer"), &.{}, .i64);
|
||||
b.currentFunc().is_pure = true;
|
||||
const entry = b.appendBlock(str(&module, "entry"), &.{});
|
||||
b.switchToBlock(entry);
|
||||
|
||||
b.emitVoid(.{ .inline_asm = .{
|
||||
.template = str(&module, "ret"),
|
||||
.operands = &.{},
|
||||
.clobbers = &.{},
|
||||
.has_side_effects = true,
|
||||
} }, .void);
|
||||
b.emitUnreachable();
|
||||
b.finalize();
|
||||
|
||||
var emitter = LLVMEmitter.init(alloc, &module, "test_pure", .{});
|
||||
defer emitter.deinit();
|
||||
emitter.emit();
|
||||
|
||||
try std.testing.expect(emitter.verify());
|
||||
|
||||
const ir_str = emitter.dumpToString();
|
||||
// The naked attribute is present; a naked function carries no frame-pointer
|
||||
// attribute (incompatible with a frameless function).
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "naked") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "frame-pointer") == null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user