Merge remote-tracking branch 'origin/master' into llvm13

This commit is contained in:
Andrew Kelley 2021-08-31 18:44:15 -07:00
commit 7efca2e6f5
53 changed files with 1288 additions and 764 deletions

View File

@ -9,7 +9,7 @@ sudo apt-get install -y cmake s3cmd tidy
ZIGDIR="$(pwd)"
ARCH="$(uname -m)"
TARGET="$ARCH-linux-musl"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.0-dev.2703+c12704a33"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.1-dev.94+535615117"
PREFIX="$HOME/$CACHE_BASENAME"
MCPU="baseline"
JOBS="-j$(nproc)"

View File

@ -9,7 +9,7 @@ ZIGDIR="$(pwd)"
ARCH="x86_64"
TARGET="$ARCH-macos-gnu"
MCPU="baseline"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.0-dev.2703+c12704a33"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.1-dev.94+535615117"
PREFIX="$HOME/$CACHE_BASENAME"
JOBS="-j2"

View File

@ -783,7 +783,7 @@ pub fn main() void {
Because Zig source code is {#link|UTF-8 encoded|Source Encoding#}, any non-ASCII bytes appearing within a string literal
in source code carry their UTF-8 meaning into the content of the string in the Zig program;
the bytes are not modified by the compiler.
However, it is possible to embbed non-UTF-8 bytes into a string literal using <code>\xNN</code> notation.
However, it is possible to embed non-UTF-8 bytes into a string literal using <code>\xNN</code> notation.
</p>
<p>
Unicode code point literals have type {#syntax#}comptime_int{#endsyntax#}, the same as

View File

@ -700,7 +700,7 @@ const LinuxThreadImpl = struct {
\\ int $128
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.x86_64 => asm volatile (
@ -713,7 +713,7 @@ const LinuxThreadImpl = struct {
\\ syscall
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.arm, .armeb, .thumb, .thumbeb => asm volatile (
@ -726,7 +726,7 @@ const LinuxThreadImpl = struct {
\\ svc 0
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.aarch64, .aarch64_be, .aarch64_32 => asm volatile (
@ -739,7 +739,7 @@ const LinuxThreadImpl = struct {
\\ svc 0
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.mips, .mipsel => asm volatile (
@ -753,7 +753,7 @@ const LinuxThreadImpl = struct {
\\ syscall
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.mips64, .mips64el => asm volatile (
@ -766,7 +766,7 @@ const LinuxThreadImpl = struct {
\\ syscall
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (
@ -780,7 +780,7 @@ const LinuxThreadImpl = struct {
\\ blr
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.riscv64 => asm volatile (
@ -793,7 +793,7 @@ const LinuxThreadImpl = struct {
\\ ecall
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
.sparcv9 => asm volatile (
@ -821,7 +821,7 @@ const LinuxThreadImpl = struct {
\\ t 0x6d
:
: [ptr] "r" (@ptrToInt(self.mapped.ptr)),
[len] "r" (self.mapped.len)
[len] "r" (self.mapped.len),
: "memory"
),
else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)),

View File

@ -293,6 +293,22 @@ pub fn ArrayHashMap(
return self.unmanaged.getPtrAdapted(key, ctx);
}
/// Find the actual key associated with an adapted key
pub fn getKey(self: Self, key: K) ?K {
return self.unmanaged.getKeyContext(key, self.ctx);
}
pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
return self.unmanaged.getKeyAdapted(key, ctx);
}
/// Find a pointer to the actual key associated with an adapted key
pub fn getKeyPtr(self: Self, key: K) ?*K {
return self.unmanaged.getKeyPtrContext(key, self.ctx);
}
pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
return self.unmanaged.getKeyPtrAdapted(key, ctx);
}
/// Check whether a key is stored in the map
pub fn contains(self: Self, key: K) bool {
return self.unmanaged.containsContext(key, self.ctx);
@ -967,6 +983,34 @@ pub fn ArrayHashMapUnmanaged(
return if (@sizeOf(*V) == 0) @as(*V, undefined) else &self.values()[index];
}
/// Find the actual key associated with an adapted key
pub fn getKey(self: Self, key: K) ?K {
if (@sizeOf(Context) != 0)
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getKeyContext instead.");
return self.getKeyContext(key, undefined);
}
pub fn getKeyContext(self: Self, key: K, ctx: Context) ?K {
return self.getKeyAdapted(key, ctx);
}
pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
const index = self.getIndexAdapted(key, ctx) orelse return null;
return self.keys()[index];
}
/// Find a pointer to the actual key associated with an adapted key
pub fn getKeyPtr(self: Self, key: K) ?*K {
if (@sizeOf(Context) != 0)
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getKeyPtrContext instead.");
return self.getKeyPtrContext(key, undefined);
}
pub fn getKeyPtrContext(self: Self, key: K, ctx: Context) ?*K {
return self.getKeyPtrAdapted(key, ctx);
}
pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
const index = self.getIndexAdapted(key, ctx) orelse return null;
return &self.keys()[index];
}
/// Check whether a key is stored in the map
pub fn contains(self: Self, key: K) bool {
if (@sizeOf(Context) != 0)

View File

@ -176,69 +176,69 @@ pub fn Atomic(comptime T: type) type {
2 => switch (op) {
.Set => asm volatile ("lock btsw %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Reset => asm volatile ("lock btrw %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Toggle => asm volatile ("lock btcw %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
},
4 => switch (op) {
.Set => asm volatile ("lock btsl %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Reset => asm volatile ("lock btrl %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Toggle => asm volatile ("lock btcl %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
},
8 => switch (op) {
.Set => asm volatile ("lock btsq %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Reset => asm volatile ("lock btrq %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
.Toggle => asm volatile ("lock btcq %[bit], %[ptr]"
// LLVM doesn't support u1 flag register return values
: [result] "={@ccc}" (-> u8)
: [result] "={@ccc}" (-> u8),
: [ptr] "*p" (&self.value),
[bit] "X" (@as(T, bit))
[bit] "X" (@as(T, bit)),
: "cc", "memory"
),
},

View File

@ -94,6 +94,8 @@ pub const Builder = struct {
name: []const u8,
type_id: TypeId,
description: []const u8,
/// If the `type_id` is `enum` this provides the list of enum options
enum_options: ?[]const []const u8,
};
const UserInputOption = struct {
@ -482,10 +484,21 @@ pub const Builder = struct {
const name = self.dupe(name_raw);
const description = self.dupe(description_raw);
const type_id = comptime typeToEnum(T);
const enum_options = if (type_id == .@"enum") blk: {
const fields = comptime std.meta.fields(T);
var options = ArrayList([]const u8).initCapacity(self.allocator, fields.len) catch unreachable;
inline for (fields) |field| {
options.appendAssumeCapacity(field.name);
}
break :blk options.toOwnedSlice();
} else null;
const available_option = AvailableOption{
.name = name,
.type_id = type_id,
.description = description,
.enum_options = enum_options,
};
if ((self.available_options_map.fetchPut(name, available_option) catch unreachable) != null) {
panic("Option '{s}' declared twice", .{name});

View File

@ -34,9 +34,9 @@ pub const Block = struct {
return Block{
.repr = asm (
\\ vaesenc %[rk], %[in], %[out]
: [out] "=x" (-> BlockVec)
: [out] "=x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (round_key.repr)
[rk] "x" (round_key.repr),
),
};
}
@ -46,9 +46,9 @@ pub const Block = struct {
return Block{
.repr = asm (
\\ vaesenclast %[rk], %[in], %[out]
: [out] "=x" (-> BlockVec)
: [out] "=x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (round_key.repr)
[rk] "x" (round_key.repr),
),
};
}
@ -58,9 +58,9 @@ pub const Block = struct {
return Block{
.repr = asm (
\\ vaesdec %[rk], %[in], %[out]
: [out] "=x" (-> BlockVec)
: [out] "=x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (inv_round_key.repr)
[rk] "x" (inv_round_key.repr),
),
};
}
@ -70,9 +70,9 @@ pub const Block = struct {
return Block{
.repr = asm (
\\ vaesdeclast %[rk], %[in], %[out]
: [out] "=x" (-> BlockVec)
: [out] "=x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (inv_round_key.repr)
[rk] "x" (inv_round_key.repr),
),
};
}
@ -190,11 +190,11 @@ fn KeySchedule(comptime Aes: type) type {
\\ vpxor %[ts], %[r], %[r]
: [r] "=&x" (-> BlockVec),
[s] "=&x" (s),
[ts] "=&x" (ts)
[ts] "=&x" (ts),
: [rc] "n" (rc),
[t] "x" (t),
[tx] "x" (tx),
[mask] "n" (@as(u8, if (second) 0xaa else 0xff))
[mask] "n" (@as(u8, if (second) 0xaa else 0xff)),
);
}
@ -235,8 +235,8 @@ fn KeySchedule(comptime Aes: type) type {
inv_round_keys[i] = Block{
.repr = asm (
\\ vaesimc %[rk], %[inv_rk]
: [inv_rk] "=x" (-> BlockVec)
: [rk] "x" (round_keys[rounds - i].repr)
: [inv_rk] "=x" (-> BlockVec),
: [rk] "x" (round_keys[rounds - i].repr),
),
};
}

View File

@ -39,10 +39,10 @@ pub const Block = struct {
\\ aese %[out].16b, %[zero].16b
\\ aesmc %[out].16b, %[out].16b
\\ eor %[out].16b, %[out].16b, %[rk].16b
: [out] "=&x" (-> BlockVec)
: [out] "=&x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (round_key.repr),
[zero] "x" (zero)
[zero] "x" (zero),
),
};
}
@ -54,10 +54,10 @@ pub const Block = struct {
\\ mov %[out].16b, %[in].16b
\\ aese %[out].16b, %[zero].16b
\\ eor %[out].16b, %[out].16b, %[rk].16b
: [out] "=&x" (-> BlockVec)
: [out] "=&x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (round_key.repr),
[zero] "x" (zero)
[zero] "x" (zero),
),
};
}
@ -70,10 +70,10 @@ pub const Block = struct {
\\ aesd %[out].16b, %[zero].16b
\\ aesimc %[out].16b, %[out].16b
\\ eor %[out].16b, %[out].16b, %[rk].16b
: [out] "=&x" (-> BlockVec)
: [out] "=&x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (inv_round_key.repr),
[zero] "x" (zero)
[zero] "x" (zero),
),
};
}
@ -85,10 +85,10 @@ pub const Block = struct {
\\ mov %[out].16b, %[in].16b
\\ aesd %[out].16b, %[zero].16b
\\ eor %[out].16b, %[out].16b, %[rk].16b
: [out] "=&x" (-> BlockVec)
: [out] "=&x" (-> BlockVec),
: [in] "x" (block.repr),
[rk] "x" (inv_round_key.repr),
[zero] "x" (zero)
[zero] "x" (zero),
),
};
}
@ -210,11 +210,11 @@ fn KeySchedule(comptime Aes: type) type {
[v1] "=&x" (v1),
[v2] "=&x" (v2),
[v3] "=&x" (v3),
[v4] "=&x" (v4)
[v4] "=&x" (v4),
: [rc] "N" (rc),
[t] "x" (t),
[zero] "x" (zero),
[mask] "x" (mask1)
[mask] "x" (mask1),
);
}
@ -240,12 +240,12 @@ fn KeySchedule(comptime Aes: type) type {
[v1] "=&x" (v1),
[v2] "=&x" (v2),
[v3] "=&x" (v3),
[v4] "=&x" (v4)
[v4] "=&x" (v4),
: [rc] "N" (if (second) @as(u8, 0) else rc),
[t] "x" (t),
[tx] "x" (tx),
[zero] "x" (zero),
[mask] "x" (if (second) mask2 else mask1)
[mask] "x" (if (second) mask2 else mask1),
);
}
@ -286,8 +286,8 @@ fn KeySchedule(comptime Aes: type) type {
inv_round_keys[i] = Block{
.repr = asm (
\\ aesimc %[inv_rk].16b, %[rk].16b
: [inv_rk] "=x" (-> BlockVec)
: [rk] "x" (round_keys[rounds - i].repr)
: [inv_rk] "=x" (-> BlockVec),
: [rk] "x" (round_keys[rounds - i].repr),
),
};
}

View File

@ -94,9 +94,9 @@ pub const Ghash = struct {
const Vector = std.meta.Vector;
const product = asm (
\\ vpclmulqdq $0x00, %[x], %[y], %[out]
: [out] "=x" (-> Vector(2, u64))
: [out] "=x" (-> Vector(2, u64)),
: [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))),
[y] "x" (@bitCast(Vector(2, u64), @as(u128, y)))
[y] "x" (@bitCast(Vector(2, u64), @as(u128, y))),
);
return product[0];
}
@ -105,9 +105,9 @@ pub const Ghash = struct {
const Vector = std.meta.Vector;
const product = asm (
\\ pmull %[out].1q, %[x].1d, %[y].1d
: [out] "=w" (-> Vector(2, u64))
: [out] "=w" (-> Vector(2, u64)),
: [x] "w" (@bitCast(Vector(2, u64), @as(u128, x))),
[y] "w" (@bitCast(Vector(2, u64), @as(u128, y)))
[y] "w" (@bitCast(Vector(2, u64), @as(u128, y))),
);
return product[0];
}

View File

@ -1634,7 +1634,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, comptime msg: u
pub fn dumpStackPointerAddr(prefix: []const u8) void {
const sp = asm (""
: [argc] "={rsp}" (-> usize)
: [argc] "={rsp}" (-> usize),
);
std.debug.warn("{} sp = 0x{x}\n", .{ prefix, sp });
}

View File

@ -1200,8 +1200,6 @@ pub fn formatFloatDecimal(
while (i < precision) : (i += 1) {
try writer.writeAll("0");
}
} else {
try writer.writeAll(".0");
}
}
@ -2198,6 +2196,7 @@ test "float.hexadecimal.precision" {
test "float.decimal" {
try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
try expectFmt("f32: 0", "f32: {d:.0}", .{@as(f32, 0.0)});
try expectFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
try expectFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
// -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).

View File

@ -561,6 +561,21 @@ pub fn HashMap(
return self.unmanaged.getPtrAdapted(key, ctx);
}
/// Finds the actual key associated with an adapted key in the map
pub fn getKey(self: Self, key: K) ?K {
return self.unmanaged.getKeyContext(key, self.ctx);
}
pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
return self.unmanaged.getKeyAdapted(key, ctx);
}
pub fn getKeyPtr(self: Self, key: K) ?*K {
return self.unmanaged.getKeyPtrContext(key, self.ctx);
}
pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
return self.unmanaged.getKeyPtrAdapted(key, ctx);
}
/// Finds the key and value associated with a key in the map
pub fn getEntry(self: Self, key: K) ?Entry {
return self.unmanaged.getEntryContext(key, self.ctx);
@ -1124,6 +1139,38 @@ pub fn HashMapUnmanaged(
result.value_ptr.* = value;
}
/// Get an optional pointer to the actual key associated with adapted key, if present.
pub fn getKeyPtr(self: Self, key: K) ?*K {
if (@sizeOf(Context) != 0)
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getKeyPtrContext instead.");
return self.getKeyPtrContext(key, undefined);
}
pub fn getKeyPtrContext(self: Self, key: K, ctx: Context) ?*K {
return self.getKeyPtrAdapted(key, ctx);
}
pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
if (self.getIndex(key, ctx)) |idx| {
return &self.keys()[idx];
}
return null;
}
/// Get a copy of the actual key associated with adapted key, if present.
pub fn getKey(self: Self, key: K) ?K {
if (@sizeOf(Context) != 0)
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getKeyContext instead.");
return self.getKeyContext(key, undefined);
}
pub fn getKeyContext(self: Self, key: K, ctx: Context) ?K {
return self.getKeyAdapted(key, ctx);
}
pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
if (self.getIndex(key, ctx)) |idx| {
return self.keys()[idx];
}
return null;
}
/// Get an optional pointer to the value associated with key, if present.
pub fn getPtr(self: Self, key: K) ?*V {
if (@sizeOf(Context) != 0)
@ -1948,6 +1995,7 @@ test "std.hash_map getOrPutAdapted" {
try testing.expect(result.found_existing);
try testing.expectEqual(real_keys[i], result.key_ptr.*);
try testing.expectEqual(@as(u64, i) * 2, result.value_ptr.*);
try testing.expectEqual(real_keys[i], map.getKeyAdapted(key_str, AdaptedContext{}).?);
}
}

View File

@ -2860,7 +2860,7 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {
pub fn doNotOptimizeAway(val: anytype) void {
asm volatile (""
:
: [val] "rm" (val)
: [val] "rm" (val),
: "memory"
);
}

View File

@ -2,63 +2,63 @@ usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [number] "{r7}" (@enumToInt(number))
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
: "memory"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1)
[arg1] "{r0}" (arg1),
: "memory"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2)
[arg2] "{r1}" (arg2),
: "memory"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3)
[arg3] "{r2}" (arg3),
: "memory"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4)
[arg4] "{r3}" (arg4),
: "memory"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4),
[arg5] "{r4}" (arg5)
[arg5] "{r4}" (arg5),
: "memory"
);
}
@ -73,14 +73,14 @@ pub fn syscall6(
arg6: usize,
) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [number] "{r7}" (@enumToInt(number)),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4),
[arg5] "{r4}" (arg5),
[arg6] "{r5}" (arg6)
[arg6] "{r5}" (arg6),
: "memory"
);
}
@ -91,7 +91,7 @@ pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags:
pub fn restore() callconv(.Naked) void {
return asm volatile ("svc #0"
:
: [number] "{r7}" (@enumToInt(SYS.sigreturn))
: [number] "{r7}" (@enumToInt(SYS.sigreturn)),
: "memory"
);
}
@ -99,7 +99,7 @@ pub fn restore() callconv(.Naked) void {
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("svc #0"
:
: [number] "{r7}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{r7}" (@enumToInt(SYS.rt_sigreturn)),
: "memory"
);
}

