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

This commit is contained in:
Andrew Kelley 2023-03-17 14:55:22 -07:00
commit 5c4bbd0657
21 changed files with 213 additions and 62 deletions

View File

@ -204,7 +204,11 @@ pub fn main() !void {
} else if (mem.eql(u8, arg, "--verbose-air")) {
builder.verbose_air = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
builder.verbose_llvm_ir = true;
builder.verbose_llvm_ir = "-";
} else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
builder.verbose_llvm_ir = arg["--verbose-llvm-ir=".len..];
} else if (mem.eql(u8, arg, "--verbose-llvm-bc=")) {
builder.verbose_llvm_bc = arg["--verbose-llvm-bc=".len..];
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
builder.verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-cc")) {
@ -990,7 +994,8 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
\\ --debug-pkg-config Fail if unknown pkg-config flags encountered
\\ --verbose-link Enable compiler debug output for linking
\\ --verbose-air Enable compiler debug output for Zig AIR
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
\\ --verbose-llvm-ir[=file] Enable compiler debug output for LLVM IR
\\ --verbose-llvm-bc=[file] Enable compiler debug output for LLVM BC
\\ --verbose-cimport Enable compiler debug output for C imports
\\ --verbose-cc Enable compiler debug output for C compilation
\\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
@ -1003,13 +1008,13 @@ fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype
process.exit(1);
}
fn nextArg(args: [][]const u8, idx: *usize) ?[]const u8 {
fn nextArg(args: [][:0]const u8, idx: *usize) ?[:0]const u8 {
if (idx.* >= args.len) return null;
defer idx.* += 1;
return args[idx.*];
}
fn argsRest(args: [][]const u8, idx: usize) ?[][]const u8 {
fn argsRest(args: [][:0]const u8, idx: usize) ?[][:0]const u8 {
if (idx >= args.len) return null;
return args[idx..];
}

View File

@ -54,12 +54,13 @@ verbose: bool,
verbose_link: bool,
verbose_cc: bool,
verbose_air: bool,
verbose_llvm_ir: bool,
verbose_llvm_ir: ?[]const u8,
verbose_llvm_bc: ?[]const u8,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool,
reference_trace: ?u32 = null,
invalid_user_input: bool,
zig_exe: []const u8,
zig_exe: [:0]const u8,
default_step: *Step,
env_map: *EnvMap,
top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
@ -183,7 +184,7 @@ pub const DirList = struct {
pub fn create(
allocator: Allocator,
zig_exe: []const u8,
zig_exe: [:0]const u8,
build_root: Cache.Directory,
cache_root: Cache.Directory,
global_cache_root: Cache.Directory,
@ -204,7 +205,8 @@ pub fn create(
.verbose_link = false,
.verbose_cc = false,
.verbose_air = false,
.verbose_llvm_ir = false,
.verbose_llvm_ir = null,
.verbose_llvm_bc = null,
.verbose_cimport = false,
.verbose_llvm_cpu_features = false,
.invalid_user_input = false,
@ -292,6 +294,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
.verbose_cc = parent.verbose_cc,
.verbose_air = parent.verbose_air,
.verbose_llvm_ir = parent.verbose_llvm_ir,
.verbose_llvm_bc = parent.verbose_llvm_bc,
.verbose_cimport = parent.verbose_cimport,
.verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
.reference_trace = parent.reference_trace,

View File

@ -1438,7 +1438,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
if (b.verbose_cimport) try zig_args.append("--verbose-cimport");
if (b.verbose_air) try zig_args.append("--verbose-air");
if (b.verbose_llvm_ir) try zig_args.append("--verbose-llvm-ir");
if (b.verbose_llvm_ir) |path| try zig_args.append(b.fmt("--verbose-llvm-ir={s}", .{path}));
if (b.verbose_llvm_bc) |path| try zig_args.append(b.fmt("--verbose-llvm-bc={s}", .{path}));
if (b.verbose_link or self.verbose_link) try zig_args.append("--verbose-link");
if (b.verbose_cc or self.verbose_cc) try zig_args.append("--verbose-cc");
if (b.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features");

View File

@ -16,9 +16,30 @@ const testing = std.testing;
/// var a_clone = a; // creates a copy - the structure doesn't use any internal pointers
/// ```
pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
return BoundedArrayAligned(T, @alignOf(T), buffer_capacity);
}
/// A structure with an array, length and alignment, that can be used as a
/// slice.
///
/// Useful to pass around small explicitly-aligned arrays whose exact size is
/// only known at runtime, but whose maximum size is known at comptime, without
/// requiring an `Allocator`.
/// ```zig
// var a = try BoundedArrayAligned(u8, 16, 2).init(0);
// try a.append(255);
// try a.append(255);
// const b = @ptrCast(*const [1]u16, a.constSlice().ptr);
// try testing.expectEqual(@as(u16, 65535), b[0]);
/// ```
pub fn BoundedArrayAligned(
comptime T: type,
comptime alignment: u29,
comptime buffer_capacity: usize,
) type {
return struct {
const Self = @This();
buffer: [buffer_capacity]T = undefined,
buffer: [buffer_capacity]T align(alignment) = undefined,
len: usize = 0,
/// Set the actual length of the slice.
@ -30,15 +51,15 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
/// View the internal array as a slice whose size was previously set.
pub fn slice(self: anytype) switch (@TypeOf(&self.buffer)) {
*[buffer_capacity]T => []T,
*const [buffer_capacity]T => []const T,
*align(alignment) [buffer_capacity]T => []align(alignment) T,
*align(alignment) const [buffer_capacity]T => []align(alignment) const T,
else => unreachable,
} {
return self.buffer[0..self.len];
}
/// View the internal array as a constant slice whose size was previously set.
pub fn constSlice(self: *const Self) []const T {
pub fn constSlice(self: *const Self) []align(alignment) const T {
return self.slice();
}
@ -94,7 +115,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
/// Resize the slice, adding `n` new elements, which have `undefined` values.
/// The return value is a slice pointing to the uninitialized elements.
pub fn addManyAsArray(self: *Self, comptime n: usize) error{Overflow}!*[n]T {
pub fn addManyAsArray(self: *Self, comptime n: usize) error{Overflow}!*align(alignment) [n]T {
const prev_len = self.len;
try self.resize(self.len + n);
return self.slice()[prev_len..][0..n];
@ -118,7 +139,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
/// This can be useful for writing directly into it.
/// Note that such an operation must be followed up with a
/// call to `resize()`
pub fn unusedCapacitySlice(self: *Self) []T {
pub fn unusedCapacitySlice(self: *Self) []align(alignment) T {
return self.buffer[self.len..];
}
@ -365,3 +386,15 @@ test "BoundedArray" {
try w.writeAll(s);
try testing.expectEqualStrings(s, a.constSlice());
}
test "BoundedArrayAligned" {
var a = try BoundedArrayAligned(u8, 16, 4).init(0);
try a.append(0);
try a.append(0);
try a.append(255);
try a.append(255);
const b = @ptrCast(*const [2]u16, a.constSlice().ptr);
try testing.expectEqual(@as(u16, 0), b[0]);
try testing.expectEqual(@as(u16, 65535), b[1]);
}

View File

@ -215,6 +215,10 @@ pub const NamedGroup = enum(u16) {
ffdhe6144 = 0x0103,
ffdhe8192 = 0x0104,
// Hybrid post-quantum key agreements
x25519_kyber512d00 = 0xFE30,
x25519_kyber768d00 = 0xFE31,
_,
};

View File

@ -158,6 +158,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
// Only possible to happen if the private key is all zeroes.
error.IdentityElement => return error.InsufficientEntropy,
};
const kyber768_kp = crypto.kem.kyber_d00.Kyber768.KeyPair.create(null) catch {};
const extensions_payload =
tls.extension(.supported_versions, [_]u8{
@ -175,6 +176,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
.rsa_pkcs1_sha512,
.ed25519,
})) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{
.x25519_kyber768d00,
.secp256r1,
.x25519,
})) ++ tls.extension(
@ -182,7 +184,9 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++
array(1, x25519_kp.public_key) ++
int2(@enumToInt(tls.NamedGroup.secp256r1)) ++
array(1, secp256r1_kp.public_key.toUncompressedSec1())),
array(1, secp256r1_kp.public_key.toUncompressedSec1()) ++
int2(@enumToInt(tls.NamedGroup.x25519_kyber768d00)) ++
array(1, x25519_kp.public_key ++ kyber768_kp.public_key.toBytes())),
) ++
int2(@enumToInt(tls.ExtensionType.server_name)) ++
int2(host_len + 5) ++ // byte length of this extension payload
@ -274,7 +278,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
const extensions_size = hsd.decode(u16);
var all_extd = try hsd.sub(extensions_size);
var supported_version: u16 = 0;
var shared_key: [32]u8 = undefined;
var shared_key: []const u8 = undefined;
var have_shared_key = false;
while (!all_extd.eof()) {
try all_extd.ensure(2 + 2);
@ -295,14 +299,29 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
const key_size = extd.decode(u16);
try extd.ensure(key_size);
switch (named_group) {
.x25519 => {
if (key_size != 32) return error.TlsIllegalParameter;
const server_pub_key = extd.array(32);
.x25519_kyber768d00 => {
const xksl = crypto.dh.X25519.public_length;
const hksl = xksl + crypto.kem.kyber_d00.Kyber768.ciphertext_length;
if (key_size != hksl)
return error.TlsIllegalParameter;
const server_ks = extd.array(hksl);
shared_key = crypto.dh.X25519.scalarmult(
shared_key = &((crypto.dh.X25519.scalarmult(
x25519_kp.secret_key,
server_ks[0..xksl].*,
) catch return error.TlsDecryptFailure) ++ (kyber768_kp.secret_key.decaps(
server_ks[xksl..hksl],
) catch return error.TlsDecryptFailure));
},
.x25519 => {
const ksl = crypto.dh.X25519.public_length;
if (key_size != ksl) return error.TlsIllegalParameter;
const server_pub_key = extd.array(ksl);
shared_key = &(crypto.dh.X25519.scalarmult(
x25519_kp.secret_key,
server_pub_key.*,
) catch return error.TlsDecryptFailure;
) catch return error.TlsDecryptFailure);
},
.secp256r1 => {
const server_pub_key = extd.slice(key_size);
@ -314,7 +333,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
const mul = pk.p.mulPublic(secp256r1_kp.secret_key.bytes, .Big) catch {
return error.TlsDecryptFailure;
};
shared_key = mul.affineCoordinates().x.toBytes(.Big);
shared_key = &mul.affineCoordinates().x.toBytes(.Big);
},
else => {
return error.TlsIllegalParameter;
@ -358,7 +377,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
const early_secret = P.Hkdf.extract(&[1]u8{0}, &zeroes);
const empty_hash = tls.emptyHash(P.Hash);
const hs_derived_secret = hkdfExpandLabel(P.Hkdf, early_secret, "derived", &empty_hash, P.Hash.digest_length);
p.handshake_secret = P.Hkdf.extract(&hs_derived_secret, &shared_key);
p.handshake_secret = P.Hkdf.extract(&hs_derived_secret, shared_key);
const ap_derived_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "derived", &empty_hash, P.Hash.digest_length);
p.master_secret = P.Hkdf.extract(&ap_derived_secret, &zeroes);
const client_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "c hs traffic", &hello_hash, P.Hash.digest_length);

View File

@ -741,7 +741,7 @@ pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream {
return Stream{ .handle = sockfd };
}
const GetAddressListError = std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.os.SocketError || std.os.BindError || error{
const GetAddressListError = std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.os.SocketError || std.os.BindError || std.os.SetSockOptError || error{
// TODO: break this up into error sets from the various underlying functions
TemporaryNameServerFailure,
@ -1534,15 +1534,10 @@ fn resMSendRc(
ns[i] = iplit.addr;
assert(ns[i].getPort() == 53);
if (iplit.addr.any.family != os.AF.INET) {
sl = @sizeOf(os.sockaddr.in6);
family = os.AF.INET6;
}
}
// Get local address and open/bind a socket
var sa: Address = undefined;
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
sa.any.family = family;
const flags = os.SOCK.DGRAM | os.SOCK.CLOEXEC | os.SOCK.NONBLOCK;
const fd = os.socket(family, flags, 0) catch |err| switch (err) {
error.AddressFamilyNotSupported => blk: {
@ -1556,27 +1551,35 @@ fn resMSendRc(
else => |e| return e,
};
defer os.closeSocket(fd);
try os.bind(fd, &sa.any, sl);
// Past this point, there are no errors. Each individual query will
// yield either no reply (indicated by zero length) or an answer
// packet which is up to the caller to interpret.
// Convert any IPv4 addresses in a mixed environment to v4-mapped
// TODO
//if (family == AF.INET6) {
// setsockopt(fd, IPPROTO.IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
// for (i=0; i<nns; i++) {
// if (ns[i].sin.sin_family != AF.INET) continue;
// memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
// &ns[i].sin.sin_addr, 4);
// memcpy(ns[i].sin6.sin6_addr.s6_addr,
// "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
// ns[i].sin6.sin6_family = AF.INET6;
// ns[i].sin6.sin6_flowinfo = 0;
// ns[i].sin6.sin6_scope_id = 0;
// }
//}
if (family == os.AF.INET6) {
try os.setsockopt(
fd,
os.SOL.IPV6,
os.linux.IPV6.V6ONLY,
&mem.toBytes(@as(c_int, 0)),
);
for (0..ns.len) |i| {
if (ns[i].any.family != os.AF.INET) continue;
mem.writeIntNative(u32, ns[i].in6.sa.addr[12..], ns[i].in.sa.addr);
mem.copy(u8, ns[i].in6.sa.addr[0..12], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
ns[i].any.family = os.AF.INET6;
ns[i].in6.sa.flowinfo = 0;
ns[i].in6.sa.scope_id = 0;
}
sl = @sizeOf(os.sockaddr.in6);
}
// Get local address and open/bind a socket
var sa: Address = undefined;
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
sa.any.family = family;
try os.bind(fd, &sa.any, sl);
var pfd = [1]os.pollfd{os.pollfd{
.fd = fd,

View File

@ -9,6 +9,7 @@ pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
pub const AutoHashMap = hash_map.AutoHashMap;
pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;
pub const BoundedArray = @import("bounded_array.zig").BoundedArray;
pub const BoundedArrayAligned = @import("bounded_array.zig").BoundedArrayAligned;
pub const Build = @import("Build.zig");
pub const BufMap = @import("buf_map.zig").BufMap;
pub const BufSet = @import("buf_set.zig").BufSet;

View File

@ -86,7 +86,8 @@ clang_preprocessor_mode: ClangPreprocessorMode,
/// Whether to print clang argvs to stdout.
verbose_cc: bool,
verbose_air: bool,
verbose_llvm_ir: bool,
verbose_llvm_ir: ?[]const u8,
verbose_llvm_bc: ?[]const u8,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool,
disable_c_depfile: bool,
@ -585,7 +586,8 @@ pub const InitOptions = struct {
verbose_cc: bool = false,
verbose_link: bool = false,
verbose_air: bool = false,
verbose_llvm_ir: bool = false,
verbose_llvm_ir: ?[]const u8 = null,
verbose_llvm_bc: ?[]const u8 = null,
verbose_cimport: bool = false,
verbose_llvm_cpu_features: bool = false,
is_test: bool = false,
@ -1559,6 +1561,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.verbose_cc = options.verbose_cc,
.verbose_air = options.verbose_air,
.verbose_llvm_ir = options.verbose_llvm_ir,
.verbose_llvm_bc = options.verbose_llvm_bc,
.verbose_cimport = options.verbose_cimport,
.verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
.disable_c_depfile = options.disable_c_depfile,
@ -5349,6 +5352,7 @@ fn buildOutputFromZig(
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,
@ -5426,6 +5430,7 @@ pub fn build_crt_file(
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,

View File

@ -4263,7 +4263,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
comp.emit_llvm_bc == null);
const dump_air = builtin.mode == .Debug and comp.verbose_air;
const dump_llvm_ir = builtin.mode == .Debug and comp.verbose_llvm_ir;
const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
if (no_bin_file and !dump_air and !dump_llvm_ir) return;
@ -6395,7 +6395,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
comp.emit_llvm_ir == null and
comp.emit_llvm_bc == null);
const dump_llvm_ir = builtin.mode == .Debug and comp.verbose_llvm_ir;
const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
if (no_bin_file and !dump_llvm_ir) return;

View File

@ -4712,6 +4712,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
.Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}),
}
if ((try sema.typeHasOnePossibleValue(operand_ty.childType())) != null) {
// No need to validate the actual pointer value, we don't need it!
return;
}
const elem_ty = operand_ty.elemType2();
if (try sema.resolveMaybeUndefVal(operand)) |val| {
if (val.isUndef()) {
@ -15449,9 +15454,13 @@ fn zirRetAddr(
block: *Block,
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
try sema.requireRuntimeBlock(block, src, null);
return try block.addNoOp(.ret_addr);
_ = extended;
if (block.is_comptime) {
// TODO: we could give a meaningful lazy value here. #14938
return sema.addIntUnsigned(Type.usize, 0);
} else {
return block.addNoOp(.ret_addr);
}
}
fn zirFrameAddress(

View File

@ -756,8 +756,35 @@ pub const Object = struct {
dib.finalize();
}
if (comp.verbose_llvm_ir) {
self.llvm_module.dump();
if (comp.verbose_llvm_ir) |path| {
if (std.mem.eql(u8, path, "-")) {
self.llvm_module.dump();
} else {
const path_z = try comp.gpa.dupeZ(u8, path);
defer comp.gpa.free(path_z);
var error_message: [*:0]const u8 = undefined;
if (self.llvm_module.printModuleToFile(path_z, &error_message).toBool()) {
defer llvm.disposeMessage(error_message);
log.err("dump LLVM module failed ir={s}: {s}", .{
path, error_message,
});
}
}
}
if (comp.verbose_llvm_bc) |path| {
const path_z = try comp.gpa.dupeZ(u8, path);
defer comp.gpa.free(path_z);
const error_code = self.llvm_module.writeBitcodeToFile(path_z);
if (error_code != 0) {
log.err("dump LLVM module failed bc={s}: {d}", .{
path, error_code,
});
}
}
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);

View File

@ -422,6 +422,9 @@ pub const Module = opaque {
pub const printModuleToFile = LLVMPrintModuleToFile;
extern fn LLVMPrintModuleToFile(M: *Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool;
pub const writeBitcodeToFile = LLVMWriteBitcodeToFile;
extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int;
};
pub const lookupIntrinsicID = LLVMLookupIntrinsicID;

View File

@ -1097,6 +1097,7 @@ fn buildSharedLib(
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,

View File

@ -250,6 +250,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,
@ -410,6 +411,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,

View File

@ -226,6 +226,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,

View File

@ -122,6 +122,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.verbose_link = comp.bin_file.options.verbose_link,
.verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode,

View File

@ -370,10 +370,10 @@ const usage_build_generic =
\\ -fno-emit-bin Do not output machine code
\\ -femit-asm[=path] Output .s (assembly code)
\\ -fno-emit-asm (default) Do not output .s (assembly code)
\\ -femit-llvm-ir[=path] Produce a .ll file with LLVM IR (requires LLVM extensions)
\\ -fno-emit-llvm-ir (default) Do not produce a .ll file with LLVM IR
\\ -femit-llvm-bc[=path] Produce a LLVM module as a .bc file (requires LLVM extensions)
\\ -fno-emit-llvm-bc (default) Do not produce a LLVM module as a .bc file
\\ -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions)
\\ -fno-emit-llvm-ir (default) Do not produce a .ll file with optimized LLVM IR
\\ -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions)
\\ -fno-emit-llvm-bc (default) Do not produce an optimized LLVM module as a .bc file
\\ -femit-h[=path] Generate a C header file (.h)
\\ -fno-emit-h (default) Do not generate a C header file (.h)
\\ -femit-docs[=path] Create a docs/ dir with html documentation
@ -555,13 +555,14 @@ const usage_build_generic =
\\ --test-runner [path] Specify a custom test runner
\\
\\Debug Options (Zig Compiler Development):
\\ -fopt-bisect-limit [limit] Only run [limit] first LLVM optimization passes
\\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes
\\ -ftime-report Print timing diagnostics
\\ -fstack-report Print stack size diagnostics
\\ --verbose-link Display linker invocations
\\ --verbose-cc Display C compiler invocations
\\ --verbose-air Enable compiler debug output for Zig AIR
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
\\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR
\\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC
\\ --verbose-cimport Enable compiler debug output for C imports
\\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
\\ --debug-log [scope] Enable printing debug/info log messages for scope
@ -704,7 +705,8 @@ fn buildOutputType(
var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");
var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
var verbose_air = false;
var verbose_llvm_ir = false;
var verbose_llvm_ir: ?[]const u8 = null;
var verbose_llvm_bc: ?[]const u8 = null;
var verbose_cimport = false;
var verbose_llvm_cpu_features = false;
var time_report = false;
@ -1441,7 +1443,11 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "--verbose-air")) {
verbose_air = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
verbose_llvm_ir = true;
verbose_llvm_ir = "-";
} else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
verbose_llvm_ir = arg["--verbose-llvm-ir=".len..];
} else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) {
verbose_llvm_bc = arg["--verbose-llvm-bc=".len..];
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
@ -3226,6 +3232,7 @@ fn buildOutputType(
.verbose_link = verbose_link,
.verbose_air = verbose_air,
.verbose_llvm_ir = verbose_llvm_ir,
.verbose_llvm_bc = verbose_llvm_bc,
.verbose_cimport = verbose_cimport,
.verbose_llvm_cpu_features = verbose_llvm_cpu_features,
.machine_code_model = machine_code_model,

View File

@ -191,6 +191,7 @@ test {
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/return_address.zig");
_ = @import("behavior/saturating_arithmetic.zig");
_ = @import("behavior/select.zig");
_ = @import("behavior/shuffle.zig");

View File

@ -420,3 +420,11 @@ test "mutate entire slice at comptime" {
buf[1..3].* = x;
}
}
test "dereference undefined pointer to zero-bit type" {
const p0: *void = undefined;
try testing.expectEqual({}, p0.*);
const p1: *[0]u32 = undefined;
try testing.expect(p1.*.len == 0);
}

View File

@ -0,0 +1,17 @@
const builtin = @import("builtin");
const testing = @import("std").testing;
fn retAddr() usize {
return @returnAddress();
}
test "return address" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
_ = retAddr();
// TODO: #14938
try testing.expectEqual(0, comptime retAddr());
}