Skip to content

Commit 7bd0500

Browse files
committed
Merge remote-tracking branch 'origin/master' into register-allocation
2 parents 8e425c0 + 0e1c720 commit 7bd0500

File tree

17 files changed

+1883
-1218
lines changed

17 files changed

+1883
-1218
lines changed

ci/azure/linux_script

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ sudo apt-get update -q
1212

1313
sudo apt-get remove -y llvm-*
1414
sudo rm -rf /usr/local/*
15-
sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-7 ninja-build
15+
sudo apt-get install -y libxml2-dev libclang-10-dev llvm-10 llvm-10-dev liblld-10-dev cmake s3cmd gcc-7 g++-7 ninja-build tidy
1616

1717
QEMUBASE="qemu-linux-x86_64-5.0.0-49ee115552"
1818
wget https://ziglang.org/deps/$QEMUBASE.tar.xz
@@ -51,6 +51,10 @@ cd build
5151
cmake .. -DCMAKE_BUILD_TYPE=Release -GNinja
5252
ninja install
5353
./zig build test -Denable-qemu -Denable-wasmtime
54+
55+
# look for HTML errors
56+
tidy -qe ../zig-cache/langref.html
57+
5458
VERSION="$(./zig version)"
5559

5660
if [ "${BUILD_REASON}" != "PullRequest" ]; then

doc/langref.html.in

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@
9797
margin: auto;
9898
}
9999

100-
#index {
100+
#toc {
101101
padding: 0 1em;
102102
}
103103

104104
@media screen and (min-width: 1025px) {
105105
#main-wrapper {
106106
flex-direction: row;
107107
}
108-
#contents-wrapper, #index {
108+
#contents-wrapper, #toc {
109109
overflow: auto;
110110
}
111111
}
@@ -181,15 +181,15 @@
181181
</head>
182182
<body>
183183
<div id="main-wrapper">
184-
<div id="index">
184+
<div id="toc">
185185
<a href="https://ziglang.org/documentation/0.1.1/">0.1.1</a> |
186186
<a href="https://ziglang.org/documentation/0.2.0/">0.2.0</a> |
187187
<a href="https://ziglang.org/documentation/0.3.0/">0.3.0</a> |
188188
<a href="https://ziglang.org/documentation/0.4.0/">0.4.0</a> |
189189
<a href="https://ziglang.org/documentation/0.5.0/">0.5.0</a> |
190190
<a href="https://ziglang.org/documentation/0.6.0/">0.6.0</a> |
191191
master
192-
<h1>Index</h1>
192+
<h1>Contents</h1>
193193
{#nav#}
194194
</div>
195195
<div id="contents-wrapper"><div id="contents">
@@ -3861,6 +3861,48 @@ test "if error union" {
38613861
unreachable;
38623862
}
38633863
}
3864+
3865+
test "if error union with optional" {
3866+
// If expressions test for errors before unwrapping optionals.
3867+
// The |optional_value| capture's type is ?u32.
3868+
3869+
const a: anyerror!?u32 = 0;
3870+
if (a) |optional_value| {
3871+
assert(optional_value.? == 0);
3872+
} else |err| {
3873+
unreachable;
3874+
}
3875+
3876+
const b: anyerror!?u32 = null;
3877+
if (b) |optional_value| {
3878+
assert(optional_value == null);
3879+
} else |err| {
3880+
unreachable;
3881+
}
3882+
3883+
const c: anyerror!?u32 = error.BadValue;
3884+
if (c) |optional_value| {
3885+
unreachable;
3886+
} else |err| {
3887+
assert(err == error.BadValue);
3888+
}
3889+
3890+
// Access the value by reference by using a pointer capture each time.
3891+
var d: anyerror!?u32 = 3;
3892+
if (d) |*optional_value| {
3893+
if (optional_value.*) |*value| {
3894+
value.* = 9;
3895+
}
3896+
} else |err| {
3897+
unreachable;
3898+
}
3899+
3900+
if (d) |optional_value| {
3901+
assert(optional_value.? == 9);
3902+
} else |err| {
3903+
unreachable;
3904+
}
3905+
}
38643906
{#code_end#}
38653907
{#see_also|Optionals|Errors#}
38663908
{#header_close#}
@@ -8393,6 +8435,7 @@ fn foo(comptime T: type, ptr: *T) T {
83938435
{#header_close#}
83948436

83958437
{#header_open|Opaque Types#}
8438+
<p>
83968439
{#syntax#}@Type(.Opaque){#endsyntax#} creates a new type with an unknown (but non-zero) size and alignment.
83978440
</p>
83988441
<p>

lib/std/fs.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@ pub const Dir = struct {
453453

454454
pub const Error = IteratorError;
455455

456+
/// Memory such as file names referenced in this returned entry becomes invalid
457+
/// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
456458
pub fn next(self: *Self) Error!?Entry {
457459
start_over: while (true) {
458460
const w = os.windows;

lib/std/fs/test.zig

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,53 @@ const testing = std.testing;
33
const builtin = std.builtin;
44
const fs = std.fs;
55
const mem = std.mem;
6+
const wasi = std.os.wasi;
67

8+
const ArenaAllocator = std.heap.ArenaAllocator;
9+
const Dir = std.fs.Dir;
710
const File = std.fs.File;
811
const tmpDir = testing.tmpDir;
912

13+
test "Dir.Iterator" {
14+
var tmp_dir = tmpDir(.{ .iterate = true });
15+
defer tmp_dir.cleanup();
16+
17+
// First, create a couple of entries to iterate over.
18+
const file = try tmp_dir.dir.createFile("some_file", .{});
19+
file.close();
20+
21+
try tmp_dir.dir.makeDir("some_dir");
22+
23+
var arena = ArenaAllocator.init(testing.allocator);
24+
defer arena.deinit();
25+
26+
var entries = std.ArrayList(Dir.Entry).init(&arena.allocator);
27+
28+
// Create iterator.
29+
var iter = tmp_dir.dir.iterate();
30+
while (try iter.next()) |entry| {
31+
// We cannot just store `entry` as on Windows, we're re-using the name buffer
32+
// which means we'll actually share the `name` pointer between entries!
33+
const name = try arena.allocator.dupe(u8, entry.name);
34+
try entries.append(Dir.Entry{ .name = name, .kind = entry.kind });
35+
}
36+
37+
testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..'
38+
testing.expect(contains(&entries, Dir.Entry{ .name = "some_file", .kind = Dir.Entry.Kind.File }));
39+
testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory }));
40+
}
41+
42+
fn entry_eql(lhs: Dir.Entry, rhs: Dir.Entry) bool {
43+
return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind;
44+
}
45+
46+
fn contains(entries: *const std.ArrayList(Dir.Entry), el: Dir.Entry) bool {
47+
for (entries.items) |entry| {
48+
if (entry_eql(entry, el)) return true;
49+
}
50+
return false;
51+
}
52+
1053
test "readAllAlloc" {
1154
var tmp_dir = tmpDir(.{});
1255
defer tmp_dir.cleanup();
@@ -237,7 +280,7 @@ test "fs.copyFile" {
237280
try expectFileContents(tmp.dir, dest_file2, data);
238281
}
239282

240-
fn expectFileContents(dir: fs.Dir, file_path: []const u8, data: []const u8) !void {
283+
fn expectFileContents(dir: Dir, file_path: []const u8, data: []const u8) !void {
241284
const contents = try dir.readFileAlloc(testing.allocator, file_path, 1000);
242285
defer testing.allocator.free(contents);
243286

lib/std/hash_map.zig

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,13 @@ pub fn HashMapUnmanaged(
533533
}
534534

535535
pub fn clone(self: Self, allocator: *Allocator) !Self {
536-
// TODO this can be made more efficient by directly allocating
537-
// the memory slices and memcpying the elements.
538-
var other = Self.init();
539-
try other.initCapacity(allocator, self.entries.len);
540-
for (self.entries.items) |entry| {
541-
other.putAssumeCapacityNoClobber(entry.key, entry.value);
536+
var other: Self = .{};
537+
try other.entries.appendSlice(allocator, self.entries.items);
538+
539+
if (self.index_header) |header| {
540+
const new_header = try IndexHeader.alloc(allocator, header.indexes_len);
541+
other.insertAllEntriesIntoNewHeader(new_header);
542+
other.index_header = new_header;
542543
}
543544
return other;
544545
}
@@ -980,6 +981,25 @@ test "ensure capacity" {
980981
testing.expect(initial_capacity == map.capacity());
981982
}
982983

984+
test "clone" {
985+
var original = AutoHashMap(i32, i32).init(std.testing.allocator);
986+
defer original.deinit();
987+
988+
// put more than `linear_scan_max` so we can test that the index header is properly cloned
989+
var i: u8 = 0;
990+
while (i < 10) : (i += 1) {
991+
try original.putNoClobber(i, i * 10);
992+
}
993+
994+
var copy = try original.clone();
995+
defer copy.deinit();
996+
997+
i = 0;
998+
while (i < 10) : (i += 1) {
999+
testing.expect(copy.get(i).? == i * 10);
1000+
}
1001+
}
1002+
9831003
pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {
9841004
return struct {
9851005
fn hash(key: K) u32 {

src-self-hosted/Module.zig

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ root_pkg: *Package,
2727
/// Module owns this resource.
2828
/// The `Scope` is either a `Scope.ZIRModule` or `Scope.File`.
2929
root_scope: *Scope,
30-
bin_file: link.ElfFile,
30+
bin_file: *link.File,
3131
bin_file_dir: std.fs.Dir,
3232
bin_file_path: []const u8,
3333
/// It's rare for a decl to be exported, so we save memory by having a sparse map of
@@ -46,7 +46,7 @@ export_owners: std.AutoHashMapUnmanaged(*Decl, []*Export) = .{},
4646
decl_table: std.HashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql, false) = .{},
4747

4848
optimize_mode: std.builtin.Mode,
49-
link_error_flags: link.ElfFile.ErrorFlags = .{},
49+
link_error_flags: link.File.ErrorFlags = .{},
5050

5151
work_queue: std.fifo.LinearFifo(WorkItem, .Dynamic),
5252

@@ -90,7 +90,7 @@ pub const Export = struct {
9090
/// Byte offset into the file that contains the export directive.
9191
src: usize,
9292
/// Represents the position of the export, if any, in the output file.
93-
link: link.ElfFile.Export,
93+
link: link.File.Elf.Export,
9494
/// The Decl that performs the export. Note that this is *not* the Decl being exported.
9595
owner_decl: *Decl,
9696
/// The Decl being exported. Note this is *not* the Decl performing the export.
@@ -168,7 +168,7 @@ pub const Decl = struct {
168168

169169
/// Represents the position of the code in the output file.
170170
/// This is populated regardless of semantic analysis and code generation.
171-
link: link.ElfFile.TextBlock = link.ElfFile.TextBlock.empty,
171+
link: link.File.Elf.TextBlock = link.File.Elf.TextBlock.empty,
172172

173173
contents_hash: std.zig.SrcHash,
174174

@@ -723,17 +723,19 @@ pub const InitOptions = struct {
723723
object_format: ?std.builtin.ObjectFormat = null,
724724
optimize_mode: std.builtin.Mode = .Debug,
725725
keep_source_files_loaded: bool = false,
726+
cbe: bool = false,
726727
};
727728

728729
pub fn init(gpa: *Allocator, options: InitOptions) !Module {
729730
const bin_file_dir = options.bin_file_dir orelse std.fs.cwd();
730-
var bin_file = try link.openBinFilePath(gpa, bin_file_dir, options.bin_file_path, .{
731+
const bin_file = try link.openBinFilePath(gpa, bin_file_dir, options.bin_file_path, .{
731732
.target = options.target,
732733
.output_mode = options.output_mode,
733734
.link_mode = options.link_mode orelse .Static,
734735
.object_format = options.object_format orelse options.target.getObjectFormat(),
736+
.cbe = options.cbe,
735737
});
736-
errdefer bin_file.deinit();
738+
errdefer bin_file.destroy();
737739

738740
const root_scope = blk: {
739741
if (mem.endsWith(u8, options.root_pkg.root_src_path, ".zig")) {
@@ -776,7 +778,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
776778
}
777779

778780
pub fn deinit(self: *Module) void {
779-
self.bin_file.deinit();
781+
self.bin_file.destroy();
780782
const gpa = self.gpa;
781783
self.deletion_set.deinit(gpa);
782784
self.work_queue.deinit();
@@ -825,7 +827,7 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
825827
}
826828

827829
pub fn target(self: Module) std.Target {
828-
return self.bin_file.options.target;
830+
return self.bin_file.options().target;
829831
}
830832

831833
/// Detect changes to source files, perform semantic analysis, and update the output files.
@@ -872,7 +874,7 @@ pub fn update(self: *Module) !void {
872874
try self.bin_file.flush();
873875
}
874876

875-
self.link_error_flags = self.bin_file.error_flags;
877+
self.link_error_flags = self.bin_file.errorFlags();
876878
std.log.debug(.module, "link_error_flags: {}\n", .{self.link_error_flags});
877879

878880
// If there are any errors, we anticipate the source files being loaded
@@ -1985,8 +1987,9 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
19851987
self.decl_exports.removeAssertDiscard(exp.exported_decl);
19861988
}
19871989
}
1988-
1989-
self.bin_file.deleteExport(exp.link);
1990+
if (self.bin_file.cast(link.File.Elf)) |elf| {
1991+
elf.deleteExport(exp.link);
1992+
}
19901993
if (self.failed_exports.remove(exp)) |entry| {
19911994
entry.value.destroy(self.gpa);
19921995
}
@@ -2048,7 +2051,7 @@ fn allocateNewDecl(
20482051
.analysis = .unreferenced,
20492052
.deletion_flag = false,
20502053
.contents_hash = contents_hash,
2051-
.link = link.ElfFile.TextBlock.empty,
2054+
.link = link.File.Elf.TextBlock.empty,
20522055
.generation = 0,
20532056
};
20542057
return new_decl;
@@ -2559,7 +2562,7 @@ fn createAnonymousDecl(
25592562
) !*Decl {
25602563
const name_index = self.getNextAnonNameIndex();
25612564
const scope_decl = scope.decl().?;
2562-
const name = try std.fmt.allocPrint(self.gpa, "{}${}", .{ scope_decl.name, name_index });
2565+
const name = try std.fmt.allocPrint(self.gpa, "{}__anon_{}", .{ scope_decl.name, name_index });
25632566
defer self.gpa.free(name);
25642567
const name_hash = scope.namespace().fullyQualifiedNameHash(name);
25652568
const src_hash: std.zig.SrcHash = undefined;

src-self-hosted/cbe.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#if __STDC_VERSION__ >= 201112L
2+
#define noreturn _Noreturn
3+
#elif __GNUC__ && !__STRICT_ANSI__
4+
#define noreturn __attribute__ ((noreturn))
5+
#else
6+
#define noreturn
7+
#endif
8+

0 commit comments

Comments
 (0)