View File

@ -2,63 +2,63 @@ usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [number] "{x8}" (@enumToInt(number))
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
: "memory", "cc"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1)
[arg1] "{x0}" (arg1),
: "memory", "cc"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2)
[arg2] "{x1}" (arg2),
: "memory", "cc"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3)
[arg3] "{x2}" (arg3),
: "memory", "cc"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3),
[arg4] "{x3}" (arg4)
[arg4] "{x3}" (arg4),
: "memory", "cc"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3),
[arg4] "{x3}" (arg4),
[arg5] "{x4}" (arg5)
[arg5] "{x4}" (arg5),
: "memory", "cc"
);
}
@ -73,14 +73,14 @@ pub fn syscall6(
arg6: usize,
) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [ret] "={x0}" (-> usize),
: [number] "{x8}" (@enumToInt(number)),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3),
[arg4] "{x3}" (arg4),
[arg5] "{x4}" (arg5),
[arg6] "{x5}" (arg6)
[arg6] "{x5}" (arg6),
: "memory", "cc"
);
}
@ -93,7 +93,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("svc #0"
:
: [number] "{x8}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
: "memory", "cc"
);
}

View File

@ -2,63 +2,63 @@ usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (@enumToInt(number))
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
: "memory"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1)
[arg1] "{ebx}" (arg1),
: "memory"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1),
[arg2] "{ecx}" (arg2)
[arg2] "{ecx}" (arg2),
: "memory"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1),
[arg2] "{ecx}" (arg2),
[arg3] "{edx}" (arg3)
[arg3] "{edx}" (arg3),
: "memory"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1),
[arg2] "{ecx}" (arg2),
[arg3] "{edx}" (arg3),
[arg4] "{esi}" (arg4)
[arg4] "{esi}" (arg4),
: "memory"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1),
[arg2] "{ecx}" (arg2),
[arg3] "{edx}" (arg3),
[arg4] "{esi}" (arg4),
[arg5] "{edi}" (arg5)
[arg5] "{edi}" (arg5),
: "memory"
);
}
@ -83,24 +83,24 @@ pub fn syscall6(
\\ int $0x80
\\ pop %%ebp
\\ add $4, %%esp
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(number)),
[arg1] "{ebx}" (arg1),
[arg2] "{ecx}" (arg2),
[arg3] "{edx}" (arg3),
[arg4] "{esi}" (arg4),
[arg5] "{edi}" (arg5),
[arg6] "rm" (arg6)
[arg6] "rm" (arg6),
: "memory"
);
}
pub fn socketcall(call: usize, args: [*]usize) usize {
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [ret] "={eax}" (-> usize),
: [number] "{eax}" (@enumToInt(SYS.socketcall)),
[arg1] "{ebx}" (call),
[arg2] "{ecx}" (@ptrToInt(args))
[arg2] "{ecx}" (@ptrToInt(args)),
: "memory"
);
}
@ -111,7 +111,7 @@ pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags:
pub fn restore() callconv(.Naked) void {
return asm volatile ("int $0x80"
:
: [number] "{eax}" (@enumToInt(SYS.sigreturn))
: [number] "{eax}" (@enumToInt(SYS.sigreturn)),
: "memory"
);
}
@ -119,7 +119,7 @@ pub fn restore() callconv(.Naked) void {
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("int $0x80"
:
: [number] "{eax}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{eax}" (@enumToInt(SYS.rt_sigreturn)),
: "memory"
);
}

View File

@ -6,8 +6,8 @@ pub fn syscall0(number: SYS) usize {
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [number] "{$2}" (@enumToInt(number))
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
: "memory", "cc", "$7"
);
}
@ -25,9 +25,9 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
\\ sw $2, 0($4)
\\ sw $3, 4($4)
\\ 2:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(SYS.pipe)),
[fd] "{$4}" (fd)
[fd] "{$4}" (fd),
: "memory", "cc", "$7"
);
}
@ -38,9 +38,9 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1)
[arg1] "{$4}" (arg1),
: "memory", "cc", "$7"
);
}
@ -51,10 +51,10 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2)
[arg2] "{$5}" (arg2),
: "memory", "cc", "$7"
);
}
@ -65,11 +65,11 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2),
[arg3] "{$6}" (arg3)
[arg3] "{$6}" (arg3),
: "memory", "cc", "$7"
);
}
@ -80,12 +80,12 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2),
[arg3] "{$6}" (arg3),
[arg4] "{$7}" (arg4)
[arg4] "{$7}" (arg4),
: "memory", "cc", "$7"
);
}
@ -100,13 +100,13 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2),
[arg3] "{$6}" (arg3),
[arg4] "{$7}" (arg4),
[arg5] "r" (arg5)
[arg5] "r" (arg5),
: "memory", "cc", "$7"
);
}
@ -133,14 +133,14 @@ pub fn syscall6(
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2),
[arg3] "{$6}" (arg3),
[arg4] "{$7}" (arg4),
[arg5] "r" (arg5),
[arg6] "r" (arg6)
[arg6] "r" (arg6),
: "memory", "cc", "$7"
);
}
@ -166,7 +166,7 @@ pub fn syscall7(
\\ blez $7, 1f
\\ subu $2, $0, $2
\\ 1:
: [ret] "={$2}" (-> usize)
: [ret] "={$2}" (-> usize),
: [number] "{$2}" (@enumToInt(number)),
[arg1] "{$4}" (arg1),
[arg2] "{$5}" (arg2),
@ -174,7 +174,7 @@ pub fn syscall7(
[arg4] "{$7}" (arg4),
[arg5] "r" (arg5),
[arg6] "r" (arg6),
[arg7] "r" (arg7)
[arg7] "r" (arg7),
: "memory", "cc", "$7"
);
}
@ -185,7 +185,7 @@ pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags:
pub fn restore() callconv(.Naked) void {
return asm volatile ("syscall"
:
: [number] "{$2}" (@enumToInt(SYS.sigreturn))
: [number] "{$2}" (@enumToInt(SYS.sigreturn)),
: "memory", "cc", "$7"
);
}
@ -193,7 +193,7 @@ pub fn restore() callconv(.Naked) void {
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("syscall"
:
: [number] "{$2}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{$2}" (@enumToInt(SYS.rt_sigreturn)),
: "memory", "cc", "$7"
);
}

View File

@ -6,8 +6,8 @@ pub fn syscall0(number: SYS) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [number] "{r0}" (@enumToInt(number))
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -18,9 +18,9 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1)
[arg1] "{r3}" (arg1),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -31,10 +31,10 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2)
[arg2] "{r4}" (arg2),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -45,11 +45,11 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3)
[arg3] "{r5}" (arg3),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -60,12 +60,12 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4)
[arg4] "{r6}" (arg4),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -76,13 +76,13 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4),
[arg5] "{r7}" (arg5)
[arg5] "{r7}" (arg5),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -101,14 +101,14 @@ pub fn syscall6(
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4),
[arg5] "{r7}" (arg5),
[arg6] "{r8}" (arg6)
[arg6] "{r8}" (arg6),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -121,7 +121,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("sc"
:
: [number] "{r0}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{r0}" (@enumToInt(SYS.rt_sigreturn)),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}

View File

@ -6,8 +6,8 @@ pub fn syscall0(number: SYS) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [number] "{r0}" (@enumToInt(number))
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -18,9 +18,9 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1)
[arg1] "{r3}" (arg1),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -31,10 +31,10 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2)
[arg2] "{r4}" (arg2),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -45,11 +45,11 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3)
[arg3] "{r5}" (arg3),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -60,12 +60,12 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4)
[arg4] "{r6}" (arg4),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -76,13 +76,13 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4),
[arg5] "{r7}" (arg5)
[arg5] "{r7}" (arg5),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -101,14 +101,14 @@ pub fn syscall6(
\\ bns+ 1f
\\ neg 3, 3
\\ 1:
: [ret] "={r3}" (-> usize)
: [ret] "={r3}" (-> usize),
: [number] "{r0}" (@enumToInt(number)),
[arg1] "{r3}" (arg1),
[arg2] "{r4}" (arg2),
[arg3] "{r5}" (arg3),
[arg4] "{r6}" (arg4),
[arg5] "{r7}" (arg5),
[arg6] "{r8}" (arg6)
[arg6] "{r8}" (arg6),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}
@ -121,7 +121,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("sc"
:
: [number] "{r0}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{r0}" (@enumToInt(SYS.rt_sigreturn)),
: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
);
}

View File

@ -2,63 +2,63 @@ usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [number] "{x17}" (@enumToInt(number))
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
: "memory"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1)
[arg1] "{x10}" (arg1),
: "memory"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1),
[arg2] "{x11}" (arg2)
[arg2] "{x11}" (arg2),
: "memory"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1),
[arg2] "{x11}" (arg2),
[arg3] "{x12}" (arg3)
[arg3] "{x12}" (arg3),
: "memory"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1),
[arg2] "{x11}" (arg2),
[arg3] "{x12}" (arg3),
[arg4] "{x13}" (arg4)
[arg4] "{x13}" (arg4),
: "memory"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1),
[arg2] "{x11}" (arg2),
[arg3] "{x12}" (arg3),
[arg4] "{x13}" (arg4),
[arg5] "{x14}" (arg5)
[arg5] "{x14}" (arg5),
: "memory"
);
}
@ -73,14 +73,14 @@ pub fn syscall6(
arg6: usize,
) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
: [ret] "={x10}" (-> usize),
: [number] "{x17}" (@enumToInt(number)),
[arg1] "{x10}" (arg1),
[arg2] "{x11}" (arg2),
[arg3] "{x12}" (arg3),
[arg4] "{x13}" (arg4),
[arg5] "{x14}" (arg5),
[arg6] "{x15}" (arg6)
[arg6] "{x15}" (arg6),
: "memory"
);
}
@ -92,7 +92,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("ecall"
:
: [number] "{x17}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{x17}" (@enumToInt(SYS.rt_sigreturn)),
: "memory"
);
}

View File

@ -14,9 +14,9 @@ pub fn syscall_pipe(fd: *[2]i32) usize {
\\ st %%o1, [%%g3+4]
\\ clr %%o0
\\2:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(SYS.pipe)),
[arg] "r" (fd)
[arg] "r" (fd),
: "memory", "g3"
);
}
@ -38,8 +38,8 @@ pub fn syscall_fork() usize {
\\ dec %%o1
\\ and %%o1, %%o0, %%o0
\\ 2:
: [ret] "={o0}" (-> usize)
: [number] "{g1}" (@enumToInt(SYS.fork))
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(SYS.fork)),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -51,8 +51,8 @@ pub fn syscall0(number: SYS) usize {
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [number] "{g1}" (@enumToInt(number))
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -64,9 +64,9 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1)
[arg1] "{o0}" (arg1),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -78,10 +78,10 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1),
[arg2] "{o1}" (arg2)
[arg2] "{o1}" (arg2),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -93,11 +93,11 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1),
[arg2] "{o1}" (arg2),
[arg3] "{o2}" (arg3)
[arg3] "{o2}" (arg3),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -109,12 +109,12 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1),
[arg2] "{o1}" (arg2),
[arg3] "{o2}" (arg3),
[arg4] "{o3}" (arg4)
[arg4] "{o3}" (arg4),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -126,13 +126,13 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1),
[arg2] "{o1}" (arg2),
[arg3] "{o2}" (arg3),
[arg4] "{o3}" (arg4),
[arg5] "{o4}" (arg5)
[arg5] "{o4}" (arg5),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -152,14 +152,14 @@ pub fn syscall6(
\\ nop
\\ neg %%o0
\\ 1:
: [ret] "={o0}" (-> usize)
: [ret] "={o0}" (-> usize),
: [number] "{g1}" (@enumToInt(number)),
[arg1] "{o0}" (arg1),
[arg2] "{o1}" (arg2),
[arg3] "{o2}" (arg3),
[arg4] "{o3}" (arg4),
[arg5] "{o4}" (arg5),
[arg6] "{o5}" (arg6)
[arg6] "{o5}" (arg6),
: "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7"
);
}
@ -174,7 +174,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.C) void {
return asm volatile ("t 0x6d"
:
: [number] "{g1}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{g1}" (@enumToInt(SYS.rt_sigreturn)),
: "memory", "xcc", "o0", "o1", "o2", "o3", "o4", "o5", "o7"
);
}

