Merge branch 'cc-work' of https://github.com/LemonBoy/zig into LemonBoy-cc-work
This commit is contained in:
commit
0a9daeb37e
@ -818,6 +818,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
|
|||||||
.Keyword_resume,
|
.Keyword_resume,
|
||||||
.Keyword_return,
|
.Keyword_return,
|
||||||
.Keyword_linksection,
|
.Keyword_linksection,
|
||||||
|
.Keyword_callconv,
|
||||||
.Keyword_stdcallcc,
|
.Keyword_stdcallcc,
|
||||||
.Keyword_struct,
|
.Keyword_struct,
|
||||||
.Keyword_suspend,
|
.Keyword_suspend,
|
||||||
|
@ -2829,7 +2829,7 @@ test "@tagName" {
|
|||||||
<p>
|
<p>
|
||||||
By default, enums are not guaranteed to be compatible with the C ABI:
|
By default, enums are not guaranteed to be compatible with the C ABI:
|
||||||
</p>
|
</p>
|
||||||
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'ccc'#}
|
{#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'C'#}
|
||||||
const Foo = enum { A, B, C };
|
const Foo = enum { A, B, C };
|
||||||
export fn entry(foo: Foo) void { }
|
export fn entry(foo: Foo) void { }
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
|
@ -14,6 +14,7 @@ pub const TranslateCStep = struct {
|
|||||||
source: build.FileSource,
|
source: build.FileSource,
|
||||||
output_dir: ?[]const u8,
|
output_dir: ?[]const u8,
|
||||||
out_basename: []const u8,
|
out_basename: []const u8,
|
||||||
|
target: std.Target = .Native,
|
||||||
|
|
||||||
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
|
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
|
||||||
const self = builder.allocator.create(TranslateCStep) catch unreachable;
|
const self = builder.allocator.create(TranslateCStep) catch unreachable;
|
||||||
@ -38,6 +39,10 @@ pub const TranslateCStep = struct {
|
|||||||
) catch unreachable;
|
) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setTarget(self: *TranslateCStep, target: std.Target) void {
|
||||||
|
self.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a step to build an executable from the translated source.
|
/// Creates a step to build an executable from the translated source.
|
||||||
pub fn addExecutable(self: *TranslateCStep) *LibExeObjStep {
|
pub fn addExecutable(self: *TranslateCStep) *LibExeObjStep {
|
||||||
return self.builder.addExecutableSource("translated_c", @as(build.FileSource, .{ .translate_c = self }));
|
return self.builder.addExecutableSource("translated_c", @as(build.FileSource, .{ .translate_c = self }));
|
||||||
@ -50,16 +55,25 @@ pub const TranslateCStep = struct {
|
|||||||
fn make(step: *Step) !void {
|
fn make(step: *Step) !void {
|
||||||
const self = @fieldParentPtr(TranslateCStep, "step", step);
|
const self = @fieldParentPtr(TranslateCStep, "step", step);
|
||||||
|
|
||||||
const argv = [_][]const u8{
|
var argv_list = std.ArrayList([]const u8).init(self.builder.allocator);
|
||||||
self.builder.zig_exe,
|
try argv_list.append(self.builder.zig_exe);
|
||||||
"translate-c",
|
try argv_list.append("translate-c");
|
||||||
"-lc",
|
try argv_list.append("-lc");
|
||||||
"--cache",
|
|
||||||
"on",
|
|
||||||
self.source.getPath(self.builder),
|
|
||||||
};
|
|
||||||
|
|
||||||
const output_path_nl = try self.builder.exec(&argv);
|
try argv_list.append("--cache");
|
||||||
|
try argv_list.append("on");
|
||||||
|
|
||||||
|
switch (self.target) {
|
||||||
|
.Native => {},
|
||||||
|
.Cross => {
|
||||||
|
try argv_list.append("-target");
|
||||||
|
try argv_list.append(try self.target.zigTriple(self.builder.allocator));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
try argv_list.append(self.source.getPath(self.builder));
|
||||||
|
|
||||||
|
const output_path_nl = try self.builder.exec(argv_list.toSliceConst());
|
||||||
const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
|
const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
|
||||||
|
|
||||||
self.out_basename = fs.path.basename(output_path);
|
self.out_basename = fs.path.basename(output_path);
|
||||||
|
@ -91,6 +91,25 @@ pub const Mode = enum {
|
|||||||
ReleaseSmall,
|
ReleaseSmall,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This data structure is used by the Zig language code generation and
|
||||||
|
/// therefore must be kept in sync with the compiler implementation.
|
||||||
|
pub const CallingConvention = enum {
|
||||||
|
Unspecified,
|
||||||
|
C,
|
||||||
|
Cold,
|
||||||
|
Naked,
|
||||||
|
Async,
|
||||||
|
Interrupt,
|
||||||
|
Signal,
|
||||||
|
Stdcall,
|
||||||
|
Fastcall,
|
||||||
|
Vectorcall,
|
||||||
|
Thiscall,
|
||||||
|
APCS,
|
||||||
|
AAPCS,
|
||||||
|
AAPCSVFP,
|
||||||
|
};
|
||||||
|
|
||||||
pub const TypeId = @TagType(TypeInfo);
|
pub const TypeId = @TagType(TypeInfo);
|
||||||
|
|
||||||
/// This data structure is used by the Zig language code generation and
|
/// This data structure is used by the Zig language code generation and
|
||||||
@ -253,17 +272,6 @@ pub const TypeInfo = union(enum) {
|
|||||||
decls: []Declaration,
|
decls: []Declaration,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This data structure is used by the Zig language code generation and
|
|
||||||
/// therefore must be kept in sync with the compiler implementation.
|
|
||||||
pub const CallingConvention = enum {
|
|
||||||
Unspecified,
|
|
||||||
C,
|
|
||||||
Cold,
|
|
||||||
Naked,
|
|
||||||
Stdcall,
|
|
||||||
Async,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This data structure is used by the Zig language code generation and
|
/// This data structure is used by the Zig language code generation and
|
||||||
/// therefore must be kept in sync with the compiler implementation.
|
/// therefore must be kept in sync with the compiler implementation.
|
||||||
pub const FnArg = struct {
|
pub const FnArg = struct {
|
||||||
@ -416,7 +424,7 @@ pub const CallOptions = struct {
|
|||||||
/// therefore must be kept in sync with the compiler implementation.
|
/// therefore must be kept in sync with the compiler implementation.
|
||||||
pub const TestFn = struct {
|
pub const TestFn = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
func: fn()anyerror!void,
|
func: fn () anyerror!void,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This function type is used by the Zig language code generation and
|
/// This function type is used by the Zig language code generation and
|
||||||
|
@ -2475,7 +2475,7 @@ extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *con
|
|||||||
os.abort();
|
os.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
stdcallcc fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) c_long {
|
fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.Stdcall) c_long {
|
||||||
const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
|
const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
|
||||||
switch (info.ExceptionRecord.ExceptionCode) {
|
switch (info.ExceptionRecord.ExceptionCode) {
|
||||||
windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access", .{}),
|
windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access", .{}),
|
||||||
|
@ -73,8 +73,8 @@ pub const Mutex = if (builtin.single_threaded)
|
|||||||
return self.tryAcquire() orelse @panic("deadlock detected");
|
return self.tryAcquire() orelse @panic("deadlock detected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (builtin.os == .windows)
|
else if (builtin.os == .windows)
|
||||||
// https://locklessinc.com/articles/keyed_events/
|
// https://locklessinc.com/articles/keyed_events/
|
||||||
extern union {
|
extern union {
|
||||||
locked: u8,
|
locked: u8,
|
||||||
waiters: u32,
|
waiters: u32,
|
||||||
@ -122,8 +122,8 @@ else if (builtin.os == .windows)
|
|||||||
return Held{ .mutex = self };
|
return Held{ .mutex = self };
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, try and update the waiting count.
|
// otherwise, try and update the waiting count.
|
||||||
// then unset the WAKE bit so that another unlocker can wake up a thread.
|
// then unset the WAKE bit so that another unlocker can wake up a thread.
|
||||||
} else if (@cmpxchgWeak(u32, &self.waiters, waiters, (waiters + WAIT) | 1, .Monotonic, .Monotonic) == null) {
|
} else if (@cmpxchgWeak(u32, &self.waiters, waiters, (waiters + WAIT) | 1, .Monotonic, .Monotonic) == null) {
|
||||||
const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);
|
const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);
|
||||||
assert(rc == 0);
|
assert(rc == 0);
|
||||||
@ -143,7 +143,7 @@ else if (builtin.os == .windows)
|
|||||||
|
|
||||||
while (true) : (SpinLock.loopHint(1)) {
|
while (true) : (SpinLock.loopHint(1)) {
|
||||||
const waiters = @atomicLoad(u32, &self.mutex.waiters, .Monotonic);
|
const waiters = @atomicLoad(u32, &self.mutex.waiters, .Monotonic);
|
||||||
|
|
||||||
// no one is waiting
|
// no one is waiting
|
||||||
if (waiters < WAIT) return;
|
if (waiters < WAIT) return;
|
||||||
// someone grabbed the lock and will do the wake instead
|
// someone grabbed the lock and will do the wake instead
|
||||||
@ -155,14 +155,14 @@ else if (builtin.os == .windows)
|
|||||||
if (@cmpxchgWeak(u32, &self.mutex.waiters, waiters, waiters - WAIT + WAKE, .Release, .Monotonic) == null) {
|
if (@cmpxchgWeak(u32, &self.mutex.waiters, waiters, waiters - WAIT + WAKE, .Release, .Monotonic) == null) {
|
||||||
const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
|
const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
|
||||||
assert(rc == 0);
|
assert(rc == 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (builtin.link_libc or builtin.os == .linux)
|
else if (builtin.link_libc or builtin.os == .linux)
|
||||||
// stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs
|
// stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs
|
||||||
struct {
|
struct {
|
||||||
state: usize,
|
state: usize,
|
||||||
|
|
||||||
@ -195,8 +195,8 @@ else if (builtin.link_libc or builtin.os == .linux)
|
|||||||
|
|
||||||
pub fn acquire(self: *Mutex) Held {
|
pub fn acquire(self: *Mutex) Held {
|
||||||
return self.tryAcquire() orelse {
|
return self.tryAcquire() orelse {
|
||||||
self.acquireSlow();
|
self.acquireSlow();
|
||||||
return Held{ .mutex = self };
|
return Held{ .mutex = self };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ else if (builtin.link_libc or builtin.os == .linux)
|
|||||||
|
|
||||||
fn releaseSlow(self: *Mutex) void {
|
fn releaseSlow(self: *Mutex) void {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
|
|
||||||
// try and lock the LFIO queue to pop a node off,
|
// try and lock the LFIO queue to pop a node off,
|
||||||
// stopping altogether if its already locked or the queue is empty
|
// stopping altogether if its already locked or the queue is empty
|
||||||
var state = @atomicLoad(usize, &self.state, .Monotonic);
|
var state = @atomicLoad(usize, &self.state, .Monotonic);
|
||||||
@ -293,9 +293,10 @@ else if (builtin.link_libc or builtin.os == .linux)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for platforms without a known OS blocking
|
// for platforms without a known OS blocking
|
||||||
// primitive, default to SpinLock for correctness
|
// primitive, default to SpinLock for correctness
|
||||||
else SpinLock;
|
else
|
||||||
|
SpinLock;
|
||||||
|
|
||||||
const TestContext = struct {
|
const TestContext = struct {
|
||||||
mutex: *Mutex,
|
mutex: *Mutex,
|
||||||
|
@ -451,11 +451,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
|
|||||||
.next = null,
|
.next = null,
|
||||||
};
|
};
|
||||||
var res: *os.addrinfo = undefined;
|
var res: *os.addrinfo = undefined;
|
||||||
switch (os.system.getaddrinfo(
|
switch (os.system.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res)) {
|
||||||
name_c.ptr,
|
|
||||||
@ptrCast([*:0]const u8, port_c.ptr),
|
|
||||||
&hints,
|
|
||||||
&res)) {
|
|
||||||
0 => {},
|
0 => {},
|
||||||
c.EAI_ADDRFAMILY => return error.HostLacksNetworkAddresses,
|
c.EAI_ADDRFAMILY => return error.HostLacksNetworkAddresses,
|
||||||
c.EAI_AGAIN => return error.TemporaryNameServerFailure,
|
c.EAI_AGAIN => return error.TemporaryNameServerFailure,
|
||||||
|
@ -97,7 +97,7 @@ pub extern fn getThreadPointer() usize {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn restore() void {
|
pub fn restore() callconv(.Naked) void {
|
||||||
return asm volatile ("svc #0"
|
return asm volatile ("svc #0"
|
||||||
:
|
:
|
||||||
: [number] "{r7}" (@as(usize, SYS_sigreturn))
|
: [number] "{r7}" (@as(usize, SYS_sigreturn))
|
||||||
@ -105,7 +105,7 @@ pub nakedcc fn restore() void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("svc #0"
|
return asm volatile ("svc #0"
|
||||||
:
|
:
|
||||||
: [number] "{r7}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{r7}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -90,7 +90,7 @@ pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, a
|
|||||||
|
|
||||||
pub const restore = restore_rt;
|
pub const restore = restore_rt;
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("svc #0"
|
return asm volatile ("svc #0"
|
||||||
:
|
:
|
||||||
: [number] "{x8}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{x8}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -102,7 +102,7 @@ pub fn socketcall(call: usize, args: [*]usize) usize {
|
|||||||
/// This matches the libc clone function.
|
/// This matches the libc clone function.
|
||||||
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
|
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
|
||||||
|
|
||||||
pub nakedcc fn restore() void {
|
pub fn restore() callconv(.Naked) void {
|
||||||
return asm volatile ("int $0x80"
|
return asm volatile ("int $0x80"
|
||||||
:
|
:
|
||||||
: [number] "{eax}" (@as(usize, SYS_sigreturn))
|
: [number] "{eax}" (@as(usize, SYS_sigreturn))
|
||||||
@ -110,7 +110,7 @@ pub nakedcc fn restore() void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("int $0x80"
|
return asm volatile ("int $0x80"
|
||||||
:
|
:
|
||||||
: [number] "{eax}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{eax}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -144,7 +144,7 @@ pub fn syscall6(
|
|||||||
/// This matches the libc clone function.
|
/// This matches the libc clone function.
|
||||||
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
|
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
|
||||||
|
|
||||||
pub nakedcc fn restore() void {
|
pub fn restore() callconv(.Naked) void {
|
||||||
return asm volatile ("syscall"
|
return asm volatile ("syscall"
|
||||||
:
|
:
|
||||||
: [number] "{$2}" (@as(usize, SYS_sigreturn))
|
: [number] "{$2}" (@as(usize, SYS_sigreturn))
|
||||||
@ -152,7 +152,7 @@ pub nakedcc fn restore() void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("syscall"
|
return asm volatile ("syscall"
|
||||||
:
|
:
|
||||||
: [number] "{$2}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{$2}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -89,7 +89,7 @@ pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, a
|
|||||||
|
|
||||||
pub const restore = restore_rt;
|
pub const restore = restore_rt;
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("ecall"
|
return asm volatile ("ecall"
|
||||||
:
|
:
|
||||||
: [number] "{x17}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{x17}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -90,7 +90,7 @@ pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: usize,
|
|||||||
|
|
||||||
pub const restore = restore_rt;
|
pub const restore = restore_rt;
|
||||||
|
|
||||||
pub nakedcc fn restore_rt() void {
|
pub fn restore_rt() callconv(.Naked) void {
|
||||||
return asm volatile ("syscall"
|
return asm volatile ("syscall"
|
||||||
:
|
:
|
||||||
: [number] "{rax}" (@as(usize, SYS_rt_sigreturn))
|
: [number] "{rax}" (@as(usize, SYS_rt_sigreturn))
|
||||||
|
@ -166,7 +166,7 @@ test "sigaltstack" {
|
|||||||
// analyzed
|
// analyzed
|
||||||
const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
|
const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
|
||||||
|
|
||||||
export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
|
extern fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
|
||||||
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -27,4 +27,3 @@ pub const SimpleTextInputProtocol = extern struct {
|
|||||||
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
|
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
usingnamespace @import("bits.zig");
|
usingnamespace @import("bits.zig");
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn RegOpenKeyExW(
|
pub extern "advapi32" fn RegOpenKeyExW(
|
||||||
hKey: HKEY,
|
hKey: HKEY,
|
||||||
lpSubKey: LPCWSTR,
|
lpSubKey: LPCWSTR,
|
||||||
ulOptions: DWORD,
|
ulOptions: DWORD,
|
||||||
samDesired: REGSAM,
|
samDesired: REGSAM,
|
||||||
phkResult: *HKEY,
|
phkResult: *HKEY,
|
||||||
) LSTATUS;
|
) callconv(.Stdcall) LSTATUS;
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn RegQueryValueExW(
|
pub extern "advapi32" fn RegQueryValueExW(
|
||||||
hKey: HKEY,
|
hKey: HKEY,
|
||||||
lpValueName: LPCWSTR,
|
lpValueName: LPCWSTR,
|
||||||
lpReserved: LPDWORD,
|
lpReserved: LPDWORD,
|
||||||
lpType: LPDWORD,
|
lpType: LPDWORD,
|
||||||
lpData: LPBYTE,
|
lpData: LPBYTE,
|
||||||
lpcbData: LPDWORD,
|
lpcbData: LPDWORD,
|
||||||
) LSTATUS;
|
) callconv(.Stdcall) LSTATUS;
|
||||||
|
|
||||||
// RtlGenRandom is known as SystemFunction036 under advapi32
|
// RtlGenRandom is known as SystemFunction036 under advapi32
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
|
||||||
pub extern "advapi32" stdcallcc fn SystemFunction036(output: [*]u8, length: ULONG) BOOL;
|
pub extern "advapi32" fn SystemFunction036(output: [*]u8, length: ULONG) callconv(.Stdcall) BOOL;
|
||||||
pub const RtlGenRandom = SystemFunction036;
|
pub const RtlGenRandom = SystemFunction036;
|
||||||
|
@ -892,7 +892,7 @@ pub const EXCEPTION_POINTERS = extern struct {
|
|||||||
ContextRecord: *c_void,
|
ContextRecord: *c_void,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const VECTORED_EXCEPTION_HANDLER = stdcallcc fn (ExceptionInfo: *EXCEPTION_POINTERS) c_long;
|
pub const VECTORED_EXCEPTION_HANDLER = fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(.Stdcall) c_long;
|
||||||
|
|
||||||
pub const OBJECT_ATTRIBUTES = extern struct {
|
pub const OBJECT_ATTRIBUTES = extern struct {
|
||||||
Length: ULONG,
|
Length: ULONG,
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
usingnamespace @import("bits.zig");
|
usingnamespace @import("bits.zig");
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void;
|
pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(.Stdcall) ?*c_void;
|
||||||
pub extern "kernel32" stdcallcc fn RemoveVectoredExceptionHandler(Handle: HANDLE) c_ulong;
|
pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(.Stdcall) c_ulong;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
|
pub extern "kernel32" fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
|
pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: [*]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;
|
pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateEventExW(
|
pub extern "kernel32" fn CreateEventExW(
|
||||||
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
|
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
|
||||||
lpName: [*:0]const u16,
|
lpName: [*:0]const u16,
|
||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
dwDesiredAccess: DWORD,
|
dwDesiredAccess: DWORD,
|
||||||
) ?HANDLE;
|
) callconv(.Stdcall) ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateFileW(
|
pub extern "kernel32" fn CreateFileW(
|
||||||
lpFileName: [*]const u16, // TODO null terminated pointer type
|
lpFileName: [*]const u16, // TODO null terminated pointer type
|
||||||
dwDesiredAccess: DWORD,
|
dwDesiredAccess: DWORD,
|
||||||
dwShareMode: DWORD,
|
dwShareMode: DWORD,
|
||||||
@ -24,16 +24,16 @@ pub extern "kernel32" stdcallcc fn CreateFileW(
|
|||||||
dwCreationDisposition: DWORD,
|
dwCreationDisposition: DWORD,
|
||||||
dwFlagsAndAttributes: DWORD,
|
dwFlagsAndAttributes: DWORD,
|
||||||
hTemplateFile: ?HANDLE,
|
hTemplateFile: ?HANDLE,
|
||||||
) HANDLE;
|
) callconv(.Stdcall) HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreatePipe(
|
pub extern "kernel32" fn CreatePipe(
|
||||||
hReadPipe: *HANDLE,
|
hReadPipe: *HANDLE,
|
||||||
hWritePipe: *HANDLE,
|
hWritePipe: *HANDLE,
|
||||||
lpPipeAttributes: *const SECURITY_ATTRIBUTES,
|
lpPipeAttributes: *const SECURITY_ATTRIBUTES,
|
||||||
nSize: DWORD,
|
nSize: DWORD,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateProcessW(
|
pub extern "kernel32" fn CreateProcessW(
|
||||||
lpApplicationName: ?LPWSTR,
|
lpApplicationName: ?LPWSTR,
|
||||||
lpCommandLine: LPWSTR,
|
lpCommandLine: LPWSTR,
|
||||||
lpProcessAttributes: ?*SECURITY_ATTRIBUTES,
|
lpProcessAttributes: ?*SECURITY_ATTRIBUTES,
|
||||||
@ -44,15 +44,15 @@ pub extern "kernel32" stdcallcc fn CreateProcessW(
|
|||||||
lpCurrentDirectory: ?LPWSTR,
|
lpCurrentDirectory: ?LPWSTR,
|
||||||
lpStartupInfo: *STARTUPINFOW,
|
lpStartupInfo: *STARTUPINFOW,
|
||||||
lpProcessInformation: *PROCESS_INFORMATION,
|
lpProcessInformation: *PROCESS_INFORMATION,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateSymbolicLinkW(lpSymlinkFileName: [*]const u16, lpTargetFileName: [*]const u16, dwFlags: DWORD) BOOLEAN;
|
pub extern "kernel32" fn CreateSymbolicLinkW(lpSymlinkFileName: [*]const u16, lpTargetFileName: [*]const u16, dwFlags: DWORD) callconv(.Stdcall) BOOLEAN;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateIoCompletionPort(FileHandle: HANDLE, ExistingCompletionPort: ?HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) ?HANDLE;
|
pub extern "kernel32" fn CreateIoCompletionPort(FileHandle: HANDLE, ExistingCompletionPort: ?HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) callconv(.Stdcall) ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: ?LPVOID, dwCreationFlags: DWORD, lpThreadId: ?LPDWORD) ?HANDLE;
|
pub extern "kernel32" fn CreateThread(lpThreadAttributes: ?LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: ?LPVOID, dwCreationFlags: DWORD, lpThreadId: ?LPDWORD) callconv(.Stdcall) ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn DeviceIoControl(
|
pub extern "kernel32" fn DeviceIoControl(
|
||||||
h: HANDLE,
|
h: HANDLE,
|
||||||
dwIoControlCode: DWORD,
|
dwIoControlCode: DWORD,
|
||||||
lpInBuffer: ?*const c_void,
|
lpInBuffer: ?*const c_void,
|
||||||
@ -61,107 +61,107 @@ pub extern "kernel32" stdcallcc fn DeviceIoControl(
|
|||||||
nOutBufferSize: DWORD,
|
nOutBufferSize: DWORD,
|
||||||
lpBytesReturned: ?*DWORD,
|
lpBytesReturned: ?*DWORD,
|
||||||
lpOverlapped: ?*OVERLAPPED,
|
lpOverlapped: ?*OVERLAPPED,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
|
pub extern "kernel32" fn DeleteFileW(lpFileName: [*]const u16) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) BOOL;
|
pub extern "kernel32" fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
|
pub extern "kernel32" fn ExitProcess(exit_code: UINT) callconv(.Stdcall) noreturn;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
|
pub extern "kernel32" fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) callconv(.Stdcall) HANDLE;
|
||||||
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
|
pub extern "kernel32" fn FindClose(hFindFile: HANDLE) callconv(.Stdcall) BOOL;
|
||||||
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
|
pub extern "kernel32" fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FormatMessageW(dwFlags: DWORD, lpSource: ?LPVOID, dwMessageId: DWORD, dwLanguageId: DWORD, lpBuffer: LPWSTR, nSize: DWORD, Arguments: ?*va_list) DWORD;
|
pub extern "kernel32" fn FormatMessageW(dwFlags: DWORD, lpSource: ?LPVOID, dwMessageId: DWORD, dwLanguageId: DWORD, lpBuffer: LPWSTR, nSize: DWORD, Arguments: ?*va_list) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
|
pub extern "kernel32" fn FreeEnvironmentStringsW(penv: [*]u16) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
|
pub extern "kernel32" fn GetCommandLineA() callconv(.Stdcall) LPSTR;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: *DWORD) BOOL;
|
pub extern "kernel32" fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: *DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: *CONSOLE_SCREEN_BUFFER_INFO) BOOL;
|
pub extern "kernel32" fn GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: *CONSOLE_SCREEN_BUFFER_INFO) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) DWORD;
|
pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
|
pub extern "kernel32" fn GetCurrentThread() callconv(.Stdcall) HANDLE;
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
|
pub extern "kernel32" fn GetCurrentThreadId() callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
|
pub extern "kernel32" fn GetEnvironmentStringsW() callconv(.Stdcall) ?[*]u16;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
|
pub extern "kernel32" fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
|
pub extern "kernel32" fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: *LARGE_INTEGER) BOOL;
|
pub extern "kernel32" fn GetFileSizeEx(hFile: HANDLE, lpFileSize: *LARGE_INTEGER) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetFileAttributesW(lpFileName: [*]const WCHAR) DWORD;
|
pub extern "kernel32" fn GetFileAttributesW(lpFileName: [*]const WCHAR) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;
|
pub extern "kernel32" fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;
|
pub extern "kernel32" fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) callconv(.Stdcall) HMODULE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetLastError() DWORD;
|
pub extern "kernel32" fn GetLastError() callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetFileInformationByHandle(
|
pub extern "kernel32" fn GetFileInformationByHandle(
|
||||||
hFile: HANDLE,
|
hFile: HANDLE,
|
||||||
lpFileInformation: *BY_HANDLE_FILE_INFORMATION,
|
lpFileInformation: *BY_HANDLE_FILE_INFORMATION,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(
|
pub extern "kernel32" fn GetFileInformationByHandleEx(
|
||||||
in_hFile: HANDLE,
|
in_hFile: HANDLE,
|
||||||
in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
|
in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
|
||||||
out_lpFileInformation: *c_void,
|
out_lpFileInformation: *c_void,
|
||||||
in_dwBufferSize: DWORD,
|
in_dwBufferSize: DWORD,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleW(
|
pub extern "kernel32" fn GetFinalPathNameByHandleW(
|
||||||
hFile: HANDLE,
|
hFile: HANDLE,
|
||||||
lpszFilePath: [*]u16,
|
lpszFilePath: [*]u16,
|
||||||
cchFilePath: DWORD,
|
cchFilePath: DWORD,
|
||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
) DWORD;
|
) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERLAPPED, lpNumberOfBytesTransferred: *DWORD, bWait: BOOL) BOOL;
|
pub extern "kernel32" fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERLAPPED, lpNumberOfBytesTransferred: *DWORD, bWait: BOOL) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetProcessHeap() ?HANDLE;
|
pub extern "kernel32" fn GetProcessHeap() callconv(.Stdcall) ?HANDLE;
|
||||||
pub extern "kernel32" stdcallcc fn GetQueuedCompletionStatus(CompletionPort: HANDLE, lpNumberOfBytesTransferred: LPDWORD, lpCompletionKey: *ULONG_PTR, lpOverlapped: *?*OVERLAPPED, dwMilliseconds: DWORD) BOOL;
|
pub extern "kernel32" fn GetQueuedCompletionStatus(CompletionPort: HANDLE, lpNumberOfBytesTransferred: LPDWORD, lpCompletionKey: *ULONG_PTR, lpOverlapped: *?*OVERLAPPED, dwMilliseconds: DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) void;
|
pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(.Stdcall) void;
|
||||||
pub extern "kernel32" stdcallcc fn GetSystemTimeAsFileTime(*FILETIME) void;
|
pub extern "kernel32" fn GetSystemTimeAsFileTime(*FILETIME) callconv(.Stdcall) void;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) ?HANDLE;
|
pub extern "kernel32" fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) callconv(.Stdcall) ?HANDLE;
|
||||||
pub extern "kernel32" stdcallcc fn HeapDestroy(hHeap: HANDLE) BOOL;
|
pub extern "kernel32" fn HeapDestroy(hHeap: HANDLE) callconv(.Stdcall) BOOL;
|
||||||
pub extern "kernel32" stdcallcc fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void, dwBytes: SIZE_T) ?*c_void;
|
pub extern "kernel32" fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void, dwBytes: SIZE_T) callconv(.Stdcall) ?*c_void;
|
||||||
pub extern "kernel32" stdcallcc fn HeapSize(hHeap: HANDLE, dwFlags: DWORD, lpMem: *const c_void) SIZE_T;
|
pub extern "kernel32" fn HeapSize(hHeap: HANDLE, dwFlags: DWORD, lpMem: *const c_void) callconv(.Stdcall) SIZE_T;
|
||||||
pub extern "kernel32" stdcallcc fn HeapCompact(hHeap: HANDLE, dwFlags: DWORD) SIZE_T;
|
pub extern "kernel32" fn HeapCompact(hHeap: HANDLE, dwFlags: DWORD) callconv(.Stdcall) SIZE_T;
|
||||||
pub extern "kernel32" stdcallcc fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) BOOL;
|
pub extern "kernel32" fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) ?HANDLE;
|
pub extern "kernel32" fn GetStdHandle(in_nStdHandle: DWORD) callconv(.Stdcall) ?HANDLE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) ?*c_void;
|
pub extern "kernel32" fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) callconv(.Stdcall) ?*c_void;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void) BOOL;
|
pub extern "kernel32" fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) BOOL;
|
pub extern "kernel32" fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*const c_void) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) ?LPVOID;
|
pub extern "kernel32" fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) callconv(.Stdcall) ?LPVOID;
|
||||||
pub extern "kernel32" stdcallcc fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) BOOL;
|
pub extern "kernel32" fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn MoveFileExW(
|
pub extern "kernel32" fn MoveFileExW(
|
||||||
lpExistingFileName: [*]const u16,
|
lpExistingFileName: [*]const u16,
|
||||||
lpNewFileName: [*]const u16,
|
lpNewFileName: [*]const u16,
|
||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn PostQueuedCompletionStatus(CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: ULONG_PTR, lpOverlapped: ?*OVERLAPPED) BOOL;
|
pub extern "kernel32" fn PostQueuedCompletionStatus(CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: ULONG_PTR, lpOverlapped: ?*OVERLAPPED) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn QueryPerformanceCounter(lpPerformanceCount: *LARGE_INTEGER) BOOL;
|
pub extern "kernel32" fn QueryPerformanceCounter(lpPerformanceCount: *LARGE_INTEGER) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn QueryPerformanceFrequency(lpFrequency: *LARGE_INTEGER) BOOL;
|
pub extern "kernel32" fn QueryPerformanceFrequency(lpFrequency: *LARGE_INTEGER) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn ReadDirectoryChangesW(
|
pub extern "kernel32" fn ReadDirectoryChangesW(
|
||||||
hDirectory: HANDLE,
|
hDirectory: HANDLE,
|
||||||
lpBuffer: [*]align(@alignOf(FILE_NOTIFY_INFORMATION)) u8,
|
lpBuffer: [*]align(@alignOf(FILE_NOTIFY_INFORMATION)) u8,
|
||||||
nBufferLength: DWORD,
|
nBufferLength: DWORD,
|
||||||
@ -170,79 +170,79 @@ pub extern "kernel32" stdcallcc fn ReadDirectoryChangesW(
|
|||||||
lpBytesReturned: ?*DWORD,
|
lpBytesReturned: ?*DWORD,
|
||||||
lpOverlapped: ?*OVERLAPPED,
|
lpOverlapped: ?*OVERLAPPED,
|
||||||
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn ReadFile(
|
pub extern "kernel32" fn ReadFile(
|
||||||
in_hFile: HANDLE,
|
in_hFile: HANDLE,
|
||||||
out_lpBuffer: [*]u8,
|
out_lpBuffer: [*]u8,
|
||||||
in_nNumberOfBytesToRead: DWORD,
|
in_nNumberOfBytesToRead: DWORD,
|
||||||
out_lpNumberOfBytesRead: ?*DWORD,
|
out_lpNumberOfBytesRead: ?*DWORD,
|
||||||
in_out_lpOverlapped: ?*OVERLAPPED,
|
in_out_lpOverlapped: ?*OVERLAPPED,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn RemoveDirectoryW(lpPathName: [*]const u16) BOOL;
|
pub extern "kernel32" fn RemoveDirectoryW(lpPathName: [*]const u16) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) BOOL;
|
pub extern "kernel32" fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn SetFilePointerEx(
|
pub extern "kernel32" fn SetFilePointerEx(
|
||||||
in_fFile: HANDLE,
|
in_fFile: HANDLE,
|
||||||
in_liDistanceToMove: LARGE_INTEGER,
|
in_liDistanceToMove: LARGE_INTEGER,
|
||||||
out_opt_ldNewFilePointer: ?*LARGE_INTEGER,
|
out_opt_ldNewFilePointer: ?*LARGE_INTEGER,
|
||||||
in_dwMoveMethod: DWORD,
|
in_dwMoveMethod: DWORD,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn SetFileTime(
|
pub extern "kernel32" fn SetFileTime(
|
||||||
hFile: HANDLE,
|
hFile: HANDLE,
|
||||||
lpCreationTime: ?*const FILETIME,
|
lpCreationTime: ?*const FILETIME,
|
||||||
lpLastAccessTime: ?*const FILETIME,
|
lpLastAccessTime: ?*const FILETIME,
|
||||||
lpLastWriteTime: ?*const FILETIME,
|
lpLastWriteTime: ?*const FILETIME,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) BOOL;
|
pub extern "kernel32" fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
|
pub extern "kernel32" fn Sleep(dwMilliseconds: DWORD) callconv(.Stdcall) void;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn SwitchToThread() BOOL;
|
pub extern "kernel32" fn SwitchToThread() callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;
|
pub extern "kernel32" fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD;
|
pub extern "kernel32" fn TlsAlloc() callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL;
|
pub extern "kernel32" fn TlsFree(dwTlsIndex: DWORD) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
|
pub extern "kernel32" fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL) DWORD;
|
pub extern "kernel32" fn WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WaitForMultipleObjects(nCount: DWORD, lpHandle: [*]const HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD) DWORD;
|
pub extern "kernel32" fn WaitForMultipleObjects(nCount: DWORD, lpHandle: [*]const HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WaitForMultipleObjectsEx(
|
pub extern "kernel32" fn WaitForMultipleObjectsEx(
|
||||||
nCount: DWORD,
|
nCount: DWORD,
|
||||||
lpHandle: [*]const HANDLE,
|
lpHandle: [*]const HANDLE,
|
||||||
bWaitAll: BOOL,
|
bWaitAll: BOOL,
|
||||||
dwMilliseconds: DWORD,
|
dwMilliseconds: DWORD,
|
||||||
bAlertable: BOOL,
|
bAlertable: BOOL,
|
||||||
) DWORD;
|
) callconv(.Stdcall) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WriteFile(
|
pub extern "kernel32" fn WriteFile(
|
||||||
in_hFile: HANDLE,
|
in_hFile: HANDLE,
|
||||||
in_lpBuffer: [*]const u8,
|
in_lpBuffer: [*]const u8,
|
||||||
in_nNumberOfBytesToWrite: DWORD,
|
in_nNumberOfBytesToWrite: DWORD,
|
||||||
out_lpNumberOfBytesWritten: ?*DWORD,
|
out_lpNumberOfBytesWritten: ?*DWORD,
|
||||||
in_out_lpOverlapped: ?*OVERLAPPED,
|
in_out_lpOverlapped: ?*OVERLAPPED,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
|
pub extern "kernel32" fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
|
pub extern "kernel32" fn LoadLibraryW(lpLibFileName: [*]const u16) callconv(.Stdcall) ?HMODULE;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
|
pub extern "kernel32" fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) callconv(.Stdcall) ?FARPROC;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL;
|
pub extern "kernel32" fn FreeLibrary(hModule: HMODULE) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
|
pub extern "kernel32" fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) callconv(.Stdcall) void;
|
||||||
pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
|
pub extern "kernel32" fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) callconv(.Stdcall) void;
|
||||||
pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
|
pub extern "kernel32" fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) callconv(.Stdcall) void;
|
||||||
pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
|
pub extern "kernel32" fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) callconv(.Stdcall) void;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL;
|
pub extern "kernel32" fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) callconv(.Stdcall) BOOL;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
usingnamespace @import("bits.zig");
|
usingnamespace @import("bits.zig");
|
||||||
|
|
||||||
pub extern "NtDll" stdcallcc fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) WORD;
|
pub extern "NtDll" fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) callconv(.Stdcall) WORD;
|
||||||
pub extern "NtDll" stdcallcc fn NtQueryInformationFile(
|
pub extern "NtDll" fn NtQueryInformationFile(
|
||||||
FileHandle: HANDLE,
|
FileHandle: HANDLE,
|
||||||
IoStatusBlock: *IO_STATUS_BLOCK,
|
IoStatusBlock: *IO_STATUS_BLOCK,
|
||||||
FileInformation: *c_void,
|
FileInformation: *c_void,
|
||||||
Length: ULONG,
|
Length: ULONG,
|
||||||
FileInformationClass: FILE_INFORMATION_CLASS,
|
FileInformationClass: FILE_INFORMATION_CLASS,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtCreateFile(
|
pub extern "NtDll" fn NtCreateFile(
|
||||||
FileHandle: *HANDLE,
|
FileHandle: *HANDLE,
|
||||||
DesiredAccess: ACCESS_MASK,
|
DesiredAccess: ACCESS_MASK,
|
||||||
ObjectAttributes: *OBJECT_ATTRIBUTES,
|
ObjectAttributes: *OBJECT_ATTRIBUTES,
|
||||||
@ -20,8 +20,8 @@ pub extern "NtDll" stdcallcc fn NtCreateFile(
|
|||||||
CreateOptions: ULONG,
|
CreateOptions: ULONG,
|
||||||
EaBuffer: ?*c_void,
|
EaBuffer: ?*c_void,
|
||||||
EaLength: ULONG,
|
EaLength: ULONG,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtDeviceIoControlFile(
|
pub extern "NtDll" fn NtDeviceIoControlFile(
|
||||||
FileHandle: HANDLE,
|
FileHandle: HANDLE,
|
||||||
Event: ?HANDLE,
|
Event: ?HANDLE,
|
||||||
ApcRoutine: ?IO_APC_ROUTINE,
|
ApcRoutine: ?IO_APC_ROUTINE,
|
||||||
@ -32,17 +32,17 @@ pub extern "NtDll" stdcallcc fn NtDeviceIoControlFile(
|
|||||||
InputBufferLength: ULONG,
|
InputBufferLength: ULONG,
|
||||||
OutputBuffer: ?PVOID,
|
OutputBuffer: ?PVOID,
|
||||||
OutputBufferLength: ULONG,
|
OutputBufferLength: ULONG,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtClose(Handle: HANDLE) NTSTATUS;
|
pub extern "NtDll" fn NtClose(Handle: HANDLE) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn RtlDosPathNameToNtPathName_U(
|
pub extern "NtDll" fn RtlDosPathNameToNtPathName_U(
|
||||||
DosPathName: [*]const u16,
|
DosPathName: [*]const u16,
|
||||||
NtPathName: *UNICODE_STRING,
|
NtPathName: *UNICODE_STRING,
|
||||||
NtFileNamePart: ?*?[*]const u16,
|
NtFileNamePart: ?*?[*]const u16,
|
||||||
DirectoryInfo: ?*CURDIR,
|
DirectoryInfo: ?*CURDIR,
|
||||||
) BOOL;
|
) callconv(.Stdcall) BOOL;
|
||||||
pub extern "NtDll" stdcallcc fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) void;
|
pub extern "NtDll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(.Stdcall) void;
|
||||||
|
|
||||||
pub extern "NtDll" stdcallcc fn NtQueryDirectoryFile(
|
pub extern "NtDll" fn NtQueryDirectoryFile(
|
||||||
FileHandle: HANDLE,
|
FileHandle: HANDLE,
|
||||||
Event: ?HANDLE,
|
Event: ?HANDLE,
|
||||||
ApcRoutine: ?IO_APC_ROUTINE,
|
ApcRoutine: ?IO_APC_ROUTINE,
|
||||||
@ -54,22 +54,22 @@ pub extern "NtDll" stdcallcc fn NtQueryDirectoryFile(
|
|||||||
ReturnSingleEntry: BOOLEAN,
|
ReturnSingleEntry: BOOLEAN,
|
||||||
FileName: ?*UNICODE_STRING,
|
FileName: ?*UNICODE_STRING,
|
||||||
RestartScan: BOOLEAN,
|
RestartScan: BOOLEAN,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtCreateKeyedEvent(
|
pub extern "NtDll" fn NtCreateKeyedEvent(
|
||||||
KeyedEventHandle: *HANDLE,
|
KeyedEventHandle: *HANDLE,
|
||||||
DesiredAccess: ACCESS_MASK,
|
DesiredAccess: ACCESS_MASK,
|
||||||
ObjectAttributes: ?PVOID,
|
ObjectAttributes: ?PVOID,
|
||||||
Flags: ULONG,
|
Flags: ULONG,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtReleaseKeyedEvent(
|
pub extern "NtDll" fn NtReleaseKeyedEvent(
|
||||||
EventHandle: HANDLE,
|
EventHandle: HANDLE,
|
||||||
Key: *const c_void,
|
Key: *const c_void,
|
||||||
Alertable: BOOLEAN,
|
Alertable: BOOLEAN,
|
||||||
Timeout: ?*LARGE_INTEGER,
|
Timeout: ?*LARGE_INTEGER,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
pub extern "NtDll" stdcallcc fn NtWaitForKeyedEvent(
|
pub extern "NtDll" fn NtWaitForKeyedEvent(
|
||||||
EventHandle: HANDLE,
|
EventHandle: HANDLE,
|
||||||
Key: *const c_void,
|
Key: *const c_void,
|
||||||
Alertable: BOOLEAN,
|
Alertable: BOOLEAN,
|
||||||
Timeout: ?*LARGE_INTEGER,
|
Timeout: ?*LARGE_INTEGER,
|
||||||
) NTSTATUS;
|
) callconv(.Stdcall) NTSTATUS;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
usingnamespace @import("bits.zig");
|
usingnamespace @import("bits.zig");
|
||||||
|
|
||||||
pub extern "ole32" stdcallcc fn CoTaskMemFree(pv: LPVOID) void;
|
pub extern "ole32" fn CoTaskMemFree(pv: LPVOID) callconv(.Stdcall) void;
|
||||||
pub extern "ole32" stdcallcc fn CoUninitialize() void;
|
pub extern "ole32" fn CoUninitialize() callconv(.Stdcall) void;
|
||||||
pub extern "ole32" stdcallcc fn CoGetCurrentProcess() DWORD;
|
pub extern "ole32" fn CoGetCurrentProcess() callconv(.Stdcall) DWORD;
|
||||||
pub extern "ole32" stdcallcc fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) HRESULT;
|
pub extern "ole32" fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) callconv(.Stdcall) HRESULT;
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
usingnamespace @import("bits.zig");
|
usingnamespace @import("bits.zig");
|
||||||
|
|
||||||
pub extern "shell32" stdcallcc fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*]WCHAR) HRESULT;
|
pub extern "shell32" fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*]WCHAR) callconv(.Stdcall) HRESULT;
|
||||||
|
@ -315,30 +315,30 @@ const IOC_WS2 = 0x08000000;
|
|||||||
|
|
||||||
pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34;
|
pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34;
|
||||||
|
|
||||||
pub extern "ws2_32" stdcallcc fn WSAStartup(
|
pub extern "ws2_32" fn WSAStartup(
|
||||||
wVersionRequired: WORD,
|
wVersionRequired: WORD,
|
||||||
lpWSAData: *WSADATA,
|
lpWSAData: *WSADATA,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSACleanup() c_int;
|
pub extern "ws2_32" fn WSACleanup() callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSAGetLastError() c_int;
|
pub extern "ws2_32" fn WSAGetLastError() callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSASocketA(
|
pub extern "ws2_32" fn WSASocketA(
|
||||||
af: c_int,
|
af: c_int,
|
||||||
type: c_int,
|
type: c_int,
|
||||||
protocol: c_int,
|
protocol: c_int,
|
||||||
lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
|
lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
|
||||||
g: GROUP,
|
g: GROUP,
|
||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
) SOCKET;
|
) callconv(.Stdcall) SOCKET;
|
||||||
pub extern "ws2_32" stdcallcc fn WSASocketW(
|
pub extern "ws2_32" fn WSASocketW(
|
||||||
af: c_int,
|
af: c_int,
|
||||||
type: c_int,
|
type: c_int,
|
||||||
protocol: c_int,
|
protocol: c_int,
|
||||||
lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
|
lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
|
||||||
g: GROUP,
|
g: GROUP,
|
||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
) SOCKET;
|
) callconv(.Stdcall) SOCKET;
|
||||||
pub extern "ws2_32" stdcallcc fn closesocket(s: SOCKET) c_int;
|
pub extern "ws2_32" fn closesocket(s: SOCKET) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSAIoctl(
|
pub extern "ws2_32" fn WSAIoctl(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
dwIoControlCode: DWORD,
|
dwIoControlCode: DWORD,
|
||||||
lpvInBuffer: ?*const c_void,
|
lpvInBuffer: ?*const c_void,
|
||||||
@ -348,18 +348,18 @@ pub extern "ws2_32" stdcallcc fn WSAIoctl(
|
|||||||
lpcbBytesReturned: LPDWORD,
|
lpcbBytesReturned: LPDWORD,
|
||||||
lpOverlapped: ?*WSAOVERLAPPED,
|
lpOverlapped: ?*WSAOVERLAPPED,
|
||||||
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn accept(
|
pub extern "ws2_32" fn accept(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
addr: ?*sockaddr,
|
addr: ?*sockaddr,
|
||||||
addrlen: socklen_t,
|
addrlen: socklen_t,
|
||||||
) SOCKET;
|
) callconv(.Stdcall) SOCKET;
|
||||||
pub extern "ws2_32" stdcallcc fn connect(
|
pub extern "ws2_32" fn connect(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
name: *const sockaddr,
|
name: *const sockaddr,
|
||||||
namelen: socklen_t,
|
namelen: socklen_t,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSARecv(
|
pub extern "ws2_32" fn WSARecv(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
lpBuffers: [*]const WSABUF,
|
lpBuffers: [*]const WSABUF,
|
||||||
dwBufferCount: DWORD,
|
dwBufferCount: DWORD,
|
||||||
@ -367,8 +367,8 @@ pub extern "ws2_32" stdcallcc fn WSARecv(
|
|||||||
lpFlags: *DWORD,
|
lpFlags: *DWORD,
|
||||||
lpOverlapped: ?*WSAOVERLAPPED,
|
lpOverlapped: ?*WSAOVERLAPPED,
|
||||||
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSARecvFrom(
|
pub extern "ws2_32" fn WSARecvFrom(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
lpBuffers: [*]const WSABUF,
|
lpBuffers: [*]const WSABUF,
|
||||||
dwBufferCount: DWORD,
|
dwBufferCount: DWORD,
|
||||||
@ -378,8 +378,8 @@ pub extern "ws2_32" stdcallcc fn WSARecvFrom(
|
|||||||
lpFromlen: socklen_t,
|
lpFromlen: socklen_t,
|
||||||
lpOverlapped: ?*WSAOVERLAPPED,
|
lpOverlapped: ?*WSAOVERLAPPED,
|
||||||
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSASend(
|
pub extern "ws2_32" fn WSASend(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
lpBuffers: [*]WSABUF,
|
lpBuffers: [*]WSABUF,
|
||||||
dwBufferCount: DWORD,
|
dwBufferCount: DWORD,
|
||||||
@ -387,8 +387,8 @@ pub extern "ws2_32" stdcallcc fn WSASend(
|
|||||||
dwFlags: DWORD,
|
dwFlags: DWORD,
|
||||||
lpOverlapped: ?*WSAOVERLAPPED,
|
lpOverlapped: ?*WSAOVERLAPPED,
|
||||||
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
pub extern "ws2_32" stdcallcc fn WSASendTo(
|
pub extern "ws2_32" fn WSASendTo(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
lpBuffers: [*]WSABUF,
|
lpBuffers: [*]WSABUF,
|
||||||
dwBufferCount: DWORD,
|
dwBufferCount: DWORD,
|
||||||
@ -398,4 +398,4 @@ pub extern "ws2_32" stdcallcc fn WSASendTo(
|
|||||||
iTolen: socklen_t,
|
iTolen: socklen_t,
|
||||||
lpOverlapped: ?*WSAOVERLAPPED,
|
lpOverlapped: ?*WSAOVERLAPPED,
|
||||||
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) c_int;
|
) callconv(.Stdcall) c_int;
|
||||||
|
@ -14,13 +14,12 @@ const windows = os.windows;
|
|||||||
pub const ResetEvent = struct {
|
pub const ResetEvent = struct {
|
||||||
os_event: OsEvent,
|
os_event: OsEvent,
|
||||||
|
|
||||||
pub const OsEvent =
|
pub const OsEvent = if (builtin.single_threaded)
|
||||||
if (builtin.single_threaded)
|
DebugEvent
|
||||||
DebugEvent
|
else if (builtin.link_libc and builtin.os != .windows and builtin.os != .linux)
|
||||||
else if (builtin.link_libc and builtin.os != .windows and builtin.os != .linux)
|
PosixEvent
|
||||||
PosixEvent
|
else
|
||||||
else
|
AtomicEvent;
|
||||||
AtomicEvent;
|
|
||||||
|
|
||||||
pub fn init() ResetEvent {
|
pub fn init() ResetEvent {
|
||||||
return ResetEvent{ .os_event = OsEvent.init() };
|
return ResetEvent{ .os_event = OsEvent.init() };
|
||||||
@ -105,7 +104,7 @@ const PosixEvent = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *PosixEvent) void {
|
fn deinit(self: *PosixEvent) void {
|
||||||
// on dragonfly, *destroy() functions can return EINVAL
|
// on dragonfly, *destroy() functions can return EINVAL
|
||||||
// for statically initialized pthread structures
|
// for statically initialized pthread structures
|
||||||
const err = if (builtin.os == .dragonfly) os.EINVAL else 0;
|
const err = if (builtin.os == .dragonfly) os.EINVAL else 0;
|
||||||
|
|
||||||
@ -212,8 +211,7 @@ const AtomicEvent = struct {
|
|||||||
fn wait(self: *AtomicEvent, timeout: ?u64) !void {
|
fn wait(self: *AtomicEvent, timeout: ?u64) !void {
|
||||||
var waiters = @atomicLoad(u32, &self.waiters, .Acquire);
|
var waiters = @atomicLoad(u32, &self.waiters, .Acquire);
|
||||||
while (waiters != WAKE) {
|
while (waiters != WAKE) {
|
||||||
waiters = @cmpxchgWeak(u32, &self.waiters, waiters, waiters + WAIT, .Acquire, .Acquire)
|
waiters = @cmpxchgWeak(u32, &self.waiters, waiters, waiters + WAIT, .Acquire, .Acquire) orelse return Futex.wait(&self.waiters, timeout);
|
||||||
orelse return Futex.wait(&self.waiters, timeout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +279,7 @@ const AtomicEvent = struct {
|
|||||||
pub fn wake(waiters: *u32, wake_count: u32) void {
|
pub fn wake(waiters: *u32, wake_count: u32) void {
|
||||||
const handle = getEventHandle() orelse return SpinFutex.wake(waiters, wake_count);
|
const handle = getEventHandle() orelse return SpinFutex.wake(waiters, wake_count);
|
||||||
const key = @ptrCast(*const c_void, waiters);
|
const key = @ptrCast(*const c_void, waiters);
|
||||||
|
|
||||||
var waiting = wake_count;
|
var waiting = wake_count;
|
||||||
while (waiting != 0) : (waiting -= 1) {
|
while (waiting != 0) : (waiting -= 1) {
|
||||||
const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
|
const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
|
||||||
@ -408,7 +406,7 @@ test "std.ResetEvent" {
|
|||||||
// wait for receiver to update value and signal output
|
// wait for receiver to update value and signal output
|
||||||
self.out.wait();
|
self.out.wait();
|
||||||
testing.expect(self.value == 2);
|
testing.expect(self.value == 2);
|
||||||
|
|
||||||
// update value and signal final input
|
// update value and signal final input
|
||||||
self.value = 3;
|
self.value = 3;
|
||||||
self.in.set();
|
self.in.set();
|
||||||
@ -418,12 +416,12 @@ test "std.ResetEvent" {
|
|||||||
// wait for sender to update value and signal input
|
// wait for sender to update value and signal input
|
||||||
self.in.wait();
|
self.in.wait();
|
||||||
assert(self.value == 1);
|
assert(self.value == 1);
|
||||||
|
|
||||||
// update value and signal output
|
// update value and signal output
|
||||||
self.in.reset();
|
self.in.reset();
|
||||||
self.value = 2;
|
self.value = 2;
|
||||||
self.out.set();
|
self.out.set();
|
||||||
|
|
||||||
// wait for sender to update value and signal final input
|
// wait for sender to update value and signal final input
|
||||||
self.in.wait();
|
self.in.wait();
|
||||||
assert(self.value == 3);
|
assert(self.value == 3);
|
||||||
|
@ -195,7 +195,7 @@ extern fn __stack_chk_fail() noreturn {
|
|||||||
// TODO we should be able to put this directly in std/linux/x86_64.zig but
|
// TODO we should be able to put this directly in std/linux/x86_64.zig but
|
||||||
// it causes a segfault in release mode. this is a workaround of calling it
|
// it causes a segfault in release mode. this is a workaround of calling it
|
||||||
// across .o file boundaries. fix comptime @ptrCast of nakedcc functions.
|
// across .o file boundaries. fix comptime @ptrCast of nakedcc functions.
|
||||||
nakedcc fn clone() void {
|
fn clone() callconv(.Naked) void {
|
||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
.i386 => {
|
.i386 => {
|
||||||
// __clone(func, stack, flags, arg, ptid, tls, ctid)
|
// __clone(func, stack, flags, arg, ptid, tls, ctid)
|
||||||
|
@ -528,7 +528,7 @@ fn usesThumb1PreArmv6(arch: builtin.Arch) bool {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn __aeabi_memcpy() noreturn {
|
fn __aeabi_memcpy() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (use_thumb_1) {
|
if (use_thumb_1) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@ -544,7 +544,7 @@ nakedcc fn __aeabi_memcpy() noreturn {
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn __aeabi_memmove() noreturn {
|
fn __aeabi_memmove() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (use_thumb_1) {
|
if (use_thumb_1) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@ -560,7 +560,7 @@ nakedcc fn __aeabi_memmove() noreturn {
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn __aeabi_memset() noreturn {
|
fn __aeabi_memset() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (use_thumb_1_pre_armv6) {
|
if (use_thumb_1_pre_armv6) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@ -591,7 +591,7 @@ nakedcc fn __aeabi_memset() noreturn {
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn __aeabi_memclr() noreturn {
|
fn __aeabi_memclr() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (use_thumb_1_pre_armv6) {
|
if (use_thumb_1_pre_armv6) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@ -619,7 +619,7 @@ nakedcc fn __aeabi_memclr() noreturn {
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn __aeabi_memcmp() noreturn {
|
fn __aeabi_memcmp() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
if (use_thumb_1) {
|
if (use_thumb_1) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
|
@ -12,31 +12,31 @@ const ConditionalOperator = enum {
|
|||||||
Gt,
|
Gt,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_dcmpeq() noreturn {
|
pub fn __aeabi_dcmpeq() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq});
|
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_dcmplt() noreturn {
|
pub fn __aeabi_dcmplt() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt});
|
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_dcmple() noreturn {
|
pub fn __aeabi_dcmple() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le});
|
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_dcmpge() noreturn {
|
pub fn __aeabi_dcmpge() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge});
|
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_dcmpgt() noreturn {
|
pub fn __aeabi_dcmpgt() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt});
|
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt});
|
||||||
unreachable;
|
unreachable;
|
||||||
|
@ -12,31 +12,31 @@ const ConditionalOperator = enum {
|
|||||||
Gt,
|
Gt,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_fcmpeq() noreturn {
|
pub fn __aeabi_fcmpeq() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq});
|
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_fcmplt() noreturn {
|
pub fn __aeabi_fcmplt() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt});
|
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_fcmple() noreturn {
|
pub fn __aeabi_fcmple() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le});
|
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_fcmpge() noreturn {
|
pub fn __aeabi_fcmpge() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge});
|
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge});
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn __aeabi_fcmpgt() noreturn {
|
pub fn __aeabi_fcmpgt() callconv(.Naked) noreturn {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt});
|
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt});
|
||||||
unreachable;
|
unreachable;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub extern stdcallcc fn _alldiv(a: i64, b: i64) i64 {
|
pub extern fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {
|
||||||
@setRuntimeSafety(builtin.is_test);
|
@setRuntimeSafety(builtin.is_test);
|
||||||
const s_a = a >> (i64.bit_count - 1);
|
const s_a = a >> (i64.bit_count - 1);
|
||||||
const s_b = b >> (i64.bit_count - 1);
|
const s_b = b >> (i64.bit_count - 1);
|
||||||
@ -13,7 +13,7 @@ pub extern stdcallcc fn _alldiv(a: i64, b: i64) i64 {
|
|||||||
return (@bitCast(i64, r) ^ s) -% s;
|
return (@bitCast(i64, r) ^ s) -% s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn _aulldiv() void {
|
pub fn _aulldiv() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
|
|
||||||
// The stack layout is:
|
// The stack layout is:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub extern stdcallcc fn _allrem(a: i64, b: i64) i64 {
|
pub extern fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {
|
||||||
@setRuntimeSafety(builtin.is_test);
|
@setRuntimeSafety(builtin.is_test);
|
||||||
const s_a = a >> (i64.bit_count - 1);
|
const s_a = a >> (i64.bit_count - 1);
|
||||||
const s_b = b >> (i64.bit_count - 1);
|
const s_b = b >> (i64.bit_count - 1);
|
||||||
@ -13,7 +13,7 @@ pub extern stdcallcc fn _allrem(a: i64, b: i64) i64 {
|
|||||||
return (@bitCast(i64, r) ^ s) -% s;
|
return (@bitCast(i64, r) ^ s) -% s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub nakedcc fn _aullrem() void {
|
pub fn _aullrem() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
|
|
||||||
// The stack layout is:
|
// The stack layout is:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
// Zig's own stack-probe routine (available only on x86 and x86_64)
|
// Zig's own stack-probe routine (available only on x86 and x86_64)
|
||||||
pub nakedcc fn zig_probe_stack() void {
|
pub fn zig_probe_stack() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
|
|
||||||
// Versions of the Linux kernel before 5.1 treat any access below SP as
|
// Versions of the Linux kernel before 5.1 treat any access below SP as
|
||||||
@ -180,11 +180,11 @@ fn win_probe_stack_adjust_sp() void {
|
|||||||
// ___chkstk (__alloca) | yes | yes |
|
// ___chkstk (__alloca) | yes | yes |
|
||||||
// ___chkstk_ms | no | no |
|
// ___chkstk_ms | no | no |
|
||||||
|
|
||||||
pub nakedcc fn _chkstk() void {
|
pub fn _chkstk() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
|
@call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
|
||||||
}
|
}
|
||||||
pub nakedcc fn __chkstk() void {
|
pub fn __chkstk() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
.i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),
|
.i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),
|
||||||
@ -192,15 +192,15 @@ pub nakedcc fn __chkstk() void {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub nakedcc fn ___chkstk() void {
|
pub fn ___chkstk() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
|
@call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
|
||||||
}
|
}
|
||||||
pub nakedcc fn __chkstk_ms() void {
|
pub fn __chkstk_ms() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
|
@call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
|
||||||
}
|
}
|
||||||
pub nakedcc fn ___chkstk_ms() void {
|
pub fn ___chkstk_ms() callconv(.Naked) void {
|
||||||
@setRuntimeSafety(false);
|
@setRuntimeSafety(false);
|
||||||
@call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
|
@call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,16 @@ pub const SpinLock = struct {
|
|||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
// these instructions use a memory clobber as they
|
// these instructions use a memory clobber as they
|
||||||
// flush the pipeline of any speculated reads/writes.
|
// flush the pipeline of any speculated reads/writes.
|
||||||
.i386, .x86_64 => asm volatile ("pause" ::: "memory"),
|
.i386, .x86_64 => asm volatile ("pause"
|
||||||
.arm, .aarch64 => asm volatile ("yield" ::: "memory"),
|
:
|
||||||
|
:
|
||||||
|
: "memory"
|
||||||
|
),
|
||||||
|
.arm, .aarch64 => asm volatile ("yield"
|
||||||
|
:
|
||||||
|
:
|
||||||
|
: "memory"
|
||||||
|
),
|
||||||
else => std.os.sched_yield() catch {},
|
else => std.os.sched_yield() catch {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,11 +43,11 @@ comptime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stdcallcc fn _DllMainCRTStartup(
|
fn _DllMainCRTStartup(
|
||||||
hinstDLL: std.os.windows.HINSTANCE,
|
hinstDLL: std.os.windows.HINSTANCE,
|
||||||
fdwReason: std.os.windows.DWORD,
|
fdwReason: std.os.windows.DWORD,
|
||||||
lpReserved: std.os.windows.LPVOID,
|
lpReserved: std.os.windows.LPVOID,
|
||||||
) std.os.windows.BOOL {
|
) callconv(.Stdcall) std.os.windows.BOOL {
|
||||||
if (@hasDecl(root, "DllMain")) {
|
if (@hasDecl(root, "DllMain")) {
|
||||||
return root.DllMain(hinstDLL, fdwReason, lpReserved);
|
return root.DllMain(hinstDLL, fdwReason, lpReserved);
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nakedcc fn _start() noreturn {
|
fn _start() callconv(.Naked) noreturn {
|
||||||
if (builtin.os == builtin.Os.wasi) {
|
if (builtin.os == builtin.Os.wasi) {
|
||||||
// This is marked inline because for some reason LLVM in release mode fails to inline it,
|
// This is marked inline because for some reason LLVM in release mode fails to inline it,
|
||||||
// and we want fewer call frames in stack traces.
|
// and we want fewer call frames in stack traces.
|
||||||
@ -127,7 +127,7 @@ nakedcc fn _start() noreturn {
|
|||||||
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
|
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
stdcallcc fn WinMainCRTStartup() noreturn {
|
fn WinMainCRTStartup() callconv(.Stdcall) noreturn {
|
||||||
@setAlignStack(16);
|
@setAlignStack(16);
|
||||||
if (!builtin.single_threaded) {
|
if (!builtin.single_threaded) {
|
||||||
_ = @import("start_windows_tls.zig");
|
_ = @import("start_windows_tls.zig");
|
||||||
|
@ -860,6 +860,7 @@ pub const Node = struct {
|
|||||||
lib_name: ?*Node, // populated if this is an extern declaration
|
lib_name: ?*Node, // populated if this is an extern declaration
|
||||||
align_expr: ?*Node, // populated if align(A) is present
|
align_expr: ?*Node, // populated if align(A) is present
|
||||||
section_expr: ?*Node, // populated if linksection(A) is present
|
section_expr: ?*Node, // populated if linksection(A) is present
|
||||||
|
callconv_expr: ?*Node, // populated if callconv(A) is present
|
||||||
|
|
||||||
pub const ParamList = SegmentedList(*Node, 2);
|
pub const ParamList = SegmentedList(*Node, 2);
|
||||||
|
|
||||||
|
@ -311,6 +311,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
|||||||
const rparen = try expectToken(it, tree, .RParen);
|
const rparen = try expectToken(it, tree, .RParen);
|
||||||
const align_expr = try parseByteAlign(arena, it, tree);
|
const align_expr = try parseByteAlign(arena, it, tree);
|
||||||
const section_expr = try parseLinkSection(arena, it, tree);
|
const section_expr = try parseLinkSection(arena, it, tree);
|
||||||
|
const callconv_expr = try parseCallconv(arena, it, tree);
|
||||||
const exclamation_token = eatToken(it, .Bang);
|
const exclamation_token = eatToken(it, .Bang);
|
||||||
|
|
||||||
const return_type_expr = (try parseVarType(arena, it, tree)) orelse
|
const return_type_expr = (try parseVarType(arena, it, tree)) orelse
|
||||||
@ -347,6 +348,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
|||||||
.lib_name = null,
|
.lib_name = null,
|
||||||
.align_expr = align_expr,
|
.align_expr = align_expr,
|
||||||
.section_expr = section_expr,
|
.section_expr = section_expr,
|
||||||
|
.callconv_expr = callconv_expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cc) |kind| {
|
if (cc) |kind| {
|
||||||
@ -1678,6 +1680,17 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
|
|||||||
return expr_node;
|
return expr_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
|
||||||
|
fn parseCallconv(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||||
|
_ = eatToken(it, .Keyword_callconv) orelse return null;
|
||||||
|
_ = try expectToken(it, tree, .LParen);
|
||||||
|
const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
|
||||||
|
.ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
|
||||||
|
});
|
||||||
|
_ = try expectToken(it, tree, .RParen);
|
||||||
|
return expr_node;
|
||||||
|
}
|
||||||
|
|
||||||
/// FnCC
|
/// FnCC
|
||||||
/// <- KEYWORD_nakedcc
|
/// <- KEYWORD_nakedcc
|
||||||
/// / KEYWORD_stdcallcc
|
/// / KEYWORD_stdcallcc
|
||||||
|
@ -9,6 +9,18 @@ test "zig fmt: change @typeOf to @TypeOf" {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove nakedcc/stdcallcc once zig 0.6.0 is released. See https://github.com/ziglang/zig/pull/3977
|
||||||
|
test "zig fmt: convert nakedcc/stdcallcc into callconv(...)" {
|
||||||
|
try testTransform(
|
||||||
|
\\nakedcc fn foo1() void {}
|
||||||
|
\\stdcallcc fn foo2() void {}
|
||||||
|
,
|
||||||
|
\\fn foo1() callconv(.Naked) void {}
|
||||||
|
\\fn foo2() callconv(.Stdcall) void {}
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
test "zig fmt: comptime struct field" {
|
test "zig fmt: comptime struct field" {
|
||||||
try testCanonical(
|
try testCanonical(
|
||||||
\\const Foo = struct {
|
\\const Foo = struct {
|
||||||
@ -234,7 +246,7 @@ test "zig fmt: threadlocal" {
|
|||||||
test "zig fmt: linksection" {
|
test "zig fmt: linksection" {
|
||||||
try testCanonical(
|
try testCanonical(
|
||||||
\\export var aoeu: u64 linksection(".text.derp") = 1234;
|
\\export var aoeu: u64 linksection(".text.derp") = 1234;
|
||||||
\\export nakedcc fn _start() linksection(".text.boot") noreturn {}
|
\\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2326,7 +2338,7 @@ test "zig fmt: fn type" {
|
|||||||
\\
|
\\
|
||||||
\\const a: fn (u8) u8 = undefined;
|
\\const a: fn (u8) u8 = undefined;
|
||||||
\\const b: extern fn (u8) u8 = undefined;
|
\\const b: extern fn (u8) u8 = undefined;
|
||||||
\\const c: nakedcc fn (u8) u8 = undefined;
|
\\const c: fn (u8) callconv(.Naked) u8 = undefined;
|
||||||
\\const ap: fn (u8) u8 = a;
|
\\const ap: fn (u8) u8 = a;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
@ -1319,8 +1319,16 @@ fn renderExpression(
|
|||||||
try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space);
|
try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some extra machinery is needed to rewrite the old-style cc
|
||||||
|
// notation to the new callconv one
|
||||||
|
var cc_rewrite_str: ?[*:0]const u8 = null;
|
||||||
if (fn_proto.cc_token) |cc_token| {
|
if (fn_proto.cc_token) |cc_token| {
|
||||||
try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
|
var str = tree.tokenSlicePtr(tree.tokens.at(cc_token));
|
||||||
|
if (mem.eql(u8, str, "stdcallcc")) {
|
||||||
|
cc_rewrite_str = ".Stdcall";
|
||||||
|
} else if (mem.eql(u8, str, "nakedcc")) {
|
||||||
|
cc_rewrite_str = ".Naked";
|
||||||
|
} else try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
|
||||||
}
|
}
|
||||||
|
|
||||||
const lparen = if (fn_proto.name_token) |name_token| blk: {
|
const lparen = if (fn_proto.name_token) |name_token| blk: {
|
||||||
@ -1392,6 +1400,21 @@ fn renderExpression(
|
|||||||
try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // )
|
try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fn_proto.callconv_expr) |callconv_expr| {
|
||||||
|
const callconv_rparen = tree.nextToken(callconv_expr.lastToken());
|
||||||
|
const callconv_lparen = tree.prevToken(callconv_expr.firstToken());
|
||||||
|
const callconv_kw = tree.prevToken(callconv_lparen);
|
||||||
|
|
||||||
|
try renderToken(tree, stream, callconv_kw, indent, start_col, Space.None); // section
|
||||||
|
try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // (
|
||||||
|
try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None);
|
||||||
|
try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // )
|
||||||
|
} else if (cc_rewrite_str) |str| {
|
||||||
|
try stream.write("callconv(");
|
||||||
|
try stream.write(mem.toSliceConst(u8, str));
|
||||||
|
try stream.write(") ");
|
||||||
|
}
|
||||||
|
|
||||||
switch (fn_proto.return_type) {
|
switch (fn_proto.return_type) {
|
||||||
ast.Node.FnProto.ReturnType.Explicit => |node| {
|
ast.Node.FnProto.ReturnType.Explicit => |node| {
|
||||||
return renderExpression(allocator, stream, tree, indent, start_col, node, space);
|
return renderExpression(allocator, stream, tree, indent, start_col, node, space);
|
||||||
|
@ -30,6 +30,7 @@ pub const Token = struct {
|
|||||||
Keyword.init("async", .Keyword_async),
|
Keyword.init("async", .Keyword_async),
|
||||||
Keyword.init("await", .Keyword_await),
|
Keyword.init("await", .Keyword_await),
|
||||||
Keyword.init("break", .Keyword_break),
|
Keyword.init("break", .Keyword_break),
|
||||||
|
Keyword.init("callconv", .Keyword_callconv),
|
||||||
Keyword.init("catch", .Keyword_catch),
|
Keyword.init("catch", .Keyword_catch),
|
||||||
Keyword.init("comptime", .Keyword_comptime),
|
Keyword.init("comptime", .Keyword_comptime),
|
||||||
Keyword.init("const", .Keyword_const),
|
Keyword.init("const", .Keyword_const),
|
||||||
@ -162,6 +163,7 @@ pub const Token = struct {
|
|||||||
Keyword_async,
|
Keyword_async,
|
||||||
Keyword_await,
|
Keyword_await,
|
||||||
Keyword_break,
|
Keyword_break,
|
||||||
|
Keyword_callconv,
|
||||||
Keyword_catch,
|
Keyword_catch,
|
||||||
Keyword_comptime,
|
Keyword_comptime,
|
||||||
Keyword_const,
|
Keyword_const,
|
||||||
@ -286,6 +288,7 @@ pub const Token = struct {
|
|||||||
.Keyword_async => "async",
|
.Keyword_async => "async",
|
||||||
.Keyword_await => "await",
|
.Keyword_await => "await",
|
||||||
.Keyword_break => "break",
|
.Keyword_break => "break",
|
||||||
|
.Keyword_callconv => "callconv",
|
||||||
.Keyword_catch => "catch",
|
.Keyword_catch => "catch",
|
||||||
.Keyword_comptime => "comptime",
|
.Keyword_comptime => "comptime",
|
||||||
.Keyword_const => "const",
|
.Keyword_const => "const",
|
||||||
|
@ -11,7 +11,7 @@ const CToken = ctok.CToken;
|
|||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
|
|
||||||
const CallingConvention = std.builtin.TypeInfo.CallingConvention;
|
const CallingConvention = std.builtin.CallingConvention;
|
||||||
|
|
||||||
pub const ClangErrMsg = Stage2ErrorMsg;
|
pub const ClangErrMsg = Stage2ErrorMsg;
|
||||||
|
|
||||||
@ -3690,6 +3690,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
|
|||||||
.lib_name = null,
|
.lib_name = null,
|
||||||
.align_expr = null,
|
.align_expr = null,
|
||||||
.section_expr = null,
|
.section_expr = null,
|
||||||
|
.callconv_expr = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const block = try transCreateNodeBlock(c, null);
|
const block = try transCreateNodeBlock(c, null);
|
||||||
@ -4141,6 +4142,11 @@ fn transCC(
|
|||||||
switch (clang_cc) {
|
switch (clang_cc) {
|
||||||
.C => return CallingConvention.C,
|
.C => return CallingConvention.C,
|
||||||
.X86StdCall => return CallingConvention.Stdcall,
|
.X86StdCall => return CallingConvention.Stdcall,
|
||||||
|
.X86FastCall => return CallingConvention.Fastcall,
|
||||||
|
.X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall,
|
||||||
|
.X86ThisCall => return CallingConvention.Thiscall,
|
||||||
|
.AAPCS => return CallingConvention.AAPCS,
|
||||||
|
.AAPCS_VFP => return CallingConvention.AAPCSVFP,
|
||||||
else => return revertAndWarn(
|
else => return revertAndWarn(
|
||||||
rp,
|
rp,
|
||||||
error.UnsupportedType,
|
error.UnsupportedType,
|
||||||
@ -4196,7 +4202,6 @@ fn finishTransFnProto(
|
|||||||
|
|
||||||
// pub extern fn name(...) T
|
// pub extern fn name(...) T
|
||||||
const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
|
const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
|
||||||
const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
|
|
||||||
const extern_export_inline_tok = if (is_export)
|
const extern_export_inline_tok = if (is_export)
|
||||||
try appendToken(rp.c, .Keyword_export, "export")
|
try appendToken(rp.c, .Keyword_export, "export")
|
||||||
else if (cc == .C and is_extern)
|
else if (cc == .C and is_extern)
|
||||||
@ -4303,6 +4308,14 @@ fn finishTransFnProto(
|
|||||||
break :blk null;
|
break :blk null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const callconv_expr = if (extern_export_inline_tok != null) null else blk: {
|
||||||
|
_ = try appendToken(rp.c, .Keyword_callconv, "callconv");
|
||||||
|
_ = try appendToken(rp.c, .LParen, "(");
|
||||||
|
const expr = try transCreateNodeEnumLiteral(rp.c, @tagName(cc));
|
||||||
|
_ = try appendToken(rp.c, .RParen, ")");
|
||||||
|
break :blk expr;
|
||||||
|
};
|
||||||
|
|
||||||
const return_type_node = blk: {
|
const return_type_node = blk: {
|
||||||
if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
|
if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
|
||||||
break :blk try transCreateNodeIdentifier(rp.c, "noreturn");
|
break :blk try transCreateNodeIdentifier(rp.c, "noreturn");
|
||||||
@ -4333,11 +4346,12 @@ fn finishTransFnProto(
|
|||||||
.return_type = .{ .Explicit = return_type_node },
|
.return_type = .{ .Explicit = return_type_node },
|
||||||
.var_args_token = null, // TODO this field is broken in the AST data model
|
.var_args_token = null, // TODO this field is broken in the AST data model
|
||||||
.extern_export_inline_token = extern_export_inline_tok,
|
.extern_export_inline_token = extern_export_inline_tok,
|
||||||
.cc_token = cc_tok,
|
.cc_token = null,
|
||||||
.body_node = null,
|
.body_node = null,
|
||||||
.lib_name = null,
|
.lib_name = null,
|
||||||
.align_expr = align_expr,
|
.align_expr = align_expr,
|
||||||
.section_expr = linksection_expr,
|
.section_expr = linksection_expr,
|
||||||
|
.callconv_expr = callconv_expr,
|
||||||
};
|
};
|
||||||
return fn_proto;
|
return fn_proto;
|
||||||
}
|
}
|
||||||
@ -4686,6 +4700,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
|
|||||||
.lib_name = null,
|
.lib_name = null,
|
||||||
.align_expr = null,
|
.align_expr = null,
|
||||||
.section_expr = null,
|
.section_expr = null,
|
||||||
|
.callconv_expr = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const block = try transCreateNodeBlock(c, null);
|
const block = try transCreateNodeBlock(c, null);
|
||||||
|
@ -337,7 +337,7 @@ pub const Type = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const CallingConvention = builtin.TypeInfo.CallingConvention;
|
const CallingConvention = builtin.CallingConvention;
|
||||||
|
|
||||||
pub const Param = struct {
|
pub const Param = struct {
|
||||||
is_noalias: bool,
|
is_noalias: bool,
|
||||||
@ -352,6 +352,7 @@ pub const Type = struct {
|
|||||||
.Naked => "nakedcc ",
|
.Naked => "nakedcc ",
|
||||||
.Stdcall => "stdcallcc ",
|
.Stdcall => "stdcallcc ",
|
||||||
.Async => "async ",
|
.Async => "async ",
|
||||||
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,23 @@ enum PtrLen {
|
|||||||
PtrLenC,
|
PtrLenC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CallingConvention {
|
||||||
|
CallingConventionUnspecified,
|
||||||
|
CallingConventionC,
|
||||||
|
CallingConventionCold,
|
||||||
|
CallingConventionNaked,
|
||||||
|
CallingConventionAsync,
|
||||||
|
CallingConventionInterrupt,
|
||||||
|
CallingConventionSignal,
|
||||||
|
CallingConventionStdcall,
|
||||||
|
CallingConventionFastcall,
|
||||||
|
CallingConventionVectorcall,
|
||||||
|
CallingConventionThiscall,
|
||||||
|
CallingConventionAPCS,
|
||||||
|
CallingConventionAAPCS,
|
||||||
|
CallingConventionAAPCSVFP,
|
||||||
|
};
|
||||||
|
|
||||||
// This one corresponds to the builtin.zig enum.
|
// This one corresponds to the builtin.zig enum.
|
||||||
enum BuiltinPtrSize {
|
enum BuiltinPtrSize {
|
||||||
BuiltinPtrSizeOne,
|
BuiltinPtrSizeOne,
|
||||||
@ -398,6 +415,7 @@ struct LazyValueFnType {
|
|||||||
IrInstruction *align_inst; // can be null
|
IrInstruction *align_inst; // can be null
|
||||||
IrInstruction *return_type;
|
IrInstruction *return_type;
|
||||||
|
|
||||||
|
CallingConvention cc;
|
||||||
bool is_generic;
|
bool is_generic;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -612,15 +630,6 @@ enum NodeType {
|
|||||||
NodeTypeVarFieldType,
|
NodeTypeVarFieldType,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CallingConvention {
|
|
||||||
CallingConventionUnspecified,
|
|
||||||
CallingConventionC,
|
|
||||||
CallingConventionCold,
|
|
||||||
CallingConventionNaked,
|
|
||||||
CallingConventionStdcall,
|
|
||||||
CallingConventionAsync,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FnInline {
|
enum FnInline {
|
||||||
FnInlineAuto,
|
FnInlineAuto,
|
||||||
FnInlineAlways,
|
FnInlineAlways,
|
||||||
@ -639,10 +648,14 @@ struct AstNodeFnProto {
|
|||||||
AstNode *align_expr;
|
AstNode *align_expr;
|
||||||
// populated if the "section(S)" is present
|
// populated if the "section(S)" is present
|
||||||
AstNode *section_expr;
|
AstNode *section_expr;
|
||||||
|
// populated if the "callconv(S)" is present
|
||||||
|
AstNode *callconv_expr;
|
||||||
Buf doc_comments;
|
Buf doc_comments;
|
||||||
|
|
||||||
FnInline fn_inline;
|
FnInline fn_inline;
|
||||||
CallingConvention cc;
|
bool is_nakedcc;
|
||||||
|
bool is_stdcallcc;
|
||||||
|
bool is_async;
|
||||||
|
|
||||||
VisibMod visib_mod;
|
VisibMod visib_mod;
|
||||||
bool auto_err_set;
|
bool auto_err_set;
|
||||||
@ -1597,6 +1610,7 @@ struct ZigFn {
|
|||||||
Buf **param_names;
|
Buf **param_names;
|
||||||
IrInstruction *err_code_spill;
|
IrInstruction *err_code_spill;
|
||||||
AstNode *assumed_non_async;
|
AstNode *assumed_non_async;
|
||||||
|
CallingConvention cc;
|
||||||
|
|
||||||
AstNode *fn_no_inline_set_node;
|
AstNode *fn_no_inline_set_node;
|
||||||
AstNode *fn_static_eval_set_node;
|
AstNode *fn_static_eval_set_node;
|
||||||
@ -3549,6 +3563,7 @@ struct IrInstructionFnProto {
|
|||||||
|
|
||||||
IrInstruction **param_types;
|
IrInstruction **param_types;
|
||||||
IrInstruction *align_value;
|
IrInstruction *align_value;
|
||||||
|
IrInstruction *callconv_value;
|
||||||
IrInstruction *return_type;
|
IrInstruction *return_type;
|
||||||
bool is_var_args;
|
bool is_var_args;
|
||||||
};
|
};
|
||||||
|
173
src/analyze.cpp
173
src/analyze.cpp
@ -919,24 +919,20 @@ ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry) {
|
|||||||
|
|
||||||
const char *calling_convention_name(CallingConvention cc) {
|
const char *calling_convention_name(CallingConvention cc) {
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case CallingConventionUnspecified: return "undefined";
|
case CallingConventionUnspecified: return "Unspecified";
|
||||||
case CallingConventionC: return "ccc";
|
case CallingConventionC: return "C";
|
||||||
case CallingConventionCold: return "coldcc";
|
case CallingConventionCold: return "Cold";
|
||||||
case CallingConventionNaked: return "nakedcc";
|
case CallingConventionNaked: return "Naked";
|
||||||
case CallingConventionStdcall: return "stdcallcc";
|
case CallingConventionAsync: return "Async";
|
||||||
case CallingConventionAsync: return "async";
|
case CallingConventionInterrupt: return "Interrupt";
|
||||||
}
|
case CallingConventionSignal: return "Signal";
|
||||||
zig_unreachable();
|
case CallingConventionStdcall: return "Stdcall";
|
||||||
}
|
case CallingConventionFastcall: return "Fastcall";
|
||||||
|
case CallingConventionVectorcall: return "Vectorcall";
|
||||||
static const char *calling_convention_fn_type_str(CallingConvention cc) {
|
case CallingConventionThiscall: return "Thiscall";
|
||||||
switch (cc) {
|
case CallingConventionAPCS: return "Apcs";
|
||||||
case CallingConventionUnspecified: return "";
|
case CallingConventionAAPCS: return "Aapcs";
|
||||||
case CallingConventionC: return "extern ";
|
case CallingConventionAAPCSVFP: return "Aapcsvfp";
|
||||||
case CallingConventionCold: return "coldcc ";
|
|
||||||
case CallingConventionNaked: return "nakedcc ";
|
|
||||||
case CallingConventionStdcall: return "stdcallcc ";
|
|
||||||
case CallingConventionAsync: return "async ";
|
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -949,7 +945,15 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
|
|||||||
case CallingConventionC:
|
case CallingConventionC:
|
||||||
case CallingConventionCold:
|
case CallingConventionCold:
|
||||||
case CallingConventionNaked:
|
case CallingConventionNaked:
|
||||||
|
case CallingConventionInterrupt:
|
||||||
|
case CallingConventionSignal:
|
||||||
case CallingConventionStdcall:
|
case CallingConventionStdcall:
|
||||||
|
case CallingConventionFastcall:
|
||||||
|
case CallingConventionVectorcall:
|
||||||
|
case CallingConventionThiscall:
|
||||||
|
case CallingConventionAPCS:
|
||||||
|
case CallingConventionAAPCS:
|
||||||
|
case CallingConventionAAPCSVFP:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
@ -1006,8 +1010,8 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
|
|
||||||
// populate the name of the type
|
// populate the name of the type
|
||||||
buf_resize(&fn_type->name, 0);
|
buf_resize(&fn_type->name, 0);
|
||||||
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
|
if (fn_type->data.fn.fn_type_id.cc == CallingConventionC)
|
||||||
buf_appendf(&fn_type->name, "%s", cc_str);
|
buf_append_str(&fn_type->name, "extern ");
|
||||||
buf_appendf(&fn_type->name, "fn(");
|
buf_appendf(&fn_type->name, "fn(");
|
||||||
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
|
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
|
||||||
FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
|
FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
|
||||||
@ -1026,6 +1030,9 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
if (fn_type_id->alignment != 0) {
|
if (fn_type_id->alignment != 0) {
|
||||||
buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment);
|
buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment);
|
||||||
}
|
}
|
||||||
|
if (fn_type_id->cc != CallingConventionUnspecified && fn_type_id->cc != CallingConventionC) {
|
||||||
|
buf_appendf(&fn_type->name, " callconv(%s)", calling_convention_name(fn_type_id->cc));
|
||||||
|
}
|
||||||
buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name));
|
buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name));
|
||||||
|
|
||||||
// The fn_type is a pointer; not to be confused with the raw function type.
|
// The fn_type is a pointer; not to be confused with the raw function type.
|
||||||
@ -1444,8 +1451,8 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
|
|||||||
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
||||||
ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
|
ZigType *fn_type = new_type_table_entry(ZigTypeIdFn);
|
||||||
buf_resize(&fn_type->name, 0);
|
buf_resize(&fn_type->name, 0);
|
||||||
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
|
if (fn_type->data.fn.fn_type_id.cc == CallingConventionC)
|
||||||
buf_appendf(&fn_type->name, "%s", cc_str);
|
buf_append_str(&fn_type->name, "extern ");
|
||||||
buf_appendf(&fn_type->name, "fn(");
|
buf_appendf(&fn_type->name, "fn(");
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (; i < fn_type_id->next_param_index; i += 1) {
|
for (; i < fn_type_id->next_param_index; i += 1) {
|
||||||
@ -1457,7 +1464,11 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
const char *comma_str = (i == 0) ? "" : ",";
|
const char *comma_str = (i == 0) ? "" : ",";
|
||||||
buf_appendf(&fn_type->name, "%svar", comma_str);
|
buf_appendf(&fn_type->name, "%svar", comma_str);
|
||||||
}
|
}
|
||||||
buf_appendf(&fn_type->name, ")var");
|
buf_append_str(&fn_type->name, ")");
|
||||||
|
if (fn_type_id->cc != CallingConventionUnspecified && fn_type_id->cc != CallingConventionC) {
|
||||||
|
buf_appendf(&fn_type->name, " callconv(%s)", calling_convention_name(fn_type_id->cc));
|
||||||
|
}
|
||||||
|
buf_append_str(&fn_type->name, " var");
|
||||||
|
|
||||||
fn_type->data.fn.fn_type_id = *fn_type_id;
|
fn_type->data.fn.fn_type_id = *fn_type_id;
|
||||||
fn_type->data.fn.is_generic = true;
|
fn_type->data.fn.is_generic = true;
|
||||||
@ -1467,17 +1478,25 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
|||||||
return fn_type;
|
return fn_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc) {
|
CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto) {
|
||||||
|
if (fn_proto->is_nakedcc)
|
||||||
|
return CallingConventionNaked;
|
||||||
|
if (fn_proto->is_stdcallcc)
|
||||||
|
return CallingConventionStdcall;
|
||||||
|
if (fn_proto->is_async)
|
||||||
|
return CallingConventionAsync;
|
||||||
|
// Compatible with the C ABI
|
||||||
|
if (fn_proto->is_extern || fn_proto->is_export)
|
||||||
|
return CallingConventionC;
|
||||||
|
|
||||||
|
return CallingConventionUnspecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConvention cc, size_t param_count_alloc) {
|
||||||
assert(proto_node->type == NodeTypeFnProto);
|
assert(proto_node->type == NodeTypeFnProto);
|
||||||
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
||||||
|
|
||||||
if (fn_proto->cc == CallingConventionUnspecified) {
|
fn_type_id->cc = cc;
|
||||||
bool extern_abi = fn_proto->is_extern || fn_proto->is_export;
|
|
||||||
fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified;
|
|
||||||
} else {
|
|
||||||
fn_type_id->cc = fn_proto->cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn_type_id->param_count = fn_proto->params.length;
|
fn_type_id->param_count = fn_proto->params.length;
|
||||||
fn_type_id->param_info = allocate<FnTypeParamInfo>(param_count_alloc);
|
fn_type_id->param_info = allocate<FnTypeParamInfo>(param_count_alloc);
|
||||||
fn_type_id->next_param_index = 0;
|
fn_type_id->next_param_index = 0;
|
||||||
@ -1691,8 +1710,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
|
|||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
return type_allowed_in_extern(g, type_entry->data.array.child_type, result);
|
return type_allowed_in_extern(g, type_entry->data.array.child_type, result);
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
*result = type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
|
*result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);
|
||||||
type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall;
|
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||||
@ -1752,7 +1770,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
|
|||||||
Error err;
|
Error err;
|
||||||
|
|
||||||
FnTypeId fn_type_id = {0};
|
FnTypeId fn_type_id = {0};
|
||||||
init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
|
init_fn_type_id(&fn_type_id, proto_node, fn_entry->cc, proto_node->data.fn_proto.params.length);
|
||||||
|
|
||||||
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
|
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
|
||||||
AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);
|
AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);
|
||||||
@ -2164,7 +2182,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
|
|||||||
ZigType *field_type = resolve_struct_field_type(g, field);
|
ZigType *field_type = resolve_struct_field_type(g, field);
|
||||||
if (field_type == nullptr) {
|
if (field_type == nullptr) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
return err;
|
return ErrorSemanticAnalyzeFail;
|
||||||
}
|
}
|
||||||
if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
|
if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
@ -2254,7 +2272,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
|
|||||||
ZigType *field_type = resolve_struct_field_type(g, field);
|
ZigType *field_type = resolve_struct_field_type(g, field);
|
||||||
if (field_type == nullptr) {
|
if (field_type == nullptr) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
return err;
|
return ErrorSemanticAnalyzeFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
|
if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
|
||||||
@ -2324,7 +2342,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
|
|||||||
&field->align))
|
&field->align))
|
||||||
{
|
{
|
||||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||||
return err;
|
return ErrorSemanticAnalyzeFail;
|
||||||
}
|
}
|
||||||
add_node_error(g, field->decl_node,
|
add_node_error(g, field->decl_node,
|
||||||
buf_create_from_str("TODO implement field alignment syntax for unions. https://github.com/ziglang/zig/issues/3125"));
|
buf_create_from_str("TODO implement field alignment syntax for unions. https://github.com/ziglang/zig/issues/3125"));
|
||||||
@ -2451,6 +2469,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
|
|||||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||||
return ErrorSemanticAnalyzeFail;
|
return ErrorSemanticAnalyzeFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_packed) {
|
if (is_packed) {
|
||||||
if ((err = emit_error_unless_type_allowed_in_packed_union(g, field_type, union_field->decl_node))) {
|
if ((err = emit_error_unless_type_allowed_in_packed_union(g, field_type, union_field->decl_node))) {
|
||||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||||
@ -2909,7 +2928,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
|
|||||||
&field->align))
|
&field->align))
|
||||||
{
|
{
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
return err;
|
return ErrorSemanticAnalyzeFail;
|
||||||
}
|
}
|
||||||
} else if (packed) {
|
} else if (packed) {
|
||||||
field->align = 1;
|
field->align = 1;
|
||||||
@ -3395,27 +3414,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||||||
get_fully_qualified_decl_name(g, &fn_table_entry->symbol_name, &tld_fn->base, false);
|
get_fully_qualified_decl_name(g, &fn_table_entry->symbol_name, &tld_fn->base, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_proto->is_export) {
|
|
||||||
switch (fn_proto->cc) {
|
|
||||||
case CallingConventionAsync: {
|
|
||||||
add_node_error(g, fn_def_node,
|
|
||||||
buf_sprintf("exported function cannot be async"));
|
|
||||||
} break;
|
|
||||||
case CallingConventionC:
|
|
||||||
case CallingConventionNaked:
|
|
||||||
case CallingConventionCold:
|
|
||||||
case CallingConventionStdcall:
|
|
||||||
case CallingConventionUnspecified:
|
|
||||||
// An exported function without a specific calling
|
|
||||||
// convention defaults to C
|
|
||||||
CallingConvention cc = (fn_proto->cc != CallingConventionUnspecified) ?
|
|
||||||
fn_proto->cc : CallingConventionC;
|
|
||||||
add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name),
|
|
||||||
GlobalLinkageIdStrong, cc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_extern) {
|
if (!is_extern) {
|
||||||
fn_table_entry->fndef_scope = create_fndef_scope(g,
|
fn_table_entry->fndef_scope = create_fndef_scope(g,
|
||||||
fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry);
|
fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry);
|
||||||
@ -3434,19 +3432,70 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||||||
|
|
||||||
Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
|
Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
|
||||||
|
|
||||||
fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
|
fn_table_entry->cc = cc_from_fn_proto(fn_proto);
|
||||||
|
if (fn_proto->callconv_expr != nullptr) {
|
||||||
|
ZigType *cc_enum_value = get_builtin_type(g, "CallingConvention");
|
||||||
|
|
||||||
|
ZigValue *result_val = analyze_const_value(g, child_scope, fn_proto->callconv_expr,
|
||||||
|
cc_enum_value, nullptr, UndefBad);
|
||||||
|
if (type_is_invalid(result_val->type)) {
|
||||||
|
fn_table_entry->type_entry = g->builtin_types.entry_invalid;
|
||||||
|
tld_fn->base.resolution = TldResolutionInvalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_table_entry->cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag);
|
||||||
|
}
|
||||||
|
|
||||||
if (fn_proto->section_expr != nullptr) {
|
if (fn_proto->section_expr != nullptr) {
|
||||||
if (!analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name)) {
|
if (!analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name)) {
|
||||||
fn_table_entry->type_entry = g->builtin_types.entry_invalid;
|
fn_table_entry->type_entry = g->builtin_types.entry_invalid;
|
||||||
|
tld_fn->base.resolution = TldResolutionInvalid;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) {
|
fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
|
||||||
|
|
||||||
|
if (type_is_invalid(fn_table_entry->type_entry)) {
|
||||||
tld_fn->base.resolution = TldResolutionInvalid;
|
tld_fn->base.resolution = TldResolutionInvalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CallingConvention fn_cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
|
||||||
|
|
||||||
|
if (fn_proto->is_export) {
|
||||||
|
switch (fn_cc) {
|
||||||
|
case CallingConventionAsync:
|
||||||
|
add_node_error(g, fn_def_node,
|
||||||
|
buf_sprintf("exported function cannot be async"));
|
||||||
|
fn_table_entry->type_entry = g->builtin_types.entry_invalid;
|
||||||
|
tld_fn->base.resolution = TldResolutionInvalid;
|
||||||
|
return;
|
||||||
|
case CallingConventionC:
|
||||||
|
case CallingConventionCold:
|
||||||
|
case CallingConventionNaked:
|
||||||
|
case CallingConventionInterrupt:
|
||||||
|
case CallingConventionSignal:
|
||||||
|
case CallingConventionStdcall:
|
||||||
|
case CallingConventionFastcall:
|
||||||
|
case CallingConventionVectorcall:
|
||||||
|
case CallingConventionThiscall:
|
||||||
|
case CallingConventionAPCS:
|
||||||
|
case CallingConventionAAPCS:
|
||||||
|
case CallingConventionAAPCSVFP:
|
||||||
|
add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name),
|
||||||
|
GlobalLinkageIdStrong, fn_cc);
|
||||||
|
break;
|
||||||
|
case CallingConventionUnspecified:
|
||||||
|
// An exported function without a specific calling
|
||||||
|
// convention defaults to C
|
||||||
|
add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name),
|
||||||
|
GlobalLinkageIdStrong, CallingConventionC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!fn_table_entry->type_entry->data.fn.is_generic) {
|
if (!fn_table_entry->type_entry->data.fn.is_generic) {
|
||||||
if (fn_def_node)
|
if (fn_def_node)
|
||||||
g->fn_defs.append(fn_table_entry);
|
g->fn_defs.append(fn_table_entry);
|
||||||
@ -3455,7 +3504,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||||||
// if the calling convention implies that it cannot be async, we save that for later
|
// if the calling convention implies that it cannot be async, we save that for later
|
||||||
// and leave the value to be nullptr to indicate that we have not emitted possible
|
// and leave the value to be nullptr to indicate that we have not emitted possible
|
||||||
// compile errors for improperly calling async functions.
|
// compile errors for improperly calling async functions.
|
||||||
if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) {
|
if (fn_cc == CallingConventionAsync) {
|
||||||
fn_table_entry->inferred_async_node = fn_table_entry->proto_node;
|
fn_table_entry->inferred_async_node = fn_table_entry->proto_node;
|
||||||
}
|
}
|
||||||
} else if (source_node->type == NodeTypeTestDecl) {
|
} else if (source_node->type == NodeTypeTestDecl) {
|
||||||
|
@ -100,7 +100,7 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
|
|||||||
void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type);
|
void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type);
|
||||||
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
|
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
|
||||||
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
|
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
|
||||||
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
|
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConvention cc, size_t param_count_alloc);
|
||||||
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
|
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
|
||||||
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
|
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
|
||||||
void complete_enum(CodeGen *g, ZigType *enum_type);
|
void complete_enum(CodeGen *g, ZigType *enum_type);
|
||||||
@ -259,6 +259,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
|
|||||||
|
|
||||||
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
|
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
|
||||||
bool fn_is_async(ZigFn *fn);
|
bool fn_is_async(ZigFn *fn);
|
||||||
|
CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto);
|
||||||
|
|
||||||
Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
|
Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
|
||||||
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
|
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
|
||||||
|
@ -488,6 +488,11 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
|||||||
render_node_grouped(ar, node->data.fn_proto.section_expr);
|
render_node_grouped(ar, node->data.fn_proto.section_expr);
|
||||||
fprintf(ar->f, ")");
|
fprintf(ar->f, ")");
|
||||||
}
|
}
|
||||||
|
if (node->data.fn_proto.callconv_expr) {
|
||||||
|
fprintf(ar->f, " callconv(");
|
||||||
|
render_node_grouped(ar, node->data.fn_proto.callconv_expr);
|
||||||
|
fprintf(ar->f, ")");
|
||||||
|
}
|
||||||
|
|
||||||
if (node->data.fn_proto.return_var_token != nullptr) {
|
if (node->data.fn_proto.return_var_token != nullptr) {
|
||||||
fprintf(ar->f, "var");
|
fprintf(ar->f, "var");
|
||||||
|
116
src/codegen.cpp
116
src/codegen.cpp
@ -263,36 +263,66 @@ static const char *get_mangled_name(CodeGen *g, const char *original_name, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
|
static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
case CallingConventionUnspecified: return LLVMFastCallConv;
|
case CallingConventionUnspecified:
|
||||||
case CallingConventionC: return LLVMCCallConv;
|
return ZigLLVM_Fast;
|
||||||
|
case CallingConventionC:
|
||||||
|
return ZigLLVM_C;
|
||||||
case CallingConventionCold:
|
case CallingConventionCold:
|
||||||
// cold calling convention only works on x86.
|
if ((g->zig_target->arch == ZigLLVM_x86 ||
|
||||||
if (g->zig_target->arch == ZigLLVM_x86 ||
|
g->zig_target->arch == ZigLLVM_x86_64) &&
|
||||||
g->zig_target->arch == ZigLLVM_x86_64)
|
g->zig_target->os != OsWindows)
|
||||||
{
|
return ZigLLVM_Cold;
|
||||||
// cold calling convention is not supported on windows
|
return ZigLLVM_C;
|
||||||
if (g->zig_target->os == OsWindows) {
|
|
||||||
return LLVMCCallConv;
|
|
||||||
} else {
|
|
||||||
return LLVMColdCallConv;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return LLVMCCallConv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallingConventionNaked:
|
case CallingConventionNaked:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case CallingConventionStdcall:
|
case CallingConventionStdcall:
|
||||||
// stdcall calling convention only works on x86.
|
if (g->zig_target->arch == ZigLLVM_x86)
|
||||||
if (g->zig_target->arch == ZigLLVM_x86) {
|
return ZigLLVM_X86_StdCall;
|
||||||
return LLVMX86StdcallCallConv;
|
return ZigLLVM_C;
|
||||||
} else {
|
case CallingConventionFastcall:
|
||||||
return LLVMCCallConv;
|
if (g->zig_target->arch == ZigLLVM_x86)
|
||||||
}
|
return ZigLLVM_X86_FastCall;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionVectorcall:
|
||||||
|
if (g->zig_target->arch == ZigLLVM_x86)
|
||||||
|
return ZigLLVM_X86_VectorCall;
|
||||||
|
if (target_is_arm(g->zig_target) &&
|
||||||
|
target_arch_pointer_bit_width(g->zig_target->arch) == 64)
|
||||||
|
return ZigLLVM_AArch64_VectorCall;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionThiscall:
|
||||||
|
if (g->zig_target->arch == ZigLLVM_x86)
|
||||||
|
return ZigLLVM_X86_ThisCall;
|
||||||
|
return ZigLLVM_C;
|
||||||
case CallingConventionAsync:
|
case CallingConventionAsync:
|
||||||
return LLVMFastCallConv;
|
return ZigLLVM_Fast;
|
||||||
|
case CallingConventionAPCS:
|
||||||
|
if (target_is_arm(g->zig_target))
|
||||||
|
return ZigLLVM_ARM_APCS;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionAAPCS:
|
||||||
|
if (target_is_arm(g->zig_target))
|
||||||
|
return ZigLLVM_ARM_AAPCS;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionAAPCSVFP:
|
||||||
|
if (target_is_arm(g->zig_target))
|
||||||
|
return ZigLLVM_ARM_AAPCS_VFP;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionInterrupt:
|
||||||
|
if (g->zig_target->arch == ZigLLVM_x86 ||
|
||||||
|
g->zig_target->arch == ZigLLVM_x86_64)
|
||||||
|
return ZigLLVM_X86_INTR;
|
||||||
|
if (g->zig_target->arch == ZigLLVM_avr)
|
||||||
|
return ZigLLVM_AVR_INTR;
|
||||||
|
if (g->zig_target->arch == ZigLLVM_msp430)
|
||||||
|
return ZigLLVM_MSP430_INTR;
|
||||||
|
return ZigLLVM_C;
|
||||||
|
case CallingConventionSignal:
|
||||||
|
if (g->zig_target->arch == ZigLLVM_avr)
|
||||||
|
return ZigLLVM_AVR_SIGNAL;
|
||||||
|
return ZigLLVM_C;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -384,7 +414,15 @@ static bool cc_want_sret_attr(CallingConvention cc) {
|
|||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case CallingConventionC:
|
case CallingConventionC:
|
||||||
case CallingConventionCold:
|
case CallingConventionCold:
|
||||||
|
case CallingConventionInterrupt:
|
||||||
|
case CallingConventionSignal:
|
||||||
case CallingConventionStdcall:
|
case CallingConventionStdcall:
|
||||||
|
case CallingConventionFastcall:
|
||||||
|
case CallingConventionVectorcall:
|
||||||
|
case CallingConventionThiscall:
|
||||||
|
case CallingConventionAPCS:
|
||||||
|
case CallingConventionAAPCS:
|
||||||
|
case CallingConventionAAPCSVFP:
|
||||||
return true;
|
return true;
|
||||||
case CallingConventionAsync:
|
case CallingConventionAsync:
|
||||||
case CallingConventionUnspecified:
|
case CallingConventionUnspecified:
|
||||||
@ -481,7 +519,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
|
|||||||
if (cc == CallingConventionNaked) {
|
if (cc == CallingConventionNaked) {
|
||||||
addLLVMFnAttr(llvm_fn, "naked");
|
addLLVMFnAttr(llvm_fn, "naked");
|
||||||
} else {
|
} else {
|
||||||
LLVMSetFunctionCallConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));
|
ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool want_cold = fn->is_cold || cc == CallingConventionCold;
|
bool want_cold = fn->is_cold || cc == CallingConventionCold;
|
||||||
@ -976,7 +1014,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
|
|||||||
{
|
{
|
||||||
assert(g->panic_fn != nullptr);
|
assert(g->panic_fn != nullptr);
|
||||||
LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
|
LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
|
||||||
LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
|
ZigLLVM_CallingConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc);
|
||||||
if (stack_trace_arg == nullptr) {
|
if (stack_trace_arg == nullptr) {
|
||||||
stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
|
stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g)));
|
||||||
}
|
}
|
||||||
@ -1087,7 +1125,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
|
|||||||
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
||||||
addLLVMFnAttr(fn_val, "alwaysinline");
|
addLLVMFnAttr(fn_val, "alwaysinline");
|
||||||
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
||||||
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
||||||
addLLVMFnAttr(fn_val, "nounwind");
|
addLLVMFnAttr(fn_val, "nounwind");
|
||||||
add_uwtable_attr(g, fn_val);
|
add_uwtable_attr(g, fn_val);
|
||||||
// Error return trace memory is in the stack, which is impossible to be at address 0
|
// Error return trace memory is in the stack, which is impossible to be at address 0
|
||||||
@ -1168,7 +1206,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
|
|||||||
addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address
|
addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address
|
||||||
addLLVMFnAttr(fn_val, "cold");
|
addLLVMFnAttr(fn_val, "cold");
|
||||||
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
||||||
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
||||||
addLLVMFnAttr(fn_val, "nounwind");
|
addLLVMFnAttr(fn_val, "nounwind");
|
||||||
add_uwtable_attr(g, fn_val);
|
add_uwtable_attr(g, fn_val);
|
||||||
if (codegen_have_frame_pointer(g)) {
|
if (codegen_have_frame_pointer(g)) {
|
||||||
@ -1252,7 +1290,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
|||||||
addLLVMFnAttr(fn_val, "noreturn");
|
addLLVMFnAttr(fn_val, "noreturn");
|
||||||
addLLVMFnAttr(fn_val, "cold");
|
addLLVMFnAttr(fn_val, "cold");
|
||||||
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
||||||
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
||||||
addLLVMFnAttr(fn_val, "nounwind");
|
addLLVMFnAttr(fn_val, "nounwind");
|
||||||
add_uwtable_attr(g, fn_val);
|
add_uwtable_attr(g, fn_val);
|
||||||
if (codegen_have_frame_pointer(g)) {
|
if (codegen_have_frame_pointer(g)) {
|
||||||
@ -2148,7 +2186,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
|
|||||||
const char *fn_name = get_mangled_name(g, "__zig_merge_error_return_traces", false);
|
const char *fn_name = get_mangled_name(g, "__zig_merge_error_return_traces", false);
|
||||||
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
||||||
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
||||||
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
||||||
addLLVMFnAttr(fn_val, "nounwind");
|
addLLVMFnAttr(fn_val, "nounwind");
|
||||||
add_uwtable_attr(g, fn_val);
|
add_uwtable_attr(g, fn_val);
|
||||||
addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
|
addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
|
||||||
@ -2325,7 +2363,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar
|
|||||||
LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
|
LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
|
||||||
LLVMConstInt(usize_type_ref, resume_id, false));
|
LLVMConstInt(usize_type_ref, resume_id, false));
|
||||||
LLVMValueRef args[] = {target_frame_ptr, arg_val};
|
LLVMValueRef args[] = {target_frame_ptr, arg_val};
|
||||||
return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_CallAttrAuto, "");
|
return ZigLLVMBuildCall(g->builder, fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
|
static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
|
||||||
@ -4215,7 +4253,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMCallConv llvm_cc = get_llvm_cc(g, cc);
|
ZigLLVM_CallingConv llvm_cc = get_llvm_cc(g, cc);
|
||||||
LLVMValueRef result;
|
LLVMValueRef result;
|
||||||
|
|
||||||
if (callee_is_async) {
|
if (callee_is_async) {
|
||||||
@ -4925,7 +4963,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
|
|||||||
buf_ptr(buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name))), false);
|
buf_ptr(buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name))), false);
|
||||||
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref);
|
||||||
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
LLVMSetLinkage(fn_val, LLVMInternalLinkage);
|
||||||
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
ZigLLVMFunctionSetCallingConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
|
||||||
addLLVMFnAttr(fn_val, "nounwind");
|
addLLVMFnAttr(fn_val, "nounwind");
|
||||||
add_uwtable_attr(g, fn_val);
|
add_uwtable_attr(g, fn_val);
|
||||||
if (codegen_have_frame_pointer(g)) {
|
if (codegen_have_frame_pointer(g)) {
|
||||||
@ -8463,8 +8501,16 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
|||||||
static_assert(CallingConventionC == 1, "");
|
static_assert(CallingConventionC == 1, "");
|
||||||
static_assert(CallingConventionCold == 2, "");
|
static_assert(CallingConventionCold == 2, "");
|
||||||
static_assert(CallingConventionNaked == 3, "");
|
static_assert(CallingConventionNaked == 3, "");
|
||||||
static_assert(CallingConventionStdcall == 4, "");
|
static_assert(CallingConventionAsync == 4, "");
|
||||||
static_assert(CallingConventionAsync == 5, "");
|
static_assert(CallingConventionInterrupt == 5, "");
|
||||||
|
static_assert(CallingConventionSignal == 6, "");
|
||||||
|
static_assert(CallingConventionStdcall == 7, "");
|
||||||
|
static_assert(CallingConventionFastcall == 8, "");
|
||||||
|
static_assert(CallingConventionVectorcall == 9, "");
|
||||||
|
static_assert(CallingConventionThiscall == 10, "");
|
||||||
|
static_assert(CallingConventionAPCS == 11, "");
|
||||||
|
static_assert(CallingConventionAAPCS == 12, "");
|
||||||
|
static_assert(CallingConventionAAPCSVFP == 13, "");
|
||||||
|
|
||||||
static_assert(FnInlineAuto == 0, "");
|
static_assert(FnInlineAuto == 0, "");
|
||||||
static_assert(FnInlineAlways == 1, "");
|
static_assert(FnInlineAlways == 1, "");
|
||||||
|
58
src/ir.cpp
58
src/ir.cpp
@ -3248,12 +3248,13 @@ static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||||
IrInstruction **param_types, IrInstruction *align_value, IrInstruction *return_type,
|
IrInstruction **param_types, IrInstruction *align_value, IrInstruction *callconv_value,
|
||||||
bool is_var_args)
|
IrInstruction *return_type, bool is_var_args)
|
||||||
{
|
{
|
||||||
IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node);
|
IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node);
|
||||||
instruction->param_types = param_types;
|
instruction->param_types = param_types;
|
||||||
instruction->align_value = align_value;
|
instruction->align_value = align_value;
|
||||||
|
instruction->callconv_value = callconv_value;
|
||||||
instruction->return_type = return_type;
|
instruction->return_type = return_type;
|
||||||
instruction->is_var_args = is_var_args;
|
instruction->is_var_args = is_var_args;
|
||||||
|
|
||||||
@ -3264,6 +3265,7 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s
|
|||||||
if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block);
|
if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block);
|
||||||
}
|
}
|
||||||
if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
|
if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
|
||||||
|
if (callconv_value != nullptr) ir_ref_instruction(callconv_value, irb->current_basic_block);
|
||||||
ir_ref_instruction(return_type, irb->current_basic_block);
|
ir_ref_instruction(return_type, irb->current_basic_block);
|
||||||
|
|
||||||
return &instruction->base;
|
return &instruction->base;
|
||||||
@ -8843,6 +8845,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
|
|||||||
return irb->codegen->invalid_instruction;
|
return irb->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IrInstruction *callconv_value = nullptr;
|
||||||
|
if (node->data.fn_proto.callconv_expr != nullptr) {
|
||||||
|
callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope);
|
||||||
|
if (callconv_value == irb->codegen->invalid_instruction)
|
||||||
|
return irb->codegen->invalid_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
IrInstruction *return_type;
|
IrInstruction *return_type;
|
||||||
if (node->data.fn_proto.return_var_token == nullptr) {
|
if (node->data.fn_proto.return_var_token == nullptr) {
|
||||||
if (node->data.fn_proto.return_type == nullptr) {
|
if (node->data.fn_proto.return_type == nullptr) {
|
||||||
@ -8859,7 +8868,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
|
|||||||
//return_type = nullptr;
|
//return_type = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);
|
return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
|
static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||||
@ -16729,9 +16738,17 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
|
|||||||
add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
|
add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
|
||||||
} break;
|
} break;
|
||||||
case CallingConventionC:
|
case CallingConventionC:
|
||||||
case CallingConventionNaked:
|
|
||||||
case CallingConventionCold:
|
case CallingConventionCold:
|
||||||
|
case CallingConventionNaked:
|
||||||
|
case CallingConventionInterrupt:
|
||||||
|
case CallingConventionSignal:
|
||||||
case CallingConventionStdcall:
|
case CallingConventionStdcall:
|
||||||
|
case CallingConventionFastcall:
|
||||||
|
case CallingConventionVectorcall:
|
||||||
|
case CallingConventionThiscall:
|
||||||
|
case CallingConventionAPCS:
|
||||||
|
case CallingConventionAAPCS:
|
||||||
|
case CallingConventionAAPCSVFP:
|
||||||
add_fn_export(ira->codegen, fn_entry, buf_ptr(symbol_name), global_linkage_id, cc);
|
add_fn_export(ira->codegen, fn_entry, buf_ptr(symbol_name), global_linkage_id, cc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -18094,7 +18111,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (fn_type_id->is_var_args) {
|
if (fn_type_id->is_var_args) {
|
||||||
if (call_param_count < src_param_count) {
|
if (call_param_count < src_param_count) {
|
||||||
ErrorMsg *msg = ir_add_error_node(ira, source_node,
|
ErrorMsg *msg = ir_add_error_node(ira, source_node,
|
||||||
@ -18247,8 +18263,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i
|
|||||||
buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
|
buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name);
|
||||||
impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn);
|
impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn);
|
||||||
impl_fn->child_scope = &impl_fn->fndef_scope->base;
|
impl_fn->child_scope = &impl_fn->fndef_scope->base;
|
||||||
|
impl_fn->cc = fn_entry->cc;
|
||||||
FnTypeId inst_fn_type_id = {0};
|
FnTypeId inst_fn_type_id = {0};
|
||||||
init_fn_type_id(&inst_fn_type_id, fn_proto_node, new_fn_arg_count);
|
init_fn_type_id(&inst_fn_type_id, fn_proto_node, fn_type_id->cc, new_fn_arg_count);
|
||||||
inst_fn_type_id.param_count = 0;
|
inst_fn_type_id.param_count = 0;
|
||||||
inst_fn_type_id.is_var_args = false;
|
inst_fn_type_id.is_var_args = false;
|
||||||
|
|
||||||
@ -22585,8 +22602,8 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
|
|||||||
// calling_convention: TypeInfo.CallingConvention
|
// calling_convention: TypeInfo.CallingConvention
|
||||||
ensure_field_index(fn_decl_val->type, "calling_convention", 2);
|
ensure_field_index(fn_decl_val->type, "calling_convention", 2);
|
||||||
fn_decl_fields[2]->special = ConstValSpecialStatic;
|
fn_decl_fields[2]->special = ConstValSpecialStatic;
|
||||||
fn_decl_fields[2]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr);
|
fn_decl_fields[2]->type = get_builtin_type(ira->codegen, "CallingConvention");
|
||||||
bigint_init_unsigned(&fn_decl_fields[2]->data.x_enum_tag, fn_node->cc);
|
bigint_init_unsigned(&fn_decl_fields[2]->data.x_enum_tag, fn_entry->cc);
|
||||||
// is_var_args: bool
|
// is_var_args: bool
|
||||||
ensure_field_index(fn_decl_val->type, "is_var_args", 3);
|
ensure_field_index(fn_decl_val->type, "is_var_args", 3);
|
||||||
bool is_varargs = fn_node->is_var_args;
|
bool is_varargs = fn_node->is_var_args;
|
||||||
@ -23273,7 +23290,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
|||||||
// calling_convention: TypeInfo.CallingConvention
|
// calling_convention: TypeInfo.CallingConvention
|
||||||
ensure_field_index(result->type, "calling_convention", 0);
|
ensure_field_index(result->type, "calling_convention", 0);
|
||||||
fields[0]->special = ConstValSpecialStatic;
|
fields[0]->special = ConstValSpecialStatic;
|
||||||
fields[0]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr);
|
fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention");
|
||||||
bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
|
bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
|
||||||
// is_generic: bool
|
// is_generic: bool
|
||||||
ensure_field_index(result->type, "is_generic", 1);
|
ensure_field_index(result->type, "is_generic", 1);
|
||||||
@ -26185,6 +26202,21 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
|
|||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_fn_type->cc = cc_from_fn_proto(&proto_node->data.fn_proto);
|
||||||
|
if (instruction->callconv_value != nullptr) {
|
||||||
|
ZigType *cc_enum_type = get_builtin_type(ira->codegen, "CallingConvention");
|
||||||
|
|
||||||
|
IrInstruction *casted_value = ir_implicit_cast(ira, instruction->callconv_value, cc_enum_type);
|
||||||
|
if (type_is_invalid(casted_value->value->type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
ZigValue *const_value = ir_resolve_const(ira, casted_value, UndefBad);
|
||||||
|
if (const_value == nullptr)
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
lazy_fn_type->cc = (CallingConvention)bigint_as_u32(&const_value->data.x_enum_tag);
|
||||||
|
}
|
||||||
|
|
||||||
size_t param_count = proto_node->data.fn_proto.params.length;
|
size_t param_count = proto_node->data.fn_proto.params.length;
|
||||||
lazy_fn_type->proto_node = proto_node;
|
lazy_fn_type->proto_node = proto_node;
|
||||||
lazy_fn_type->param_types = allocate<IrInstruction *>(param_count);
|
lazy_fn_type->param_types = allocate<IrInstruction *>(param_count);
|
||||||
@ -26195,9 +26227,11 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
|
|||||||
|
|
||||||
bool param_is_var_args = param_node->data.param_decl.is_var_args;
|
bool param_is_var_args = param_node->data.param_decl.is_var_args;
|
||||||
if (param_is_var_args) {
|
if (param_is_var_args) {
|
||||||
if (proto_node->data.fn_proto.cc == CallingConventionC) {
|
const CallingConvention cc = lazy_fn_type->cc;
|
||||||
|
|
||||||
|
if (cc == CallingConventionC) {
|
||||||
break;
|
break;
|
||||||
} else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) {
|
} else if (cc == CallingConventionUnspecified) {
|
||||||
lazy_fn_type->is_generic = true;
|
lazy_fn_type->is_generic = true;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@ -29076,7 +29110,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La
|
|||||||
AstNode *proto_node = lazy_fn_type->proto_node;
|
AstNode *proto_node = lazy_fn_type->proto_node;
|
||||||
|
|
||||||
FnTypeId fn_type_id = {0};
|
FnTypeId fn_type_id = {0};
|
||||||
init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
|
init_fn_type_id(&fn_type_id, proto_node, lazy_fn_type->cc, proto_node->data.fn_proto.params.length);
|
||||||
|
|
||||||
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
|
for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
|
||||||
AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
|
AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
|
||||||
|
@ -92,6 +92,7 @@ static Token *ast_parse_block_label(ParseContext *pc);
|
|||||||
static AstNode *ast_parse_field_init(ParseContext *pc);
|
static AstNode *ast_parse_field_init(ParseContext *pc);
|
||||||
static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
|
static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
|
||||||
static AstNode *ast_parse_link_section(ParseContext *pc);
|
static AstNode *ast_parse_link_section(ParseContext *pc);
|
||||||
|
static AstNode *ast_parse_callconv(ParseContext *pc);
|
||||||
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
|
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
|
||||||
static AstNode *ast_parse_param_decl(ParseContext *pc);
|
static AstNode *ast_parse_param_decl(ParseContext *pc);
|
||||||
static AstNode *ast_parse_param_type(ParseContext *pc);
|
static AstNode *ast_parse_param_type(ParseContext *pc);
|
||||||
@ -676,7 +677,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
|
|||||||
fn_proto->column = first->start_column;
|
fn_proto->column = first->start_column;
|
||||||
fn_proto->data.fn_proto.visib_mod = visib_mod;
|
fn_proto->data.fn_proto.visib_mod = visib_mod;
|
||||||
fn_proto->data.fn_proto.doc_comments = *doc_comments;
|
fn_proto->data.fn_proto.doc_comments = *doc_comments;
|
||||||
fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
|
// ast_parse_fn_cc may set it
|
||||||
|
if (!fn_proto->data.fn_proto.is_extern)
|
||||||
|
fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
|
||||||
fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
|
fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
|
||||||
switch (first->id) {
|
switch (first->id) {
|
||||||
case TokenIdKeywordInline:
|
case TokenIdKeywordInline:
|
||||||
@ -761,7 +764,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
|||||||
// The extern keyword for fn CC is also used for container decls.
|
// The extern keyword for fn CC is also used for container decls.
|
||||||
// We therefore put it back, as allow container decl to consume it
|
// We therefore put it back, as allow container decl to consume it
|
||||||
// later.
|
// later.
|
||||||
if (fn_cc.cc == CallingConventionC) {
|
if (fn_cc.is_extern) {
|
||||||
fn = eat_token_if(pc, TokenIdKeywordFn);
|
fn = eat_token_if(pc, TokenIdKeywordFn);
|
||||||
if (fn == nullptr) {
|
if (fn == nullptr) {
|
||||||
put_back_token(pc);
|
put_back_token(pc);
|
||||||
@ -784,6 +787,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
|||||||
|
|
||||||
AstNode *align_expr = ast_parse_byte_align(pc);
|
AstNode *align_expr = ast_parse_byte_align(pc);
|
||||||
AstNode *section_expr = ast_parse_link_section(pc);
|
AstNode *section_expr = ast_parse_link_section(pc);
|
||||||
|
AstNode *callconv_expr = ast_parse_callconv(pc);
|
||||||
Token *var = eat_token_if(pc, TokenIdKeywordVar);
|
Token *var = eat_token_if(pc, TokenIdKeywordVar);
|
||||||
Token *exmark = nullptr;
|
Token *exmark = nullptr;
|
||||||
AstNode *return_type = nullptr;
|
AstNode *return_type = nullptr;
|
||||||
@ -798,6 +802,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
|||||||
res->data.fn_proto.params = params;
|
res->data.fn_proto.params = params;
|
||||||
res->data.fn_proto.align_expr = align_expr;
|
res->data.fn_proto.align_expr = align_expr;
|
||||||
res->data.fn_proto.section_expr = section_expr;
|
res->data.fn_proto.section_expr = section_expr;
|
||||||
|
res->data.fn_proto.callconv_expr = callconv_expr;
|
||||||
res->data.fn_proto.return_var_token = var;
|
res->data.fn_proto.return_var_token = var;
|
||||||
res->data.fn_proto.auto_err_set = exmark != nullptr;
|
res->data.fn_proto.auto_err_set = exmark != nullptr;
|
||||||
res->data.fn_proto.return_type = return_type;
|
res->data.fn_proto.return_type = return_type;
|
||||||
@ -2099,6 +2104,18 @@ static AstNode *ast_parse_link_section(ParseContext *pc) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
|
||||||
|
static AstNode *ast_parse_callconv(ParseContext *pc) {
|
||||||
|
Token *first = eat_token_if(pc, TokenIdKeywordCallconv);
|
||||||
|
if (first == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
expect_token(pc, TokenIdLParen);
|
||||||
|
AstNode *res = ast_expect(pc, ast_parse_expr);
|
||||||
|
expect_token(pc, TokenIdRParen);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// FnCC
|
// FnCC
|
||||||
// <- KEYWORD_nakedcc
|
// <- KEYWORD_nakedcc
|
||||||
// / KEYWORD_stdcallcc
|
// / KEYWORD_stdcallcc
|
||||||
@ -2107,19 +2124,19 @@ static AstNode *ast_parse_link_section(ParseContext *pc) {
|
|||||||
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {
|
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {
|
||||||
AstNodeFnProto res = {};
|
AstNodeFnProto res = {};
|
||||||
if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) {
|
if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) {
|
||||||
res.cc = CallingConventionNaked;
|
res.is_nakedcc = true;
|
||||||
return Optional<AstNodeFnProto>::some(res);
|
return Optional<AstNodeFnProto>::some(res);
|
||||||
}
|
}
|
||||||
if (eat_token_if(pc, TokenIdKeywordStdcallCC) != nullptr) {
|
if (eat_token_if(pc, TokenIdKeywordStdcallCC) != nullptr) {
|
||||||
res.cc = CallingConventionStdcall;
|
res.is_stdcallcc = true;
|
||||||
return Optional<AstNodeFnProto>::some(res);
|
|
||||||
}
|
|
||||||
if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) {
|
|
||||||
res.cc = CallingConventionC;
|
|
||||||
return Optional<AstNodeFnProto>::some(res);
|
return Optional<AstNodeFnProto>::some(res);
|
||||||
}
|
}
|
||||||
if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) {
|
if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) {
|
||||||
res.cc = CallingConventionAsync;
|
res.is_async = true;
|
||||||
|
return Optional<AstNodeFnProto>::some(res);
|
||||||
|
}
|
||||||
|
if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) {
|
||||||
|
res.is_extern = true;
|
||||||
return Optional<AstNodeFnProto>::some(res);
|
return Optional<AstNodeFnProto>::some(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ static const struct ZigKeyword zig_keywords[] = {
|
|||||||
{"async", TokenIdKeywordAsync},
|
{"async", TokenIdKeywordAsync},
|
||||||
{"await", TokenIdKeywordAwait},
|
{"await", TokenIdKeywordAwait},
|
||||||
{"break", TokenIdKeywordBreak},
|
{"break", TokenIdKeywordBreak},
|
||||||
|
{"callconv", TokenIdKeywordCallconv},
|
||||||
{"catch", TokenIdKeywordCatch},
|
{"catch", TokenIdKeywordCatch},
|
||||||
{"comptime", TokenIdKeywordCompTime},
|
{"comptime", TokenIdKeywordCompTime},
|
||||||
{"const", TokenIdKeywordConst},
|
{"const", TokenIdKeywordConst},
|
||||||
@ -1545,6 +1546,7 @@ const char * token_name(TokenId id) {
|
|||||||
case TokenIdKeywordAsm: return "asm";
|
case TokenIdKeywordAsm: return "asm";
|
||||||
case TokenIdKeywordBreak: return "break";
|
case TokenIdKeywordBreak: return "break";
|
||||||
case TokenIdKeywordCatch: return "catch";
|
case TokenIdKeywordCatch: return "catch";
|
||||||
|
case TokenIdKeywordCallconv: return "callconv";
|
||||||
case TokenIdKeywordCompTime: return "comptime";
|
case TokenIdKeywordCompTime: return "comptime";
|
||||||
case TokenIdKeywordConst: return "const";
|
case TokenIdKeywordConst: return "const";
|
||||||
case TokenIdKeywordContinue: return "continue";
|
case TokenIdKeywordContinue: return "continue";
|
||||||
|
@ -59,6 +59,7 @@ enum TokenId {
|
|||||||
TokenIdKeywordAwait,
|
TokenIdKeywordAwait,
|
||||||
TokenIdKeywordBreak,
|
TokenIdKeywordBreak,
|
||||||
TokenIdKeywordCatch,
|
TokenIdKeywordCatch,
|
||||||
|
TokenIdKeywordCallconv,
|
||||||
TokenIdKeywordCompTime,
|
TokenIdKeywordCompTime,
|
||||||
TokenIdKeywordConst,
|
TokenIdKeywordConst,
|
||||||
TokenIdKeywordContinue,
|
TokenIdKeywordContinue,
|
||||||
|
@ -273,10 +273,10 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
|
LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
|
||||||
unsigned NumArgs, unsigned CC, ZigLLVM_CallAttr attr, const char *Name)
|
unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name)
|
||||||
{
|
{
|
||||||
CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);
|
CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);
|
||||||
call_inst->setCallingConv(CC);
|
call_inst->setCallingConv(static_cast<CallingConv::ID>(CC));
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
case ZigLLVM_CallAttrAuto:
|
case ZigLLVM_CallAttrAuto:
|
||||||
break;
|
break;
|
||||||
@ -932,6 +932,9 @@ void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) {
|
|||||||
unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data));
|
unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, ZigLLVM_CallingConv cc) {
|
||||||
|
unwrap<Function>(function)->setCallingConv(static_cast<CallingConv::ID>(cc));
|
||||||
|
}
|
||||||
|
|
||||||
class MyOStream: public raw_ostream {
|
class MyOStream: public raw_ostream {
|
||||||
public:
|
public:
|
||||||
@ -1315,3 +1318,49 @@ static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
|
|||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
|
static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
|
static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_XCOFF == Triple::XCOFF, "");
|
static_assert((Triple::ObjectFormatType)ZigLLVM_XCOFF == Triple::XCOFF, "");
|
||||||
|
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_C == llvm::CallingConv::C, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_Fast == llvm::CallingConv::Fast, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_Cold == llvm::CallingConv::Cold, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_GHC == llvm::CallingConv::GHC, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_HiPE == llvm::CallingConv::HiPE, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_WebKit_JS == llvm::CallingConv::WebKit_JS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AnyReg == llvm::CallingConv::AnyReg, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_PreserveMost == llvm::CallingConv::PreserveMost, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_PreserveAll == llvm::CallingConv::PreserveAll, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_Swift == llvm::CallingConv::Swift, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_CXX_FAST_TLS == llvm::CallingConv::CXX_FAST_TLS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_FirstTargetCC == llvm::CallingConv::FirstTargetCC, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_StdCall == llvm::CallingConv::X86_StdCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_FastCall == llvm::CallingConv::X86_FastCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_ARM_APCS == llvm::CallingConv::ARM_APCS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_ARM_AAPCS == llvm::CallingConv::ARM_AAPCS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_ARM_AAPCS_VFP == llvm::CallingConv::ARM_AAPCS_VFP, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_MSP430_INTR == llvm::CallingConv::MSP430_INTR, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_ThisCall == llvm::CallingConv::X86_ThisCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_PTX_Kernel == llvm::CallingConv::PTX_Kernel, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_PTX_Device == llvm::CallingConv::PTX_Device, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_SPIR_FUNC == llvm::CallingConv::SPIR_FUNC, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_SPIR_KERNEL == llvm::CallingConv::SPIR_KERNEL, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_Intel_OCL_BI == llvm::CallingConv::Intel_OCL_BI, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_64_SysV == llvm::CallingConv::X86_64_SysV, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_Win64 == llvm::CallingConv::Win64, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_VectorCall == llvm::CallingConv::X86_VectorCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_HHVM == llvm::CallingConv::HHVM, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_HHVM_C == llvm::CallingConv::HHVM_C, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_INTR == llvm::CallingConv::X86_INTR, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AVR_INTR == llvm::CallingConv::AVR_INTR, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AVR_SIGNAL == llvm::CallingConv::AVR_SIGNAL, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AVR_BUILTIN == llvm::CallingConv::AVR_BUILTIN, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_VS == llvm::CallingConv::AMDGPU_VS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_GS == llvm::CallingConv::AMDGPU_GS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_PS == llvm::CallingConv::AMDGPU_PS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_CS == llvm::CallingConv::AMDGPU_CS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_KERNEL == llvm::CallingConv::AMDGPU_KERNEL, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_X86_RegCall == llvm::CallingConv::X86_RegCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_HS == llvm::CallingConv::AMDGPU_HS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_MSP430_BUILTIN == llvm::CallingConv::MSP430_BUILTIN, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_LS == llvm::CallingConv::AMDGPU_LS, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AMDGPU_ES == llvm::CallingConv::AMDGPU_ES, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_AArch64_VectorCall == llvm::CallingConv::AArch64_VectorCall, "");
|
||||||
|
static_assert((CallingConv::ID)ZigLLVM_MaxID == llvm::CallingConv::MaxID, "");
|
||||||
|
@ -64,6 +64,54 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
|
|||||||
|
|
||||||
ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
|
ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
|
||||||
|
|
||||||
|
enum ZigLLVM_CallingConv {
|
||||||
|
ZigLLVM_C = 0,
|
||||||
|
ZigLLVM_Fast = 8,
|
||||||
|
ZigLLVM_Cold = 9,
|
||||||
|
ZigLLVM_GHC = 10,
|
||||||
|
ZigLLVM_HiPE = 11,
|
||||||
|
ZigLLVM_WebKit_JS = 12,
|
||||||
|
ZigLLVM_AnyReg = 13,
|
||||||
|
ZigLLVM_PreserveMost = 14,
|
||||||
|
ZigLLVM_PreserveAll = 15,
|
||||||
|
ZigLLVM_Swift = 16,
|
||||||
|
ZigLLVM_CXX_FAST_TLS = 17,
|
||||||
|
ZigLLVM_FirstTargetCC = 64,
|
||||||
|
ZigLLVM_X86_StdCall = 64,
|
||||||
|
ZigLLVM_X86_FastCall = 65,
|
||||||
|
ZigLLVM_ARM_APCS = 66,
|
||||||
|
ZigLLVM_ARM_AAPCS = 67,
|
||||||
|
ZigLLVM_ARM_AAPCS_VFP = 68,
|
||||||
|
ZigLLVM_MSP430_INTR = 69,
|
||||||
|
ZigLLVM_X86_ThisCall = 70,
|
||||||
|
ZigLLVM_PTX_Kernel = 71,
|
||||||
|
ZigLLVM_PTX_Device = 72,
|
||||||
|
ZigLLVM_SPIR_FUNC = 75,
|
||||||
|
ZigLLVM_SPIR_KERNEL = 76,
|
||||||
|
ZigLLVM_Intel_OCL_BI = 77,
|
||||||
|
ZigLLVM_X86_64_SysV = 78,
|
||||||
|
ZigLLVM_Win64 = 79,
|
||||||
|
ZigLLVM_X86_VectorCall = 80,
|
||||||
|
ZigLLVM_HHVM = 81,
|
||||||
|
ZigLLVM_HHVM_C = 82,
|
||||||
|
ZigLLVM_X86_INTR = 83,
|
||||||
|
ZigLLVM_AVR_INTR = 84,
|
||||||
|
ZigLLVM_AVR_SIGNAL = 85,
|
||||||
|
ZigLLVM_AVR_BUILTIN = 86,
|
||||||
|
ZigLLVM_AMDGPU_VS = 87,
|
||||||
|
ZigLLVM_AMDGPU_GS = 88,
|
||||||
|
ZigLLVM_AMDGPU_PS = 89,
|
||||||
|
ZigLLVM_AMDGPU_CS = 90,
|
||||||
|
ZigLLVM_AMDGPU_KERNEL = 91,
|
||||||
|
ZigLLVM_X86_RegCall = 92,
|
||||||
|
ZigLLVM_AMDGPU_HS = 93,
|
||||||
|
ZigLLVM_MSP430_BUILTIN = 94,
|
||||||
|
ZigLLVM_AMDGPU_LS = 95,
|
||||||
|
ZigLLVM_AMDGPU_ES = 96,
|
||||||
|
ZigLLVM_AArch64_VectorCall = 97,
|
||||||
|
ZigLLVM_MaxID = 1023,
|
||||||
|
};
|
||||||
|
|
||||||
enum ZigLLVM_CallAttr {
|
enum ZigLLVM_CallAttr {
|
||||||
ZigLLVM_CallAttrAuto,
|
ZigLLVM_CallAttrAuto,
|
||||||
ZigLLVM_CallAttrNeverTail,
|
ZigLLVM_CallAttrNeverTail,
|
||||||
@ -72,7 +120,7 @@ enum ZigLLVM_CallAttr {
|
|||||||
ZigLLVM_CallAttrAlwaysInline,
|
ZigLLVM_CallAttrAlwaysInline,
|
||||||
};
|
};
|
||||||
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
|
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
|
||||||
unsigned NumArgs, unsigned CC, enum ZigLLVM_CallAttr attr, const char *Name);
|
unsigned NumArgs, enum ZigLLVM_CallingConv CC, enum ZigLLVM_CallAttr attr, const char *Name);
|
||||||
|
|
||||||
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
|
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
|
||||||
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
|
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
|
||||||
@ -215,6 +263,7 @@ ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigne
|
|||||||
ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
|
ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
|
||||||
ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call);
|
ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call);
|
||||||
ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data);
|
ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data);
|
||||||
|
ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc);
|
||||||
|
|
||||||
ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
|
ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
|
||||||
ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
|
ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val);
|
||||||
|
@ -752,7 +752,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ _ = @frame();
|
\\ _ = @frame();
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",
|
"tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
|
||||||
"tmp.zig:5:9: note: @frame() causes function to be async",
|
"tmp.zig:5:9: note: @frame() causes function to be async",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -765,7 +765,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ suspend;
|
\\ suspend;
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",
|
"tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
|
||||||
"tmp.zig:3:18: note: await here is a suspend point",
|
"tmp.zig:3:18: note: await here is a suspend point",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -843,7 +843,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ suspend;
|
\\ suspend;
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",
|
"tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
|
||||||
"tmp.zig:2:8: note: async function call here",
|
"tmp.zig:2:8: note: async function call here",
|
||||||
"tmp.zig:5:8: note: async function call here",
|
"tmp.zig:5:8: note: async function call here",
|
||||||
"tmp.zig:8:5: note: suspends here",
|
"tmp.zig:8:5: note: suspends here",
|
||||||
@ -1140,7 +1140,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ while (true) {}
|
\\ while (true) {}
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn([]const u8,var)var'",
|
"error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn([]const u8,var) var'",
|
||||||
"note: only one of the functions is generic",
|
"note: only one of the functions is generic",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1362,7 +1362,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ return 0;
|
\\ return 0;
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'",
|
"tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("C pointer to c_void",
|
cases.add("C pointer to c_void",
|
||||||
@ -2187,7 +2187,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ f(g);
|
\\ f(g);
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:9: error: parameter of type 'fn(var)var' must be declared comptime",
|
"tmp.zig:1:9: error: parameter of type 'fn(var) var' must be declared comptime",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("optional pointer to void in extern struct",
|
cases.add("optional pointer to void in extern struct",
|
||||||
@ -2859,7 +2859,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\const Foo = enum { A, B, C };
|
\\const Foo = enum { A, B, C };
|
||||||
\\export fn entry(foo: Foo) void { }
|
\\export fn entry(foo: Foo) void { }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'",
|
"tmp.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("function with non-extern non-packed struct parameter",
|
cases.add("function with non-extern non-packed struct parameter",
|
||||||
@ -2870,7 +2870,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\};
|
\\};
|
||||||
\\export fn entry(foo: Foo) void { }
|
\\export fn entry(foo: Foo) void { }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'",
|
"tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("function with non-extern non-packed union parameter",
|
cases.add("function with non-extern non-packed union parameter",
|
||||||
@ -2881,7 +2881,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\};
|
\\};
|
||||||
\\export fn entry(foo: Foo) void { }
|
\\export fn entry(foo: Foo) void { }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'",
|
"tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("switch on enum with 1 field with no prongs",
|
cases.add("switch on enum with 1 field with no prongs",
|
||||||
@ -2977,8 +2977,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ bar(&{});
|
\\ bar(&{});
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
|
"tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'",
|
||||||
"tmp.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
|
"tmp.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("implicit semicolon - block statement",
|
cases.add("implicit semicolon - block statement",
|
||||||
@ -4552,7 +4552,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ return x + y;
|
\\ return x + y;
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'",
|
"tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("extern function with comptime parameter",
|
cases.add("extern function with comptime parameter",
|
||||||
@ -4562,7 +4562,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\}
|
\\}
|
||||||
\\export fn entry() usize { return @sizeOf(@TypeOf(f)); }
|
\\export fn entry() usize { return @sizeOf(@TypeOf(f)); }
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'",
|
"tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("convert fixed size array to slice with invalid size",
|
cases.add("convert fixed size array to slice with invalid size",
|
||||||
@ -6303,7 +6303,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ _ = @TypeOf(generic).ReturnType;
|
\\ _ = @TypeOf(generic).ReturnType;
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(var)var' is generic",
|
"tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(var) var' is generic",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("getting @ArgType of generic function",
|
cases.add("getting @ArgType of generic function",
|
||||||
@ -6312,7 +6312,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||||||
\\ _ = @ArgType(@TypeOf(generic), 0);
|
\\ _ = @ArgType(@TypeOf(generic), 0);
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",
|
"tmp.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var) var' is generic",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("unsupported modifier at start of asm output constraint",
|
cases.add("unsupported modifier at start of asm output constraint",
|
||||||
|
@ -19,6 +19,7 @@ pub const TranslateCContext = struct {
|
|||||||
sources: ArrayList(SourceFile),
|
sources: ArrayList(SourceFile),
|
||||||
expected_lines: ArrayList([]const u8),
|
expected_lines: ArrayList([]const u8),
|
||||||
allow_warnings: bool,
|
allow_warnings: bool,
|
||||||
|
target: std.Target = .Native,
|
||||||
|
|
||||||
const SourceFile = struct {
|
const SourceFile = struct {
|
||||||
filename: []const u8,
|
filename: []const u8,
|
||||||
@ -71,6 +72,18 @@ pub const TranslateCContext = struct {
|
|||||||
self.addCase(tc);
|
self.addCase(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addWithTarget(
|
||||||
|
self: *TranslateCContext,
|
||||||
|
name: []const u8,
|
||||||
|
target: std.Target,
|
||||||
|
source: []const u8,
|
||||||
|
expected_lines: []const []const u8,
|
||||||
|
) void {
|
||||||
|
const tc = self.create(false, "source.h", name, source, expected_lines);
|
||||||
|
tc.target = target;
|
||||||
|
self.addCase(tc);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn addAllowWarnings(
|
pub fn addAllowWarnings(
|
||||||
self: *TranslateCContext,
|
self: *TranslateCContext,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
@ -101,6 +114,7 @@ pub const TranslateCContext = struct {
|
|||||||
.basename = case.sources.toSliceConst()[0].filename,
|
.basename = case.sources.toSliceConst()[0].filename,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
translate_c.setTarget(case.target);
|
||||||
|
|
||||||
const check_file = translate_c.addCheckFile(case.expected_lines.toSliceConst());
|
const check_file = translate_c.addCheckFile(case.expected_lines.toSliceConst());
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ fn testUnion() void {
|
|||||||
expect(typeinfo_info.Union.fields[4].enum_field != null);
|
expect(typeinfo_info.Union.fields[4].enum_field != null);
|
||||||
expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
|
expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
|
||||||
expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
|
expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
|
||||||
expect(typeinfo_info.Union.decls.len == 21);
|
expect(typeinfo_info.Union.decls.len == 20);
|
||||||
|
|
||||||
const TestNoTagUnion = union {
|
const TestNoTagUnion = union {
|
||||||
Foo: void,
|
Foo: void,
|
||||||
@ -266,7 +266,7 @@ test "type info: function type info" {
|
|||||||
fn testFunction() void {
|
fn testFunction() void {
|
||||||
const fn_info = @typeInfo(@TypeOf(foo));
|
const fn_info = @typeInfo(@TypeOf(foo));
|
||||||
expect(@as(TypeId, fn_info) == TypeId.Fn);
|
expect(@as(TypeId, fn_info) == TypeId.Fn);
|
||||||
expect(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
|
expect(fn_info.Fn.calling_convention == .Unspecified);
|
||||||
expect(fn_info.Fn.is_generic);
|
expect(fn_info.Fn.is_generic);
|
||||||
expect(fn_info.Fn.args.len == 2);
|
expect(fn_info.Fn.args.len == 2);
|
||||||
expect(fn_info.Fn.is_var_args);
|
expect(fn_info.Fn.is_var_args);
|
||||||
|
@ -205,7 +205,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\static void bar(void) {}
|
\\static void bar(void) {}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub export fn foo() void {}
|
\\pub export fn foo() void {}
|
||||||
\\pub fn bar() void {}
|
\\pub fn bar() callconv(.C) void {}
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("typedef void",
|
cases.add("typedef void",
|
||||||
@ -957,6 +957,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\pub const fn1 = ?extern fn (u8) void;
|
\\pub const fn1 = ?extern fn (u8) void;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cases.addWithTarget("Calling convention", tests.Target{
|
||||||
|
.Cross = .{ .os = .linux, .arch = .i386, .abi = .none },
|
||||||
|
},
|
||||||
|
\\void __attribute__((fastcall)) foo1(float *a);
|
||||||
|
\\void __attribute__((stdcall)) foo2(float *a);
|
||||||
|
\\void __attribute__((vectorcall)) foo3(float *a);
|
||||||
|
\\void __attribute__((cdecl)) foo4(float *a);
|
||||||
|
\\void __attribute__((thiscall)) foo5(float *a);
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub fn foo1(a: [*c]f32) callconv(.Fastcall) void;
|
||||||
|
\\pub fn foo2(a: [*c]f32) callconv(.Stdcall) void;
|
||||||
|
\\pub fn foo3(a: [*c]f32) callconv(.Vectorcall) void;
|
||||||
|
\\pub extern fn foo4(a: [*c]f32) void;
|
||||||
|
\\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void;
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.addWithTarget("Calling convention", tests.Target{
|
||||||
|
.Cross = .{ .os = .linux, .arch = .{ .arm = .v8_5a }, .abi = .none },
|
||||||
|
},
|
||||||
|
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
|
||||||
|
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub fn foo1(a: [*c]f32) callconv(.AAPCS) void;
|
||||||
|
\\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
|
||||||
|
});
|
||||||
|
|
||||||
|
cases.addWithTarget("Calling convention", tests.Target{
|
||||||
|
.Cross = .{ .os = .linux, .arch = .{ .aarch64 = .v8_5a }, .abi = .none },
|
||||||
|
},
|
||||||
|
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void;
|
||||||
|
});
|
||||||
|
|
||||||
cases.add("Parameterless function prototypes",
|
cases.add("Parameterless function prototypes",
|
||||||
\\void a() {}
|
\\void a() {}
|
||||||
\\void b(void) {}
|
\\void b(void) {}
|
||||||
@ -985,7 +1019,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\ char *arr1[10] ={0};
|
\\ char *arr1[10] ={0};
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub fn foo() void {
|
\\pub fn foo() callconv(.C) void {
|
||||||
\\ var arr: [10]u8 = .{
|
\\ var arr: [10]u8 = .{
|
||||||
\\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
|
\\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
|
||||||
\\ } ++ .{0} ** 9;
|
\\ } ++ .{0} ** 9;
|
||||||
@ -2262,7 +2296,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\ baz();
|
\\ baz();
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub fn bar() void {}
|
\\pub fn bar() callconv(.C) void {}
|
||||||
\\pub export fn foo(arg_baz: ?extern fn () [*c]c_int) void {
|
\\pub export fn foo(arg_baz: ?extern fn () [*c]c_int) void {
|
||||||
\\ var baz = arg_baz;
|
\\ var baz = arg_baz;
|
||||||
\\ bar();
|
\\ bar();
|
||||||
@ -2321,7 +2355,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\ do {} while (0);
|
\\ do {} while (0);
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub fn foo() void {
|
\\pub fn foo() callconv(.C) void {
|
||||||
\\ if (@as(c_int, 1) != 0) while (true) {
|
\\ if (@as(c_int, 1) != 0) while (true) {
|
||||||
\\ if (!(@as(c_int, 0) != 0)) break;
|
\\ if (!(@as(c_int, 0) != 0)) break;
|
||||||
\\ };
|
\\ };
|
||||||
@ -2413,9 +2447,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\void c(void) {}
|
\\void c(void) {}
|
||||||
\\static void foo() {}
|
\\static void foo() {}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub fn a() void {}
|
\\pub fn a() callconv(.C) void {}
|
||||||
\\pub fn b() void {}
|
\\pub fn b() callconv(.C) void {}
|
||||||
\\pub export fn c() void {}
|
\\pub export fn c() void {}
|
||||||
\\pub fn foo() void {}
|
\\pub fn foo() callconv(.C) void {}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user