aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--lib/std/build.zig7
-rw-r--r--lib/std/build/emit_raw.zig4
-rw-r--r--lib/std/builtin.zig36
-rw-r--r--lib/std/fs.zig9
-rw-r--r--lib/std/fs/file.zig29
-rw-r--r--lib/std/math.zig5
-rw-r--r--lib/std/math/ceil.zig43
-rw-r--r--lib/std/math/floor.zig43
-rw-r--r--lib/std/math/round.zig50
-rw-r--r--lib/std/math/trunc.zig37
-rw-r--r--lib/std/meta.zig12
-rw-r--r--lib/std/unicode.zig41
-rw-r--r--src-self-hosted/main.zig17
-rw-r--r--src/all_types.hpp6
-rw-r--r--src/analyze.cpp13
-rw-r--r--src/analyze.hpp3
-rw-r--r--src/codegen.cpp1
-rw-r--r--src/ir.cpp198
-rw-r--r--src/ir_print.cpp9
-rw-r--r--src/softfloat_ext.cpp25
-rw-r--r--src/softfloat_ext.hpp9
-rw-r--r--test/compile_errors.zig8
-rw-r--r--test/stage1/behavior.zig1
-rw-r--r--test/stage1/behavior/math.zig122
-rw-r--r--test/stage1/behavior/src.zig17
-rw-r--r--test/stage1/behavior/type.zig23
-rw-r--r--test/stage1/behavior/type_info.zig15
28 files changed, 746 insertions, 38 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8599d01a5d..94219c1631 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -288,6 +288,7 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/target.cpp"
"${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
"${CMAKE_SOURCE_DIR}/src/util.cpp"
+ "${CMAKE_SOURCE_DIR}/src/softfloat_ext.cpp"
"${ZIG_SOURCES_MEM_PROFILE}"
)
set(OPTIMIZED_C_SOURCES
diff --git a/lib/std/build.zig b/lib/std/build.zig
index d98ef71a59..a4d922f2ad 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -2558,3 +2558,10 @@ pub const InstalledFile = struct {
dir: InstallDir,
path: []const u8,
};
+
+test "" {
+ // The only purpose of this test is to get all these untested functions
+ // to be referenced to avoid regression so it is okay to skip some targets.
+ if (comptime std.Target.current.cpu.arch.ptrBitWidth() == 64)
+ std.meta.refAllDecls(@This());
+}
diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig
index 8fd27d6cfc..746b0ac91b 100644
--- a/lib/std/build/emit_raw.zig
+++ b/lib/std/build/emit_raw.zig
@@ -215,3 +215,7 @@ pub const InstallRawStep = struct {
try emitRaw(builder.allocator, full_src_path, full_dest_path);
}
};
+
+test "" {
+ std.meta.refAllDecls(InstallRawStep);
+}
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index af8033ae91..0c7e534bed 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -131,6 +131,15 @@ pub const CallingConvention = enum {
AAPCSVFP,
};
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const SourceLocation = struct {
+ file: [:0]const u8,
+ fn_name: [:0]const u8,
+ line: u32,
+ column: u32,
+};
+
pub const TypeId = @TagType(TypeInfo);
/// This data structure is used by the Zig language code generation and
@@ -157,7 +166,7 @@ pub const TypeInfo = union(enum) {
Fn: Fn,
BoundFn: Fn,
Opaque: void,
- Frame: void,
+ Frame: Frame,
AnyFrame: AnyFrame,
Vector: Vector,
EnumLiteral: void,
@@ -235,8 +244,8 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Struct = struct {
layout: ContainerLayout,
- fields: []StructField,
- decls: []Declaration,
+ fields: []const StructField,
+ decls: []const Declaration,
};
/// This data structure is used by the Zig language code generation and
@@ -256,12 +265,13 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Error = struct {
name: []const u8,
+ /// This field is ignored when using @Type().
value: comptime_int,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
- pub const ErrorSet = ?[]Error;
+ pub const ErrorSet = ?[]const Error;
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
@@ -275,8 +285,8 @@ pub const TypeInfo = union(enum) {
pub const Enum = struct {
layout: ContainerLayout,
tag_type: type,
- fields: []EnumField,
- decls: []Declaration,
+ fields: []const EnumField,
+ decls: []const Declaration,
is_exhaustive: bool,
};
@@ -293,8 +303,8 @@ pub const TypeInfo = union(enum) {
pub const Union = struct {
layout: ContainerLayout,
tag_type: ?type,
- fields: []UnionField,
- decls: []Declaration,
+ fields: []const UnionField,
+ decls: []const Declaration,
};
/// This data structure is used by the Zig language code generation and
@@ -312,7 +322,13 @@ pub const TypeInfo = union(enum) {
is_generic: bool,
is_var_args: bool,
return_type: ?type,
- args: []FnArg,
+ args: []const FnArg,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Frame = struct {
+ function: var,
};
/// This data structure is used by the Zig language code generation and
@@ -352,7 +368,7 @@ pub const TypeInfo = union(enum) {
is_export: bool,
lib_name: ?[]const u8,
return_type: type,
- arg_names: [][]const u8,
+ arg_names: []const []const u8,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 262aa4872d..3ff4819ac5 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1229,14 +1229,9 @@ pub const Dir = struct {
var file = try self.openFile(file_path, .{});
defer file.close();
- const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize);
- if (size > max_bytes) return error.FileTooBig;
+ const stat_size = try file.getEndPos();
- const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
- errdefer allocator.free(buf);
-
- try file.inStream().readNoEof(buf);
- return buf;
+ return file.readAllAllocOptions(allocator, stat_size, max_bytes, alignment, optional_sentinel);
}
pub const DeleteTreeError = error{
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index d950a1cfa4..0a3c1b5ab7 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -209,7 +209,7 @@ pub const File = struct {
/// TODO: integrate with async I/O
pub fn mode(self: File) ModeError!Mode {
if (builtin.os.tag == .windows) {
- return {};
+ return 0;
}
return (try self.stat()).mode;
}
@@ -306,6 +306,33 @@ pub const File = struct {
try os.futimens(self.handle, &times);
}
+ /// On success, caller owns returned buffer.
+ /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+ pub fn readAllAlloc(self: File, allocator: *mem.Allocator, stat_size: u64, max_bytes: usize) ![]u8 {
+ return self.readAllAllocOptions(allocator, stat_size, max_bytes, @alignOf(u8), null);
+ }
+
+ /// On success, caller owns returned buffer.
+ /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
+ /// Allows specifying alignment and a sentinel value.
+ pub fn readAllAllocOptions(
+ self: File,
+ allocator: *mem.Allocator,
+ stat_size: u64,
+ max_bytes: usize,
+ comptime alignment: u29,
+ comptime optional_sentinel: ?u8,
+ ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
+ const size = math.cast(usize, stat_size) catch math.maxInt(usize);
+ if (size > max_bytes) return error.FileTooBig;
+
+ const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);
+ errdefer allocator.free(buf);
+
+ try self.inStream().readNoEof(buf);
+ return buf;
+ }
+
pub const ReadError = os.ReadError;
pub const PReadError = os.PReadError;
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 5cf6d40d8a..799c42846b 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -122,6 +122,11 @@ pub fn forceEval(value: var) void {
const p = @ptrCast(*volatile f64, &x);
p.* = x;
},
+ f128 => {
+ var x: f128 = undefined;
+ const p = @ptrCast(*volatile f128, &x);
+ p.* = x;
+ },
else => {
@compileError("forceEval not implemented for " ++ @typeName(T));
},
diff --git a/lib/std/math/ceil.zig b/lib/std/math/ceil.zig
index b94e13a176..e3b5679318 100644
--- a/lib/std/math/ceil.zig
+++ b/lib/std/math/ceil.zig
@@ -20,6 +20,7 @@ pub fn ceil(x: var) @TypeOf(x) {
return switch (T) {
f32 => ceil32(x),
f64 => ceil64(x),
+ f128 => ceil128(x),
else => @compileError("ceil not implemented for " ++ @typeName(T)),
};
}
@@ -86,9 +87,37 @@ fn ceil64(x: f64) f64 {
}
}
+fn ceil128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112 or x == 0) return x;
+
+ if (u >> 127 != 0) {
+ y = x - math.f128_toint + math.f128_toint - x;
+ } else {
+ y = x + math.f128_toint - math.f128_toint - x;
+ }
+
+ if (e <= 0x3FFF - 1) {
+ math.forceEval(y);
+ if (u >> 127 != 0) {
+ return -0.0;
+ } else {
+ return 1.0;
+ }
+ } else if (y < 0) {
+ return x + y + 1;
+ } else {
+ return x + y;
+ }
+}
+
test "math.ceil" {
expect(ceil(@as(f32, 0.0)) == ceil32(0.0));
expect(ceil(@as(f64, 0.0)) == ceil64(0.0));
+ expect(ceil(@as(f128, 0.0)) == ceil128(0.0));
}
test "math.ceil32" {
@@ -103,6 +132,12 @@ test "math.ceil64" {
expect(ceil64(0.2) == 1.0);
}
+test "math.ceil128" {
+ expect(ceil128(1.3) == 2.0);
+ expect(ceil128(-1.3) == -1.0);
+ expect(ceil128(0.2) == 1.0);
+}
+
test "math.ceil32.special" {
expect(ceil32(0.0) == 0.0);
expect(ceil32(-0.0) == -0.0);
@@ -118,3 +153,11 @@ test "math.ceil64.special" {
expect(math.isNegativeInf(ceil64(-math.inf(f64))));
expect(math.isNan(ceil64(math.nan(f64))));
}
+
+test "math.ceil128.special" {
+ expect(ceil128(0.0) == 0.0);
+ expect(ceil128(-0.0) == -0.0);
+ expect(math.isPositiveInf(ceil128(math.inf(f128))));
+ expect(math.isNegativeInf(ceil128(-math.inf(f128))));
+ expect(math.isNan(ceil128(math.nan(f128))));
+}
diff --git a/lib/std/math/floor.zig b/lib/std/math/floor.zig
index 1eda362e69..565e2911a9 100644
--- a/lib/std/math/floor.zig
+++ b/lib/std/math/floor.zig
@@ -21,6 +21,7 @@ pub fn floor(x: var) @TypeOf(x) {
f16 => floor16(x),
f32 => floor32(x),
f64 => floor64(x),
+ f128 => floor128(x),
else => @compileError("floor not implemented for " ++ @typeName(T)),
};
}
@@ -122,10 +123,38 @@ fn floor64(x: f64) f64 {
}
}
+fn floor128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112 or x == 0) return x;
+
+ if (u >> 127 != 0) {
+ y = x - math.f128_toint + math.f128_toint - x;
+ } else {
+ y = x + math.f128_toint - math.f128_toint - x;
+ }
+
+ if (e <= 0x3FFF - 1) {
+ math.forceEval(y);
+ if (u >> 127 != 0) {
+ return -1.0;
+ } else {
+ return 0.0;
+ }
+ } else if (y > 0) {
+ return x + y - 1;
+ } else {
+ return x + y;
+ }
+}
+
test "math.floor" {
expect(floor(@as(f16, 1.3)) == floor16(1.3));
expect(floor(@as(f32, 1.3)) == floor32(1.3));
expect(floor(@as(f64, 1.3)) == floor64(1.3));
+ expect(floor(@as(f128, 1.3)) == floor128(1.3));
}
test "math.floor16" {
@@ -146,6 +175,12 @@ test "math.floor64" {
expect(floor64(0.2) == 0.0);
}
+test "math.floor128" {
+ expect(floor128(1.3) == 1.0);
+ expect(floor128(-1.3) == -2.0);
+ expect(floor128(0.2) == 0.0);
+}
+
test "math.floor16.special" {
expect(floor16(0.0) == 0.0);
expect(floor16(-0.0) == -0.0);
@@ -169,3 +204,11 @@ test "math.floor64.special" {
expect(math.isNegativeInf(floor64(-math.inf(f64))));
expect(math.isNan(floor64(math.nan(f64))));
}
+
+test "math.floor128.special" {
+ expect(floor128(0.0) == 0.0);
+ expect(floor128(-0.0) == -0.0);
+ expect(math.isPositiveInf(floor128(math.inf(f128))));
+ expect(math.isNegativeInf(floor128(-math.inf(f128))));
+ expect(math.isNan(floor128(math.nan(f128))));
+}
diff --git a/lib/std/math/round.zig b/lib/std/math/round.zig
index dceb3ed770..052c0f7670 100644
--- a/lib/std/math/round.zig
+++ b/lib/std/math/round.zig
@@ -20,6 +20,7 @@ pub fn round(x: var) @TypeOf(x) {
return switch (T) {
f32 => round32(x),
f64 => round64(x),
+ f128 => round128(x),
else => @compileError("round not implemented for " ++ @typeName(T)),
};
}
@@ -90,9 +91,43 @@ fn round64(x_: f64) f64 {
}
}
+fn round128(x_: f128) f128 {
+ var x = x_;
+ const u = @bitCast(u128, x);
+ const e = (u >> 112) & 0x7FFF;
+ var y: f128 = undefined;
+
+ if (e >= 0x3FFF + 112) {
+ return x;
+ }
+ if (u >> 127 != 0) {
+ x = -x;
+ }
+ if (e < 0x3FFF - 1) {
+ math.forceEval(x + math.f64_toint);
+ return 0 * @bitCast(f128, u);
+ }
+
+ y = x + math.f128_toint - math.f128_toint - x;
+ if (y > 0.5) {
+ y = y + x - 1;
+ } else if (y <= -0.5) {
+ y = y + x + 1;
+ } else {
+ y = y + x;
+ }
+
+ if (u >> 127 != 0) {
+ return -y;
+ } else {
+ return y;
+ }
+}
+
test "math.round" {
expect(round(@as(f32, 1.3)) == round32(1.3));
expect(round(@as(f64, 1.3)) == round64(1.3));
+ expect(round(@as(f128, 1.3)) == round128(1.3));
}
test "math.round32" {
@@ -109,6 +144,13 @@ test "math.round64" {
expect(round64(1.8) == 2.0);
}
+test "math.round128" {
+ expect(round128(1.3) == 1.0);
+ expect(round128(-1.3) == -1.0);
+ expect(round128(0.2) == 0.0);
+ expect(round128(1.8) == 2.0);
+}
+
test "math.round32.special" {
expect(round32(0.0) == 0.0);
expect(round32(-0.0) == -0.0);
@@ -124,3 +166,11 @@ test "math.round64.special" {
expect(math.isNegativeInf(round64(-math.inf(f64))));
expect(math.isNan(round64(math.nan(f64))));
}
+
+test "math.round128.special" {
+ expect(round128(0.0) == 0.0);
+ expect(round128(-0.0) == -0.0);
+ expect(math.isPositiveInf(round128(math.inf(f128))));
+ expect(math.isNegativeInf(round128(-math.inf(f128))));
+ expect(math.isNan(round128(math.nan(f128))));
+}
diff --git a/lib/std/math/trunc.zig b/lib/std/math/trunc.zig
index b70f0c6be3..cdd2fa3c6b 100644
--- a/lib/std/math/trunc.zig
+++ b/lib/std/math/trunc.zig
@@ -20,6 +20,7 @@ pub fn trunc(x: var) @TypeOf(x) {
return switch (T) {
f32 => trunc32(x),
f64 => trunc64(x),
+ f128 => trunc128(x),
else => @compileError("trunc not implemented for " ++ @typeName(T)),
};
}
@@ -66,9 +67,31 @@ fn trunc64(x: f64) f64 {
}
}
+fn trunc128(x: f128) f128 {
+ const u = @bitCast(u128, x);
+ var e = @intCast(i32, ((u >> 112) & 0x7FFF)) - 0x3FFF + 16;
+ var m: u128 = undefined;
+
+ if (e >= 112 + 16) {
+ return x;
+ }
+ if (e < 16) {
+ e = 1;
+ }
+
+ m = @as(u128, maxInt(u128)) >> @intCast(u7, e);
+ if (u & m == 0) {
+ return x;
+ } else {
+ math.forceEval(x + 0x1p120);
+ return @bitCast(f128, u & ~m);
+ }
+}
+
test "math.trunc" {
expect(trunc(@as(f32, 1.3)) == trunc32(1.3));
expect(trunc(@as(f64, 1.3)) == trunc64(1.3));
+ expect(trunc(@as(f128, 1.3)) == trunc128(1.3));
}
test "math.trunc32" {
@@ -83,6 +106,12 @@ test "math.trunc64" {
expect(trunc64(0.2) == 0.0);
}
+test "math.trunc128" {
+ expect(trunc128(1.3) == 1.0);
+ expect(trunc128(-1.3) == -1.0);
+ expect(trunc128(0.2) == 0.0);
+}
+
test "math.trunc32.special" {
expect(trunc32(0.0) == 0.0); // 0x3F800000
expect(trunc32(-0.0) == -0.0);
@@ -98,3 +127,11 @@ test "math.trunc64.special" {
expect(math.isNegativeInf(trunc64(-math.inf(f64))));
expect(math.isNan(trunc64(math.nan(f64))));
}
+
+test "math.trunc128.special" {
+ expect(trunc128(0.0) == 0.0);
+ expect(trunc128(-0.0) == -0.0);
+ expect(math.isPositiveInf(trunc128(math.inf(f128))));
+ expect(math.isNegativeInf(trunc128(-math.inf(f128))));
+ expect(math.isNan(trunc128(math.nan(f128))));
+}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 75f507da74..f93f035429 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -250,7 +250,7 @@ test "std.meta.containerLayout" {
testing.expect(containerLayout(U3) == .Extern);
}
-pub fn declarations(comptime T: type) []TypeInfo.Declaration {
+pub fn declarations(comptime T: type) []const TypeInfo.Declaration {
return switch (@typeInfo(T)) {
.Struct => |info| info.decls,
.Enum => |info| info.decls,
@@ -274,7 +274,7 @@ test "std.meta.declarations" {
fn a() void {}
};
- const decls = comptime [_][]TypeInfo.Declaration{
+ const decls = comptime [_][]const TypeInfo.Declaration{
declarations(E1),
declarations(S1),
declarations(U1),
@@ -323,10 +323,10 @@ test "std.meta.declarationInfo" {
}
pub fn fields(comptime T: type) switch (@typeInfo(T)) {
- .Struct => []TypeInfo.StructField,
- .Union => []TypeInfo.UnionField,
- .ErrorSet => []TypeInfo.Error,
- .Enum => []TypeInfo.EnumField,
+ .Struct => []const TypeInfo.StructField,
+ .Union => []const TypeInfo.UnionField,
+ .ErrorSet => []const TypeInfo.Error,
+ .Enum => []const TypeInfo.EnumField,
else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"),
} {
return switch (@typeInfo(T)) {
diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig
index df2e16a4bf..2c88d2ba0c 100644
--- a/lib/std/unicode.zig
+++ b/lib/std/unicode.zig
@@ -235,6 +235,22 @@ pub const Utf8Iterator = struct {
else => unreachable,
}
}
+
+ /// Look ahead at the next n codepoints without advancing the iterator.
+ /// If fewer than n codepoints are available, then return the remainder of the string.
+ pub fn peek(it: *Utf8Iterator, n: usize) []const u8 {
+ const original_i = it.i;
+ defer it.i = original_i;
+
+ var end_ix = original_i;
+ var found: usize = 0;
+ while (found < n) : (found += 1) {
+ const next_codepoint = it.nextCodepointSlice() orelse return it.bytes[original_i..];
+ end_ix += next_codepoint.len;
+ }
+
+ return it.bytes[original_i..end_ix];
+ }
};
pub const Utf16LeIterator = struct {
@@ -451,6 +467,31 @@ fn testMiscInvalidUtf8() void {
testValid("\xee\x80\x80", 0xe000);
}
+test "utf8 iterator peeking" {
+ comptime testUtf8Peeking();
+ testUtf8Peeking();
+}
+
+fn testUtf8Peeking() void {
+ const s = Utf8View.initComptime("noël");
+ var it = s.iterator();
+
+ testing.expect(std.mem.eql(u8, "n", it.nextCodepointSlice().?));
+
+ testing.expect(std.mem.eql(u8, "o", it.peek(1)));
+ testing.expect(std.mem.eql(u8, "oë", it.peek(2)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(3)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(4)));
+ testing.expect(std.mem.eql(u8, "oël", it.peek(10)));
+
+ testing.expect(std.mem.eql(u8, "o", it.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "ë", it.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "l", it.nextCodepointSlice().?));
+ testing.expect(it.nextCodepointSlice() == null);
+
+ testing.expect(std.mem.eql(u8, &[_]u8{}, it.peek(1)));
+}
+
fn testError(bytes: []const u8, expected_err: anyerror) void {
testing.expectError(expected_err, testDecode(bytes));
}
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index eda9dcfc31..6c13f8ab00 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -684,7 +684,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
if (fmt.seen.exists(real_path)) return;
try fmt.seen.put(real_path);
- const source_code = fs.cwd().readFileAlloc(fmt.gpa, real_path, max_src_size) catch |err| switch (err) {
+ const source_file = fs.cwd().openFile(real_path, .{}) catch |err| switch (err) {
error.IsDir, error.AccessDenied => {
var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
defer dir.close();
@@ -705,6 +705,19 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
return;
},
};
+ defer source_file.close();
+
+ const stat = source_file.stat() catch |err| {
+ std.debug.warn("unable to stat '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ };
+
+ const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| {
+ std.debug.warn("unable to read '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ };
defer fmt.gpa.free(source_code);
const tree = std.zig.parse(fmt.gpa, source_code) catch |err| {
@@ -729,7 +742,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
fmt.any_error = true;
}
} else {
- const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{});
+ const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = stat.mode });
defer baf.destroy();
const anything_changed = try std.zig.render(fmt.gpa, baf.stream(), tree);
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 9413ea73a4..88c7e96943 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1827,6 +1827,7 @@ enum BuiltinFnId {
BuiltinFnIdBitSizeof,
BuiltinFnIdWasmMemorySize,
BuiltinFnIdWasmMemoryGrow,
+ BuiltinFnIdSrc,
};
struct BuiltinFnEntry {
@@ -2754,6 +2755,7 @@ enum IrInstSrcId {
IrInstSrcIdSpillEnd,
IrInstSrcIdWasmMemorySize,
IrInstSrcIdWasmMemoryGrow,
+ IrInstSrcIdSrc,
};
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
@@ -3761,6 +3763,10 @@ struct IrInstGenWasmMemoryGrow {
IrInstGen *delta;
};
+struct IrInstSrcSrc {
+ IrInstSrc base;
+};
+
struct IrInstSrcSlice {
IrInstSrc base;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 9062c1fb13..542fbb56ce 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -6012,6 +6012,19 @@ ZigValue *create_const_null(CodeGen *g, ZigType *type) {
return const_val;
}
+void init_const_fn(ZigValue *const_val, ZigFn *fn) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->type = fn->type_entry;
+ const_val->data.x_ptr.special = ConstPtrSpecialFunction;
+ const_val->data.x_ptr.data.fn.fn_entry = fn;
+}
+
+ZigValue *create_const_fn(CodeGen *g, ZigFn *fn) {
+ ZigValue *const_val = g->pass1_arena->create<ZigValue>();
+ init_const_fn(const_val, fn);
+ return const_val;
+}
+
void init_const_float(ZigValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 5899db8a64..d75c967394 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -180,6 +180,9 @@ ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size
void init_const_null(ZigValue *const_val, ZigType *type);
ZigValue *create_const_null(CodeGen *g, ZigType *type);
+void init_const_fn(ZigValue *const_val, ZigFn *fn);
+ZigValue *create_const_fn(CodeGen *g, ZigFn *fn);
+
ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count);
ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f945dd6545..e20d6d60f5 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -8714,6 +8714,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
+ create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
}
static const char *bool_to_str(bool b) {
diff --git a/src/ir.cpp b/src/ir.cpp
index 71e3b473b2..635af397c4 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -13,6 +13,7 @@
#include "os.hpp"
#include "range_set.hpp"
#include "softfloat.hpp"
+#include "softfloat_ext.hpp"
#include "util.hpp"
#include "mem_list.hpp"
#include "all_types.hpp"
@@ -561,6 +562,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
case IrInstSrcIdWasmMemoryGrow:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst));
+ case IrInstSrcIdSrc:
+ return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSrc *>(inst));
}
zig_unreachable();
}
@@ -1627,6 +1630,9 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
return IrInstSrcIdWasmMemoryGrow;
}
+static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) {
+ return IrInstSrcIdSrc;
+}
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
return IrInstGenIdDeclVar;
@@ -5030,6 +5036,11 @@ static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_i
return &instruction->base;
}
+static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
+ IrInstSrcSrc *instruction = ir_build_instruction<IrInstSrcSrc>(irb, scope, source_node);
+
+ return &instruction->base;
+}
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
@@ -7450,6 +7461,11 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
lval, result_loc);
}
+ case BuiltinFnIdSrc:
+ {
+ IrInstSrc *src_inst = ir_build_src(irb, scope, node);
+ return ir_lval_wrap(irb, scope, src_inst, lval, result_loc);
+ }
}
zig_unreachable();
}
@@ -25594,9 +25610,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
break;
}
case ZigTypeIdFnFrame:
- ir_add_error(ira, source_instr,
- buf_sprintf("compiler bug: TODO @typeInfo for async function frames. https://github.com/ziglang/zig/issues/3066"));
- return ErrorSemanticAnalyzeFail;
+ {
+ result = ira->codegen->pass1_arena->create<ZigValue>();
+ result->special = ConstValSpecialStatic;
+ result->type = ir_type_info_get_type(ira, "Frame", nullptr);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
+ result->data.x_struct.fields = fields;
+ ZigFn *fn = type_entry->data.frame.fn;
+ // function: var
+ ensure_field_index(result->type, "function", 0);
+ fields[0] = create_const_fn(ira->codegen, fn);
+ break;
+ }
}
assert(result != nullptr);
@@ -25865,10 +25890,90 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
ZigType *child_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "child", 0);
return get_any_frame_type(ira->codegen, child_type);
}
- case ZigTypeIdErrorSet:
- case ZigTypeIdEnum:
- case ZigTypeIdFnFrame:
case ZigTypeIdEnumLiteral:
+ return ira->codegen->builtin_types.entry_enum_literal;
+ case ZigTypeIdFnFrame: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Frame", nullptr));
+ ZigValue *function = get_const_field(ira, source_instr->source_node, payload, "function", 0);
+ assert(function->type->id == ZigTypeIdFn);
+ ZigFn *fn = function->data.x_ptr.data.fn.fn_entry;
+ return get_fn_frame_type(ira->codegen, fn);
+ }
+ case ZigTypeIdErrorSet: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type->id == ZigTypeIdOptional);
+ ZigValue *slice = payload->data.x_optional;
+ if (slice == nullptr)
+ return ira->codegen->builtin_types.entry_global_error_set;
+ assert(slice->special == ConstValSpecialStatic);
+ assert(is_slice(slice->type));
+ ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
+ Buf bare_name = BUF_INIT;
+ buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name));
+ err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
+ err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
+ err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
+ ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index];
+ assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);;
+ assert(ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val;
+ assert(arr->special == ConstValSpecialStatic);
+ assert(arr->data.x_array.special == ConstArraySpecialNone);
+ ZigValue *len = slice->data.x_struct.fields[slice_len_index];
+ size_t count = bigint_as_usize(&len->data.x_bigint);
+ err_set_type->data.error_set.err_count = count;
+ err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(count);
+ bool *already_set = heap::c_allocator.allocate<bool>(ira->codegen->errors_by_index.length + count);
+ for (size_t i = 0; i < count; i++) {
+ ZigValue *error = &arr->data.x_array.data.s_none.elements[i];
+ assert(error->type == ir_type_info_get_type(ira, "Error", nullptr));
+ ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>();
+ err_entry->decl_node = source_instr->source_node;
+ ZigValue *name_slice = get_const_field(ira, source_instr->source_node, error, "name", 0);
+ ZigValue *name_ptr = name_slice->data.x_struct.fields[slice_ptr_index];
+ ZigValue *name_len = name_slice->data.x_struct.fields[slice_len_index];
+ assert(name_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ assert(name_ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *name_arr = name_ptr->data.x_ptr.data.base_array.array_val;
+ assert(name_arr->special == ConstValSpecialStatic);
+ switch (name_arr->data.x_array.special) {
+ case ConstArraySpecialUndef:
+ return ira->codegen->invalid_inst_gen->value->type;
+ case ConstArraySpecialNone: {
+ buf_resize(&err_entry->name, 0);
+ size_t name_count = bigint_as_usize(&name_len->data.x_bigint);
+ for (size_t j = 0; j < name_count; j++) {
+ ZigValue *ch_val = &name_arr->data.x_array.data.s_none.elements[j];
+ unsigned ch = bigint_as_u32(&ch_val->data.x_bigint);
+ buf_append_char(&err_entry->name, ch);
+ }
+ break;
+ }
+ case ConstArraySpecialBuf:
+ buf_init_from_buf(&err_entry->name, name_arr->data.x_array.data.s_buf);
+ break;
+ }
+ auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry);
+ if (existing_entry) {
+ err_entry->value = existing_entry->value->value;
+ } else {
+ size_t error_value_count = ira->codegen->errors_by_index.length;
+ assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count));
+ err_entry->value = error_value_count;
+ ira->codegen->errors_by_index.append(err_entry);
+ }
+ if (already_set[err_entry->value]) {
+ ir_add_error(ira, source_instr, buf_sprintf("duplicate error: %s", buf_ptr(&err_entry->name)));
+ return ira->codegen->invalid_inst_gen->value->type;
+ } else {
+ already_set[err_entry->value] = true;
+ }
+ err_set_type->data.error_set.errors[i] = err_entry;
+ }
+ return err_set_type;
+ }
+ case ZigTypeIdEnum:
ir_add_error(ira, source_instr, buf_sprintf(
"TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
return ira->codegen->invalid_inst_gen->value->type;
@@ -30263,6 +30368,21 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdSqrt:
f128M_sqrt(in, out);
break;
+ case BuiltinFnIdFabs:
+ f128M_abs(in, out);
+ break;
+ case BuiltinFnIdFloor:
+ f128M_roundToInt(in, softfloat_round_min, false, out);
+ break;
+ case BuiltinFnIdCeil:
+ f128M_roundToInt(in, softfloat_round_max, false, out);
+ break;
+ case BuiltinFnIdTrunc:
+ f128M_trunc(in, out);
+ break;
+ case BuiltinFnIdRound:
+ f128M_roundToInt(in, softfloat_round_near_maxMag, false, out);
+ break;
case BuiltinFnIdNearbyInt:
case BuiltinFnIdSin:
case BuiltinFnIdCos:
@@ -30271,11 +30391,6 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF
case BuiltinFnIdLog:
case BuiltinFnIdLog10:
case BuiltinFnIdLog2:
- case BuiltinFnIdFabs:
- case BuiltinFnIdFloor:
- case BuiltinFnIdCeil:
- case BuiltinFnIdTrunc:
- case BuiltinFnIdRound:
return ir_add_error(ira, source_instr,
buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
float_op_to_name(fop), buf_ptr(&float_type->name)));
@@ -30859,6 +30974,64 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil
return ir_build_spill_end_gen(ira, &instruction->base.base, begin, operand->value->type);
}
+static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instruction) {
+ ZigFn *fn_entry = scope_fn_entry(instruction->base.base.scope);
+ if (fn_entry == nullptr) {
+ ir_add_error(ira, &instruction->base.base, buf_sprintf("@src outside function"));
+ return ira->codegen->invalid_inst_gen;
+ }
+
+ ZigType *u8_ptr = get_pointer_to_type_extra2(
+ ira->codegen, ira->codegen->builtin_types.entry_u8,
+ true, false, PtrLenUnknown,
+ 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, ira->codegen->intern.for_zero_byte());
+ ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
+
+ ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
+ if (type_resolve(ira->codegen, source_location_type, ResolveStatusSizeKnown)) {
+ zig_unreachable();
+ }
+
+ ZigValue *result = ira->codegen->pass1_arena->create<ZigValue>();
+ result->special = ConstValSpecialStatic;
+ result->type = source_location_type;
+
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
+ result->data.x_struct.fields = fields;
+
+ // file: [:0]const u8
+ ensure_field_index(source_location_type, "file", 0);
+ fields[0]->special = ConstValSpecialStatic;
+
+ ZigType *import = instruction->base.base.source_node->owner;
+ Buf *path = import->data.structure.root_struct->path;
+ ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true);
+ fields[0]->type = u8_slice;
+
+ // fn_name: [:0]const u8
+ ensure_field_index(source_location_type, "fn_name", 1);
+ fields[1]->special = ConstValSpecialStatic;
+
+ ZigValue *fn_name = create_const_str_lit(ira->codegen, &fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
+ init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true);
+ fields[1]->type = u8_slice;
+
+ // line: u32
+ ensure_field_index(source_location_type, "line", 2);
+ fields[2]->special = ConstValSpecialStatic;
+ fields[2]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1);
+
+ // column: u32
+ ensure_field_index(source_location_type, "column", 3);
+ fields[3]->special = ConstValSpecialStatic;
+ fields[3]->type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1);
+
+ return ir_const_move(ira, &instruction->base.base, result);
+}
+
static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruction) {
switch (instruction->id) {
case IrInstSrcIdInvalid:
@@ -31130,6 +31303,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
case IrInstSrcIdWasmMemoryGrow:
return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
+ case IrInstSrcIdSrc:
+ return ir_analyze_instruction_src(ira, (IrInstSrcSrc *)instruction);
}
zig_unreachable();
}
@@ -31525,6 +31700,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdAlloca:
case IrInstSrcIdSpillEnd:
case IrInstSrcIdWasmMemorySize:
+ case IrInstSrcIdSrc:
return false;
case IrInstSrcIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index c826d76e03..27bedff47f 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -325,6 +325,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcWasmMemorySize";
case IrInstSrcIdWasmMemoryGrow:
return "SrcWasmMemoryGrow";
+ case IrInstSrcIdSrc:
+ return "SrcSrc";
}
zig_unreachable();
}
@@ -1744,6 +1746,10 @@ static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *
fprintf(irp->f, ")");
}
+static void ir_print_builtin_src(IrPrintSrc *irp, IrInstSrcSrc *instruction) {
+ fprintf(irp->f, "@src()");
+}
+
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
fprintf(irp->f, "@memset(");
ir_print_other_inst_src(irp, instruction->dest_ptr);
@@ -2994,6 +3000,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdWasmMemoryGrow:
ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
break;
+ case IrInstSrcIdSrc:
+ ir_print_builtin_src(irp, (IrInstSrcSrc *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/softfloat_ext.cpp b/src/softfloat_ext.cpp
new file mode 100644
index 0000000000..8408a15116
--- /dev/null
+++ b/src/softfloat_ext.cpp
@@ -0,0 +1,25 @@
+#include "softfloat_ext.hpp"
+
+extern "C" {
+ #include "softfloat.h"
+}
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_sub(&zero_float, aPtr, zPtr);
+ } else {
+ *zPtr = *aPtr;
+ }
+}
+
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
+ float128_t zero_float;
+ ui32_to_f128M(0, &zero_float);
+ if (f128M_lt(aPtr, &zero_float)) {
+ f128M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
+ } else {
+ f128M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
+ }
+} \ No newline at end of file
diff --git a/src/softfloat_ext.hpp b/src/softfloat_ext.hpp
new file mode 100644
index 0000000000..0a1f958933
--- /dev/null
+++ b/src/softfloat_ext.hpp
@@ -0,0 +1,9 @@
+#ifndef ZIG_SOFTFLOAT_EXT_HPP
+#define ZIG_SOFTFLOAT_EXT_HPP
+
+#include "softfloat_types.h"
+
+void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
+void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
+
+#endif \ No newline at end of file
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 278d66ab9f..3f898cc337 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,14 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add("@src outside function",
+ \\comptime {
+ \\ @src();
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:5: error: @src outside function",
+ });
+
cases.add("call assigned to constant",
\\const Foo = struct {
\\ x: i32,
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index 1620aa52df..8c567fa99f 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -131,4 +131,5 @@ comptime {
}
_ = @import("behavior/while.zig");
_ = @import("behavior/widening.zig");
+ _ = @import("behavior/src.zig");
}
diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig
index 1d361494eb..b13b1ce1e0 100644
--- a/test/stage1/behavior/math.zig
+++ b/test/stage1/behavior/math.zig
@@ -634,6 +634,128 @@ fn testSqrt(comptime T: type, x: T) void {
expect(@sqrt(x * x) == x);
}
+test "@fabs" {
+ testFabs(f128, 12.0);
+ comptime testFabs(f128, 12.0);
+ testFabs(f64, 12.0);
+ comptime testFabs(f64, 12.0);
+ testFabs(f32, 12.0);
+ comptime testFabs(f32, 12.0);
+ testFabs(f16, 12.0);
+ comptime testFabs(f16, 12.0);
+
+ const x = 14.0;
+ const y = -x;
+ const z = @fabs(y);
+ comptime expectEqual(x, z);
+}
+
+fn testFabs(comptime T: type, x: T) void {
+ const y = -x;
+ const z = @fabs(y);
+ expectEqual(x, z);
+}
+
+test "@floor" {
+ // FIXME: Generates a floorl function call
+ // testFloor(f128, 12.0);
+ comptime testFloor(f128, 12.0);
+ testFloor(f64, 12.0);
+ comptime testFloor(f64, 12.0);
+ testFloor(f32, 12.0);
+ comptime testFloor(f32, 12.0);
+ testFloor(f16, 12.0);
+ comptime testFloor(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.7;
+ const z = @floor(y);
+ comptime expectEqual(x, z);
+}
+
+fn testFloor(comptime T: type, x: T) void {
+ const y = x + 0.6;
+ const z = @floor(y);
+ expectEqual(x, z);
+}
+
+test "@ceil" {
+ // FIXME: Generates a ceill function call
+ //testCeil(f128, 12.0);
+ comptime testCeil(f128, 12.0);
+ testCeil(f64, 12.0);
+ comptime testCeil(f64, 12.0);
+ testCeil(f32, 12.0);
+ comptime testCeil(f32, 12.0);
+ testCeil(f16, 12.0);
+ comptime testCeil(f16, 12.0);
+
+ const x = 14.0;
+ const y = x - 0.7;
+ const z = @ceil(y);
+ comptime expectEqual(x, z);
+}
+
+fn testCeil(comptime T: type, x: T) void {
+ const y = x - 0.8;
+ const z = @ceil(y);
+ expectEqual(x, z);
+}
+
+test "@trunc" {
+ // FIXME: Generates a truncl function call
+ //testTrunc(f128, 12.0);
+ comptime testTrunc(f128, 12.0);
+ testTrunc(f64, 12.0);
+ comptime testTrunc(f64, 12.0);
+ testTrunc(f32, 12.0);
+ comptime testTrunc(f32, 12.0);
+ testTrunc(f16, 12.0);
+ comptime testTrunc(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.7;
+ const z = @trunc(y);
+ comptime expectEqual(x, z);
+}
+
+fn testTrunc(comptime T: type, x: T) void {
+ {
+ const y = x + 0.8;
+ const z = @trunc(y);
+ expectEqual(x, z);
+ }
+
+ {
+ const y = -x - 0.8;
+ const z = @trunc(y);
+ expectEqual(-x, z);
+ }
+}
+
+test "@round" {
+ // FIXME: Generates a roundl function call
+ //testRound(f128, 12.0);
+ comptime testRound(f128, 12.0);
+ testRound(f64, 12.0);
+ comptime testRound(f64, 12.0);
+ testRound(f32, 12.0);
+ comptime testRound(f32, 12.0);
+ testRound(f16, 12.0);
+ comptime testRound(f16, 12.0);
+
+ const x = 14.0;
+ const y = x + 0.4;
+ const z = @round(y);
+ comptime expectEqual(x, z);
+}
+
+fn testRound(comptime T: type, x: T) void {
+ const y = x - 0.5;
+ const z = @round(y);
+ expectEqual(x, z);
+}
+
test "comptime_int param and return" {
const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
expect(a == 137114567242441932203689521744947848950);
diff --git a/test/stage1/behavior/src.zig b/test/stage1/behavior/src.zig
new file mode 100644
index 0000000000..27fa144e54
--- /dev/null
+++ b/test/stage1/behavior/src.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "@src" {
+ doTheTest();
+}
+
+fn doTheTest() void {
+ const src = @src();
+
+ expect(src.line == 9);
+ expect(src.column == 17);
+ expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
+ expect(std.mem.endsWith(u8, src.file, "src.zig"));
+ expect(src.fn_name[src.fn_name.len] == 0);
+ expect(src.file[src.file.len] == 0);
+}
diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig
index 2860229cb8..f21e9f1ce9 100644
--- a/test/stage1/behavior/type.zig
+++ b/test/stage1/behavior/type.zig
@@ -213,3 +213,26 @@ test "Type.AnyFrame" {
anyframe->anyframe->u8,
});
}
+
+test "Type.EnumLiteral" {
+ testTypes(&[_]type{
+ @TypeOf(.Dummy),
+ });
+}
+
+fn add(a: i32, b: i32) i32 {
+ return a + b;
+}
+
+test "Type.Frame" {
+ testTypes(&[_]type{
+ @Frame(add),
+ });
+}
+
+test "Type.ErrorSet" {
+ // error sets don't compare equal so just check if they compile
+ _ = @Type(@typeInfo(error{}));
+ _ = @Type(@typeInfo(error{A}));
+ _ = @Type(@typeInfo(error{ A, B, C }));
+}
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
index c897276f83..41301f290d 100644
--- a/test/stage1/behavior/type_info.zig
+++ b/test/stage1/behavior/type_info.zig
@@ -202,7 +202,7 @@ fn testUnion() void {
expect(typeinfo_info.Union.fields[4].enum_field != null);
expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
- expect(typeinfo_info.Union.decls.len == 20);
+ expect(typeinfo_info.Union.decls.len == 21);
const TestNoTagUnion = union {
Foo: void,
@@ -389,3 +389,16 @@ test "defaut value for a var-typed field" {
const S = struct { x: var };
expect(@typeInfo(S).Struct.fields[0].default_value == null);
}
+
+fn add(a: i32, b: i32) i32 {
+ return a + b;
+}
+
+test "type info for async frames" {
+ switch (@typeInfo(@Frame(add))) {
+ .Frame => |frame| {
+ expect(frame.function == add);
+ },
+ else => unreachable,
+ }
+}