View File

@ -30,13 +30,13 @@ fn getDynamicSymbol() [*]elf.Dyn {
\\ call 1f
\\ 1: pop %[ret]
\\ lea _DYNAMIC-1b(%[ret]), %[ret]
: [ret] "=r" (-> [*]elf.Dyn)
: [ret] "=r" (-> [*]elf.Dyn),
),
.x86_64 => asm volatile (
\\ .weak _DYNAMIC
\\ .hidden _DYNAMIC
\\ lea _DYNAMIC(%%rip), %[ret]
: [ret] "=r" (-> [*]elf.Dyn)
: [ret] "=r" (-> [*]elf.Dyn),
),
// Work around the limited offset range of `ldr`
.arm => asm volatile (
@ -47,7 +47,7 @@ fn getDynamicSymbol() [*]elf.Dyn {
\\ b 2f
\\ 1: .word _DYNAMIC-1b
\\ 2:
: [ret] "=r" (-> [*]elf.Dyn)
: [ret] "=r" (-> [*]elf.Dyn),
),
// A simple `adr` is not enough as it has a limited offset range
.aarch64 => asm volatile (
@ -55,13 +55,13 @@ fn getDynamicSymbol() [*]elf.Dyn {
\\ .hidden _DYNAMIC
\\ adrp %[ret], _DYNAMIC
\\ add %[ret], %[ret], #:lo12:_DYNAMIC
: [ret] "=r" (-> [*]elf.Dyn)
: [ret] "=r" (-> [*]elf.Dyn),
),
.riscv64 => asm volatile (
\\ .weak _DYNAMIC
\\ .hidden _DYNAMIC
\\ lla %[ret], _DYNAMIC
: [ret] "=r" (-> [*]elf.Dyn)
: [ret] "=r" (-> [*]elf.Dyn),
),
else => {
@compileError("PIE startup is not yet supported for this target!");

View File

@ -15,8 +15,8 @@ pub fn syscall0(number: SYS) usize {
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [tmp] "{r1}" (buf)
: [ret] "={r0}" (-> usize),
: [tmp] "{r1}" (buf),
: "memory"
);
}
@ -30,9 +30,9 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r1}" (buf),
[arg1] "{r0}" (arg1)
[arg1] "{r0}" (arg1),
: "memory"
);
}
@ -46,10 +46,10 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r2}" (buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2)
[arg2] "{r1}" (arg2),
: "memory"
);
}
@ -63,11 +63,11 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r3}" (buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3)
[arg3] "{r2}" (arg3),
: "memory"
);
}
@ -81,12 +81,12 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r4}" (buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4)
[arg4] "{r3}" (arg4),
: "memory"
);
}
@ -100,13 +100,13 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r5}" (buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4),
[arg5] "{r4}" (arg5)
[arg5] "{r4}" (arg5),
: "memory"
);
}
@ -128,14 +128,14 @@ pub fn syscall6(
\\ ldr r7, [%[tmp]]
\\ svc #0
\\ ldr r7, [%[tmp], #4]
: [ret] "={r0}" (-> usize)
: [ret] "={r0}" (-> usize),
: [tmp] "{r6}" (buf),
[arg1] "{r0}" (arg1),
[arg2] "{r1}" (arg2),
[arg3] "{r2}" (arg3),
[arg4] "{r3}" (arg4),
[arg5] "{r4}" (arg5),
[arg6] "{r5}" (arg6)
[arg6] "{r5}" (arg6),
: "memory"
);
}
@ -148,7 +148,7 @@ pub fn restore() callconv(.Naked) void {
\\ mov r7, %[number]
\\ svc #0
:
: [number] "I" (@enumToInt(SYS.sigreturn))
: [number] "I" (@enumToInt(SYS.sigreturn)),
);
}
@ -157,7 +157,7 @@ pub fn restore_rt() callconv(.Naked) void {
\\ mov r7, %[number]
\\ svc #0
:
: [number] "I" (@enumToInt(SYS.rt_sigreturn))
: [number] "I" (@enumToInt(SYS.rt_sigreturn)),
: "memory"
);
}

View File

@ -131,7 +131,7 @@ pub fn setThreadPointer(addr: usize) void {
// Update the %gs selector
asm volatile ("movl %[gs_val], %%gs"
:
: [gs_val] "r" (gdt_entry_number << 3 | 3)
: [gs_val] "r" (gdt_entry_number << 3 | 3),
);
},
.x86_64 => {
@ -142,7 +142,7 @@ pub fn setThreadPointer(addr: usize) void {
asm volatile (
\\ msr tpidr_el0, %[addr]
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
},
.arm, .thumb => {
@ -153,7 +153,7 @@ pub fn setThreadPointer(addr: usize) void {
asm volatile (
\\ mv tp, %[addr]
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
},
.mips, .mipsel => {
@ -164,21 +164,21 @@ pub fn setThreadPointer(addr: usize) void {
asm volatile (
\\ mr 2, %[addr]
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
},
.powerpc64, .powerpc64le => {
asm volatile (
\\ mr 13, %[addr]
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
},
.sparcv9 => {
asm volatile (
\\ mov %[addr], %%g7
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
},
else => @compileError("Unsupported architecture"),

View File

@ -2,63 +2,63 @@ usingnamespace @import("../bits/linux.zig");
pub fn syscall0(number: SYS) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [number] "{rax}" (@enumToInt(number))
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
: "rcx", "r11", "memory"
);
}
pub fn syscall1(number: SYS, arg1: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1)
[arg1] "{rdi}" (arg1),
: "rcx", "r11", "memory"
);
}
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2)
[arg2] "{rsi}" (arg2),
: "rcx", "r11", "memory"
);
}
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3)
[arg3] "{rdx}" (arg3),
: "rcx", "r11", "memory"
);
}
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4)
[arg4] "{r10}" (arg4),
: "rcx", "r11", "memory"
);
}
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5)
[arg5] "{r8}" (arg5),
: "rcx", "r11", "memory"
);
}
@ -73,14 +73,14 @@ pub fn syscall6(
arg6: usize,
) usize {
return asm volatile ("syscall"
: [ret] "={rax}" (-> usize)
: [ret] "={rax}" (-> usize),
: [number] "{rax}" (@enumToInt(number)),
[arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5),
[arg6] "{r9}" (arg6)
[arg6] "{r9}" (arg6),
: "rcx", "r11", "memory"
);
}
@ -93,7 +93,7 @@ pub const restore = restore_rt;
pub fn restore_rt() callconv(.Naked) void {
return asm volatile ("syscall"
:
: [number] "{rax}" (@enumToInt(SYS.rt_sigreturn))
: [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
: "rcx", "r11", "memory"
);
}

View File

@ -1723,15 +1723,15 @@ pub fn teb() *TEB {
return switch (builtin.target.cpu.arch) {
.i386 => asm volatile (
\\ movl %%fs:0x18, %[ptr]
: [ptr] "=r" (-> *TEB)
: [ptr] "=r" (-> *TEB),
),
.x86_64 => asm volatile (
\\ movq %%gs:0x30, %[ptr]
: [ptr] "=r" (-> *TEB)
: [ptr] "=r" (-> *TEB),
),
.aarch64 => asm volatile (
\\ mov %[ptr], x18
: [ptr] "=r" (-> *TEB)
: [ptr] "=r" (-> *TEB),
),
else => @compileError("unsupported arch"),
};

View File

@ -245,6 +245,13 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
});
defer allocator.free(name);
try out_stream.print("{s:<30} {s}\n", .{ name, option.description });
if (option.enum_options) |enum_options| {
const padding = " " ** 33;
try out_stream.writeAll(padding ++ "Supported Values:\n");
for (enum_options) |enum_option| {
try out_stream.print(padding ++ " {s}\n", .{enum_option});
}
}
}
}

View File

@ -88,7 +88,7 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
asm volatile (
\\mrs %[x], ctr_el0
\\
: [x] "=r" (ctr_el0)
: [x] "=r" (ctr_el0),
);
// The DC and IC instructions must use 64-bit registers so we don't use
// uintptr_t in case this runs in an IPL32 environment.
@ -101,7 +101,7 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
while (addr < end) : (addr += dcache_line_size) {
asm volatile ("dc cvau, %[addr]"
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
}
}
@ -114,7 +114,7 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
while (addr < end) : (addr += icache_line_size) {
asm volatile ("ic ivau, %[addr]"
:
: [addr] "r" (addr)
: [addr] "r" (addr),
);
}
}

View File

@ -98,7 +98,7 @@ fn exit2(code: usize) noreturn {
asm volatile ("syscall"
:
: [number] "{rax}" (231),
[arg1] "{rdi}" (code)
[arg1] "{rdi}" (code),
: "rcx", "r11", "memory"
);
},
@ -106,7 +106,7 @@ fn exit2(code: usize) noreturn {
asm volatile ("svc #0"
:
: [number] "{r7}" (1),
[arg1] "{r0}" (code)
[arg1] "{r0}" (code),
: "memory"
);
},
@ -114,7 +114,7 @@ fn exit2(code: usize) noreturn {
asm volatile ("svc #0"
:
: [number] "{x8}" (93),
[arg1] "{x0}" (code)
[arg1] "{x0}" (code),
: "memory", "cc"
);
},
@ -128,7 +128,7 @@ fn exit2(code: usize) noreturn {
\\push $0
\\syscall
:
: [syscall_number] "{rbp}" (8)
: [syscall_number] "{rbp}" (8),
: "rcx", "r11", "memory"
);
},
@ -137,7 +137,7 @@ fn exit2(code: usize) noreturn {
.aarch64 => {
asm volatile ("svc #0"
:
: [exit] "{x0}" (0x08)
: [exit] "{x0}" (0x08),
: "memory", "cc"
);
},
@ -208,34 +208,34 @@ fn _start() callconv(.Naked) noreturn {
.x86_64 => {
argc_argv_ptr = asm volatile (
\\ xor %%rbp, %%rbp
: [argc] "={rsp}" (-> [*]usize)
: [argc] "={rsp}" (-> [*]usize),
);
},
.i386 => {
argc_argv_ptr = asm volatile (
\\ xor %%ebp, %%ebp
: [argc] "={esp}" (-> [*]usize)
: [argc] "={esp}" (-> [*]usize),
);
},
.aarch64, .aarch64_be, .arm, .armeb, .thumb => {
argc_argv_ptr = asm volatile (
\\ mov fp, #0
\\ mov lr, #0
: [argc] "={sp}" (-> [*]usize)
: [argc] "={sp}" (-> [*]usize),
);
},
.riscv64 => {
argc_argv_ptr = asm volatile (
\\ li s0, 0
\\ li ra, 0
: [argc] "={sp}" (-> [*]usize)
: [argc] "={sp}" (-> [*]usize),
);
},
.mips, .mipsel => {
// The lr is already zeroed on entry, as specified by the ABI.
argc_argv_ptr = asm volatile (
\\ move $fp, $0
: [argc] "={sp}" (-> [*]usize)
: [argc] "={sp}" (-> [*]usize),
);
},
.powerpc => {
@ -246,7 +246,7 @@ fn _start() callconv(.Naked) noreturn {
\\ stwu 1,-16(1)
\\ stw 0, 0(1)
\\ mtlr 0
: [argc] "={r4}" (-> [*]usize)
: [argc] "={r4}" (-> [*]usize),
:
: "r0"
);
@ -259,7 +259,7 @@ fn _start() callconv(.Naked) noreturn {
\\ li 0, 0
\\ stdu 0, -32(1)
\\ mtlr 0
: [argc] "={r4}" (-> [*]usize)
: [argc] "={r4}" (-> [*]usize),
:
: "r0"
);
@ -269,7 +269,7 @@ fn _start() callconv(.Naked) noreturn {
argc_argv_ptr = asm (
\\ mov %%g0, %%i6
\\ add %%o6, 2175, %[argc]
: [argc] "=r" (-> [*]usize)
: [argc] "=r" (-> [*]usize),
);
},
else => @compileError("unsupported arch"),

View File

@ -13,9 +13,9 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
\\ roll $3, %%edi ; roll $13, %%edi
\\ roll $29, %%edi ; roll $19, %%edi
\\ xchgl %%ebx,%%ebx
: [_] "={edx}" (-> usize)
: [_] "={edx}" (-> usize),
: [_] "{eax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default)
[_] "0" (default),
: "cc", "memory"
);
},
@ -24,9 +24,9 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
\\ rolq $3, %%rdi ; rolq $13, %%rdi
\\ rolq $61, %%rdi ; rolq $51, %%rdi
\\ xchgq %%rbx,%%rbx
: [_] "={rdx}" (-> usize)
: [_] "={rdx}" (-> usize),
: [_] "{rax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default)
[_] "0" (default),
: "cc", "memory"
);
},

View File

@ -1,5 +1,5 @@
test "zig fmt: preserves clobbers in inline asm with stray comma" {
try testTransform(
try testCanonical(
\\fn foo() void {
\\ asm volatile (""
\\ : [_] "" (-> type),
@ -13,20 +13,6 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {
\\ );
\\}
\\
,
\\fn foo() void {
\\ asm volatile (""
\\ : [_] "" (-> type)
\\ :
\\ : "clobber"
\\ );
\\ asm volatile (""
\\ :
\\ : [_] "" (type)
\\ : "clobber"
\\ );
\\}
\\
);
}
@ -508,15 +494,15 @@ test "zig fmt: asm expression with comptime content" {
\\pub fn main() void {
\\ asm volatile ("foo" ++ "bar");
\\ asm volatile ("foo" ++ "bar"
\\ : [_] "" (x)
\\ : [_] "" (x),
\\ );
\\ asm volatile ("foo" ++ "bar"
\\ : [_] "" (x)
\\ : [_] "" (y)
\\ : [_] "" (x),
\\ : [_] "" (y),
\\ );
\\ asm volatile ("foo" ++ "bar"
\\ : [_] "" (x)
\\ : [_] "" (y)
\\ : [_] "" (x),
\\ : [_] "" (y),
\\ : "h", "e", "l", "l", "o"
\\ );
\\}
@ -2058,11 +2044,11 @@ test "zig fmt: simple asm" {
\\ );
\\
\\ asm ("not real assembly"
\\ : [a] "x" (x)
\\ : [a] "x" (x),
\\ );
\\ asm ("not real assembly"
\\ : [a] "x" (-> i32)
\\ : [a] "x" (1)
\\ : [a] "x" (-> i32),
\\ : [a] "x" (1),
\\ );
\\ asm ("still not real assembly" ::: "a", "b");
\\}
@ -3712,9 +3698,9 @@ test "zig fmt: inline asm" {
try testCanonical(
\\pub fn syscall1(number: usize, arg1: usize) usize {
\\ return asm volatile ("syscall"
\\ : [ret] "={rax}" (-> usize)
\\ : [ret] "={rax}" (-> usize),
\\ : [number] "{rax}" (number),
\\ [arg1] "{rdi}" (arg1)
\\ [arg1] "{rdi}" (arg1),
\\ : "rcx", "r11"
\\ );
\\}
@ -3817,14 +3803,14 @@ test "zig fmt: inline asm parameter alignment" {
\\ \\ foo
\\ \\ bar
\\ : [_] "" (-> usize),
\\ [_] "" (-> usize)
\\ [_] "" (-> usize),
\\ );
\\ asm volatile (
\\ \\ foo
\\ \\ bar
\\ :
\\ : [_] "" (0),
\\ [_] "" (0)
\\ [_] "" (0),
\\ );
\\ asm volatile (
\\ \\ foo
@ -3834,9 +3820,9 @@ test "zig fmt: inline asm parameter alignment" {
\\ \\ foo
\\ \\ bar
\\ : [_] "" (-> usize),
\\ [_] "" (-> usize)
\\ [_] "" (-> usize),
\\ : [_] "" (0),
\\ [_] "" (0)
\\ [_] "" (0),
\\ : "", ""
\\ );
\\}

View File

@ -1944,13 +1944,13 @@ fn renderAsm(
try renderToken(ais, tree, comma, .newline); // ,
try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));
} else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
try renderAsmOutput(gpa, ais, tree, asm_output, .newline);
try renderAsmOutput(gpa, ais, tree, asm_output, .comma);
ais.popIndent();
ais.setIndentDelta(indent_delta);
ais.popIndent();
return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
} else {
try renderAsmOutput(gpa, ais, tree, asm_output, .newline);
try renderAsmOutput(gpa, ais, tree, asm_output, .comma);
const comma_or_colon = tree.lastToken(asm_output) + 1;
ais.popIndent();
break :colon2 switch (token_tags[comma_or_colon]) {
@ -1976,13 +1976,13 @@ fn renderAsm(
try renderToken(ais, tree, first_token - 1, .newline); // ,
try renderExtraNewlineToken(ais, tree, first_token);
} else if (asm_node.first_clobber == null) {
try renderAsmInput(gpa, ais, tree, asm_input, .newline);
try renderAsmInput(gpa, ais, tree, asm_input, .comma);
ais.popIndent();
ais.setIndentDelta(indent_delta);
ais.popIndent();
return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
} else {
try renderAsmInput(gpa, ais, tree, asm_input, .newline);
try renderAsmInput(gpa, ais, tree, asm_input, .comma);
const comma_or_colon = tree.lastToken(asm_input) + 1;
ais.popIndent();
break :colon3 switch (token_tags[comma_or_colon]) {

View File

@ -543,7 +543,7 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
:
: [leaf_id] "{eax}" (leaf_id),
[subid] "{ecx}" (subid),
[leaf_ptr] "r" (&cpuid_leaf)
[leaf_ptr] "r" (&cpuid_leaf),
: "eax", "ebx", "ecx", "edx"
);
@ -555,7 +555,7 @@ fn getXCR0() u32 {
return asm volatile (
\\ xor %%ecx, %%ecx
\\ xgetbv
: [ret] "={eax}" (-> u32)
: [ret] "={eax}" (-> u32),
:
: "eax", "edx", "ecx"
);

View File

@ -2883,8 +2883,6 @@ fn fnDecl(
};
const fn_name_str_index = try astgen.identAsString(fn_name_token);
try astgen.declareNewName(scope, fn_name_str_index, decl_node, fn_name_token);
// We insert this at the beginning so that its instruction index marks the
// start of the top level declaration.
const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node);
@ -3153,8 +3151,6 @@ fn globalVarDecl(
const name_token = var_decl.ast.mut_token + 1;
const name_str_index = try astgen.identAsString(name_token);
try astgen.declareNewName(scope, name_str_index, node, name_token);
var block_scope: GenZir = .{
.parent = scope,
.decl_node_index = node,
@ -3509,9 +3505,11 @@ fn structDeclInner(
};
defer block_scope.instructions.deinit(gpa);
var namespace: Scope.Namespace = .{ .parent = scope };
var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
defer namespace.decls.deinit(gpa);
try astgen.scanDecls(&namespace, container_decl.ast.members);
var wip_decls: WipDecls = .{};
defer wip_decls.deinit(gpa);
@ -3671,7 +3669,7 @@ fn structDeclInner(
const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
.none
else
try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
fields_data.appendAssumeCapacity(@enumToInt(field_type));
known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
@ -3687,13 +3685,13 @@ fn structDeclInner(
(@as(u32, @boolToInt(unused)) << 31);
if (have_align) {
const align_inst = try expr(&block_scope, &block_scope.base, align_rl, member.ast.align_expr);
const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);
fields_data.appendAssumeCapacity(@enumToInt(align_inst));
}
if (have_value) {
const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
const default_inst = try expr(&block_scope, &block_scope.base, rl, member.ast.value_expr);
const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);
fields_data.appendAssumeCapacity(@enumToInt(default_inst));
} else if (member.comptime_token) |comptime_token| {
return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
@ -3756,7 +3754,7 @@ fn unionDeclInner(
node: ast.Node.Index,
members: []const ast.Node.Index,
layout: std.builtin.TypeInfo.ContainerLayout,
arg_inst: Zir.Inst.Ref,
arg_node: ast.Node.Index,
have_auto_enum: bool,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
@ -3778,9 +3776,16 @@ fn unionDeclInner(
};
defer block_scope.instructions.deinit(gpa);
var namespace: Scope.Namespace = .{ .parent = scope };
var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
defer namespace.decls.deinit(gpa);
try astgen.scanDecls(&namespace, members);
const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
try typeExpr(gz, &namespace.base, arg_node)
else
.none;
var wip_decls: WipDecls = .{};
defer wip_decls.deinit(gpa);
@ -3946,7 +3951,7 @@ fn unionDeclInner(
(@as(u32, @boolToInt(unused)) << 31);
if (have_type and node_tags[member.ast.type_expr] != .@"anytype") {
const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
fields_data.appendAssumeCapacity(@enumToInt(field_type));
}
if (have_align) {
@ -4046,11 +4051,6 @@ fn containerDecl(
// We must not create any types until Sema. Here the goal is only to generate
// ZIR for all the field types, alignments, and default value expressions.
const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
try comptimeExpr(gz, scope, .{ .ty = .type_type }, container_decl.ast.arg)
else
.none;
switch (token_tags[container_decl.ast.main_token]) {
.keyword_struct => {
const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
@ -4059,7 +4059,7 @@ fn containerDecl(
else => unreachable,
} else std.builtin.TypeInfo.ContainerLayout.Auto;
assert(arg_inst == .none);
assert(container_decl.ast.arg == 0);
const result = try structDeclInner(gz, scope, node, container_decl, layout);
return rvalue(gz, rl, result, node);
@ -4073,7 +4073,7 @@ fn containerDecl(
const have_auto_enum = container_decl.ast.enum_token != null;
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, arg_inst, have_auto_enum);
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, have_auto_enum);
return rvalue(gz, rl, result, node);
},
.keyword_enum => {
@ -4140,7 +4140,7 @@ fn containerDecl(
}
total_fields += 1;
if (member.ast.value_expr != 0) {
if (arg_inst == .none) {
if (container_decl.ast.arg == 0) {
return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});
}
values += 1;
@ -4159,7 +4159,7 @@ fn containerDecl(
// must be at least one tag.
return astgen.failNode(node, "enum declarations must have at least one tag", .{});
}
if (counts.nonexhaustive_node != 0 and arg_inst == .none) {
if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) {
return astgen.failNodeNotes(
node,
"non-exhaustive enum missing integer tag type",
@ -4189,9 +4189,16 @@ fn containerDecl(
};
defer block_scope.instructions.deinit(gpa);
var namespace: Scope.Namespace = .{ .parent = scope };
var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
defer namespace.decls.deinit(gpa);
try astgen.scanDecls(&namespace, container_decl.ast.members);
const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
try comptimeExpr(gz, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
else
.none;
var wip_decls: WipDecls = .{};
defer wip_decls.deinit(gpa);
@ -4364,7 +4371,7 @@ fn containerDecl(
},
);
}
const tag_value_inst = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);
fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));
}
@ -4416,9 +4423,13 @@ fn containerDecl(
return rvalue(gz, rl, indexToRef(decl_inst), node);
},
.keyword_opaque => {
var namespace: Scope.Namespace = .{ .parent = scope };
assert(container_decl.ast.arg == 0);
var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
defer namespace.decls.deinit(gpa);
try astgen.scanDecls(&namespace, container_decl.ast.members);
var wip_decls: WipDecls = .{};
defer wip_decls.deinit(gpa);
@ -6352,73 +6363,63 @@ fn identifier(
// Local variables, including function parameters.
const name_str_index = try astgen.identAsString(ident_token);
{
var s = scope;
var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already
var hit_namespace = false;
while (true) switch (s.tag) {
.local_val => {
const local_val = s.cast(Scope.LocalVal).?;
var s = scope;
var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already
var hit_namespace: ast.Node.Index = 0;
while (true) switch (s.tag) {
.local_val => {
const local_val = s.cast(Scope.LocalVal).?;
if (local_val.name == name_str_index) {
local_val.used = true;
// Captures of non-locals need to be emitted as decl_val or decl_ref.
// This *might* be capturable depending on if it is comptime known.
if (!hit_namespace) {
return rvalue(gz, rl, local_val.inst, ident);
}
if (local_val.name == name_str_index) {
local_val.used = true;
// Locals cannot shadow anything, so we do not need to look for ambiguous
// references in this case.
return rvalue(gz, rl, local_val.inst, ident);
}
s = local_val.parent;
},
.local_ptr => {
const local_ptr = s.cast(Scope.LocalPtr).?;
if (local_ptr.name == name_str_index) {
local_ptr.used = true;
if (hit_namespace != 0 and !local_ptr.maybe_comptime) {
return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
try astgen.errNoteNode(hit_namespace, "crosses namespace boundary here", .{}),
});
}
s = local_val.parent;
},
.local_ptr => {
const local_ptr = s.cast(Scope.LocalPtr).?;
if (local_ptr.name == name_str_index) {
local_ptr.used = true;
if (hit_namespace) {
if (local_ptr.maybe_comptime)
break
else
return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{
try astgen.errNoteTok(local_ptr.token_src, "declared here", .{}),
// TODO add crossed function definition here note.
// Maybe add a note to the error about it being because of the var,
// maybe recommend copying it into a const variable. -SpexGuy
});
}
switch (rl) {
.ref, .none_or_ref => return local_ptr.ptr,
else => {
const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
return rvalue(gz, rl, loaded, ident);
},
}
switch (rl) {
.ref, .none_or_ref => return local_ptr.ptr,
else => {
const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
return rvalue(gz, rl, loaded, ident);
},
}
s = local_ptr.parent;
},
.gen_zir => s = s.cast(GenZir).?.parent,
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
// look for ambiguous references to decls
.namespace => {
const ns = s.cast(Scope.Namespace).?;
if (ns.decls.get(name_str_index)) |i| {
if (found_already) |f|
return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{
try astgen.errNoteNode(i, "declared here", .{}),
try astgen.errNoteNode(f, "also declared here", .{}),
})
else
found_already = i;
}
s = local_ptr.parent;
},
.gen_zir => s = s.cast(GenZir).?.parent,
.defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
.namespace => {
const ns = s.cast(Scope.Namespace).?;
if (ns.decls.get(name_str_index)) |i| {
if (found_already) |f| {
return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{
try astgen.errNoteNode(f, "declared here", .{}),
try astgen.errNoteNode(i, "also declared here", .{}),
});
}
hit_namespace = true;
s = ns.parent;
},
.top => break,
};
}
// We found a match but must continue looking for ambiguous references to decls.
found_already = i;
}
hit_namespace = ns.node;
s = ns.parent;
},
.top => break,
};
// We can't look up Decls until Sema because the same ZIR code is supposed to be
// used for multiple generic instantiations, and this may refer to a different Decl
// depending on the scope, determined by the generic instantiation.
// Decl references happen by name rather than ZIR index so that when unrelated
// decls are modified, ZIR code containing references to them can be unmodified.
switch (rl) {
.ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
else => {
@ -8383,7 +8384,7 @@ fn nodeImpliesRuntimeBits(tree: *const ast.Tree, start_node: ast.Node.Index) boo
}
}
/// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of
/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
/// result locations must call this function on their result.
/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
/// If the `ResultLoc` is `ty`, it will coerce the result to the type.
@ -8393,6 +8394,7 @@ fn rvalue(
result: Zir.Inst.Ref,
src_node: ast.Node.Index,
) InnerError!Zir.Inst.Ref {
if (gz.endsWithNoReturn()) return result;
switch (rl) {
.none, .none_or_ref, .coerced_ty => return result,
.discard => {
@ -8941,6 +8943,7 @@ const Scope = struct {
/// Maps string table index to the source location of declaration,
/// for the purposes of reporting name shadowing compile errors.
decls: std.AutoHashMapUnmanaged(u32, ast.Node.Index) = .{},
node: ast.Node.Index,
};
const Top = struct {
@ -10014,53 +10017,6 @@ fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {
return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index;
}
fn declareNewName(
astgen: *AstGen,
start_scope: *Scope,
name_index: u32,
node: ast.Node.Index,
name_token: ast.TokenIndex,
) !void {
const gpa = astgen.gpa;
const token_bytes = astgen.tree.tokenSlice(name_token);
if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
return astgen.failTokNotes(name_token, "name shadows primitive '{s}'", .{
token_bytes,
}, &[_]u32{
try astgen.errNoteTok(name_token, "consider using @\"{s}\" to disambiguate", .{
token_bytes,
}),
});
}
var scope = start_scope;
while (true) {
switch (scope.tag) {
.gen_zir => scope = scope.cast(GenZir).?.parent,
.local_val => scope = scope.cast(Scope.LocalVal).?.parent,
.local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
.defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
.namespace => {
const ns = scope.cast(Scope.Namespace).?;
const gop = try ns.decls.getOrPut(gpa, name_index);
if (gop.found_existing) {
const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(name_index)));
defer gpa.free(name);
return astgen.failNodeNotes(node, "redeclaration of '{s}'", .{
name,
}, &[_]u32{
try astgen.errNoteNode(gop.value_ptr.*, "other declaration here", .{}),
});
}
gop.value_ptr.* = node;
break;
},
.top => break,
}
}
}
fn isPrimitive(name: []const u8) bool {
if (simple_types.get(name) != null) return true;
if (name.len < 2) return false;
@ -10183,3 +10139,56 @@ fn refToIndex(inst: Zir.Inst.Ref) ?Zir.Inst.Index {
return null;
}
}
fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const ast.Node.Index) !void {
const gpa = astgen.gpa;
const tree = astgen.tree;
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
for (members) |member_node| {
const name_token = switch (node_tags[member_node]) {
.fn_decl,
.fn_proto_simple,
.fn_proto_multi,
.fn_proto_one,
.fn_proto,
.global_var_decl,
.local_var_decl,
.simple_var_decl,
.aligned_var_decl,
=> main_tokens[member_node] + 1,
else => continue,
};
const token_bytes = astgen.tree.tokenSlice(name_token);
if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
switch (astgen.failTokNotes(name_token, "name shadows primitive '{s}'", .{
token_bytes,
}, &[_]u32{
try astgen.errNoteTok(name_token, "consider using @\"{s}\" to disambiguate", .{
token_bytes,
}),
})) {
error.AnalysisFail => continue,
error.OutOfMemory => return error.OutOfMemory,
}
}
const name_str_index = try astgen.identAsString(name_token);
const gop = try namespace.decls.getOrPut(gpa, name_str_index);
if (gop.found_existing) {
const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(name_str_index)));
defer gpa.free(name);
switch (astgen.failNodeNotes(member_node, "redeclaration of '{s}'", .{
name,
}, &[_]u32{
try astgen.errNoteNode(gop.value_ptr.*, "other declaration here", .{}),
})) {
error.AnalysisFail => continue,
error.OutOfMemory => return error.OutOfMemory,
}
}
gop.value_ptr.* = member_node;
}
}

View File

@ -2648,7 +2648,10 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void {
undefined;
defer if (data_has_safety_tag) gpa.free(safety_buffer);
const data_ptr = if (data_has_safety_tag)
@ptrCast([*]const u8, safety_buffer.ptr)
if (file.zir.instructions.len == 0)
@as([*]const u8, undefined)
else
@ptrCast([*]const u8, safety_buffer.ptr)
else
@ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);
if (data_has_safety_tag) {

View File

@ -5210,25 +5210,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return error.CodegenFail;
}
usingnamespace switch (arch) {
.i386 => @import("codegen/x86.zig"),
.x86_64 => @import("codegen/x86_64.zig"),
.riscv64 => @import("codegen/riscv64.zig"),
.arm, .armeb => @import("codegen/arm.zig"),
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig"),
else => struct {
pub const Register = enum {
dummy,
const Register = switch (arch) {
.i386 => @import("codegen/x86.zig").Register,
.x86_64 => @import("codegen/x86_64.zig").Register,
.riscv64 => @import("codegen/riscv64.zig").Register,
.arm, .armeb => @import("codegen/arm.zig").Register,
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig").Register,
else => enum {
dummy,
pub fn allocIndex(self: Register) ?u4 {
_ = self;
return null;
}
};
pub const callee_preserved_regs = [_]Register{};
pub fn allocIndex(self: Register) ?u4 {
_ = self;
return null;
}
},
};
const Instruction = switch (arch) {
.riscv64 => @import("codegen/riscv64.zig").Instruction,
.arm, .armeb => @import("codegen/arm.zig").Instruction,
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig").Instruction,
else => void,
};
const Condition = switch (arch) {
.arm, .armeb => @import("codegen/arm.zig").Condition,
else => void,
};
const callee_preserved_regs = switch (arch) {
.i386 => @import("codegen/x86.zig").callee_preserved_regs,
.x86_64 => @import("codegen/x86_64.zig").callee_preserved_regs,
.riscv64 => @import("codegen/riscv64.zig").callee_preserved_regs,
.arm, .armeb => @import("codegen/arm.zig").callee_preserved_regs,
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig").callee_preserved_regs,
else => [_]Register{},
};
const c_abi_int_param_regs = switch (arch) {
.i386 => @import("codegen/x86.zig").c_abi_int_param_regs,
.x86_64 => @import("codegen/x86_64.zig").c_abi_int_param_regs,
.arm, .armeb => @import("codegen/arm.zig").c_abi_int_param_regs,
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig").c_abi_int_param_regs,
else => [_]Register{},
};
const c_abi_int_return_regs = switch (arch) {
.i386 => @import("codegen/x86.zig").c_abi_int_return_regs,
.x86_64 => @import("codegen/x86_64.zig").c_abi_int_return_regs,
.arm, .armeb => @import("codegen/arm.zig").c_abi_int_return_regs,
.aarch64, .aarch64_be, .aarch64_32 => @import("codegen/aarch64.zig").c_abi_int_return_regs,
else => [_]Register{},
};
fn parseRegName(name: []const u8) ?Register {
if (@hasDecl(Register, "parseRegName")) {
return Register.parseRegName(name);

View File

@ -886,11 +886,11 @@ pub const Instruction = union(enum) {
return dataProcessing(cond, .mov, 1, rd, .r0, op2);
}
pub fn bic(cond: Condition, rd: Register, op2: Operand) Instruction {
pub fn bic(cond: Condition, rd: Register, rn: Register, op2: Operand) Instruction {
return dataProcessing(cond, .bic, 0, rd, rn, op2);
}
pub fn bics(cond: Condition, rd: Register, op2: Operand) Instruction {
pub fn bics(cond: Condition, rd: Register, rn: Register, op2: Operand) Instruction {
return dataProcessing(cond, .bic, 1, rd, rn, op2);
}

View File

@ -169,7 +169,7 @@ pub const Object = struct {
const context = llvm.Context.create();
errdefer context.dispose();
initializeLLVMTargets();
initializeLLVMTarget(options.target.cpu.arch);
const root_nameZ = try gpa.dupeZ(u8, options.root_name);
defer gpa.free(root_nameZ);
@ -258,14 +258,6 @@ pub const Object = struct {
gpa.destroy(self);
}
fn initializeLLVMTargets() void {
llvm.initializeAllTargets();
llvm.initializeAllTargetInfos();
llvm.initializeAllTargetMCs();
llvm.initializeAllAsmPrinters();
llvm.initializeAllAsmParsers();
}
fn locPath(
arena: *Allocator,
opt_loc: ?Compilation.EmitLoc,
@ -1960,3 +1952,144 @@ pub const FuncGen = struct {
return self.llvmModule().getIntrinsicDeclaration(id, null, 0);
}
};
fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {
switch (arch) {
.aarch64, .aarch64_be, .aarch64_32 => {
llvm.LLVMInitializeAArch64Target();
llvm.LLVMInitializeAArch64TargetInfo();
llvm.LLVMInitializeAArch64TargetMC();
llvm.LLVMInitializeAArch64AsmPrinter();
llvm.LLVMInitializeAArch64AsmParser();
},
.amdgcn => {
llvm.LLVMInitializeAMDGPUTarget();
llvm.LLVMInitializeAMDGPUTargetInfo();
llvm.LLVMInitializeAMDGPUTargetMC();
llvm.LLVMInitializeAMDGPUAsmPrinter();
llvm.LLVMInitializeAMDGPUAsmParser();
},
.arm, .armeb => {
llvm.LLVMInitializeARMTarget();
llvm.LLVMInitializeARMTargetInfo();
llvm.LLVMInitializeARMTargetMC();
llvm.LLVMInitializeARMAsmPrinter();
llvm.LLVMInitializeARMAsmParser();
},
.avr => {
llvm.LLVMInitializeAVRTarget();
llvm.LLVMInitializeAVRTargetInfo();
llvm.LLVMInitializeAVRTargetMC();
llvm.LLVMInitializeAVRAsmPrinter();
llvm.LLVMInitializeAVRAsmParser();
},
.bpfel, .bpfeb => {
llvm.LLVMInitializeBPFTarget();
llvm.LLVMInitializeBPFTargetInfo();
llvm.LLVMInitializeBPFTargetMC();
llvm.LLVMInitializeBPFAsmPrinter();
llvm.LLVMInitializeBPFAsmParser();
},
.hexagon => {
llvm.LLVMInitializeHexagonTarget();
llvm.LLVMInitializeHexagonTargetInfo();
llvm.LLVMInitializeHexagonTargetMC();
llvm.LLVMInitializeHexagonAsmPrinter();
llvm.LLVMInitializeHexagonAsmParser();
},
.lanai => {
llvm.LLVMInitializeLanaiTarget();
llvm.LLVMInitializeLanaiTargetInfo();
llvm.LLVMInitializeLanaiTargetMC();
llvm.LLVMInitializeLanaiAsmPrinter();
llvm.LLVMInitializeLanaiAsmParser();
},
.mips, .mipsel, .mips64, .mips64el => {
llvm.LLVMInitializeMipsTarget();
llvm.LLVMInitializeMipsTargetInfo();
llvm.LLVMInitializeMipsTargetMC();
llvm.LLVMInitializeMipsAsmPrinter();
llvm.LLVMInitializeMipsAsmParser();
},
.msp430 => {
llvm.LLVMInitializeMSP430Target();
llvm.LLVMInitializeMSP430TargetInfo();
llvm.LLVMInitializeMSP430TargetMC();
llvm.LLVMInitializeMSP430AsmPrinter();
llvm.LLVMInitializeMSP430AsmParser();
},
.nvptx, .nvptx64 => {
llvm.LLVMInitializeNVPTXTarget();
llvm.LLVMInitializeNVPTXTargetInfo();
llvm.LLVMInitializeNVPTXTargetMC();
llvm.LLVMInitializeNVPTXAsmPrinter();
// There is no LLVMInitializeNVPTXAsmParser function available.
},
.powerpc, .powerpcle, .powerpc64, .powerpc64le => {
llvm.LLVMInitializePowerPCTarget();
llvm.LLVMInitializePowerPCTargetInfo();
llvm.LLVMInitializePowerPCTargetMC();
llvm.LLVMInitializePowerPCAsmPrinter();
llvm.LLVMInitializePowerPCAsmParser();
},
.riscv32, .riscv64 => {
llvm.LLVMInitializeRISCVTarget();
llvm.LLVMInitializeRISCVTargetInfo();
llvm.LLVMInitializeRISCVTargetMC();
llvm.LLVMInitializeRISCVAsmPrinter();
llvm.LLVMInitializeRISCVAsmParser();
},
.sparc, .sparcv9, .sparcel => {
llvm.LLVMInitializeSparcTarget();
llvm.LLVMInitializeSparcTargetInfo();
llvm.LLVMInitializeSparcTargetMC();
llvm.LLVMInitializeSparcAsmPrinter();
llvm.LLVMInitializeSparcAsmParser();
},
.s390x => {
llvm.LLVMInitializeSystemZTarget();
llvm.LLVMInitializeSystemZTargetInfo();
llvm.LLVMInitializeSystemZTargetMC();
llvm.LLVMInitializeSystemZAsmPrinter();
llvm.LLVMInitializeSystemZAsmParser();
},
.wasm32, .wasm64 => {
llvm.LLVMInitializeWebAssemblyTarget();
llvm.LLVMInitializeWebAssemblyTargetInfo();
llvm.LLVMInitializeWebAssemblyTargetMC();
llvm.LLVMInitializeWebAssemblyAsmPrinter();
llvm.LLVMInitializeWebAssemblyAsmParser();
},
.i386, .x86_64 => {
llvm.LLVMInitializeX86Target();
llvm.LLVMInitializeX86TargetInfo();
llvm.LLVMInitializeX86TargetMC();
llvm.LLVMInitializeX86AsmPrinter();
llvm.LLVMInitializeX86AsmParser();
},
.xcore => {
llvm.LLVMInitializeXCoreTarget();
llvm.LLVMInitializeXCoreTargetInfo();
llvm.LLVMInitializeXCoreTargetMC();
llvm.LLVMInitializeXCoreAsmPrinter();
// There is no LLVMInitializeXCoreAsmParser function available.
},
.arc => {},
.csky => {},
.r600 => {},
.tce, .tcele => {},
.thumb, .thumbeb => {},
.le32, .le64 => {},
.amdil, .amdil64 => {},
.hsail, .hsail64 => {},
.spir, .spir64 => {},
.kalimba => {},
.shave => {},
.renderscript32 => {},
.renderscript64 => {},
.ve => {},
.spu_2 => {},
.spirv32 => {},
.spirv64 => {},
}
}

View File

@ -597,188 +597,93 @@ pub const Target = opaque {
extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const Target, ErrorMessage: *[*:0]const u8) Bool;
};
extern fn LLVMInitializeAArch64TargetInfo() void;
extern fn LLVMInitializeAMDGPUTargetInfo() void;
extern fn LLVMInitializeARMTargetInfo() void;
extern fn LLVMInitializeAVRTargetInfo() void;
extern fn LLVMInitializeBPFTargetInfo() void;
extern fn LLVMInitializeHexagonTargetInfo() void;
extern fn LLVMInitializeLanaiTargetInfo() void;
extern fn LLVMInitializeMipsTargetInfo() void;
extern fn LLVMInitializeMSP430TargetInfo() void;
extern fn LLVMInitializeNVPTXTargetInfo() void;
extern fn LLVMInitializePowerPCTargetInfo() void;
extern fn LLVMInitializeRISCVTargetInfo() void;
extern fn LLVMInitializeSparcTargetInfo() void;
extern fn LLVMInitializeSystemZTargetInfo() void;
extern fn LLVMInitializeWebAssemblyTargetInfo() void;
extern fn LLVMInitializeX86TargetInfo() void;
extern fn LLVMInitializeXCoreTargetInfo() void;
extern fn LLVMInitializeAArch64Target() void;
extern fn LLVMInitializeAMDGPUTarget() void;
extern fn LLVMInitializeARMTarget() void;
extern fn LLVMInitializeAVRTarget() void;
extern fn LLVMInitializeBPFTarget() void;
extern fn LLVMInitializeHexagonTarget() void;
extern fn LLVMInitializeLanaiTarget() void;
extern fn LLVMInitializeMipsTarget() void;
extern fn LLVMInitializeMSP430Target() void;
extern fn LLVMInitializeNVPTXTarget() void;
extern fn LLVMInitializePowerPCTarget() void;
extern fn LLVMInitializeRISCVTarget() void;
extern fn LLVMInitializeSparcTarget() void;
extern fn LLVMInitializeSystemZTarget() void;
extern fn LLVMInitializeWebAssemblyTarget() void;
extern fn LLVMInitializeX86Target() void;
extern fn LLVMInitializeXCoreTarget() void;
extern fn LLVMInitializeAArch64TargetMC() void;
extern fn LLVMInitializeAMDGPUTargetMC() void;
extern fn LLVMInitializeARMTargetMC() void;
extern fn LLVMInitializeAVRTargetMC() void;
extern fn LLVMInitializeBPFTargetMC() void;
extern fn LLVMInitializeHexagonTargetMC() void;
extern fn LLVMInitializeLanaiTargetMC() void;
extern fn LLVMInitializeMipsTargetMC() void;
extern fn LLVMInitializeMSP430TargetMC() void;
extern fn LLVMInitializeNVPTXTargetMC() void;
extern fn LLVMInitializePowerPCTargetMC() void;
extern fn LLVMInitializeRISCVTargetMC() void;
extern fn LLVMInitializeSparcTargetMC() void;
extern fn LLVMInitializeSystemZTargetMC() void;
extern fn LLVMInitializeWebAssemblyTargetMC() void;
extern fn LLVMInitializeX86TargetMC() void;
extern fn LLVMInitializeXCoreTargetMC() void;
extern fn LLVMInitializeAArch64AsmPrinter() void;
extern fn LLVMInitializeAMDGPUAsmPrinter() void;
extern fn LLVMInitializeARMAsmPrinter() void;
extern fn LLVMInitializeAVRAsmPrinter() void;
extern fn LLVMInitializeBPFAsmPrinter() void;
extern fn LLVMInitializeHexagonAsmPrinter() void;
extern fn LLVMInitializeLanaiAsmPrinter() void;
extern fn LLVMInitializeMipsAsmPrinter() void;
extern fn LLVMInitializeMSP430AsmPrinter() void;
extern fn LLVMInitializeNVPTXAsmPrinter() void;
extern fn LLVMInitializePowerPCAsmPrinter() void;
extern fn LLVMInitializeRISCVAsmPrinter() void;
extern fn LLVMInitializeSparcAsmPrinter() void;
extern fn LLVMInitializeSystemZAsmPrinter() void;
extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
extern fn LLVMInitializeX86AsmPrinter() void;
extern fn LLVMInitializeXCoreAsmPrinter() void;
extern fn LLVMInitializeAArch64AsmParser() void;
extern fn LLVMInitializeAMDGPUAsmParser() void;
extern fn LLVMInitializeARMAsmParser() void;
extern fn LLVMInitializeAVRAsmParser() void;
extern fn LLVMInitializeBPFAsmParser() void;
extern fn LLVMInitializeHexagonAsmParser() void;
extern fn LLVMInitializeLanaiAsmParser() void;
extern fn LLVMInitializeMipsAsmParser() void;
extern fn LLVMInitializeMSP430AsmParser() void;
extern fn LLVMInitializePowerPCAsmParser() void;
extern fn LLVMInitializeRISCVAsmParser() void;
extern fn LLVMInitializeSparcAsmParser() void;
extern fn LLVMInitializeSystemZAsmParser() void;
extern fn LLVMInitializeWebAssemblyAsmParser() void;
extern fn LLVMInitializeX86AsmParser() void;
pub extern fn LLVMInitializeAArch64TargetInfo() void;
pub extern fn LLVMInitializeAMDGPUTargetInfo() void;
pub extern fn LLVMInitializeARMTargetInfo() void;
pub extern fn LLVMInitializeAVRTargetInfo() void;
pub extern fn LLVMInitializeBPFTargetInfo() void;
pub extern fn LLVMInitializeHexagonTargetInfo() void;
pub extern fn LLVMInitializeLanaiTargetInfo() void;
pub extern fn LLVMInitializeMipsTargetInfo() void;
pub extern fn LLVMInitializeMSP430TargetInfo() void;
pub extern fn LLVMInitializeNVPTXTargetInfo() void;
pub extern fn LLVMInitializePowerPCTargetInfo() void;
pub extern fn LLVMInitializeRISCVTargetInfo() void;
pub extern fn LLVMInitializeSparcTargetInfo() void;
pub extern fn LLVMInitializeSystemZTargetInfo() void;
pub extern fn LLVMInitializeWebAssemblyTargetInfo() void;
pub extern fn LLVMInitializeX86TargetInfo() void;
pub extern fn LLVMInitializeXCoreTargetInfo() void;
pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos;
fn LLVMInitializeAllTargetInfos() callconv(.C) void {
LLVMInitializeAArch64TargetInfo();
LLVMInitializeAMDGPUTargetInfo();
LLVMInitializeARMTargetInfo();
LLVMInitializeAVRTargetInfo();
LLVMInitializeBPFTargetInfo();
LLVMInitializeHexagonTargetInfo();
LLVMInitializeLanaiTargetInfo();
LLVMInitializeMipsTargetInfo();
LLVMInitializeMSP430TargetInfo();
LLVMInitializeNVPTXTargetInfo();
LLVMInitializePowerPCTargetInfo();
LLVMInitializeRISCVTargetInfo();
LLVMInitializeSparcTargetInfo();
LLVMInitializeSystemZTargetInfo();
LLVMInitializeWebAssemblyTargetInfo();
LLVMInitializeX86TargetInfo();
LLVMInitializeXCoreTargetInfo();
}
pub const initializeAllTargets = LLVMInitializeAllTargets;
fn LLVMInitializeAllTargets() callconv(.C) void {
LLVMInitializeAArch64Target();
LLVMInitializeAMDGPUTarget();
LLVMInitializeARMTarget();
LLVMInitializeAVRTarget();
LLVMInitializeBPFTarget();
LLVMInitializeHexagonTarget();
LLVMInitializeLanaiTarget();
LLVMInitializeMipsTarget();
LLVMInitializeMSP430Target();
LLVMInitializeNVPTXTarget();
LLVMInitializePowerPCTarget();
LLVMInitializeRISCVTarget();
LLVMInitializeSparcTarget();
LLVMInitializeSystemZTarget();
LLVMInitializeWebAssemblyTarget();
LLVMInitializeX86Target();
LLVMInitializeXCoreTarget();
}
pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs;
fn LLVMInitializeAllTargetMCs() callconv(.C) void {
LLVMInitializeAArch64TargetMC();
LLVMInitializeAMDGPUTargetMC();
LLVMInitializeARMTargetMC();
LLVMInitializeAVRTargetMC();
LLVMInitializeBPFTargetMC();
LLVMInitializeHexagonTargetMC();
LLVMInitializeLanaiTargetMC();
LLVMInitializeMipsTargetMC();
LLVMInitializeMSP430TargetMC();
LLVMInitializeNVPTXTargetMC();
LLVMInitializePowerPCTargetMC();
LLVMInitializeRISCVTargetMC();
LLVMInitializeSparcTargetMC();
LLVMInitializeSystemZTargetMC();
LLVMInitializeWebAssemblyTargetMC();
LLVMInitializeX86TargetMC();
LLVMInitializeXCoreTargetMC();
}
pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters;
fn LLVMInitializeAllAsmPrinters() callconv(.C) void {
LLVMInitializeAArch64AsmPrinter();
LLVMInitializeAMDGPUAsmPrinter();
LLVMInitializeARMAsmPrinter();
LLVMInitializeAVRAsmPrinter();
LLVMInitializeBPFAsmPrinter();
LLVMInitializeHexagonAsmPrinter();
LLVMInitializeLanaiAsmPrinter();
LLVMInitializeMipsAsmPrinter();
LLVMInitializeMSP430AsmPrinter();
LLVMInitializeNVPTXAsmPrinter();
LLVMInitializePowerPCAsmPrinter();
LLVMInitializeRISCVAsmPrinter();
LLVMInitializeSparcAsmPrinter();
LLVMInitializeSystemZAsmPrinter();
LLVMInitializeWebAssemblyAsmPrinter();
LLVMInitializeX86AsmPrinter();
LLVMInitializeXCoreAsmPrinter();
}
pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers;
fn LLVMInitializeAllAsmParsers() callconv(.C) void {
LLVMInitializeAArch64AsmParser();
LLVMInitializeAMDGPUAsmParser();
LLVMInitializeARMAsmParser();
LLVMInitializeAVRAsmParser();
LLVMInitializeBPFAsmParser();
LLVMInitializeHexagonAsmParser();
LLVMInitializeLanaiAsmParser();
LLVMInitializeMipsAsmParser();
LLVMInitializeMSP430AsmParser();
LLVMInitializePowerPCAsmParser();
LLVMInitializeRISCVAsmParser();
LLVMInitializeSparcAsmParser();
LLVMInitializeSystemZAsmParser();
LLVMInitializeWebAssemblyAsmParser();
LLVMInitializeX86AsmParser();
}
pub extern fn LLVMInitializeAArch64Target() void;
pub extern fn LLVMInitializeAMDGPUTarget() void;
pub extern fn LLVMInitializeARMTarget() void;
pub extern fn LLVMInitializeAVRTarget() void;
pub extern fn LLVMInitializeBPFTarget() void;
pub extern fn LLVMInitializeHexagonTarget() void;
pub extern fn LLVMInitializeLanaiTarget() void;
pub extern fn LLVMInitializeMipsTarget() void;
pub extern fn LLVMInitializeMSP430Target() void;
pub extern fn LLVMInitializeNVPTXTarget() void;
pub extern fn LLVMInitializePowerPCTarget() void;
pub extern fn LLVMInitializeRISCVTarget() void;
pub extern fn LLVMInitializeSparcTarget() void;
pub extern fn LLVMInitializeSystemZTarget() void;
pub extern fn LLVMInitializeWebAssemblyTarget() void;
pub extern fn LLVMInitializeX86Target() void;
pub extern fn LLVMInitializeXCoreTarget() void;
pub extern fn LLVMInitializeAArch64TargetMC() void;
pub extern fn LLVMInitializeAMDGPUTargetMC() void;
pub extern fn LLVMInitializeARMTargetMC() void;
pub extern fn LLVMInitializeAVRTargetMC() void;
pub extern fn LLVMInitializeBPFTargetMC() void;
pub extern fn LLVMInitializeHexagonTargetMC() void;
pub extern fn LLVMInitializeLanaiTargetMC() void;
pub extern fn LLVMInitializeMipsTargetMC() void;
pub extern fn LLVMInitializeMSP430TargetMC() void;
pub extern fn LLVMInitializeNVPTXTargetMC() void;
pub extern fn LLVMInitializePowerPCTargetMC() void;
pub extern fn LLVMInitializeRISCVTargetMC() void;
pub extern fn LLVMInitializeSparcTargetMC() void;
pub extern fn LLVMInitializeSystemZTargetMC() void;
pub extern fn LLVMInitializeWebAssemblyTargetMC() void;
pub extern fn LLVMInitializeX86TargetMC() void;
pub extern fn LLVMInitializeXCoreTargetMC() void;
pub extern fn LLVMInitializeAArch64AsmPrinter() void;
pub extern fn LLVMInitializeAMDGPUAsmPrinter() void;
pub extern fn LLVMInitializeARMAsmPrinter() void;
pub extern fn LLVMInitializeAVRAsmPrinter() void;
pub extern fn LLVMInitializeBPFAsmPrinter() void;
pub extern fn LLVMInitializeHexagonAsmPrinter() void;
pub extern fn LLVMInitializeLanaiAsmPrinter() void;
pub extern fn LLVMInitializeMipsAsmPrinter() void;
pub extern fn LLVMInitializeMSP430AsmPrinter() void;
pub extern fn LLVMInitializeNVPTXAsmPrinter() void;
pub extern fn LLVMInitializePowerPCAsmPrinter() void;
pub extern fn LLVMInitializeRISCVAsmPrinter() void;
pub extern fn LLVMInitializeSparcAsmPrinter() void;
pub extern fn LLVMInitializeSystemZAsmPrinter() void;
pub extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
pub extern fn LLVMInitializeX86AsmPrinter() void;
pub extern fn LLVMInitializeXCoreAsmPrinter() void;
pub extern fn LLVMInitializeAArch64AsmParser() void;
pub extern fn LLVMInitializeAMDGPUAsmParser() void;
pub extern fn LLVMInitializeARMAsmParser() void;
pub extern fn LLVMInitializeAVRAsmParser() void;
pub extern fn LLVMInitializeBPFAsmParser() void;
pub extern fn LLVMInitializeHexagonAsmParser() void;
pub extern fn LLVMInitializeLanaiAsmParser() void;
pub extern fn LLVMInitializeMipsAsmParser() void;
pub extern fn LLVMInitializeMSP430AsmParser() void;
pub extern fn LLVMInitializePowerPCAsmParser() void;
pub extern fn LLVMInitializeRISCVAsmParser() void;
pub extern fn LLVMInitializeSparcAsmParser() void;
pub extern fn LLVMInitializeSystemZAsmParser() void;
pub extern fn LLVMInitializeWebAssemblyAsmParser() void;
pub extern fn LLVMInitializeX86AsmParser() void;
extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;

View File

@ -148,7 +148,7 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{},
stub_helper_stubs_start_off: ?u64 = null,
strtab: std.ArrayListUnmanaged(u8) = .{},
strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
got_entries: std.ArrayListUnmanaged(GotIndirectionKey) = .{},
got_entries_map: std.AutoHashMapUnmanaged(GotIndirectionKey, u32) = .{},
@ -938,7 +938,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
{
// Add dyld_stub_binder as the final GOT entry.
const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
.strtab = &self.strtab,
}) orelse unreachable;
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
@ -1966,7 +1966,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
code[9] = 0xff;
code[10] = 0x25;
{
const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
.strtab = &self.strtab,
}) orelse unreachable;
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
@ -2017,7 +2017,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
code[10] = 0xbf;
code[11] = 0xa9;
binder_blk_outer: {
const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
.strtab = &self.strtab,
}) orelse unreachable;
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
@ -2435,7 +2435,7 @@ fn resolveSymbols(self: *MachO) !void {
}
// Fourth pass, handle synthetic symbols and flag any undefined references.
if (self.strtab_dir.getAdapted(@as([]const u8, "___dso_handle"), StringSliceAdapter{
if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringSliceAdapter{
.strtab = &self.strtab,
})) |n_strx| blk: {
const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk;
@ -2985,7 +2985,7 @@ fn setEntryPoint(self: *MachO) !void {
// TODO we should respect the -entry flag passed in by the user to set a custom
// entrypoint. For now, assume default of `_main`.
const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "_main"), StringSliceAdapter{
const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "_main"), StringSliceAdapter{
.strtab = &self.strtab,
}) orelse {
log.err("'_main' export not found", .{});
@ -4616,7 +4616,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});
defer self.base.allocator.free(sym_name);
if (self.strtab_dir.getAdapted(@as([]const u8, sym_name), StringSliceAdapter{
if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringSliceAdapter{
.strtab = &self.strtab,
})) |n_strx| {
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
@ -5858,7 +5858,13 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
}
pub fn makeString(self: *MachO, string: []const u8) !u32 {
if (self.strtab_dir.getAdapted(@as([]const u8, string), StringSliceAdapter{ .strtab = &self.strtab })) |off| {
const gop = try self.strtab_dir.getOrPutContextAdapted(self.base.allocator, @as([]const u8, string), StringSliceAdapter{
.strtab = &self.strtab,
}, StringIndexContext{
.strtab = &self.strtab,
});
if (gop.found_existing) {
const off = gop.key_ptr.*;
log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off });
return off;
}
@ -5871,9 +5877,7 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 {
self.strtab.appendSliceAssumeCapacity(string);
self.strtab.appendAssumeCapacity(0);
try self.strtab_dir.putContext(self.base.allocator, new_off, new_off, StringIndexContext{
.strtab = &self.strtab,
});
gop.key_ptr.* = new_off;
return new_off;
}

View File

@ -656,7 +656,7 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
parsed_rel.where = .local;
parsed_rel.where_index = where_index;
} else {
const n_strx = context.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
.strtab = &context.macho_file.strtab,
}) orelse unreachable;
const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;
@ -717,7 +717,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
const where_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
subtractor = where_index;
} else {
const n_strx = context.macho_file.strtab_dir.getAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
const n_strx = context.macho_file.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), MachO.StringSliceAdapter{
.strtab = &context.macho_file.strtab,
}) orelse unreachable;
const resolv = context.macho_file.symbol_resolver.get(n_strx) orelse unreachable;

View File

@ -203,9 +203,7 @@ const Scope = struct {
/// Check if the global scope contains this name, without looking into the "future", e.g.
/// ignore the preprocessed decl and macro names.
fn containsNow(scope: *Root, name: []const u8) bool {
return isZigPrimitiveType(name) or
scope.sym_table.contains(name) or
scope.macro_table.contains(name);
return scope.sym_table.contains(name) or scope.macro_table.contains(name);
}
/// Check if the global scope contains the name, includes all decls that haven't been translated yet.
@ -495,19 +493,17 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void {
},
else => return,
} else unreachable;
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
const name = if (isZigPrimitiveType(decl_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ decl_name, c.getMangle() }) else decl_name;
const result = try c.unnamed_typedefs.getOrPut(c.gpa, addr);
if (result.found_existing) {
// One typedef can declare multiple names.
// Don't put this one in `decl_table` so it's processed later.
return;
}
result.value_ptr.* = name;
result.value_ptr.* = decl_name;
// Put this typedef in the decl_table to avoid redefinitions.
try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name);
try c.typedefs.put(c.gpa, name, {});
try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), decl_name);
try c.typedefs.put(c.gpa, decl_name, {});
}
}
}
@ -752,10 +748,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
const is_pub = mangled_name == null;
const is_threadlocal = var_decl.getTLSKind() != .None;
const scope = &c.global_scope.base;
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ var_name, c.getMangle() }) else var_name;
const var_decl_loc = var_decl.getLocation();
const qual_type = var_decl.getTypeSourceInfo_getType();
@ -774,7 +766,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
error.UnsupportedTranslation, error.UnsupportedType => {
return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});
},
error.OutOfMemory => |e| return e,
};
@ -833,11 +825,11 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
.is_threadlocal = is_threadlocal,
.linksection_string = linksection_string,
.alignment = zigAlignment(var_decl.getAlignedAttribute(c.clang_context)),
.name = checked_name,
.name = var_name,
.type = type_node,
.init = init_node,
});
return addTopLevelDecl(c, checked_name, node);
return addTopLevelDecl(c, var_name, node);
}
const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
@ -861,11 +853,7 @@ fn transTypeDef(c: *Context, scope: *Scope, typedef_decl: *const clang.TypedefNa
const toplevel = scope.id == .root;
const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
const bare_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name;
var name: []const u8 = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
try c.typedefs.put(c.gpa, name, {});
if (builtin_typedef_map.get(name)) |builtin| {
@ -1535,12 +1523,12 @@ fn transOffsetOfExpr(
/// node -> @bitCast(usize, @intCast(isize, node))
fn usizeCastForWrappingPtrArithmetic(gpa: *mem.Allocator, node: Node) TransError!Node {
const intcast_node = try Tag.int_cast.create(gpa, .{
.lhs = try Tag.identifier.create(gpa, "isize"),
.lhs = try Tag.type.create(gpa, "isize"),
.rhs = node,
});
return Tag.bit_cast.create(gpa, .{
.lhs = try Tag.identifier.create(gpa, "usize"),
.lhs = try Tag.type.create(gpa, "usize"),
.rhs = intcast_node,
});
}
@ -3345,7 +3333,7 @@ fn transSignedArrayAccess(
const then_value = try Tag.add.create(c.arena, .{
.lhs = container_node,
.rhs = try Tag.int_cast.create(c.arena, .{
.lhs = try Tag.identifier.create(c.arena, "usize"),
.lhs = try Tag.type.create(c.arena, "usize"),
.rhs = tmp_ref,
}),
});
@ -3357,7 +3345,7 @@ fn transSignedArrayAccess(
const minuend = container_node;
const signed_size = try Tag.int_cast.create(c.arena, .{
.lhs = try Tag.identifier.create(c.arena, "isize"),
.lhs = try Tag.type.create(c.arena, "isize"),
.rhs = tmp_ref,
});
const to_cast = try Tag.add_wrap.create(c.arena, .{
@ -3365,7 +3353,7 @@ fn transSignedArrayAccess(
.rhs = try Tag.negate.create(c.arena, Tag.one_literal.init()),
});
const bitcast_node = try Tag.bit_cast.create(c.arena, .{
.lhs = try Tag.identifier.create(c.arena, "usize"),
.lhs = try Tag.type.create(c.arena, "usize"),
.rhs = to_cast,
});
const subtrahend = try Tag.bit_not.create(c.arena, bitcast_node);
@ -3421,7 +3409,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
const container_node = try transExpr(c, scope, unwrapped_base, .used);
const rhs = if (is_longlong or is_signed) blk: {
// check if long long first so that signed long long doesn't just become unsigned long long
const typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, subscr_qt, false);
const typeid_node = if (is_longlong) try Tag.type.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, subscr_qt, false);
break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) });
} else try transExpr(c, scope, subscr_expr, .used);
@ -3953,7 +3941,7 @@ fn transFloatingLiteral(c: *Context, scope: *Scope, expr: *const clang.FloatingL
fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node {
// GNU extension of the ternary operator where the middle expression is
// omitted, the conditition itself is returned if it evaluates to true
// omitted, the condition itself is returned if it evaluates to true
const qt = @ptrCast(*const clang.Expr, stmt).getType();
const res_is_bool = qualTypeIsBoolean(qt);
const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
@ -4040,7 +4028,7 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
.then = then_body,
.@"else" = else_body,
});
// Clang inserts ImplicitCast(ToVoid)'s to both rhs and lhs so we don't need to supress the result here.
// Clang inserts ImplicitCast(ToVoid)'s to both rhs and lhs so we don't need to suppress the result here.
return if_node;
}
@ -4671,6 +4659,7 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
if (@ptrCast(*const clang.Decl, typedef_decl).castToNamedDecl()) |named_decl| {
const decl_name = try c.str(named_decl.getName_bytes_begin());
if (c.global_names.get(decl_name)) |_| trans_scope = &c.global_scope.base;
if (builtin_typedef_map.get(decl_name)) |builtin| return Tag.type.create(c.arena, builtin);
}
try transTypeDef(c, trans_scope, typedef_decl);
const name = c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl())).?;
@ -4994,19 +4983,6 @@ pub fn freeErrors(errors: []ClangErrMsg) void {
errors.ptr.delete(errors.len);
}
fn isZigPrimitiveType(name: []const u8) bool {
if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
for (name[1..]) |c| {
switch (c) {
'0'...'9' => {},
else => return false,
}
}
return true;
}
return @import("AstGen.zig").simple_types.has(name);
}
const PatternList = struct {
patterns: []Pattern,
@ -5311,10 +5287,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit);
const name = try c.str(raw_name);
// TODO https://github.com/ziglang/zig/issues/3756
// TODO https://github.com/ziglang/zig/issues/1802
const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ name, c.getMangle() }) else name;
if (scope.containsNow(mangled_name)) {
if (scope.containsNow(name)) {
continue;
}
@ -5328,7 +5301,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
var macro_ctx = MacroCtx{
.source = slice,
.list = tok_list.items,
.name = mangled_name,
.name = name,
.loc = begin_loc,
};
assert(mem.eql(u8, macro_ctx.slice(), name));
@ -5766,7 +5739,8 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
try m.fail(c, "TODO implement function '{s}' in std.zig.c_builtins", .{mangled_name});
return error.ParseError;
}
const identifier = try Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty);
const identifier = try Tag.identifier.create(c.arena, mangled_name);
scope.skipVariableDiscard(identifier.castTag(.identifier).?.data);
return identifier;
},
@ -6055,7 +6029,8 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_
.Identifier => {
const mangled_name = scope.getAlias(m.slice());
if (!allow_fail or c.typedefs.contains(mangled_name)) {
return try Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
if (builtin_typedef_map.get(mangled_name)) |ty| return try Tag.type.create(c.arena, ty);
return try Tag.identifier.create(c.arena, mangled_name);
}
},
.Keyword_void => return try Tag.type.create(c.arena, "c_void"),

View File

@ -801,11 +801,26 @@ const Context = struct {
}
fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {
return addTokenFmt(c, tag, "{s}", .{bytes});
return c.addTokenFmt(tag, "{s}", .{bytes});
}
fn isZigPrimitiveType(name: []const u8) bool {
if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
for (name[1..]) |c| {
switch (c) {
'0'...'9' => {},
else => return false,
}
}
return true;
}
return @import("../AstGen.zig").simple_types.has(name);
}
fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
return addTokenFmt(c, .identifier, "{s}", .{std.zig.fmtId(bytes)});
if (isZigPrimitiveType(bytes))
return c.addTokenFmt(.identifier, "@\"{s}\"", .{bytes});
return c.addTokenFmt(.identifier, "{s}", .{std.zig.fmtId(bytes)});
}
fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
@ -1999,7 +2014,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
members[1] = 0;
for (payload.fields) |field, i| {
const name_tok = try c.addIdentifier(field.name);
const name_tok = try c.addTokenFmt(.identifier, "{s}", .{std.zig.fmtId(field.name)});
_ = try c.addToken(.colon, ":");
const type_expr = try renderNode(c, field.type);
@ -2079,7 +2094,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
.main_token = try c.addToken(.period, "."),
.data = .{
.lhs = lhs,
.rhs = try c.addIdentifier(field_name),
.rhs = try c.addTokenFmt(.identifier, "{s}", .{std.zig.fmtId(field_name)}),
},
});
}

View File

@ -89,6 +89,8 @@ test {
_ = @import("behavior/byval_arg_var.zig");
_ = @import("behavior/call.zig");
_ = @import("behavior/cast_stage1.zig");
// When these tests pass, #9646 can be closed.
// _ = @import("behavior/comptime_memory.zig");
_ = @import("behavior/const_slice_child.zig");
_ = @import("behavior/defer.zig");
_ = @import("behavior/enum.zig");

View File

@ -23,12 +23,12 @@ test "output constraint modifiers" {
// This is only testing compilation.
var a: u32 = 3;
asm volatile (""
: [_] "=m,r" (a)
: [_] "=m,r" (a),
:
: ""
);
asm volatile (""
: [_] "=r,m" (a)
: [_] "=r,m" (a),
:
: ""
);
@ -38,8 +38,8 @@ test "alternative constraints" {
// Make sure we allow commas as a separator for alternative constraints.
var a: u32 = 3;
asm volatile (""
: [_] "=r,m" (a)
: [_] "r,m" (a)
: [_] "=r,m" (a),
: [_] "r,m" (a),
: ""
);
}
@ -47,42 +47,42 @@ test "alternative constraints" {
test "sized integer/float in asm input" {
asm volatile (""
:
: [_] "m" (@as(usize, 3))
: [_] "m" (@as(usize, 3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(i15, -3))
: [_] "m" (@as(i15, -3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(u3, 3))
: [_] "m" (@as(u3, 3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(i3, 3))
: [_] "m" (@as(i3, 3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(u121, 3))
: [_] "m" (@as(u121, 3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(i121, 3))
: [_] "m" (@as(i121, 3)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(f32, 3.17))
: [_] "m" (@as(f32, 3.17)),
: ""
);
asm volatile (""
:
: [_] "m" (@as(f64, 3.17))
: [_] "m" (@as(f64, 3.17)),
: ""
);
}
@ -90,15 +90,15 @@ test "sized integer/float in asm input" {
test "struct/array/union types as input values" {
asm volatile (""
:
: [_] "m" (@as([1]u32, undefined))
: [_] "m" (@as([1]u32, undefined)),
); // fails
asm volatile (""
:
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined))
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
); // fails
asm volatile (""
:
: [_] "m" (@as(union { x: u32, y: u8 }, undefined))
: [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
); // fails
}

View File

@ -0,0 +1,317 @@
const endian = @import("builtin").cpu.arch.endian();
const testing = @import("std").testing;
const ptr_size = @sizeOf(usize);
test "type pun signed and unsigned as single pointer" {
comptime {
var x: u32 = 0;
const y = @ptrCast(*i32, &x);
y.* = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), x);
}
}
test "type pun signed and unsigned as many pointer" {
comptime {
var x: u32 = 0;
const y = @ptrCast([*]i32, &x);
y[0] = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), x);
}
}
test "type pun signed and unsigned as array pointer" {
comptime {
var x: u32 = 0;
const y = @ptrCast(*[1]i32, &x);
y[0] = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), x);
}
}
test "type pun signed and unsigned as offset many pointer" {
comptime {
var x: u32 = 0;
var y = @ptrCast([*]i32, &x);
y -= 10;
y[10] = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), x);
}
}
test "type pun signed and unsigned as array pointer" {
comptime {
var x: u32 = 0;
const y = @ptrCast([*]i32, &x) - 10;
const z: *[15]i32 = y[0..15];
z[10] = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), x);
}
}
test "type pun value and struct" {
comptime {
const StructOfU32 = extern struct { x: u32 };
var inst: StructOfU32 = .{ .x = 0 };
@ptrCast(*i32, &inst.x).* = -1;
try testing.expectEqual(@as(u32, 0xFFFFFFFF), inst.x);
@ptrCast(*i32, &inst).* = -2;
try testing.expectEqual(@as(u32, 0xFFFFFFFE), inst.x);
}
}
fn bigToNativeEndian(comptime T: type, v: T) T {
return if (endian == .Big) v else @byteSwap(T, v);
}
test "type pun endianness" {
comptime {
const StructOfBytes = extern struct { x: [4]u8 };
var inst: StructOfBytes = .{ .x = [4]u8{ 0, 0, 0, 0 } };
const structPtr = @ptrCast(*align(1) u32, &inst);
const arrayPtr = @ptrCast(*align(1) u32, &inst.x);
inst.x[0] = 0xFE;
inst.x[2] = 0xBE;
try testing.expectEqual(bigToNativeEndian(u32, 0xFE00BE00), structPtr.*);
try testing.expectEqual(bigToNativeEndian(u32, 0xFE00BE00), arrayPtr.*);
structPtr.* = bigToNativeEndian(u32, 0xDEADF00D);
try testing.expectEqual(bigToNativeEndian(u32, 0xDEADF00D), structPtr.*);
try testing.expectEqual(bigToNativeEndian(u32, 0xDEADF00D), arrayPtr.*);
try testing.expectEqual(@as(u8, 0xDE), inst.x[0]);
try testing.expectEqual(@as(u8, 0xAD), inst.x[1]);
try testing.expectEqual(@as(u8, 0xF0), inst.x[2]);
try testing.expectEqual(@as(u8, 0x0D), inst.x[3]);
}
}
const Bits = packed struct {
// Note: This struct has only single byte words so it
// doesn't need to be byte swapped.
p0: u1,
p1: u4,
p2: u3,
p3: u2,
p4: u6,
p5: u8,
p6: u7,
p7: u1,
};
const ShuffledBits = packed struct {
p1: u4,
p3: u2,
p7: u1,
p0: u1,
p5: u8,
p2: u3,
p6: u7,
p4: u6,
};
fn shuffle(ptr: usize, comptime From: type, comptime To: type) usize {
if (@sizeOf(From) != @sizeOf(To))
@compileError("Mismatched sizes! " ++ @typeName(From) ++ " and " ++ @typeName(To) ++ " must have the same size!");
const array_len = @divExact(ptr_size, @sizeOf(From));
var result: usize = 0;
const pSource = @ptrCast(*align(1) const [array_len]From, &ptr);
const pResult = @ptrCast(*align(1) [array_len]To, &result);
var i: usize = 0;
while (i < array_len) : (i += 1) {
inline for (@typeInfo(To).Struct.fields) |f| {
@field(pResult[i], f.name) = @field(pSource[i], f.name);
}
}
return result;
}
fn doTypePunBitsTest(as_bits: *Bits) !void {
const as_u32 = @ptrCast(*align(1) u32, as_bits);
const as_bytes = @ptrCast(*[4]u8, as_bits);
as_u32.* = bigToNativeEndian(u32, 0xB0A7DEED);
try testing.expectEqual(@as(u1, 0x00), as_bits.p0);
try testing.expectEqual(@as(u4, 0x08), as_bits.p1);
try testing.expectEqual(@as(u3, 0x05), as_bits.p2);
try testing.expectEqual(@as(u2, 0x03), as_bits.p3);
try testing.expectEqual(@as(u6, 0x29), as_bits.p4);
try testing.expectEqual(@as(u8, 0xDE), as_bits.p5);
try testing.expectEqual(@as(u7, 0x6D), as_bits.p6);
try testing.expectEqual(@as(u1, 0x01), as_bits.p7);
as_bits.p6 = 0x2D;
as_bits.p1 = 0x0F;
try testing.expectEqual(bigToNativeEndian(u32, 0xBEA7DEAD), as_u32.*);
// clobbering one bit doesn't clobber the word
as_bits.p7 = undefined;
try testing.expectEqual(@as(u7, 0x2D), as_bits.p6);
// even when read as a whole
const u = as_u32.*;
_ = u; // u is undefined
try testing.expectEqual(@as(u7, 0x2D), as_bits.p6);
// or if a field which shares the byte is modified
as_bits.p6 = 0x6D;
try testing.expectEqual(@as(u7, 0x6D), as_bits.p6);
// but overwriting the undefined will clear it
as_bytes[3] = 0xAF;
try testing.expectEqual(bigToNativeEndian(u32, 0xBEA7DEAF), as_u32.*);
}
test "type pun bits" {
comptime {
var v: u32 = undefined;
try doTypePunBitsTest(@ptrCast(*Bits, &v));
}
}
const imports = struct {
var global_u32: u32 = 0;
};
// Make sure lazy values work on their own, before getting into more complex tests
test "basic pointer preservation" {
comptime {
const lazy_address = @ptrToInt(&imports.global_u32);
try testing.expectEqual(@ptrToInt(&imports.global_u32), lazy_address);
try testing.expectEqual(&imports.global_u32, @intToPtr(*u32, lazy_address));
}
}
test "byte copy preserves linker value" {
const ct_value = comptime blk: {
const lazy = &imports.global_u32;
var result: *u32 = undefined;
const pSource = @ptrCast(*const [ptr_size]u8, &lazy);
const pResult = @ptrCast(*[ptr_size]u8, &result);
var i: usize = 0;
while (i < ptr_size) : (i += 1) {
pResult[i] = pSource[i];
try testing.expectEqual(pSource[i], pResult[i]);
}
try testing.expectEqual(&imports.global_u32, result);
break :blk result;
};
try testing.expectEqual(&imports.global_u32, ct_value);
}
test "unordered byte copy preserves linker value" {
const ct_value = comptime blk: {
const lazy = &imports.global_u32;
var result: *u32 = undefined;
const pSource = @ptrCast(*const [ptr_size]u8, &lazy);
const pResult = @ptrCast(*[ptr_size]u8, &result);
if (ptr_size > 8) @compileError("This array needs to be expanded for platform with very big pointers");
const shuffled_indices = [_]usize{ 4, 5, 2, 6, 1, 3, 0, 7 };
for (shuffled_indices) |i| {
pResult[i] = pSource[i];
try testing.expectEqual(pSource[i], pResult[i]);
}
try testing.expectEqual(&imports.global_u32, result);
break :blk result;
};
try testing.expectEqual(&imports.global_u32, ct_value);
}
test "shuffle chunks of linker value" {
const lazy_address = @ptrToInt(&imports.global_u32);
const shuffled1_rt = shuffle(lazy_address, Bits, ShuffledBits);
const unshuffled1_rt = shuffle(shuffled1_rt, ShuffledBits, Bits);
try testing.expectEqual(lazy_address, unshuffled1_rt);
const shuffled1_ct = comptime shuffle(lazy_address, Bits, ShuffledBits);
const shuffled1_ct_2 = comptime shuffle(lazy_address, Bits, ShuffledBits);
comptime try testing.expectEqual(shuffled1_ct, shuffled1_ct_2);
const unshuffled1_ct = comptime shuffle(shuffled1_ct, ShuffledBits, Bits);
comptime try testing.expectEqual(lazy_address, unshuffled1_ct);
try testing.expectEqual(shuffled1_ct, shuffled1_rt);
}
test "dance on linker values" {
comptime {
var arr: [2]usize = undefined;
arr[0] = @ptrToInt(&imports.global_u32);
arr[1] = @ptrToInt(&imports.global_u32);
const weird_ptr = @ptrCast([*]Bits, @ptrCast([*]u8, &arr) + @sizeOf(usize) - 3);
try doTypePunBitsTest(&weird_ptr[0]);
if (ptr_size > @sizeOf(Bits))
try doTypePunBitsTest(&weird_ptr[1]);
var arr_bytes = @ptrCast(*[2][ptr_size]u8, &arr);
var rebuilt_bytes: [ptr_size]u8 = undefined;
var i: usize = 0;
while (i < ptr_size - 3) : (i += 1) {
rebuilt_bytes[i] = arr_bytes[0][i];
}
while (i < ptr_size) : (i += 1) {
rebuilt_bytes[i] = arr_bytes[1][i];
}
try testing.expectEqual(&imports.global_u32, @intToPtr(*u32, @bitCast(usize, rebuilt_bytes)));
}
}
test "offset array ptr by element size" {
comptime {
const VirtualStruct = struct { x: u32 };
var arr: [4]VirtualStruct = .{
.{ .x = bigToNativeEndian(u32, 0x0004080c) },
.{ .x = bigToNativeEndian(u32, 0x0105090d) },
.{ .x = bigToNativeEndian(u32, 0x02060a0e) },
.{ .x = bigToNativeEndian(u32, 0x03070b0f) },
};
const address = @ptrToInt(&arr);
try testing.expectEqual(@ptrToInt(&arr[0]), address);
try testing.expectEqual(@ptrToInt(&arr[0]) + 10, address + 10);
try testing.expectEqual(@ptrToInt(&arr[1]), address + @sizeOf(VirtualStruct));
try testing.expectEqual(@ptrToInt(&arr[2]), address + 2 * @sizeOf(VirtualStruct));
try testing.expectEqual(@ptrToInt(&arr[3]), address + @sizeOf(VirtualStruct) * 3);
const secondElement = @intToPtr(*VirtualStruct, @ptrToInt(&arr[0]) + 2 * @sizeOf(VirtualStruct));
try testing.expectEqual(bigToNativeEndian(u32, 0x02060a0e), secondElement.x);
}
}
test "offset instance by field size" {
comptime {
const VirtualStruct = struct { x: u32, y: u32, z: u32, w: u32 };
var inst = VirtualStruct{ .x = 0, .y = 1, .z = 2, .w = 3 };
var ptr = @ptrToInt(&inst);
ptr -= 4;
ptr += @offsetOf(VirtualStruct, "x");
try testing.expectEqual(@as(u32, 0), @intToPtr([*]u32, ptr)[1]);
ptr -= @offsetOf(VirtualStruct, "x");
ptr += @offsetOf(VirtualStruct, "y");
try testing.expectEqual(@as(u32, 1), @intToPtr([*]u32, ptr)[1]);
ptr = ptr - @offsetOf(VirtualStruct, "y") + @offsetOf(VirtualStruct, "z");
try testing.expectEqual(@as(u32, 2), @intToPtr([*]u32, ptr)[1]);
ptr = @ptrToInt(&inst.z) - 4 - @offsetOf(VirtualStruct, "z");
ptr += @offsetOf(VirtualStruct, "w");
try testing.expectEqual(@as(u32, 3), @intToPtr(*u32, ptr + 4).*);
}
}
test "offset field ptr by enclosing array element size" {
comptime {
const VirtualStruct = struct { x: u32 };
var arr: [4]VirtualStruct = .{
.{ .x = bigToNativeEndian(u32, 0x0004080c) },
.{ .x = bigToNativeEndian(u32, 0x0105090d) },
.{ .x = bigToNativeEndian(u32, 0x02060a0e) },
.{ .x = bigToNativeEndian(u32, 0x03070b0f) },
};
var i: usize = 0;
while (i < 4) : (i += 1) {
var ptr: [*]u8 = @ptrCast([*]u8, &arr[0]);
ptr += i;
ptr += @offsetOf(VirtualStruct, "x");
var j: usize = 0;
while (j < 4) : (j += 1) {
const base = ptr + j * @sizeOf(VirtualStruct);
try testing.expectEqual(@intCast(u8, i * 4 + j), base[0]);
}
}
}
}

View File

@ -91,7 +91,8 @@ test "type constructed by comptime function call" {
}
fn SimpleList(comptime L: usize) type {
var T = u8;
var mutable_T = u8;
const T = mutable_T;
return struct {
array: [L]T,
};

View File

@ -506,7 +506,7 @@ test "lazy typeInfo value as generic parameter" {
S.foo(@typeInfo(@TypeOf(.{})));
}
fn A() type {
fn ZA() type {
return struct {
b: B(),
@ -520,7 +520,7 @@ fn A() type {
};
}
test "non-ambiguous reference of shadowed decls" {
try expect(A().B().Self != A().Self);
try expect(ZA().B().Self != ZA().Self);
}
test "use of declaration with same name as primitive" {

View File

@ -984,8 +984,8 @@ pub fn addCases(ctx: *TestContext) !void {
\\};
, &.{
":4:17: error: ambiguous reference",
":1:1: note: declared here",
":2:5: note: also declared here",
":2:5: note: declared here",
":1:1: note: also declared here",
});
ctx.compileError("inner func accessing outer var", linux_x64,
@ -999,8 +999,9 @@ pub fn addCases(ctx: *TestContext) !void {
\\ _ = S;
\\}
, &.{
":5:20: error: 'bar' not accessible from inner function",
":2:9: note: declared here",
":5:20: error: mutable 'bar' not accessible from here",
":2:9: note: declared mutable here",
":3:15: note: crosses namespace boundary here",
});
ctx.compileError("global variable redeclaration", linux_x64,

View File

@ -5342,6 +5342,17 @@ pub fn addCases(ctx: *TestContext) !void {
"tmp.zig:2:1: note: declared here",
});
ctx.objErrStage1("local shadows global that occurs later",
\\pub fn main() void {
\\ var foo = true;
\\ _ = foo;
\\}
\\fn foo() void {}
, &[_][]const u8{
"tmp.zig:2:9: error: local shadows declaration of 'foo'",
"tmp.zig:5:1: note: declared here",
});
ctx.objErrStage1("switch expression - missing enumeration prong",
\\const Number = enum {
\\ One,
@ -8814,4 +8825,17 @@ pub fn addCases(ctx: *TestContext) !void {
, &[_][]const u8{
"error: Unsupported OS",
});
ctx.objErrStage1("attempt to close over comptime variable from outer scope",
\\fn SimpleList(comptime L: usize) type {
\\ var T = u8;
\\ return struct {
\\ array: [L]T,
\\ };
\\}
, &[_][]const u8{
"tmp.zig:4:19: error: mutable 'T' not accessible from here",
"tmp.zig:2:9: note: declared mutable here",
"tmp.zig:3:12: note: crosses namespace boundary here",
});
}

View File

@ -160,24 +160,22 @@ const test_targets = blk: {
// .link_libc = true,
//},
// https://github.com/ziglang/zig/issues/8155
//TestTarget{
// .target = .{
// .cpu_arch = .mips,
// .os_tag = .linux,
// .abi = .none,
// },
//},
TestTarget{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .none,
},
},
// https://github.com/ziglang/zig/issues/8155
//TestTarget{
// .target = .{
// .cpu_arch = .mips,
// .os_tag = .linux,
// .abi = .musl,
// },
// .link_libc = true,
//},
TestTarget{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .musl,
},
.link_libc = true,
},
// https://github.com/ziglang/zig/issues/4927
//TestTarget{
@ -189,24 +187,22 @@ const test_targets = blk: {
// .link_libc = true,
//},
// https://github.com/ziglang/zig/issues/8155
//TestTarget{
// .target = .{
// .cpu_arch = .mipsel,
// .os_tag = .linux,
// .abi = .none,
// },
//},
TestTarget{
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .none,
},
},
// https://github.com/ziglang/zig/issues/8155
//TestTarget{
// .target = .{
// .cpu_arch = .mipsel,
// .os_tag = .linux,
// .abi = .musl,
// },
// .link_libc = true,
//},
TestTarget{
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .musl,
},
.link_libc = true,
},
// https://github.com/ziglang/zig/issues/4927
//TestTarget{

View File

@ -318,8 +318,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
\\pub const Color = struct_Color;
,
\\pub inline fn CLITERAL(type_1: anytype) @TypeOf(type_1) {
\\ return type_1;
\\pub inline fn CLITERAL(@"type": anytype) @TypeOf(@"type") {
\\ return @"type";
\\}
,
\\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ @as(c_int, 200), @as(c_int, 200), @as(c_int, 200), @as(c_int, 255) });
@ -2031,10 +2031,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("shadowing primitive types",
\\unsigned anyerror = 2;
\\#define noreturn _Noreturn
\\typedef enum {
\\ f32,
\\ u32,
\\} BadEnum;
, &[_][]const u8{
\\pub export var anyerror_1: c_uint = 2;
\\pub export var @"anyerror": c_uint = 2;
,
\\pub const noreturn_2 = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
\\pub const @"noreturn" = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
,
\\pub const @"f32": c_int = 0;
\\pub const @"u32": c_int = 1;
\\pub const BadEnum = c_uint;
});
cases.add("floats",