From 3038290a469fdac84e4a2a22e0e0926cd8c8448f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 14 Feb 2020 15:30:20 +0100 Subject: [PATCH 001/109] ir: Make all the payload captures do a copy The payload doesn't alias anymore the same memory it comes from and is instead a fresh copy of the original object. --- src/ir.cpp | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 9c1d168b21..323fa4ba6f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8106,9 +8106,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no if (var_symbol) { IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node, err_val_ptr, false, false); - IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ? - ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr; - ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr); + IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); } ZigList incoming_values = {0}; @@ -8156,7 +8156,8 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no true, false, false, is_comptime); Scope *err_scope = err_var->child_scope; IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); - ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr); + build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; @@ -8217,9 +8218,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no ir_set_cursor_at_end_and_append_block(irb, body_block); IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false, false); - IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ? - ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr; - ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr); + IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); + build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; @@ -8458,9 +8459,9 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); Scope *child_scope = elem_var->child_scope; - IrInstSrc *var_ptr = node->data.for_expr.elem_is_ptr ? - ir_build_ref_src(irb, &spill_scope->base, elem_node, elem_ptr, true, false) : elem_ptr; - ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr); + IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? + elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); + build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; @@ -8880,8 +8881,9 @@ static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNo var_symbol, is_const, is_const, is_shadowable, is_comptime); IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false); - IrInstSrc *var_ptr = var_is_ptr ? ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; - ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr); + IrInstSrc *var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); var_scope = var->child_scope; } else { var_scope = subexpr_scope; @@ -8962,9 +8964,9 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); - IrInstSrc *var_ptr = var_is_ptr ? - ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; - ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr); + IrInstSrc *var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); var_scope = var->child_scope; } else { var_scope = subexpr_scope; @@ -8989,7 +8991,8 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n err_symbol, is_const, is_const, is_shadowable, is_comptime); IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); - ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr); + build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); err_var_scope = var->child_scope; } else { err_var_scope = subexpr_scope; @@ -9039,22 +9042,24 @@ static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *s ZigVar *var = ir_create_var(irb, var_symbol_node, scope, var_name, is_const, is_const, is_shadowable, var_is_comptime); child_scope = var->child_scope; - IrInstSrc *var_ptr; + IrInstSrc *var_value; if (out_switch_else_var != nullptr) { IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, target_value_ptr); *out_switch_else_var = switch_else_var; IrInstSrc *payload_ptr = &switch_else_var->base; - var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; + var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); } else if (prong_values != nullptr) { IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_values, prong_values_len); - var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; + var_value = var_is_ptr ? + payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); } else { - var_ptr = var_is_ptr ? - ir_build_ref_src(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr; + var_value = var_is_ptr ? + target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); } - ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_ptr); + build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); } else { child_scope = scope; } @@ -9627,7 +9632,8 @@ static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode * is_const, is_const, is_shadowable, is_comptime); err_scope = var->child_scope; IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); - ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr); + IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr); + build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); } else { err_scope = subexpr_scope; } From 1c8ac2a0c140ba2406f1dc164dc4eeb99a8b6b5b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 14 Feb 2020 15:56:34 +0100 Subject: [PATCH 002/109] test: Add test cases for the new capture behavior --- test/stage1/behavior/for.zig | 28 ++++++++++++++++++++++++++++ test/stage1/behavior/if.zig | 19 ++++++++++++++++++- test/stage1/behavior/switch.zig | 22 ++++++++++++++++++++++ test/stage1/behavior/while.zig | 18 +++++++++++++++++- 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/test/stage1/behavior/for.zig b/test/stage1/behavior/for.zig index 29b6f934f0..c0b1cf264a 100644 --- a/test/stage1/behavior/for.zig +++ b/test/stage1/behavior/for.zig @@ -1,5 +1,6 @@ const std = @import("std"); const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; const mem = std.mem; test "continue in for loop" { @@ -142,3 +143,30 @@ test "for with null and T peer types and inferred result location type" { S.doTheTest(&[_]u8{ 1, 2 }); comptime S.doTheTest(&[_]u8{ 1, 2 }); } + +test "for copies its payload" { + const S = struct { + fn doTheTest() void { + var x = [_]usize{ 1, 2, 3 }; + for (x) |value, i| { + // Modify the original array + x[i] += 99; + expectEqual(value, i + 1); + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "for on slice with allowzero ptr" { + const S = struct { + fn doTheTest(slice: []u8) void { + var ptr = @ptrCast([*]allowzero u8, slice.ptr)[0..slice.len]; + for (ptr) |x, i| expect(x == i + 1); + for (ptr) |*x, i| expect(x.* == i + 1); + } + }; + S.doTheTest(&[_]u8{ 1, 2, 3, 4 }); + comptime S.doTheTest(&[_]u8{ 1, 2, 3, 4 }); +} diff --git a/test/stage1/behavior/if.zig b/test/stage1/behavior/if.zig index c309bc061f..de8a29c76d 100644 --- a/test/stage1/behavior/if.zig +++ b/test/stage1/behavior/if.zig @@ -1,4 +1,6 @@ -const expect = @import("std").testing.expect; +const std = @import("std"); +const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; test "if statements" { shouldBeEqual(1, 1); @@ -90,3 +92,18 @@ test "if prongs cast to expected type instead of peer type resolution" { S.doTheTest(false); comptime S.doTheTest(false); } + +test "while copies its payload" { + const S = struct { + fn doTheTest() void { + var tmp: ?i32 = 10; + if (tmp) |value| { + // Modify the original variable + tmp = null; + expectEqual(@as(i32, 10), value); + } else unreachable; + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} diff --git a/test/stage1/behavior/switch.zig b/test/stage1/behavior/switch.zig index 4e33d6505f..28979b8ae8 100644 --- a/test/stage1/behavior/switch.zig +++ b/test/stage1/behavior/switch.zig @@ -1,6 +1,7 @@ const std = @import("std"); const expect = std.testing.expect; const expectError = std.testing.expectError; +const expectEqual = std.testing.expectEqual; test "switch with numbers" { testSwitchWithNumbers(13); @@ -493,3 +494,24 @@ test "switch on error set with single else" { S.doTheTest(); comptime S.doTheTest(); } + +test "while copies its payload" { + const S = struct { + fn doTheTest() void { + var tmp: union(enum) { + A: u8, + B: u32, + } = .{ .A = 42 }; + switch (tmp) { + .A => |value| { + // Modify the original union + tmp = .{ .B = 0x10101010 }; + expectEqual(@as(u8, 42), value); + }, + else => unreachable, + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} diff --git a/test/stage1/behavior/while.zig b/test/stage1/behavior/while.zig index 0d0ef3a69f..c9207396f7 100644 --- a/test/stage1/behavior/while.zig +++ b/test/stage1/behavior/while.zig @@ -1,4 +1,5 @@ -const expect = @import("std").testing.expect; +const std = @import("std"); +const expect = std.testing.expect; test "while loop" { var i: i32 = 0; @@ -271,3 +272,18 @@ test "while error 2 break statements and an else" { S.entry(true, false); comptime S.entry(true, false); } + +test "while copies its payload" { + const S = struct { + fn doTheTest() void { + var tmp: ?i32 = 10; + while (tmp) |value| { + // Modify the original variable + tmp = null; + expect(value == 10); + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} From 058f38220afecb96d115143f8888496162029aed Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Feb 2020 16:56:26 -0500 Subject: [PATCH 003/109] enable passing freebsd tests See #3210 and #4455 --- ci/srht/freebsd_script | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script index 5e9c6fa263..c6b06f063d 100755 --- a/ci/srht/freebsd_script +++ b/ci/srht/freebsd_script @@ -34,38 +34,21 @@ release/bin/zig build test-behavior # release/bin/zig build test-std release/bin/zig build test-compiler-rt - -# This test is disabled because it triggers "out of memory" on the sr.ht CI service. -# See https://github.com/ziglang/zig/issues/3210 -# release/bin/zig build test-compare-output - -# This test is disabled because it triggers "out of memory" on the sr.ht CI service. -# See https://github.com/ziglang/zig/issues/3210 -# release/bin/zig build test-standalone - +release/bin/zig build test-compare-output +release/bin/zig build test-standalone release/bin/zig build test-stack-traces release/bin/zig build test-cli release/bin/zig build test-asm-link release/bin/zig build test-runtime-safety - -# This test is disabled because it triggers "out of memory" on the sr.ht CI service. -# See https://github.com/ziglang/zig/issues/3210 -# release/bin/zig build test-translate-c - +release/bin/zig build test-translate-c +release/bin/zig build test-run-translated-c release/bin/zig build test-gen-h - -# This test is disabled because it triggers "out of memory" on the sr.ht CI service. -# See https://github.com/ziglang/zig/issues/3210 -# release/bin/zig build test-compile-errors - -# This test is disabled because it triggers "out of memory" on the sr.ht CI service. -# See https://github.com/ziglang/zig/issues/3210 -# release/bin/zig build docs +release/bin/zig build test-compile-errors +release/bin/zig build docs if [ -f ~/.s3cfg ]; then mv ../LICENSE release/ - # Enable when `release/bin/zig build docs` passes without "out of memory" or failures - #mv ../zig-cache/langref.html release/ + mv ../zig-cache/langref.html release/ mv release/bin/zig release/ rmdir release/bin From b15958c557d3b29c8d4cee9951a8bfd30c215482 Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 14 Feb 2020 23:41:18 +0200 Subject: [PATCH 004/109] fix c tokenizer bug --- lib/std/c/tokenizer.zig | 2 ++ test/translate_c.zig | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig index 66e6d9d52d..c3f50da13d 100644 --- a/lib/std/c/tokenizer.zig +++ b/lib/std/c/tokenizer.zig @@ -616,6 +616,7 @@ pub const Tokenizer = struct { }, .BackSlash => switch (c) { '\n' => { + result.start = self.index + 1; state = .Start; }, '\r' => { @@ -631,6 +632,7 @@ pub const Tokenizer = struct { }, .BackSlashCr => switch (c) { '\n' => { + result.start = self.index + 1; state = .Start; }, else => { diff --git a/test/translate_c.zig b/test/translate_c.zig index bb2a310b0f..b69142e864 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,6 +3,13 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("macro line continuation", + \\#define FOO -\ + \\BAR + , &[_][]const u8{ + \\pub const FOO = -BAR; + }); + cases.add("function prototype translated as optional", \\typedef void (*fnptr_ty)(void); \\typedef __attribute__((cdecl)) void (*fnptr_attr_ty)(void); From 85830386402e2050a3dc97778b3a28af2be16e90 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Sat, 15 Feb 2020 05:14:31 -0500 Subject: [PATCH 005/109] =?UTF-8?q?translate-c:=20change=20OutOfMemory=20?= =?UTF-8?q?=E2=86=92=20ASTUnitFailure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - return a better error when no diagnostics are available --- src-self-hosted/stage1.zig | 2 ++ src-self-hosted/translate_c.zig | 2 +- src/error.cpp | 1 + src/userland.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 961b95d481..ffa0754bb5 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -92,6 +92,7 @@ const Error = extern enum { InvalidCpuFeatures, InvalidLlvmCpuFeaturesFormat, UnknownApplicationBinaryInterface, + ASTUnitFailure, }; const FILE = std.c.FILE; @@ -114,6 +115,7 @@ export fn stage2_translate_c( out_errors_len.* = errors.len; return Error.CCompileErrors; }, + error.ASTUnitFailure => return Error.ASTUnitFailure, error.OutOfMemory => return Error.OutOfMemory, }; return Error.None; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 0c7b3868e2..cd8d0b9d63 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -264,7 +264,7 @@ pub fn translate( &errors.len, resources_path, ) orelse { - if (errors.len == 0) return error.OutOfMemory; + if (errors.len == 0) return error.ASTUnitFailure; return error.SemanticAnalyzeFail; }; defer ZigClangASTUnit_delete(ast_unit); diff --git a/src/error.cpp b/src/error.cpp index 5bf1667db9..08575d15ec 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -64,6 +64,7 @@ const char *err_str(Error err) { case ErrorInvalidCpuFeatures: return "invalid CPU features"; case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface"; + case ErrorASTUnitFailure: return "ASTUnit failure"; } return "(invalid error)"; } diff --git a/src/userland.h b/src/userland.h index 6b16d2338e..a59f6b7da8 100644 --- a/src/userland.h +++ b/src/userland.h @@ -84,6 +84,7 @@ enum Error { ErrorInvalidCpuFeatures, ErrorInvalidLlvmCpuFeaturesFormat, ErrorUnknownApplicationBinaryInterface, + ErrorASTUnitFailure, }; // ABI warning From 72805fd66e732e29637872f540371c30cb9f8b27 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 15 Feb 2020 14:16:12 -0500 Subject: [PATCH 006/109] fix taking address of temporary async frame --- src/codegen.cpp | 8 +++++++- test/stage1/behavior/async_fn.zig | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index fd6de466ba..0f6988f986 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5018,6 +5018,12 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns if (!type_has_bits(instruction->base.value->type)) { return nullptr; } + if (instruction->operand->id == IrInstGenIdCall) { + IrInstGenCall *call = reinterpret_cast(instruction->operand); + if (call->result_loc != nullptr) { + return ir_llvm_value(g, call->result_loc); + } + } LLVMValueRef value = ir_llvm_value(g, instruction->operand); if (handle_is_ptr(instruction->operand->value->type)) { return value; @@ -6533,7 +6539,7 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { set_debug_location(g, instruction); } instruction->llvm_value = ir_render_instruction(g, executable, instruction); - if (instruction->spill != nullptr) { + if (instruction->spill != nullptr && instruction->llvm_value != nullptr) { LLVMValueRef spill_ptr = ir_llvm_value(g, instruction->spill); gen_assign_raw(g, spill_ptr, instruction->spill->value->type, instruction->llvm_value); instruction->llvm_value = nullptr; diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index dcd5102ff8..cfe82ff5a0 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1481,3 +1481,32 @@ test "handle defer interfering with return value spill" { }; S.doTheTest(); } + +test "take address of temporary async frame" { + const S = struct { + var global_frame: anyframe = undefined; + var finished = false; + + fn doTheTest() void { + _ = async asyncDoTheTest(); + resume global_frame; + expect(finished); + } + + fn asyncDoTheTest() void { + expect(finishIt(&async foo(10)) == 1245); + finished = true; + } + + fn foo(arg: i32) i32 { + global_frame = @frame(); + suspend; + return arg + 1234; + } + + fn finishIt(frame: anyframe->i32) i32 { + return (await frame) + 1; + } + }; + S.doTheTest(); +} From cb3a818699649a985d5879151936b3b88ffddfa4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 15 Feb 2020 15:05:31 -0500 Subject: [PATCH 007/109] zig fmt: support `noasync await` --- lib/std/zig/ast.zig | 4 +++- lib/std/zig/parse.zig | 16 ++++++++++++++-- lib/std/zig/parser_test.zig | 9 +++++++++ lib/std/zig/render.zig | 8 +++++++- test/stage1/behavior/async_fn.zig | 17 +++++++++++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index f34a6b3626..e01d406530 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -1564,7 +1564,9 @@ pub const Node = struct { pub const Op = union(enum) { AddressOf, ArrayType: ArrayInfo, - Await, + Await: struct { + noasync_token: ?TokenIndex = null, + }, BitNot, BoolNot, Cancel, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 1b6afc1c1a..cadf25eef6 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1129,7 +1129,7 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No /// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments /// / PrimaryTypeExpr (SuffixOp / FnCallArguments)* fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { - var maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync); + const maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync); if (maybe_async) |async_token| { const token_fn = eatToken(it, .Keyword_fn); if (async_token.ptr.id == .Keyword_async and token_fn != null) { @@ -2179,7 +2179,19 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { .MinusPercent => ops{ .NegationWrap = {} }, .Ampersand => ops{ .AddressOf = {} }, .Keyword_try => ops{ .Try = {} }, - .Keyword_await => ops{ .Await = {} }, + .Keyword_await => ops{ .Await = .{} }, + .Keyword_noasync => if (eatToken(it, .Keyword_await)) |await_tok| { + const node = try arena.create(Node.PrefixOp); + node.* = Node.PrefixOp{ + .op_token = await_tok, + .op = .{ .Await = .{ .noasync_token = token.index } }, + .rhs = undefined, // set by caller + }; + return &node.base; + } else { + putBackToken(it, token.index); + return null; + }, else => { putBackToken(it, token.index); return null; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 03bb8d4222..28bf0c9ed5 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,3 +1,12 @@ +test "zig fmt: noasync await" { + try testCanonical( + \\fn foo() void { + \\ x = noasync await y; + \\} + \\ + ); +} + test "zig fmt: trailing comma in container declaration" { try testCanonical( \\const X = struct { foo: i32 }; diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 7dd3d63b0d..e322a91dc4 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -584,12 +584,18 @@ fn renderExpression( }, .Try, - .Await, .Cancel, .Resume, => { try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space); }, + + .Await => |await_info| { + if (await_info.noasync_token) |tok| { + try renderToken(tree, stream, tok, indent, start_col, Space.Space); + } + try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space); + }, } return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index cfe82ff5a0..029a4edb7c 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1510,3 +1510,20 @@ test "take address of temporary async frame" { }; S.doTheTest(); } + +test "noasync await" { + const S = struct { + fn doTheTest() void { + var frame = async foo(false); + expect(noasync await frame == 42); + } + + fn foo(want_suspend: bool) i32 { + if (want_suspend) { + suspend; + } + return 42; + } + }; + S.doTheTest(); +} From 7f7d1fbe5ad16fd41eeaeb20e3e71a39bdd3f991 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 01:32:15 -0500 Subject: [PATCH 008/109] Implement noasync awaits Note that there is not yet runtime safety for this. See #3157 --- src/all_types.hpp | 3 +++ src/analyze.cpp | 8 ++++---- src/codegen.cpp | 4 +++- src/ir.cpp | 15 ++++++++++----- src/parser.cpp | 4 ++++ test/stage1/behavior/async_fn.zig | 4 ++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index b514f4ecbc..95f291b343 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1139,6 +1139,7 @@ struct AstNodeErrorType { }; struct AstNodeAwaitExpr { + Token *noasync_token; AstNode *expr; }; @@ -4500,6 +4501,7 @@ struct IrInstSrcAwait { IrInstSrc *frame; ResultLoc *result_loc; + bool is_noasync; }; struct IrInstGenAwait { @@ -4508,6 +4510,7 @@ struct IrInstGenAwait { IrInstGen *frame; IrInstGen *result_loc; ZigFn *target_fn; + bool is_noasync; }; struct IrInstSrcResume { diff --git a/src/analyze.cpp b/src/analyze.cpp index fc1a805d82..98366bc87d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4710,8 +4710,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstGenAwait *await = fn->await_list.at(i); - // TODO If this is a noasync await, it doesn't count - // https://github.com/ziglang/zig/issues/3157 + if (await->is_noasync) continue; switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async, CallModifierNone)) { @@ -6315,8 +6314,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { // The funtion call result of foo() must be spilled. for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstGenAwait *await = fn->await_list.at(i); - // TODO If this is a noasync await, it doesn't suspend - // https://github.com/ziglang/zig/issues/3157 + if (await->is_noasync) { + continue; + } if (await->base.value->special != ConstValSpecialRuntime) { // Known at comptime. No spill, no suspend. continue; diff --git a/src/codegen.cpp b/src/codegen.cpp index 0f6988f986..a0bc56f093 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6188,7 +6188,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI LLVMValueRef result_loc = (instruction->result_loc == nullptr) ? nullptr : ir_llvm_value(g, instruction->result_loc); - if (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)) { + if (instruction->is_noasync || + (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn))) + { return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, ptr_result_type, result_loc, true); } diff --git a/src/ir.cpp b/src/ir.cpp index 323fa4ba6f..c87424b25e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4956,11 +4956,12 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins } static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *frame, ResultLoc *result_loc) + IrInstSrc *frame, ResultLoc *result_loc, bool is_noasync) { IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); instruction->frame = frame; instruction->result_loc = result_loc; + instruction->is_noasync = is_noasync; ir_ref_instruction(frame, irb->current_basic_block); @@ -4968,13 +4969,14 @@ static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *s } static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, - IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc) + IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_noasync) { IrInstGenAwait *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->frame = frame; instruction->result_loc = result_loc; + instruction->is_noasync = is_noasync; ir_ref_inst_gen(frame, ira->new_irb.current_basic_block); if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); @@ -9953,6 +9955,8 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no { assert(node->type == NodeTypeAwaitExpr); + bool is_noasync = node->data.await_expr.noasync_token != nullptr; + AstNode *expr_node = node->data.await_expr.expr; if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; @@ -9985,7 +9989,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no if (target_inst == irb->codegen->invalid_inst_src) return irb->codegen->invalid_inst_src; - IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc); + IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_noasync); return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); } @@ -29505,7 +29509,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i ir_assert(fn_entry != nullptr, &instruction->base.base); // If it's not @Frame(func) then it's definitely a suspend point - if (target_fn == nullptr) { + if (target_fn == nullptr && !instruction->is_noasync) { if (fn_entry->inferred_async_node == nullptr) { fn_entry->inferred_async_node = instruction->base.base.source_node; } @@ -29528,7 +29532,8 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i result_loc = nullptr; } - IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc); + IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc, + instruction->is_noasync); result->target_fn = target_fn; fn_entry->await_list.append(result); return ir_finish_anal(ira, &result->base); diff --git a/src/parser.cpp b/src/parser.cpp index ef2121e20d..c8c53e81b7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2596,10 +2596,14 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { return res; } + Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync); Token *await = eat_token_if(pc, TokenIdKeywordAwait); if (await != nullptr) { AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await); + res->data.await_expr.noasync_token = noasync_token; return res; + } else if (noasync_token != nullptr) { + put_back_token(pc); } return nullptr; diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 029a4edb7c..b04d4e2b5d 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1513,9 +1513,12 @@ test "take address of temporary async frame" { test "noasync await" { const S = struct { + var finished = false; + fn doTheTest() void { var frame = async foo(false); expect(noasync await frame == 42); + finished = true; } fn foo(want_suspend: bool) i32 { @@ -1526,4 +1529,5 @@ test "noasync await" { } }; S.doTheTest(); + expect(S.finished); } From 5e37fc0746a75ed319fc57ae62d8cc966382c592 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 01:45:48 -0500 Subject: [PATCH 009/109] more user-friendly error message for some clang diagnostics See #4455 --- src/error.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.cpp b/src/error.cpp index 08575d15ec..871b6b9e35 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -64,7 +64,7 @@ const char *err_str(Error err) { case ErrorInvalidCpuFeatures: return "invalid CPU features"; case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface"; - case ErrorASTUnitFailure: return "ASTUnit failure"; + case ErrorASTUnitFailure: return "compiler bug: clang encountered a compile error, but the libclang API does not expose the error. See https://github.com/ziglang/zig/issues/4455 for more details"; } return "(invalid error)"; } From 4b02a39aa93b0043f05de0d90443051c019643ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 13:25:30 -0500 Subject: [PATCH 010/109] self-hosted libc detection * libc_installation.cpp is deleted. src-self-hosted/libc_installation.zig is now used for both stage1 and stage2 compilers. * (breaking) move `std.fs.File.access` to `std.fs.Dir.access`. The API now encourages use with an open directory handle. * Add `std.os.faccessat` and related functions. * Deprecate the "C" suffix naming convention for null-terminated parameters. "C" should be used when it is related to libc. However null-terminated parameters often have to do with the native system ABI rather than libc. "Z" suffix is the new convention. For example, `std.os.openC` is deprecated in favor of `std.os.openZ`. * Add `std.mem.dupeZ` for using an allocator to copy memory and add a null terminator. * Remove dead struct field `std.ChildProcess.llnode`. * Introduce `std.event.Batch`. This API allows expressing concurrency without forcing code to be async. It requires no Allocator and does not introduce any failure conditions. However it is not thread-safe. * There is now an ongoing experiment to transition away from `std.event.Group` in favor of `std.event.Batch`. * `std.os.execvpeC` calls `getenvZ` rather than `getenv`. This is slightly more efficient on most systems, and works around a limitation of `getenv` lack of integration with libc. * (breaking) `std.os.AccessError` gains `FileBusy`, `SymLinkLoop`, and `ReadOnlyFileSystem`. Previously these error codes were all reported as `PermissionDenied`. * Add `std.Target.isDragonFlyBSD`. * stage2: access to the windows_sdk functions is done with a manually maintained .zig binding file instead of `@cImport`. * Update src-self-hosted/libc_installation.zig with all the improvements that stage1 has seen to src/libc_installation.cpp until now. In addition, it now takes advantage of Batch so that evented I/O mode takes advantage of concurrency, but it still works in blocking I/O mode, which is how it is used in stage1. --- CMakeLists.txt | 1 - build.zig | 2 +- lib/std/c.zig | 1 + lib/std/child_process.zig | 3 - lib/std/event.zig | 2 + lib/std/event/batch.zig | 139 +++++++ lib/std/event/group.zig | 5 + lib/std/fs.zig | 32 ++ lib/std/fs/file.zig | 25 -- lib/std/mem.zig | 10 +- lib/std/os.zig | 65 ++- lib/std/os/test.zig | 2 +- lib/std/target.zig | 7 + lib/std/time.zig | 1 + src-self-hosted/c.zig | 1 - src-self-hosted/libc_installation.zig | 569 ++++++++++++++------------ src-self-hosted/stage1.zig | 229 ++++++++++- src-self-hosted/windows_sdk.zig | 22 + src/all_types.hpp | 5 +- src/codegen.cpp | 64 +-- src/codegen.hpp | 5 +- src/error.cpp | 14 + src/libc_installation.cpp | 498 ---------------------- src/libc_installation.hpp | 35 -- src/link.cpp | 14 +- src/main.cpp | 24 +- src/os.cpp | 102 ----- src/os.hpp | 4 - src/userland.cpp | 22 + src/userland.h | 41 +- src/windows_sdk.h | 4 + 31 files changed, 930 insertions(+), 1018 deletions(-) create mode 100644 lib/std/event/batch.zig create mode 100644 src-self-hosted/windows_sdk.zig delete mode 100644 src/libc_installation.cpp delete mode 100644 src/libc_installation.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 71d4e2cda3..5a4a6d3199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,7 +457,6 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/heap.cpp" "${CMAKE_SOURCE_DIR}/src/ir.cpp" "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" - "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" "${CMAKE_SOURCE_DIR}/src/link.cpp" "${CMAKE_SOURCE_DIR}/src/mem.cpp" "${CMAKE_SOURCE_DIR}/src/os.cpp" diff --git a/build.zig b/build.zig index 673fbfab7d..4567b63029 100644 --- a/build.zig +++ b/build.zig @@ -175,7 +175,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { } fn fileExists(filename: []const u8) !bool { - fs.File.access(filename) catch |err| switch (err) { + fs.cwd().access(filename, .{}) catch |err| switch (err) { error.FileNotFound => return false, else => return err, }; diff --git a/lib/std/c.zig b/lib/std/c.zig index e0c84beb78..93c6c24664 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -96,6 +96,7 @@ pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8; pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int; pub extern "c" fn fork() c_int; pub extern "c" fn access(path: [*:0]const u8, mode: c_uint) c_int; +pub extern "c" fn faccessat(dirfd: fd_t, path: [*:0]const u8, mode: c_uint, flags: c_uint) c_int; pub extern "c" fn pipe(fds: *[2]fd_t) c_int; pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int; diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index fd67e3a680..f3626f5249 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -48,7 +48,6 @@ pub const ChildProcess = struct { cwd: ?[]const u8, err_pipe: if (builtin.os == .windows) void else [2]os.fd_t, - llnode: if (builtin.os == .windows) void else TailQueue(*ChildProcess).Node, pub const SpawnError = error{ OutOfMemory, @@ -90,7 +89,6 @@ pub const ChildProcess = struct { .handle = undefined, .thread_handle = undefined, .err_pipe = undefined, - .llnode = undefined, .term = null, .env_map = null, .cwd = null, @@ -453,7 +451,6 @@ pub const ChildProcess = struct { self.pid = pid; self.err_pipe = err_pipe; - self.llnode = TailQueue(*ChildProcess).Node.init(self); self.term = null; if (self.stdin_behavior == StdIo.Pipe) { diff --git a/lib/std/event.zig b/lib/std/event.zig index 64d73a25e1..d042e2ad9b 100644 --- a/lib/std/event.zig +++ b/lib/std/event.zig @@ -1,6 +1,7 @@ pub const Channel = @import("event/channel.zig").Channel; pub const Future = @import("event/future.zig").Future; pub const Group = @import("event/group.zig").Group; +pub const Batch = @import("event/batch.zig").Batch; pub const Lock = @import("event/lock.zig").Lock; pub const Locked = @import("event/locked.zig").Locked; pub const RwLock = @import("event/rwlock.zig").RwLock; @@ -11,6 +12,7 @@ test "import event tests" { _ = @import("event/channel.zig"); _ = @import("event/future.zig"); _ = @import("event/group.zig"); + _ = @import("event/batch.zig"); _ = @import("event/lock.zig"); _ = @import("event/locked.zig"); _ = @import("event/rwlock.zig"); diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig new file mode 100644 index 0000000000..82dadb91be --- /dev/null +++ b/lib/std/event/batch.zig @@ -0,0 +1,139 @@ +const std = @import("../std.zig"); +const testing = std.testing; + +/// Performs multiple async functions in parallel, without heap allocation. +/// Async function frames are managed externally to this abstraction, and +/// passed in via the `add` function. Once all the jobs are added, call `wait`. +/// This API is *not* thread-safe. The object must be accessed from one thread at +/// a time, however, it need not be the same thread. +pub fn Batch( + /// The return value for each job. + /// If a job slot was re-used due to maxed out concurrency, then its result + /// value will be overwritten. The values can be accessed with the `results` field. + comptime Result: type, + /// How many jobs to run in parallel. + comptime max_jobs: comptime_int, + /// Controls whether the `add` and `wait` functions will be async functions. + comptime async_behavior: enum { + /// Observe the value of `std.io.is_async` to decide whether `add` + /// and `wait` will be async functions. Asserts that the jobs do not suspend when + /// `std.io.mode == .blocking`. This is a generally safe assumption, and the + /// usual recommended option for this parameter. + auto_async, + + /// Always uses the `noasync` keyword when using `await` on the jobs, + /// making `add` and `wait` non-async functions. Asserts that the jobs do not suspend. + never_async, + + /// `add` and `wait` use regular `await` keyword, making them async functions. + always_async, + }, +) type { + return struct { + jobs: [max_jobs]Job, + next_job_index: usize, + collected_result: CollectedResult, + + const Job = struct { + frame: ?anyframe->Result, + result: Result, + }; + + const Self = @This(); + + const CollectedResult = switch (@typeInfo(Result)) { + .ErrorUnion => Result, + else => void, + }; + + const async_ok = switch (async_behavior) { + .auto_async => std.io.is_async, + .never_async => false, + .always_async => true, + }; + + pub fn init() Self { + return Self{ + .jobs = [1]Job{ + .{ + .frame = null, + .result = undefined, + }, + } ** max_jobs, + .next_job_index = 0, + .collected_result = {}, + }; + } + + /// Add a frame to the Batch. If all jobs are in-flight, then this function + /// waits until one completes. + /// This function is *not* thread-safe. It must be called from one thread at + /// a time, however, it need not be the same thread. + /// TODO: "select" language feature to use the next available slot, rather than + /// awaiting the next index. + pub fn add(self: *Self, frame: anyframe->Result) void { + const job = &self.jobs[self.next_job_index]; + self.next_job_index = (self.next_job_index + 1) % max_jobs; + if (job.frame) |existing| { + job.result = if (async_ok) await existing else noasync await existing; + if (CollectedResult != void) { + job.result catch |err| { + self.collected_result = err; + }; + } + } + job.frame = frame; + } + + /// Wait for all the jobs to complete. + /// Safe to call any number of times. + /// If `Result` is an error union, this function returns the last error that occurred, if any. + /// Unlike the `results` field, the return value of `wait` will report any error that occurred; + /// hitting max parallelism will not compromise the result. + /// This function is *not* thread-safe. It must be called from one thread at + /// a time, however, it need not be the same thread. + pub fn wait(self: *Self) CollectedResult { + for (self.jobs) |*job| if (job.frame) |f| { + job.result = if (async_ok) await f else noasync await f; + if (CollectedResult != void) { + job.result catch |err| { + self.collected_result = err; + }; + } + job.frame = null; + }; + return self.collected_result; + } + }; +} + +test "std.event.Batch" { + var count: usize = 0; + var batch = Batch(void, 2).init(); + batch.add(&async sleepALittle(&count)); + batch.add(&async increaseByTen(&count)); + batch.wait(); + testing.expect(count == 11); + + var another = Batch(anyerror!void, 2).init(); + another.add(&async somethingElse()); + another.add(&async doSomethingThatFails()); + testing.expectError(error.ItBroke, another.wait()); +} + +fn sleepALittle(count: *usize) void { + std.time.sleep(1 * std.time.millisecond); + _ = @atomicRmw(usize, count, .Add, 1, .SeqCst); +} + +fn increaseByTen(count: *usize) void { + var i: usize = 0; + while (i < 10) : (i += 1) { + _ = @atomicRmw(usize, count, .Add, 1, .SeqCst); + } +} + +fn doSomethingThatFails() anyerror!void {} +fn somethingElse() anyerror!void { + return error.ItBroke; +} diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig index 98ebdbd1f8..ac1bf68245 100644 --- a/lib/std/event/group.zig +++ b/lib/std/event/group.zig @@ -5,6 +5,11 @@ const testing = std.testing; const Allocator = std.mem.Allocator; /// ReturnType must be `void` or `E!void` +/// TODO This API was created back with the old design of async/await, when calling any +/// async function required an allocator. There is an ongoing experiment to transition +/// all uses of this API to the simpler and more resource-aware `std.event.Batch` API. +/// If the transition goes well, all usages of `Group` will be gone, and this API +/// will be deleted. pub fn Group(comptime ReturnType: type) type { return struct { frame_stack: Stack, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index a39f283e55..c96aeeafc7 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1323,6 +1323,38 @@ pub const Dir = struct { defer file.close(); try file.write(data); } + + pub const AccessError = os.AccessError; + + /// Test accessing `path`. + /// `path` is UTF8-encoded. + /// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function. + /// For example, instead of testing if a file exists and then opening it, just + /// open it and handle the error for file not found. + pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void { + const path_c = try os.toPosixPath(sub_path); + return self.accessZ(&path_c, flags); + } + + /// Same as `access` except the path parameter is null-terminated. + pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void { + const os_mode = if (flags.write and flags.read) + @as(u32, os.R_OK | os.W_OK) + else if (flags.write) + @as(u32, os.W_OK) + else + @as(u32, os.F_OK); + const result = if (need_async_thread) + std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode) + else + os.faccessatZ(self.fd, sub_path, os_mode, 0); + return result; + } + + /// Same as `access` except the parameter is null-terminated UTF16LE-encoded. + pub fn accessW(self: Dir, sub_path: [*:0]const u16, flags: File.OpenFlags) AccessError!void { + return os.faccessatW(self.fd, sub_path, 0, 0); + } }; /// Returns an handle to the current working directory that is open for traversal. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 92dcfefad0..a3a428e77b 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -60,31 +60,6 @@ pub const File = struct { mode: Mode = default_mode, }; - /// Test for the existence of `path`. - /// `path` is UTF8-encoded. - /// In general it is recommended to avoid this function. For example, - /// instead of testing if a file exists and then opening it, just - /// open it and handle the error for file not found. - /// TODO: deprecate this and move it to `std.fs.Dir`. - /// TODO: integrate with async I/O - pub fn access(path: []const u8) !void { - return os.access(path, os.F_OK); - } - - /// Same as `access` except the parameter is null-terminated. - /// TODO: deprecate this and move it to `std.fs.Dir`. - /// TODO: integrate with async I/O - pub fn accessC(path: [*:0]const u8) !void { - return os.accessC(path, os.F_OK); - } - - /// Same as `access` except the parameter is null-terminated UTF16LE-encoded. - /// TODO: deprecate this and move it to `std.fs.Dir`. - /// TODO: integrate with async I/O - pub fn accessW(path: [*:0]const u16) !void { - return os.accessW(path, os.F_OK); - } - /// Upon success, the stream is in an uninitialized state. To continue using it, /// you must use the open() function. pub fn close(self: File) void { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a1b4a3c809..71be738def 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -387,13 +387,21 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool { return true; } -/// Copies ::m to newly allocated memory. Caller is responsible to free it. +/// Copies `m` to newly allocated memory. Caller owns the memory. pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T { const new_buf = try allocator.alloc(T, m.len); copy(T, new_buf, m); return new_buf; } +/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory. +pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T { + const new_buf = try allocator.alloc(T, m.len + 1); + copy(T, new_buf, m); + new_buf[m.len] = 0; + return new_buf[0..m.len :0]; +} + /// Remove values from the beginning of a slice. pub fn trimLeft(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { var begin: usize = 0; diff --git a/lib/std/os.zig b/lib/std/os.zig index 73b6cbb302..fd85f8801b 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -950,7 +950,7 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e const file_slice = mem.toSliceConst(u8, file); if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp); - const PATH = getenv("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; + const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; var path_buf: [MAX_PATH_BYTES]u8 = undefined; var it = mem.tokenize(PATH, ":"); var seen_eacces = false; @@ -1038,7 +1038,7 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) } /// Get an environment variable. -/// See also `getenvC`. +/// See also `getenvZ`. /// TODO make this go through libc when we have it pub fn getenv(key: []const u8) ?[]const u8 { for (environ) |ptr| { @@ -1056,9 +1056,12 @@ pub fn getenv(key: []const u8) ?[]const u8 { return null; } +/// Deprecated in favor of `getenvZ`. +pub const getenvC = getenvZ; + /// Get an environment variable with a null-terminated name. /// See also `getenv`. -pub fn getenvC(key: [*:0]const u8) ?[]const u8 { +pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { if (builtin.link_libc) { const value = system.getenv(key) orelse return null; return mem.toSliceConst(u8, value); @@ -2452,6 +2455,9 @@ pub const AccessError = error{ InputOutput, SystemResources, BadPathName, + FileBusy, + SymLinkLoop, + ReadOnlyFileSystem, /// On Windows, file paths must be valid Unicode. InvalidUtf8, @@ -2469,8 +2475,11 @@ pub fn access(path: []const u8, mode: u32) AccessError!void { return accessC(&path_c, mode); } +/// Deprecated in favor of `accessZ`. +pub const accessC = accessZ; + /// Same as `access` except `path` is null-terminated. -pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void { +pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { if (builtin.os == .windows) { const path_w = try windows.cStrToPrefixedFileW(path); _ = try windows.GetFileAttributesW(&path_w); @@ -2479,12 +2488,11 @@ pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void { switch (errno(system.access(path, mode))) { 0 => return, EACCES => return error.PermissionDenied, - EROFS => return error.PermissionDenied, - ELOOP => return error.PermissionDenied, - ETXTBSY => return error.PermissionDenied, + EROFS => return error.ReadOnlyFileSystem, + ELOOP => return error.SymLinkLoop, + ETXTBSY => return error.FileBusy, ENOTDIR => return error.FileNotFound, ENOENT => return error.FileNotFound, - ENAMETOOLONG => return error.NameTooLong, EINVAL => unreachable, EFAULT => unreachable, @@ -2510,6 +2518,47 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v } } +/// Check user's permissions for a file, based on an open directory handle. +/// TODO currently this ignores `mode` and `flags` on Windows. +pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void { + if (builtin.os == .windows) { + const path_w = try windows.sliceToPrefixedFileW(path); + return faccessatW(dirfd, &path_w, mode, flags); + } + const path_c = try toPosixPath(path); + return faccessatZ(dirfd, &path_c, mode, flags); +} + +/// Same as `faccessat` except the path parameter is null-terminated. +pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void { + if (builtin.os == .windows) { + const path_w = try windows.cStrToPrefixedFileW(path); + return faccessatW(dirfd, &path_w, mode, flags); + } + switch (errno(system.faccessat(dirfd, path, mode, flags))) { + 0 => return, + EACCES => return error.PermissionDenied, + EROFS => return error.ReadOnlyFileSystem, + ELOOP => return error.SymLinkLoop, + ETXTBSY => return error.FileBusy, + ENOTDIR => return error.FileNotFound, + ENOENT => return error.FileNotFound, + ENAMETOOLONG => return error.NameTooLong, + EINVAL => unreachable, + EFAULT => unreachable, + EIO => return error.InputOutput, + ENOMEM => return error.SystemResources, + else => |err| return unexpectedErrno(err), + } +} + +/// Same as `faccessat` except asserts the target is Windows and the path parameter +/// is null-terminated WTF-16 encoded. +/// TODO currently this ignores `mode` and `flags` +pub fn faccessatW(dirfd: fd_t, path: [*:0]const u16, mode: u32, flags: u32) AccessError!void { + @compileError("TODO implement faccessatW on Windows"); +} + pub const PipeError = error{ SystemFdQuotaExceeded, ProcessFdQuotaExceeded, diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 9b967955ec..9ca4044a75 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -29,7 +29,7 @@ test "makePath, put some files in it, deleteTree" { test "access file" { try fs.makePath(a, "os_test_tmp"); - if (File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt")) |ok| { + if (fs.cwd().access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", .{})) |ok| { @panic("expected error"); } else |err| { expect(err == error.FileNotFound); diff --git a/lib/std/target.zig b/lib/std/target.zig index 308f1d9923..fb3fe96075 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1037,6 +1037,13 @@ pub const Target = union(enum) { }; } + pub fn isDragonFlyBSD(self: Target) bool { + return switch (self.getOs()) { + .dragonfly => true, + else => false, + }; + } + pub fn isUefi(self: Target) bool { return switch (self.getOs()) { .uefi => true, diff --git a/lib/std/time.zig b/lib/std/time.zig index 716c999577..a5f66122cb 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -8,6 +8,7 @@ const math = std.math; pub const epoch = @import("time/epoch.zig"); /// Spurious wakeups are possible and no precision of timing is guaranteed. +/// TODO integrate with evented I/O pub fn sleep(nanoseconds: u64) void { if (builtin.os == .windows) { const ns_per_ms = ns_per_s / ms_per_s; diff --git a/src-self-hosted/c.zig b/src-self-hosted/c.zig index 1de2b6a24c..ae9a886d1b 100644 --- a/src-self-hosted/c.zig +++ b/src-self-hosted/c.zig @@ -4,5 +4,4 @@ pub usingnamespace @cImport({ @cInclude("inttypes.h"); @cInclude("config.h"); @cInclude("zig_llvm.h"); - @cInclude("windows_sdk.h"); }); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 701823c4be..8f62e91e38 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -1,20 +1,29 @@ const std = @import("std"); const builtin = @import("builtin"); -const event = std.event; const util = @import("util.zig"); const Target = std.Target; -const c = @import("c.zig"); const fs = std.fs; const Allocator = std.mem.Allocator; +const Batch = std.event.Batch; + +const is_darwin = Target.current.isDarwin(); +const is_windows = Target.current.isWindows(); +const is_freebsd = Target.current.isFreeBSD(); +const is_netbsd = Target.current.isNetBSD(); +const is_linux = Target.current.isLinux(); +const is_dragonfly = Target.current.isDragonFlyBSD(); +const is_gnu = Target.current.isGnu(); + +usingnamespace @import("windows_sdk.zig"); /// See the render function implementation for documentation of the fields. pub const LibCInstallation = struct { - include_dir: []const u8, - lib_dir: ?[]const u8, - static_lib_dir: ?[]const u8, - msvc_lib_dir: ?[]const u8, - kernel32_lib_dir: ?[]const u8, - dynamic_linker_path: ?[]const u8, + include_dir: ?[:0]const u8 = null, + sys_include_dir: ?[:0]const u8 = null, + crt_dir: ?[:0]const u8 = null, + static_crt_dir: ?[:0]const u8 = null, + msvc_lib_dir: ?[:0]const u8 = null, + kernel32_lib_dir: ?[:0]const u8 = null, pub const FindError = error{ OutOfMemory, @@ -30,28 +39,20 @@ pub const LibCInstallation = struct { }; pub fn parse( - self: *LibCInstallation, allocator: *Allocator, libc_file: []const u8, stderr: *std.io.OutStream(fs.File.WriteError), - ) !void { - self.initEmpty(); + ) !LibCInstallation { + var self: LibCInstallation = .{}; - const keys = [_][]const u8{ - "include_dir", - "lib_dir", - "static_lib_dir", - "msvc_lib_dir", - "kernel32_lib_dir", - "dynamic_linker_path", - }; + const fields = std.meta.fields(LibCInstallation); const FoundKey = struct { found: bool, - allocated: ?[]u8, + allocated: ?[:0]u8, }; - var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** keys.len; + var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** fields.len; errdefer { - self.initEmpty(); + self = .{}; for (found_keys) |found_key| { if (found_key.allocated) |s| allocator.free(s); } @@ -69,152 +70,188 @@ pub const LibCInstallation = struct { return error.ParseError; }; const value = line_it.rest(); - inline for (keys) |key, i| { - if (std.mem.eql(u8, name, key)) { + inline for (fields) |field, i| { + if (std.mem.eql(u8, name, field.name)) { found_keys[i].found = true; - switch (@typeInfo(@TypeOf(@field(self, key)))) { - .Optional => { - if (value.len == 0) { - @field(self, key) = null; - } else { - found_keys[i].allocated = try std.mem.dupe(allocator, u8, value); - @field(self, key) = found_keys[i].allocated; - } - }, - else => { - if (value.len == 0) { - try stderr.print("field cannot be empty: {}\n", .{key}); - return error.ParseError; - } - const dupe = try std.mem.dupe(allocator, u8, value); - found_keys[i].allocated = dupe; - @field(self, key) = dupe; - }, + if (value.len == 0) { + @field(self, field.name) = null; + } else { + found_keys[i].allocated = try std.mem.dupeZ(allocator, u8, value); + @field(self, field.name) = found_keys[i].allocated; } break; } } } - for (found_keys) |found_key, i| { - if (!found_key.found) { - try stderr.print("missing field: {}\n", .{keys[i]}); + inline for (fields) |field, i| { + if (!found_keys[i].found) { + try stderr.print("missing field: {}\n", .{field.name}); return error.ParseError; } } + if (self.include_dir == null) { + try stderr.print("include_dir may not be empty\n", .{}); + return error.ParseError; + } + if (self.sys_include_dir == null) { + try stderr.print("sys_include_dir may not be empty\n", .{}); + return error.ParseError; + } + if (self.crt_dir == null and is_darwin) { + try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.getOs())}); + return error.ParseError; + } + if (self.static_crt_dir == null and is_windows and is_gnu) { + try stderr.print("static_crt_dir may not be empty for {}-{}\n", .{ + @tagName(Target.current.getOs()), + @tagName(Target.current.getAbi()), + }); + return error.ParseError; + } + if (self.msvc_lib_dir == null and is_windows and !is_gnu) { + try stderr.print("msvc_lib_dir may not be empty for {}-{}\n", .{ + @tagName(Target.current.getOs()), + @tagName(Target.current.getAbi()), + }); + return error.ParseError; + } + if (self.kernel32_lib_dir == null and is_windows and !is_gnu) { + try stderr.print("kernel32_lib_dir may not be empty for {}-{}\n", .{ + @tagName(Target.current.getOs()), + @tagName(Target.current.getAbi()), + }); + return error.ParseError; + } + + return self; } - pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(fs.File.WriteError)) !void { + pub fn render(self: LibCInstallation, out: *std.io.OutStream(fs.File.WriteError)) !void { @setEvalBranchQuota(4000); - const lib_dir = self.lib_dir orelse ""; - const static_lib_dir = self.static_lib_dir orelse ""; + const include_dir = self.include_dir orelse ""; + const sys_include_dir = self.sys_include_dir orelse ""; + const crt_dir = self.crt_dir orelse ""; + const static_crt_dir = self.static_crt_dir orelse ""; const msvc_lib_dir = self.msvc_lib_dir orelse ""; const kernel32_lib_dir = self.kernel32_lib_dir orelse ""; - const dynamic_linker_path = self.dynamic_linker_path orelse util.getDynamicLinkerPath(Target{ .Native = {} }); + try out.print( \\# The directory that contains `stdlib.h`. - \\# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null` + \\# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null` \\include_dir={} \\ - \\# The directory that contains `crt1.o`. - \\# On Linux, can be found with `cc -print-file-name=crt1.o`. + \\# The system-specific include directory. May be the same as `include_dir`. + \\# On Windows it's the directory that includes `vcruntime.h`. + \\# On POSIX it's the directory that includes `sys/errno.h`. + \\sys_include_dir={} + \\ + \\# The directory that contains `crt1.o` or `crt2.o`. + \\# On POSIX, can be found with `cc -print-file-name=crt1.o`. \\# Not needed when targeting MacOS. - \\lib_dir={} + \\crt_dir={} \\ \\# The directory that contains `crtbegin.o`. - \\# On Linux, can be found with `cc -print-file-name=crtbegin.o`. - \\# Not needed when targeting MacOS or Windows. - \\static_lib_dir={} + \\# On POSIX, can be found with `cc -print-file-name=crtbegin.o`. + \\# Not needed when targeting MacOS. + \\static_crt_dir={} \\ \\# The directory that contains `vcruntime.lib`. - \\# Only needed when targeting Windows. + \\# Only needed when targeting MSVC on Windows. \\msvc_lib_dir={} \\ \\# The directory that contains `kernel32.lib`. - \\# Only needed when targeting Windows. + \\# Only needed when targeting MSVC on Windows. \\kernel32_lib_dir={} \\ - \\# The full path to the dynamic linker, on the target system. - \\# Only needed when targeting Linux. - \\dynamic_linker_path={} - \\ - , .{ self.include_dir, lib_dir, static_lib_dir, msvc_lib_dir, kernel32_lib_dir, dynamic_linker_path }); + , .{ + include_dir, + sys_include_dir, + crt_dir, + static_crt_dir, + msvc_lib_dir, + kernel32_lib_dir, + }); } /// Finds the default, native libc. - pub fn findNative(self: *LibCInstallation, allocator: *Allocator) !void { - self.initEmpty(); - var group = event.Group(FindError!void).init(allocator); - errdefer group.wait() catch {}; - var windows_sdk: ?*c.ZigWindowsSDK = null; - errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk)); + pub fn findNative(allocator: *Allocator) !LibCInstallation { + var self: LibCInstallation = .{}; - switch (builtin.os) { - .windows => { - var sdk: *c.ZigWindowsSDK = undefined; - switch (c.zig_find_windows_sdk(@ptrCast(?[*]?[*]c.ZigWindowsSDK, &sdk))) { - c.ZigFindWindowsSdkError.None => { - windows_sdk = sdk; + if (is_windows) { + if (is_gnu) { + var batch = Batch(FindError!void, 3, .auto_async).init(); + batch.add(&async self.findNativeIncludeDirPosix(allocator)); + batch.add(&async self.findNativeCrtDirPosix(allocator)); + batch.add(&async self.findNativeStaticCrtDirPosix(allocator)); + try batch.wait(); + } else { + var sdk: *ZigWindowsSDK = undefined; + switch (zig_find_windows_sdk(&sdk)) { + .None => { + defer zig_free_windows_sdk(sdk); - if (sdk.msvc_lib_dir_ptr != 0) { - self.msvc_lib_dir = try std.mem.dupe(allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); - } - try group.call(findNativeKernel32LibDir, .{ allocator, self, sdk }); - try group.call(findNativeIncludeDirWindows, .{ self, allocator, sdk }); - try group.call(findNativeLibDirWindows, .{ self, allocator, sdk }); + var batch = Batch(FindError!void, 5, .auto_async).init(); + batch.add(&async self.findNativeMsvcIncludeDir(allocator, sdk)); + batch.add(&async self.findNativeMsvcLibDir(allocator, sdk)); + batch.add(&async self.findNativeKernel32LibDir(allocator, sdk)); + batch.add(&async self.findNativeIncludeDirWindows(allocator, sdk)); + batch.add(&async self.findNativeCrtDirWindows(allocator, sdk)); + try batch.wait(); }, - c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory, - c.ZigFindWindowsSdkError.NotFound => return error.NotFound, - c.ZigFindWindowsSdkError.PathTooLong => return error.NotFound, + .OutOfMemory => return error.OutOfMemory, + .NotFound => return error.NotFound, + .PathTooLong => return error.NotFound, } - }, - .linux => { - try group.call(findNativeIncludeDirLinux, .{ self, allocator }); - try group.call(findNativeLibDirLinux, .{ self, allocator }); - try group.call(findNativeStaticLibDir, .{ self, allocator }); - try group.call(findNativeDynamicLinker, .{ self, allocator }); - }, - .macosx, .freebsd, .netbsd => { - self.include_dir = try std.mem.dupe(allocator, u8, "/usr/include"); - }, - else => @compileError("unimplemented: find libc for this OS"), + } + } else { + var batch = Batch(FindError!void, 2, .auto_async).init(); + batch.add(&async self.findNativeIncludeDirPosix(allocator)); + if (is_freebsd or is_netbsd) { + self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib"); + } else if (is_linux or is_dragonfly) { + batch.add(&async self.findNativeCrtDirPosix(allocator)); + } + try batch.wait(); } - return group.wait(); + return self; } - async fn findNativeIncludeDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void { - const cc_exe = std.os.getenv("CC") orelse "cc"; + /// Must be the same allocator passed to `parse` or `findNative`. + pub fn deinit(self: *LibCInstallation, allocator: *Allocator) void { + const fields = std.meta.fields(LibCInstallation); + inline for (fields) |field| { + if (@field(self, field.name)) |payload| { + allocator.free(payload); + } + } + self.* = undefined; + } + + fn findNativeIncludeDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { + const dev_null = if (is_windows) "nul" else "/dev/null"; + const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; const argv = [_][]const u8{ cc_exe, "-E", "-Wp,-v", "-xc", - "/dev/null", + dev_null, }; - // TODO make this use event loop - const errorable_result = std.ChildProcess.exec(allocator, &argv, null, null, 1024 * 1024); - const exec_result = if (std.debug.runtime_safety) blk: { - break :blk errorable_result catch unreachable; - } else blk: { - break :blk errorable_result catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => return error.UnableToSpawnCCompiler, - }; + const max_bytes = 1024 * 1024; + const exec_res = std.ChildProcess.exec(allocator, &argv, null, null, max_bytes) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => return error.UnableToSpawnCCompiler, }; defer { - allocator.free(exec_result.stdout); - allocator.free(exec_result.stderr); + allocator.free(exec_res.stdout); + allocator.free(exec_res.stderr); + } + switch (exec_res.term) { + .Exited => |code| if (code != 0) return error.CCompilerExitCode, + else => return error.CCompilerCrashed, } - switch (exec_result.term) { - .Exited => |code| { - if (code != 0) return error.CCompilerExitCode; - }, - else => { - return error.CCompilerCrashed; - }, - } - - var it = std.mem.tokenize(exec_result.stderr, "\n\r"); + var it = std.mem.tokenize(exec_res.stderr, "\n\r"); var search_paths = std.ArrayList([]const u8).init(allocator); defer search_paths.deinit(); while (it.next()) |line| { @@ -226,16 +263,44 @@ pub const LibCInstallation = struct { return error.CCompilerCannotFindHeaders; } - // search in reverse order + const include_dir_example_file = "stdlib.h"; + const sys_include_dir_example_file = if (is_windows) "sys\\types.h" else "sys/errno.h"; + var path_i: usize = 0; while (path_i < search_paths.len) : (path_i += 1) { + // search in reverse order const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); - const stdlib_path = try fs.path.join(allocator, &[_][]const u8{ search_path, "stdlib.h" }); - defer allocator.free(stdlib_path); + var search_dir = fs.cwd().openDirList(search_path) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => continue, - if (try fileExists(stdlib_path)) { - self.include_dir = try std.mem.dupe(allocator, u8, search_path); + else => return error.FileSystem, + }; + defer search_dir.close(); + + if (self.include_dir == null) { + if (search_dir.accessZ(include_dir_example_file, .{})) |_| { + self.include_dir = try std.mem.dupeZ(allocator, u8, search_path); + } else |err| switch (err) { + error.FileNotFound => {}, + else => return error.FileSystem, + } + } + + if (self.sys_include_dir == null) { + if (search_dir.accessZ(sys_include_dir_example_file, .{})) |_| { + self.sys_include_dir = try std.mem.dupeZ(allocator, u8, search_path); + } else |err| switch (err) { + error.FileNotFound => {}, + else => return error.FileSystem, + } + } + + if (self.include_dir != null and self.sys_include_dir != null) { + // Success. return; } } @@ -243,7 +308,7 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - async fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) !void { + fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) !void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -255,179 +320,152 @@ pub const LibCInstallation = struct { const stream = &std.io.BufferOutStream.init(&result_buf).stream; try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version }); - const stdlib_path = try fs.path.join( - allocator, - [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" }, - ); - defer allocator.free(stdlib_path); + var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => continue, - if (try fileExists(stdlib_path)) { - self.include_dir = result_buf.toOwnedSlice(); - return; - } + else => return error.FileSystem, + }; + defer dir.close(); + + dir.accessZ("stdlib.h", .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => return error.FileSystem, + }; + + self.include_dir = result_buf.toOwnedSlice(); + return; } return error.LibCStdLibHeaderNotFound; } - async fn findNativeLibDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void { + fn findNativeCrtDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); var result_buf = try std.Buffer.initSize(allocator, 0); defer result_buf.deinit(); + const arch_sub_dir = switch (builtin.arch) { + .i386 => "x86", + .x86_64 => "x64", + .arm, .armeb => "arm", + else => return error.UnsupportedArchitecture, + }; + for (searches) |search| { result_buf.shrink(0); const stream = &std.io.BufferOutStream.init(&result_buf).stream; - try stream.print("{}\\Lib\\{}\\ucrt\\", .{ search.path, search.version }); - switch (builtin.arch) { - .i386 => try stream.write("x86"), - .x86_64 => try stream.write("x64"), - .aarch64 => try stream.write("arm"), - else => return error.UnsupportedArchitecture, - } - const ucrt_lib_path = try fs.path.join( - allocator, - [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" }, - ); - defer allocator.free(ucrt_lib_path); - if (try fileExists(ucrt_lib_path)) { - self.lib_dir = result_buf.toOwnedSlice(); - return; - } + try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir }); + + var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => continue, + + else => return error.FileSystem, + }; + defer dir.close(); + + dir.accessZ("ucrt.lib", .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => return error.FileSystem, + }; + + self.crt_dir = result_buf.toOwnedSlice(); + return; } return error.LibCRuntimeNotFound; } - async fn findNativeLibDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void { - self.lib_dir = try ccPrintFileName(allocator, "crt1.o", true); + fn findNativeCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { + self.crt_dir = try ccPrintFileName(allocator, "crt1.o", .only_dir); } - async fn findNativeStaticLibDir(self: *LibCInstallation, allocator: *Allocator) FindError!void { - self.static_lib_dir = try ccPrintFileName(allocator, "crtbegin.o", true); + fn findNativeStaticCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { + self.static_crt_dir = try ccPrintFileName(allocator, "crtbegin.o", .only_dir); } - async fn findNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator) FindError!void { - var dyn_tests = [_]DynTest{ - DynTest{ - .name = "ld-linux-x86-64.so.2", - .result = null, - }, - DynTest{ - .name = "ld-musl-x86_64.so.1", - .result = null, - }, - }; - var group = event.Group(FindError!void).init(allocator); - errdefer group.wait() catch {}; - for (dyn_tests) |*dyn_test| { - try group.call(testNativeDynamicLinker, .{ self, allocator, dyn_test }); - } - try group.wait(); - for (dyn_tests) |*dyn_test| { - if (dyn_test.result) |result| { - self.dynamic_linker_path = result; - return; - } - } - } - - const DynTest = struct { - name: []const u8, - result: ?[]const u8, - }; - - async fn testNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator, dyn_test: *DynTest) FindError!void { - if (ccPrintFileName(allocator, dyn_test.name, false)) |result| { - dyn_test.result = result; - return; - } else |err| switch (err) { - error.LibCRuntimeNotFound => return, - else => return err, - } - } - - async fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void { + fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); var result_buf = try std.Buffer.initSize(allocator, 0); defer result_buf.deinit(); + const arch_sub_dir = switch (builtin.arch) { + .i386 => "x86", + .x86_64 => "x64", + .arm, .armeb => "arm", + else => return error.UnsupportedArchitecture, + }; + for (searches) |search| { result_buf.shrink(0); const stream = &std.io.BufferOutStream.init(&result_buf).stream; - try stream.print("{}\\Lib\\{}\\um\\", .{ search.path, search.version }); - switch (builtin.arch) { - .i386 => try stream.write("x86\\"), - .x86_64 => try stream.write("x64\\"), - .aarch64 => try stream.write("arm\\"), - else => return error.UnsupportedArchitecture, - } - const kernel32_path = try fs.path.join( - allocator, - [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" }, - ); - defer allocator.free(kernel32_path); - if (try fileExists(kernel32_path)) { - self.kernel32_lib_dir = result_buf.toOwnedSlice(); - return; - } + try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir }); + + var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => continue, + + else => return error.FileSystem, + }; + defer dir.close(); + + dir.accessZ("kernel32.lib", .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => return error.FileSystem, + }; + + self.kernel32_lib_dir = result_buf.toOwnedSlice(); + return; } return error.LibCKernel32LibNotFound; } - - fn initEmpty(self: *LibCInstallation) void { - self.* = LibCInstallation{ - .include_dir = @as([*]const u8, undefined)[0..0], - .lib_dir = null, - .static_lib_dir = null, - .msvc_lib_dir = null, - .kernel32_lib_dir = null, - .dynamic_linker_path = null, - }; - } }; +const default_cc_exe = if (is_windows) "cc.exe" else "cc"; + /// caller owns returned memory -fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 { - const cc_exe = std.os.getenv("CC") orelse "cc"; +pub fn ccPrintFileName( + allocator: *Allocator, + o_file: []const u8, + want_dirname: enum { full_path, only_dir }, +) ![:0]u8 { + const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{o_file}); defer allocator.free(arg1); const argv = [_][]const u8{ cc_exe, arg1 }; - // TODO This simulates evented I/O for the child process exec - event.Loop.startCpuBoundOperation(); - const errorable_result = std.ChildProcess.exec(allocator, &argv, null, null, 1024 * 1024); - const exec_result = if (std.debug.runtime_safety) blk: { - break :blk errorable_result catch unreachable; - } else blk: { - break :blk errorable_result catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => return error.UnableToSpawnCCompiler, - }; + const max_bytes = 1024 * 1024; + const exec_res = std.ChildProcess.exec(allocator, &argv, null, null, max_bytes) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => return error.UnableToSpawnCCompiler, }; defer { - allocator.free(exec_result.stdout); - allocator.free(exec_result.stderr); + allocator.free(exec_res.stdout); + allocator.free(exec_res.stderr); } - switch (exec_result.term) { - .Exited => |code| { - if (code != 0) return error.CCompilerExitCode; - }, - else => { - return error.CCompilerCrashed; - }, + switch (exec_res.term) { + .Exited => |code| if (code != 0) return error.CCompilerExitCode, + else => return error.CCompilerCrashed, } - var it = std.mem.tokenize(exec_result.stdout, "\n\r"); - const line = it.next() orelse return error.LibCRuntimeNotFound; - const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; - if (want_dirname) { - return std.mem.dupe(allocator, u8, dirname); - } else { - return std.mem.dupe(allocator, u8, line); + var it = std.mem.tokenize(exec_res.stdout, "\n\r"); + const line = it.next() orelse return error.LibCRuntimeNotFound; + switch (want_dirname) { + .full_path => return std.mem.dupeZ(allocator, u8, line), + .only_dir => { + const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; + return std.mem.dupeZ(allocator, u8, dirname); + }, } } @@ -436,34 +474,25 @@ const Search = struct { version: []const u8, }; -fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search { +fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search { var search_end: usize = 0; - if (sdk.path10_ptr != 0) { - if (sdk.version10_ptr != 0) { + if (sdk.path10_ptr) |path10_ptr| { + if (sdk.version10_ptr) |version10_ptr| { search_buf[search_end] = Search{ - .path = sdk.path10_ptr[0..sdk.path10_len], - .version = sdk.version10_ptr[0..sdk.version10_len], + .path = path10_ptr[0..sdk.path10_len], + .version = version10_ptr[0..sdk.version10_len], }; search_end += 1; } } - if (sdk.path81_ptr != 0) { - if (sdk.version81_ptr != 0) { + if (sdk.path81_ptr) |path81_ptr| { + if (sdk.version81_ptr) |version81_ptr| { search_buf[search_end] = Search{ - .path = sdk.path81_ptr[0..sdk.path81_len], - .version = sdk.version81_ptr[0..sdk.version81_len], + .path = path81_ptr[0..sdk.path81_len], + .version = version81_ptr[0..sdk.version81_len], }; search_end += 1; } } return search_buf[0..search_end]; } - -fn fileExists(path: []const u8) !bool { - if (fs.File.access(path)) |_| { - return true; - } else |err| switch (err) { - error.FileNotFound => return false, - else => return error.FileSystem, - } -} diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index ffa0754bb5..95719d47a9 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -14,6 +14,7 @@ const self_hosted_main = @import("main.zig"); const errmsg = @import("errmsg.zig"); const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; const assert = std.debug.assert; +const LibCInstallation = @import("libc_installation.zig").LibCInstallation; var stderr_file: fs.File = undefined; var stderr: *io.OutStream(fs.File.WriteError) = undefined; @@ -93,6 +94,20 @@ const Error = extern enum { InvalidLlvmCpuFeaturesFormat, UnknownApplicationBinaryInterface, ASTUnitFailure, + BadPathName, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + NoDevice, + DeviceBusy, + UnableToSpawnCCompiler, + CCompilerExitCode, + CCompilerCrashed, + CCompilerCannotFindHeaders, + LibCRuntimeNotFound, + LibCStdLibHeaderNotFound, + LibCKernel32LibNotFound, + UnsupportedArchitecture, }; const FILE = std.c.FILE; @@ -113,12 +128,12 @@ export fn stage2_translate_c( error.SemanticAnalyzeFail => { out_errors_ptr.* = errors.ptr; out_errors_len.* = errors.len; - return Error.CCompileErrors; + return .CCompileErrors; }, - error.ASTUnitFailure => return Error.ASTUnitFailure, - error.OutOfMemory => return Error.OutOfMemory, + error.ASTUnitFailure => return .ASTUnitFailure, + error.OutOfMemory => return .OutOfMemory, }; - return Error.None; + return .None; } export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { @@ -129,18 +144,18 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { const c_out_stream = &std.io.COutStream.init(output_file).stream; _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode - error.SystemResources => return Error.SystemResources, - error.OperationAborted => return Error.OperationAborted, - error.BrokenPipe => return Error.BrokenPipe, - error.DiskQuota => return Error.DiskQuota, - error.FileTooBig => return Error.FileTooBig, - error.NoSpaceLeft => return Error.NoSpaceLeft, - error.AccessDenied => return Error.AccessDenied, - error.OutOfMemory => return Error.OutOfMemory, - error.Unexpected => return Error.Unexpected, - error.InputOutput => return Error.FileSystem, + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.BrokenPipe => return .BrokenPipe, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.OutOfMemory => return .OutOfMemory, + error.Unexpected => return .Unexpected, + error.InputOutput => return .FileSystem, }; - return Error.None; + return .None; } // TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, @@ -832,3 +847,187 @@ export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeature export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { return cpu_features.llvm_features_str; } + +// ABI warning +const Stage2LibCInstallation = extern struct { + include_dir: [*:0]const u8, + include_dir_len: usize, + sys_include_dir: [*:0]const u8, + sys_include_dir_len: usize, + crt_dir: [*:0]const u8, + crt_dir_len: usize, + static_crt_dir: [*:0]const u8, + static_crt_dir_len: usize, + msvc_lib_dir: [*:0]const u8, + msvc_lib_dir_len: usize, + kernel32_lib_dir: [*:0]const u8, + kernel32_lib_dir_len: usize, + + fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { + if (libc.include_dir) |s| { + self.include_dir = s.ptr; + self.include_dir_len = s.len; + } else { + self.include_dir = ""; + self.include_dir_len = 0; + } + if (libc.sys_include_dir) |s| { + self.sys_include_dir = s.ptr; + self.sys_include_dir_len = s.len; + } else { + self.sys_include_dir = ""; + self.sys_include_dir_len = 0; + } + if (libc.crt_dir) |s| { + self.crt_dir = s.ptr; + self.crt_dir_len = s.len; + } else { + self.crt_dir = ""; + self.crt_dir_len = 0; + } + if (libc.static_crt_dir) |s| { + self.static_crt_dir = s.ptr; + self.static_crt_dir_len = s.len; + } else { + self.static_crt_dir = ""; + self.static_crt_dir_len = 0; + } + if (libc.msvc_lib_dir) |s| { + self.msvc_lib_dir = s.ptr; + self.msvc_lib_dir_len = s.len; + } else { + self.msvc_lib_dir = ""; + self.msvc_lib_dir_len = 0; + } + if (libc.kernel32_lib_dir) |s| { + self.kernel32_lib_dir = s.ptr; + self.kernel32_lib_dir_len = s.len; + } else { + self.kernel32_lib_dir = ""; + self.kernel32_lib_dir_len = 0; + } + } + + fn toStage2(self: Stage2LibCInstallation) LibCInstallation { + var libc: LibCInstallation = .{}; + if (self.include_dir_len != 0) { + libc.include_dir = self.include_dir[0..self.include_dir_len :0]; + } + if (self.sys_include_dir_len != 0) { + libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; + } + if (self.crt_dir_len != 0) { + libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; + } + if (self.static_crt_dir_len != 0) { + libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0]; + } + if (self.msvc_lib_dir_len != 0) { + libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; + } + if (self.kernel32_lib_dir_len != 0) { + libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; + } + return libc; + } +}; + +// ABI warning +export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error { + stderr_file = std.io.getStdErr(); + stderr = &stderr_file.outStream().stream; + const libc_file = mem.toSliceConst(u8, libc_file_z); + var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) { + error.ParseError => return .SemanticAnalyzeFail, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.InputOutput => return .FileSystem, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.BrokenPipe => return .BrokenPipe, + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.WouldBlock => unreachable, + error.Unexpected => return .Unexpected, + error.EndOfStream => return .EndOfFile, + error.IsDir => return .IsDir, + error.ConnectionResetByPeer => unreachable, + error.OutOfMemory => return .OutOfMemory, + error.Unseekable => unreachable, + error.SharingViolation => return .SharingViolation, + error.PathAlreadyExists => unreachable, + error.FileNotFound => return .FileNotFound, + error.PipeBusy => return .PipeBusy, + error.NameTooLong => return .PathTooLong, + error.InvalidUtf8 => return .BadPathName, + error.BadPathName => return .BadPathName, + error.SymLinkLoop => return .SymLinkLoop, + error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded, + error.NoDevice => return .NoDevice, + error.NotDir => return .NotDir, + error.DeviceBusy => return .DeviceBusy, + }; + stage1_libc.initFromStage2(libc); + return .None; +} + +// ABI warning +export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { + var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.FileSystem => return .FileSystem, + error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + error.CCompilerExitCode => return .CCompilerExitCode, + error.CCompilerCrashed => return .CCompilerCrashed, + error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders, + error.LibCRuntimeNotFound => return .LibCRuntimeNotFound, + error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, + error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, + error.UnsupportedArchitecture => return .UnsupportedArchitecture, + }; + stage1_libc.initFromStage2(libc); + return .None; +} + +// ABI warning +export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error { + var libc = stage1_libc.toStage2(); + const c_out_stream = &std.io.COutStream.init(output_file).stream; + libc.render(c_out_stream) catch |err| switch (err) { + error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.BrokenPipe => return .BrokenPipe, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.Unexpected => return .Unexpected, + error.InputOutput => return .FileSystem, + }; + return .None; +} + +// ABI warning +export fn stage2_libc_cc_print_file_name( + out_ptr: *[*:0]u8, + out_len: *usize, + o_file: [*:0]const u8, + want_dirname: bool, +) Error { + const result = @import("libc_installation.zig").ccPrintFileName( + std.heap.c_allocator, + mem.toSliceConst(u8, o_file), + if (want_dirname) .only_dir else .full_path, + ) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.LibCRuntimeNotFound => return .FileNotFound, + error.CCompilerExitCode => return .CCompilerExitCode, + error.CCompilerCrashed => return .CCompilerCrashed, + error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + }; + out_ptr.* = result.ptr; + out_len.* = result.len; + return .None; +} diff --git a/src-self-hosted/windows_sdk.zig b/src-self-hosted/windows_sdk.zig new file mode 100644 index 0000000000..6dfdeb99fd --- /dev/null +++ b/src-self-hosted/windows_sdk.zig @@ -0,0 +1,22 @@ +// C API bindings for src/windows_sdk.h + +pub const ZigWindowsSDK = extern struct { + path10_ptr: ?[*]const u8, + path10_len: usize, + version10_ptr: ?[*]const u8, + version10_len: usize, + path81_ptr: ?[*]const u8, + path81_len: usize, + version81_ptr: ?[*]const u8, + version81_len: usize, + msvc_lib_dir_ptr: ?[*]const u8, + msvc_lib_dir_len: usize, +}; +pub const ZigFindWindowsSdkError = extern enum { + None, + OutOfMemory, + NotFound, + PathTooLong, +}; +pub extern fn zig_find_windows_sdk(out_sdk: **ZigWindowsSDK) ZigFindWindowsSdkError; +pub extern fn zig_free_windows_sdk(sdk: *ZigWindowsSDK) void; diff --git a/src/all_types.hpp b/src/all_types.hpp index 95f291b343..c5804a3dc4 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -18,7 +18,6 @@ #include "bigfloat.hpp" #include "target.hpp" #include "tokenizer.hpp" -#include "libc_installation.hpp" struct AstNode; struct ZigFn; @@ -2139,7 +2138,7 @@ struct CodeGen { // As an input parameter, mutually exclusive with enable_cache. But it gets // populated in codegen_build_and_link. Buf *output_dir; - Buf **libc_include_dir_list; + const char **libc_include_dir_list; size_t libc_include_dir_len; Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir. @@ -2220,7 +2219,7 @@ struct CodeGen { ZigList lib_dirs; ZigList framework_dirs; - ZigLibCInstallation *libc; + Stage2LibCInstallation *libc; size_t version_major; size_t version_minor; diff --git a/src/codegen.cpp b/src/codegen.cpp index a0bc56f093..22d76c1372 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8982,17 +8982,20 @@ static void detect_dynamic_linker(CodeGen *g) { #if defined(ZIG_OS_LINUX) { Error err; - Buf *result = buf_alloc(); for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) { const char *lib_name = possible_ld_names[i]; - if ((err = zig_libc_cc_print_file_name(lib_name, result, false, true))) { + char *result_ptr; + size_t result_len; + if ((err = stage2_libc_cc_print_file_name(&result_ptr, &result_len, lib_name, false))) { if (err != ErrorCCompilerCannotFindFile && err != ErrorNoCCompilerInstalled) { fprintf(stderr, "Unable to detect native dynamic linker: %s\n", err_str(err)); exit(1); } continue; } - g->dynamic_linker_path = result; + g->dynamic_linker_path = buf_create_from_mem(result_ptr, result_len); + // Skips heap::c_allocator because the memory is allocated by stage2 library. + free(result_ptr); return; } } @@ -9028,16 +9031,16 @@ static void detect_libc(CodeGen *g) { buf_ptr(g->zig_lib_dir), target_os_name(g->zig_target->os)); g->libc_include_dir_len = 4; - g->libc_include_dir_list = heap::c_allocator.allocate(g->libc_include_dir_len); - g->libc_include_dir_list[0] = arch_include_dir; - g->libc_include_dir_list[1] = generic_include_dir; - g->libc_include_dir_list[2] = arch_os_include_dir; - g->libc_include_dir_list[3] = generic_os_include_dir; + g->libc_include_dir_list = heap::c_allocator.allocate(g->libc_include_dir_len); + g->libc_include_dir_list[0] = buf_ptr(arch_include_dir); + g->libc_include_dir_list[1] = buf_ptr(generic_include_dir); + g->libc_include_dir_list[2] = buf_ptr(arch_os_include_dir); + g->libc_include_dir_list[3] = buf_ptr(generic_os_include_dir); return; } if (g->zig_target->is_native) { - g->libc = heap::c_allocator.create(); + g->libc = heap::c_allocator.create(); // search for native_libc.txt in following dirs: // - LOCAL_CACHE_DIR @@ -9082,8 +9085,8 @@ static void detect_libc(CodeGen *g) { if (libc_txt == nullptr) libc_txt = &global_libc_txt; - if ((err = zig_libc_parse(g->libc, libc_txt, g->zig_target, false))) { - if ((err = zig_libc_find_native(g->libc, true))) { + if ((err = stage2_libc_parse(g->libc, buf_ptr(libc_txt)))) { + if ((err = stage2_libc_find_native(g->libc))) { fprintf(stderr, "Unable to link against libc: Unable to find libc installation: %s\n" "See `zig libc --help` for more details.\n", err_str(err)); @@ -9103,7 +9106,7 @@ static void detect_libc(CodeGen *g) { fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); exit(1); } - zig_libc_render(g->libc, file); + stage2_libc_render(g->libc, file); if (fclose(file) != 0) { fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); exit(1); @@ -9113,27 +9116,28 @@ static void detect_libc(CodeGen *g) { exit(1); } } - bool want_sys_dir = !buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir); + bool want_sys_dir = !mem_eql_mem(g->libc->include_dir, g->libc->include_dir_len, + g->libc->sys_include_dir, g->libc->sys_include_dir_len); size_t want_um_and_shared_dirs = (g->zig_target->os == OsWindows) ? 2 : 0; size_t dir_count = 1 + want_sys_dir + want_um_and_shared_dirs; g->libc_include_dir_len = 0; - g->libc_include_dir_list = heap::c_allocator.allocate(dir_count); + g->libc_include_dir_list = heap::c_allocator.allocate(dir_count); - g->libc_include_dir_list[g->libc_include_dir_len] = &g->libc->include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->include_dir; g->libc_include_dir_len += 1; if (want_sys_dir) { - g->libc_include_dir_list[g->libc_include_dir_len] = &g->libc->sys_include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->sys_include_dir; g->libc_include_dir_len += 1; } if (want_um_and_shared_dirs != 0) { - g->libc_include_dir_list[g->libc_include_dir_len] = buf_sprintf("%s" OS_SEP ".." OS_SEP "um", - buf_ptr(&g->libc->include_dir)); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( + "%s" OS_SEP ".." OS_SEP "um", g->libc->include_dir)); g->libc_include_dir_len += 1; - g->libc_include_dir_list[g->libc_include_dir_len] = buf_sprintf("%s" OS_SEP ".." OS_SEP "shared", - buf_ptr(&g->libc->include_dir)); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( + "%s" OS_SEP ".." OS_SEP "shared", g->libc->include_dir)); g->libc_include_dir_len += 1; } assert(g->libc_include_dir_len == dir_count); @@ -9208,9 +9212,9 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append(buf_ptr(g->zig_c_headers_dir)); for (size_t i = 0; i < g->libc_include_dir_len; i += 1) { - Buf *include_dir = g->libc_include_dir_list[i]; + const char *include_dir = g->libc_include_dir_list[i]; args.append("-isystem"); - args.append(buf_ptr(include_dir)); + args.append(include_dir); } if (g->zig_target->is_native) { @@ -9666,7 +9670,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose cache_buf(cache_hash, compiler_id); cache_int(cache_hash, g->err_color); cache_buf(cache_hash, g->zig_c_headers_dir); - cache_list_of_buf(cache_hash, g->libc_include_dir_list, g->libc_include_dir_len); + cache_list_of_str(cache_hash, g->libc_include_dir_list, g->libc_include_dir_len); cache_int(cache_hash, g->zig_target->is_native); cache_int(cache_hash, g->zig_target->arch); cache_int(cache_hash, g->zig_target->sub_arch); @@ -10482,11 +10486,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length); if (g->libc) { - cache_buf(ch, &g->libc->include_dir); - cache_buf(ch, &g->libc->sys_include_dir); - cache_buf(ch, &g->libc->crt_dir); - cache_buf(ch, &g->libc->msvc_lib_dir); - cache_buf(ch, &g->libc->kernel32_lib_dir); + cache_str(ch, g->libc->include_dir); + cache_str(ch, g->libc->sys_include_dir); + cache_str(ch, g->libc->crt_dir); + cache_str(ch, g->libc->msvc_lib_dir); + cache_str(ch, g->libc->kernel32_lib_dir); } cache_buf_opt(ch, g->dynamic_linker_path); cache_buf_opt(ch, g->version_script_path); @@ -10765,7 +10769,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c } CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, - ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *parent_progress_node) + Stage2LibCInstallation *libc, const char *name, Stage2ProgressNode *parent_progress_node) { Stage2ProgressNode *child_progress_node = stage2_progress_start( parent_progress_node ? parent_progress_node : parent_gen->sub_progress_node, @@ -10804,7 +10808,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *override_lib_dir, - ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) + Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) { CodeGen *g = heap::c_allocator.create(); g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); diff --git a/src/codegen.hpp b/src/codegen.hpp index b9bcf05d28..623ae12fef 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -11,17 +11,16 @@ #include "parser.hpp" #include "errmsg.hpp" #include "target.hpp" -#include "libc_installation.hpp" #include "userland.h" #include CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, - ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node); + Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node); CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, - ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node); + Stage2LibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); diff --git a/src/error.cpp b/src/error.cpp index 871b6b9e35..1e0267eb67 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -65,6 +65,20 @@ const char *err_str(Error err) { case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface"; case ErrorASTUnitFailure: return "compiler bug: clang encountered a compile error, but the libclang API does not expose the error. See https://github.com/ziglang/zig/issues/4455 for more details"; + case ErrorBadPathName: return "bad path name"; + case ErrorSymLinkLoop: return "sym link loop"; + case ErrorProcessFdQuotaExceeded: return "process fd quota exceeded"; + case ErrorSystemFdQuotaExceeded: return "system fd quota exceeded"; + case ErrorNoDevice: return "no device"; + case ErrorDeviceBusy: return "device busy"; + case ErrorUnableToSpawnCCompiler: return "unable to spawn system C compiler"; + case ErrorCCompilerExitCode: return "system C compiler exited with failure code"; + case ErrorCCompilerCrashed: return "system C compiler crashed"; + case ErrorCCompilerCannotFindHeaders: return "system C compiler cannot find libc headers"; + case ErrorLibCRuntimeNotFound: return "libc runtime not found"; + case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found"; + case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; + case ErrorUnsupportedArchitecture: return "unsupported architecture"; } return "(invalid error)"; } diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp deleted file mode 100644 index 2adc1cb69d..0000000000 --- a/src/libc_installation.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#include "libc_installation.hpp" -#include "os.hpp" -#include "windows_sdk.h" -#include "target.hpp" - -static const char *zig_libc_keys[] = { - "include_dir", - "sys_include_dir", - "crt_dir", - "static_crt_dir", - "msvc_lib_dir", - "kernel32_lib_dir", -}; - -static const size_t zig_libc_keys_len = array_length(zig_libc_keys); - -static bool zig_libc_match_key(Slice name, Slice value, bool *found_keys, - size_t index, Buf *field_ptr) -{ - if (!memEql(name, str(zig_libc_keys[index]))) return false; - buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len); - found_keys[index] = true; - return true; -} - -static void zig_libc_init_empty(ZigLibCInstallation *libc) { - *libc = {}; - buf_init_from_str(&libc->include_dir, ""); - buf_init_from_str(&libc->sys_include_dir, ""); - buf_init_from_str(&libc->crt_dir, ""); - buf_init_from_str(&libc->static_crt_dir, ""); - buf_init_from_str(&libc->msvc_lib_dir, ""); - buf_init_from_str(&libc->kernel32_lib_dir, ""); -} - -Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) { - Error err; - zig_libc_init_empty(libc); - - bool found_keys[array_length(zig_libc_keys)] = {}; - - Buf *contents = buf_alloc(); - if ((err = os_fetch_file_path(libc_file, contents))) { - if (err != ErrorFileNotFound && verbose) { - fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err)); - } - return err; - } - - SplitIterator it = memSplit(buf_to_slice(contents), str("\n")); - for (;;) { - Optional> opt_line = SplitIterator_next(&it); - if (!opt_line.is_some) - break; - - if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#') - continue; - - SplitIterator line_it = memSplit(opt_line.value, str("=")); - Slice name; - if (!SplitIterator_next(&line_it).unwrap(&name)) { - if (verbose) { - fprintf(stderr, "missing equal sign after field name\n"); - } - return ErrorSemanticAnalyzeFail; - } - Slice value = SplitIterator_rest(&line_it); - bool match = false; - match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir); - match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir); - match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir); - match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_dir); - match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir); - match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir); - } - - for (size_t i = 0; i < zig_libc_keys_len; i += 1) { - if (!found_keys[i]) { - if (verbose) { - fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]); - } - return ErrorSemanticAnalyzeFail; - } - } - - if (buf_len(&libc->include_dir) == 0) { - if (verbose) { - fprintf(stderr, "include_dir may not be empty\n"); - } - return ErrorSemanticAnalyzeFail; - } - - if (buf_len(&libc->sys_include_dir) == 0) { - if (verbose) { - fprintf(stderr, "sys_include_dir may not be empty\n"); - } - return ErrorSemanticAnalyzeFail; - } - - if (buf_len(&libc->crt_dir) == 0) { - if (!target_os_is_darwin(target->os)) { - if (verbose) { - fprintf(stderr, "crt_dir may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - - if (buf_len(&libc->static_crt_dir) == 0) { - if (target->os == OsWindows && target_abi_is_gnu(target->abi)) { - if (verbose) { - fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - - if (buf_len(&libc->msvc_lib_dir) == 0) { - if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) { - if (verbose) { - fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - - if (buf_len(&libc->kernel32_lib_dir) == 0) { - if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) { - if (verbose) { - fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - - return ErrorNone; -} - -#if defined(ZIG_OS_WINDOWS) -#define CC_EXE "cc.exe" -#else -#define CC_EXE "cc" -#endif - -static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) { - const char *cc_exe = getenv("CC"); - cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe; - ZigList args = {}; - args.append(cc_exe); - args.append("-E"); - args.append("-Wp,-v"); - args.append("-xc"); - #if defined(ZIG_OS_WINDOWS) - args.append("nul"); - #else - args.append("/dev/null"); - #endif - - Termination term; - Buf *out_stderr = buf_alloc(); - Buf *out_stdout = buf_alloc(); - Error err; - if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) { - if (verbose) { - fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err)); - } - return err; - } - if (term.how != TerminationIdClean || term.code != 0) { - if (verbose) { - fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe); - } - return ErrorCCompileErrors; - } - char *prev_newline = buf_ptr(out_stderr); - ZigList search_paths = {}; - for (;;) { - char *newline = strchr(prev_newline, '\n'); - if (newline == nullptr) { - break; - } - - #if defined(ZIG_OS_WINDOWS) - *(newline - 1) = 0; - #endif - *newline = 0; - - if (prev_newline[0] == ' ') { - search_paths.append(prev_newline); - } - prev_newline = newline + 1; - } - if (search_paths.length == 0) { - if (verbose) { - fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe); - } - return ErrorCCompileErrors; - } - for (size_t i = 0; i < search_paths.length; i += 1) { - // search in reverse order - const char *search_path = search_paths.items[search_paths.length - i - 1]; - // cut off spaces - while (*search_path == ' ') { - search_path += 1; - } - - #if defined(ZIG_OS_WINDOWS) - if (buf_len(&self->include_dir) == 0) { - Buf *stdlib_path = buf_sprintf("%s\\stdlib.h", search_path); - bool exists; - if ((err = os_file_exists(stdlib_path, &exists))) { - exists = false; - } - if (exists) { - buf_init_from_str(&self->include_dir, search_path); - } - } - if (buf_len(&self->sys_include_dir) == 0) { - Buf *stdlib_path = buf_sprintf("%s\\sys\\types.h", search_path); - bool exists; - if ((err = os_file_exists(stdlib_path, &exists))) { - exists = false; - } - if (exists) { - buf_init_from_str(&self->sys_include_dir, search_path); - } - } - #else - if (buf_len(&self->include_dir) == 0) { - Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path); - bool exists; - if ((err = os_file_exists(stdlib_path, &exists))) { - exists = false; - } - if (exists) { - buf_init_from_str(&self->include_dir, search_path); - } - } - if (buf_len(&self->sys_include_dir) == 0) { - Buf *stdlib_path = buf_sprintf("%s/sys/errno.h", search_path); - bool exists; - if ((err = os_file_exists(stdlib_path, &exists))) { - exists = false; - } - if (exists) { - buf_init_from_str(&self->sys_include_dir, search_path); - } - } - #endif - - if (buf_len(&self->include_dir) != 0 && buf_len(&self->sys_include_dir) != 0) { - return ErrorNone; - } - } - if (verbose) { - if (buf_len(&self->include_dir) == 0) { - fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe); - } - if (buf_len(&self->sys_include_dir) == 0) { - #if defined(ZIG_OS_WINDOWS) - fprintf(stderr, "unable to determine libc include path: sys/types.h not found in '%s' search paths\n", cc_exe); - #else - fprintf(stderr, "unable to determine libc include path: sys/errno.h not found in '%s' search paths\n", cc_exe); - #endif - } - } - return ErrorFileNotFound; -} - -Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) { - const char *cc_exe = getenv("CC"); - cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe; - ZigList args = {}; - args.append(cc_exe); - args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file))); - Termination term; - Buf *out_stderr = buf_alloc(); - Buf *out_stdout = buf_alloc(); - Error err; - if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) { - if (err == ErrorFileNotFound) - return ErrorNoCCompilerInstalled; - if (verbose) { - fprintf(stderr, "unable to determine libc library path: executing '%s': %s\n", cc_exe, err_str(err)); - } - return err; - } - if (term.how != TerminationIdClean || term.code != 0) { - if (verbose) { - fprintf(stderr, "unable to determine libc library path: executing '%s' failed\n", cc_exe); - } - return ErrorCCompileErrors; - } - #if defined(ZIG_OS_WINDOWS) - if (buf_ends_with_str(out_stdout, "\r\n")) { - buf_resize(out_stdout, buf_len(out_stdout) - 2); - } - #else - if (buf_ends_with_str(out_stdout, "\n")) { - buf_resize(out_stdout, buf_len(out_stdout) - 1); - } - #endif - if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) { - return ErrorCCompilerCannotFindFile; - } - if (want_dirname) { - os_path_dirname(out_stdout, out); - } else { - buf_init_from_buf(out, out_stdout); - } - return ErrorNone; -} - -#undef CC_EXE - -#if defined(ZIG_OS_WINDOWS) || defined(ZIG_OS_LINUX) || defined(ZIG_OS_DRAGONFLY) -static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) { - return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose); -} -#endif - -#if defined(ZIG_OS_WINDOWS) -static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) { - return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose); -} - -static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { - Error err; - if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) { - if (verbose) { - fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err)); - } - return err; - } - return ErrorNone; -} - -static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, - bool verbose) -{ - Error err; - if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch))) { - if (verbose) { - fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err)); - } - return err; - } - return ErrorNone; -} - -static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, - bool verbose) -{ - Error err; - if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch))) { - if (verbose) { - fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err)); - } - return err; - } - return ErrorNone; -} - -static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { - if (sdk->msvc_lib_dir_ptr == nullptr) { - if (verbose) { - fprintf(stderr, "Unable to determine vcruntime.lib path\n"); - } - return ErrorFileNotFound; - } - buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); - return ErrorNone; -} - -static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { - Error err; - if (sdk->msvc_lib_dir_ptr == nullptr) { - if (verbose) { - fprintf(stderr, "Unable to determine vcruntime.h path\n"); - } - return ErrorFileNotFound; - } - Buf search_path = BUF_INIT; - buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); - buf_append_str(&search_path, "..\\..\\include"); - - Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path)); - bool exists; - if ((err = os_file_exists(vcruntime_path, &exists))) { - exists = false; - } - if (exists) { - self->sys_include_dir = search_path; - return ErrorNone; - } - - if (verbose) { - fprintf(stderr, "Unable to determine vcruntime.h path\n"); - } - return ErrorFileNotFound; -} -#endif - -void zig_libc_render(ZigLibCInstallation *self, FILE *file) { - fprintf(file, - "# The directory that contains `stdlib.h`.\n" - "# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`\n" - "include_dir=%s\n" - "\n" - "# The system-specific include directory. May be the same as `include_dir`.\n" - "# On Windows it's the directory that includes `vcruntime.h`.\n" - "# On POSIX it's the directory that includes `sys/errno.h`.\n" - "sys_include_dir=%s\n" - "\n" - "# The directory that contains `crt1.o` or `crt2.o`.\n" - "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n" - "# Not needed when targeting MacOS.\n" - "crt_dir=%s\n" - "\n" - "# The directory that contains `crtbegin.o`.\n" - "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n" - "# Not needed when targeting MacOS.\n" - "static_crt_dir=%s\n" - "\n" - "# The directory that contains `vcruntime.lib`.\n" - "# Only needed when targeting MSVC on Windows.\n" - "msvc_lib_dir=%s\n" - "\n" - "# The directory that contains `kernel32.lib`.\n" - "# Only needed when targeting MSVC on Windows.\n" - "kernel32_lib_dir=%s\n" - "\n", - buf_ptr(&self->include_dir), - buf_ptr(&self->sys_include_dir), - buf_ptr(&self->crt_dir), - buf_ptr(&self->static_crt_dir), - buf_ptr(&self->msvc_lib_dir), - buf_ptr(&self->kernel32_lib_dir) - ); -} - -Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { - Error err; - zig_libc_init_empty(self); -#if defined(ZIG_OS_WINDOWS) - ZigTarget native_target; - get_native_target(&native_target); - if (target_abi_is_gnu(native_target.abi)) { - if ((err = zig_libc_find_native_include_dir_posix(self, verbose))) - return err; - if ((err = zig_libc_find_native_crt_dir_posix(self, verbose))) - return err; - if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose))) - return err; - return ErrorNone; - } else { - ZigWindowsSDK *sdk; - switch (zig_find_windows_sdk(&sdk)) { - case ZigFindWindowsSdkErrorNone: - if ((err = zig_libc_find_native_msvc_include_dir(self, sdk, verbose))) - return err; - if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose))) - return err; - if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose))) - return err; - if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose))) - return err; - if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose))) - return err; - return ErrorNone; - case ZigFindWindowsSdkErrorOutOfMemory: - return ErrorNoMem; - case ZigFindWindowsSdkErrorNotFound: - return ErrorFileNotFound; - case ZigFindWindowsSdkErrorPathTooLong: - return ErrorPathTooLong; - } - } - zig_unreachable(); -#else - if ((err = zig_libc_find_native_include_dir_posix(self, verbose))) - return err; -#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) - buf_init_from_str(&self->crt_dir, "/usr/lib"); -#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_DRAGONFLY) - if ((err = zig_libc_find_native_crt_dir_posix(self, verbose))) - return err; -#endif - return ErrorNone; -#endif -} diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp deleted file mode 100644 index 8ecad7ce61..0000000000 --- a/src/libc_installation.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_LIBC_INSTALLATION_HPP -#define ZIG_LIBC_INSTALLATION_HPP - -#include - -#include "buffer.hpp" -#include "error.hpp" -#include "target.hpp" - -// Must be synchronized with zig_libc_keys -struct ZigLibCInstallation { - Buf include_dir; - Buf sys_include_dir; - Buf crt_dir; - Buf static_crt_dir; - Buf msvc_lib_dir; - Buf kernel32_lib_dir; -}; - -Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, - const ZigTarget *target, bool verbose); -void zig_libc_render(ZigLibCInstallation *self, FILE *file); - -Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose); - -Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose); - -#endif diff --git a/src/link.cpp b/src/link.cpp index 2771b694c1..8b31b2519e 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1483,7 +1483,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } else { assert(parent->libc != nullptr); Buf *out_buf = buf_alloc(); - os_path_join(&parent->libc->crt_dir, buf_create_from_str(file), out_buf); + os_path_join(buf_create_from_str(parent->libc->crt_dir), buf_create_from_str(file), out_buf); return buf_ptr(out_buf); } } @@ -1747,7 +1747,7 @@ static void construct_linker_job_elf(LinkJob *lj) { if (g->libc_link_lib != nullptr) { if (g->libc != nullptr) { lj->args.append("-L"); - lj->args.append(buf_ptr(&g->libc->crt_dir)); + lj->args.append(g->libc->crt_dir); } if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) { @@ -2251,14 +2251,14 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); if (g->libc_link_lib != nullptr && g->libc != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); if (target_abi_is_gnu(g->zig_target->abi)) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->sys_include_dir))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->include_dir))); } else { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->msvc_lib_dir))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->kernel32_lib_dir))); } } diff --git a/src/main.cpp b/src/main.cpp index 2ff0ab7352..d5883d2bb3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,6 @@ #include "heap.hpp" #include "os.hpp" #include "target.hpp" -#include "libc_installation.hpp" #include "userland.h" #include "glibc.hpp" #include "dump_analysis.hpp" @@ -1027,15 +1026,22 @@ static int main0(int argc, char **argv) { switch (cmd) { case CmdLibC: { if (in_file) { - ZigLibCInstallation libc; - if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true))) + Stage2LibCInstallation libc; + if ((err = stage2_libc_parse(&libc, in_file))) { + fprintf(stderr, "unable to parse libc file: %s\n", err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); + } return main_exit(root_progress_node, EXIT_SUCCESS); } - ZigLibCInstallation libc; - if ((err = zig_libc_find_native(&libc, true))) + Stage2LibCInstallation libc; + if ((err = stage2_libc_find_native(&libc))) { + fprintf(stderr, "unable to find native libc file: %s\n", err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); - zig_libc_render(&libc, stdout); + } + if ((err = stage2_libc_render(&libc, stdout))) { + fprintf(stderr, "unable to print libc file: %s\n", err_str(err)); + return main_exit(root_progress_node, EXIT_FAILURE); + } return main_exit(root_progress_node, EXIT_SUCCESS); } case CmdBuiltin: { @@ -1125,10 +1131,10 @@ static int main0(int argc, char **argv) { if (cmd == CmdRun && buf_out_name == nullptr) { buf_out_name = buf_create_from_str("run"); } - ZigLibCInstallation *libc = nullptr; + Stage2LibCInstallation *libc = nullptr; if (libc_txt != nullptr) { - libc = heap::c_allocator.create(); - if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) { + libc = heap::c_allocator.create(); + if ((err = stage2_libc_parse(libc, libc_txt))) { fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); } diff --git a/src/os.cpp b/src/os.cpp index 3eeab2b755..aa09166fc5 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1551,108 +1551,6 @@ void os_stderr_set_color(TermColor color) { #endif } -Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { -#if defined(ZIG_OS_WINDOWS) - buf_resize(output_buf, 0); - buf_appendf(output_buf, "%sLib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr); - switch (platform_type) { - case ZigLLVM_x86: - buf_append_str(output_buf, "x86\\"); - break; - case ZigLLVM_x86_64: - buf_append_str(output_buf, "x64\\"); - break; - case ZigLLVM_arm: - buf_append_str(output_buf, "arm\\"); - break; - default: - zig_panic("Attempted to use vcruntime for non-supported platform."); - } - Buf* tmp_buf = buf_alloc(); - buf_init_from_buf(tmp_buf, output_buf); - buf_append_str(tmp_buf, "ucrt.lib"); - if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return ErrorNone; - } - else { - buf_resize(output_buf, 0); - return ErrorFileNotFound; - } -#else - return ErrorFileNotFound; -#endif -} - -Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { -#if defined(ZIG_OS_WINDOWS) - buf_resize(output_buf, 0); - buf_appendf(output_buf, "%sInclude\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr); - if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) { - return ErrorNone; - } - else { - buf_resize(output_buf, 0); - return ErrorFileNotFound; - } -#else - return ErrorFileNotFound; -#endif -} - -Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { -#if defined(ZIG_OS_WINDOWS) - { - buf_resize(output_buf, 0); - buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path10_ptr, sdk->version10_ptr); - switch (platform_type) { - case ZigLLVM_x86: - buf_append_str(output_buf, "x86\\"); - break; - case ZigLLVM_x86_64: - buf_append_str(output_buf, "x64\\"); - break; - case ZigLLVM_arm: - buf_append_str(output_buf, "arm\\"); - break; - default: - zig_panic("Attempted to use vcruntime for non-supported platform."); - } - Buf* tmp_buf = buf_alloc(); - buf_init_from_buf(tmp_buf, output_buf); - buf_append_str(tmp_buf, "kernel32.lib"); - if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return ErrorNone; - } - } - { - buf_resize(output_buf, 0); - buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path81_ptr, sdk->version81_ptr); - switch (platform_type) { - case ZigLLVM_x86: - buf_append_str(output_buf, "x86\\"); - break; - case ZigLLVM_x86_64: - buf_append_str(output_buf, "x64\\"); - break; - case ZigLLVM_arm: - buf_append_str(output_buf, "arm\\"); - break; - default: - zig_panic("Attempted to use vcruntime for non-supported platform."); - } - Buf* tmp_buf = buf_alloc(); - buf_init_from_buf(tmp_buf, output_buf); - buf_append_str(tmp_buf, "kernel32.lib"); - if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return ErrorNone; - } - } - return ErrorFileNotFound; -#else - return ErrorFileNotFound; -#endif -} - #if defined(ZIG_OS_WINDOWS) // Ported from std/unicode.zig struct Utf16LeIterator { diff --git a/src/os.hpp b/src/os.hpp index 7da846a509..6823d901b5 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -152,10 +152,6 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path); Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname); -Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); -Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); -Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); - Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList &paths); #endif diff --git a/src/userland.cpp b/src/userland.cpp index ba0e906cf9..539735f436 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -144,3 +144,25 @@ int stage2_cmd_targets(const char *zig_triple) { const char *msg = "stage0 called stage2_cmd_targets"; stage2_panic(msg, strlen(msg)); } + +enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { + const char *msg = "stage0 called stage2_libc_parse"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { + const char *msg = "stage0 called stage2_libc_render"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { + const char *msg = "stage0 called stage2_libc_find_native"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, + const char *o_file, bool want_dirname) +{ + const char *msg = "stage0 called stage2_libc_cc_print_file_name"; + stage2_panic(msg, strlen(msg)); +} diff --git a/src/userland.h b/src/userland.h index a59f6b7da8..7903dc8fe4 100644 --- a/src/userland.h +++ b/src/userland.h @@ -85,6 +85,20 @@ enum Error { ErrorInvalidLlvmCpuFeaturesFormat, ErrorUnknownApplicationBinaryInterface, ErrorASTUnitFailure, + ErrorBadPathName, + ErrorSymLinkLoop, + ErrorProcessFdQuotaExceeded, + ErrorSystemFdQuotaExceeded, + ErrorNoDevice, + ErrorDeviceBusy, + ErrorUnableToSpawnCCompiler, + ErrorCCompilerExitCode, + ErrorCCompilerCrashed, + ErrorCCompilerCannotFindHeaders, + ErrorLibCRuntimeNotFound, + ErrorLibCStdLibHeaderNotFound, + ErrorLibCKernel32LibNotFound, + ErrorUnsupportedArchitecture, }; // ABI warning @@ -185,7 +199,7 @@ ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, struct Stage2CpuFeatures; // ABI warning -ZIG_EXTERN_C Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, +ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, const char *zig_triple, const char *cpu_name, const char *cpu_features); // ABI warning @@ -205,5 +219,30 @@ ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatu // ABI warning ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); +// ABI warning +struct Stage2LibCInstallation { + const char *include_dir; + size_t include_dir_len; + const char *sys_include_dir; + size_t sys_include_dir_len; + const char *crt_dir; + size_t crt_dir_len; + const char *static_crt_dir; + size_t static_crt_dir_len; + const char *msvc_lib_dir; + size_t msvc_lib_dir_len; + const char *kernel32_lib_dir; + size_t kernel32_lib_dir_len; +}; + +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, + const char *o_file, bool want_dirname); #endif diff --git a/src/windows_sdk.h b/src/windows_sdk.h index 2d531ad372..e887209559 100644 --- a/src/windows_sdk.h +++ b/src/windows_sdk.h @@ -16,6 +16,7 @@ #include +// ABI warning - src-self-hosted/windows_sdk.zig struct ZigWindowsSDK { const char *path10_ptr; size_t path10_len; @@ -33,6 +34,7 @@ struct ZigWindowsSDK { size_t msvc_lib_dir_len; }; +// ABI warning - src-self-hosted/windows_sdk.zig enum ZigFindWindowsSdkError { ZigFindWindowsSdkErrorNone, ZigFindWindowsSdkErrorOutOfMemory, @@ -40,8 +42,10 @@ enum ZigFindWindowsSdkError { ZigFindWindowsSdkErrorPathTooLong, }; +// ABI warning - src-self-hosted/windows_sdk.zig ZIG_EXTERN_C enum ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk); +// ABI warning - src-self-hosted/windows_sdk.zig ZIG_EXTERN_C void zig_free_windows_sdk(struct ZigWindowsSDK *sdk); #endif From 096f79260b025ab53d77c4943f237676abb5b7d8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 15 Feb 2020 21:17:39 +0100 Subject: [PATCH 011/109] ir: Prevent crash when indexing undefined ptr to array Closes #4471 --- src/ir.cpp | 44 ++++++++++++++++++++++++----------------- test/compile_errors.zig | 9 +++++++++ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 323fa4ba6f..a29a5b6948 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20638,12 +20638,12 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP if (type_is_invalid(array_ptr->value->type)) return ira->codegen->invalid_inst_gen; - ZigValue *orig_array_ptr_val = array_ptr->value; - IrInstGen *elem_index = elem_ptr_instruction->elem_index->child; if (type_is_invalid(elem_index->value->type)) return ira->codegen->invalid_inst_gen; + ZigValue *orig_array_ptr_val = array_ptr->value; + ZigType *ptr_type = orig_array_ptr_val->type; assert(ptr_type->id == ZigTypeIdPointer); @@ -20653,23 +20653,25 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP // We will adjust return_type's alignment before returning it. ZigType *return_type; - if (type_is_invalid(array_type)) { + if (type_is_invalid(array_type)) return ira->codegen->invalid_inst_gen; - } else if (array_type->id == ZigTypeIdArray || - (array_type->id == ZigTypeIdPointer && - array_type->data.pointer.ptr_len == PtrLenSingle && - array_type->data.pointer.child_type->id == ZigTypeIdArray)) + + if (array_type->id == ZigTypeIdPointer && + array_type->data.pointer.ptr_len == PtrLenSingle && + array_type->data.pointer.child_type->id == ZigTypeIdArray) { - if (array_type->id == ZigTypeIdPointer) { - array_type = array_type->data.pointer.child_type; - ptr_type = ptr_type->data.pointer.child_type; - if (orig_array_ptr_val->special != ConstValSpecialRuntime) { - orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, - elem_ptr_instruction->base.base.source_node); - if (orig_array_ptr_val == nullptr) - return ira->codegen->invalid_inst_gen; - } - } + IrInstGen *ptr_value = ir_get_deref(ira, &elem_ptr_instruction->base.base, + array_ptr, nullptr); + if (type_is_invalid(ptr_value->value->type)) + return ira->codegen->invalid_inst_gen; + + array_type = array_type->data.pointer.child_type; + ptr_type = ptr_type->data.pointer.child_type; + + orig_array_ptr_val = ptr_value->value; + } + + if (array_type->id == ZigTypeIdArray) { if (array_type->data.array.len == 0) { ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index 0 outside array of size 0")); @@ -20807,8 +20809,14 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP orig_array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr && (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == ZigTypeIdArray)) { + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + elem_ptr_instruction->base.base.source_node, orig_array_ptr_val, UndefBad))) + { + return ira->codegen->invalid_inst_gen; + } + ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, - elem_ptr_instruction->base.base.source_node); + elem_ptr_instruction->base.base.source_node); if (array_ptr_val == nullptr) return ira->codegen->invalid_inst_gen; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index cc2863a046..6d46afc979 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,6 +3,15 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("access of undefined pointer to array", + \\const ram_u32: *[4096]u32 = undefined; + \\export fn entry() void { + \\ @ptrCast(*u32, &(ram_u32[0])) = &(ram_u32[0]); + \\} + , &[_][]const u8{ + "tmp.zig:3:29: error: use of undefined value here causes undefined behavior", + }); + cases.addTest("duplicate field in anonymous struct literal", \\export fn entry() void { \\ const anon = .{ From 59a243ce24e858260d289c5c40f3430223b7d98b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 15 Feb 2020 21:33:59 +0100 Subject: [PATCH 012/109] std: Remove now-superflous hack --- lib/std/json.zig | 4 +--- lib/std/zig/tokenizer.zig | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 74e008d76e..b04861eaae 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1026,10 +1026,8 @@ pub const TokenStream = struct { pub fn next(self: *TokenStream) Error!?Token { if (self.token) |token| { - // TODO: Audit this pattern once #2915 is closed - const copy = token; self.token = null; - return copy; + return token; } var t1: ?Token = undefined; diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index 327700f591..f6c71479e7 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -414,10 +414,8 @@ pub const Tokenizer = struct { pub fn next(self: *Tokenizer) Token { if (self.pending_invalid_token) |token| { - // TODO: Audit this pattern once #2915 is closed - const copy = token; self.pending_invalid_token = null; - return copy; + return token; } const start_index = self.index; var state = State.Start; @@ -1270,10 +1268,8 @@ pub const Tokenizer = struct { if (result.id == Token.Id.Eof) { if (self.pending_invalid_token) |token| { - // TODO: Audit this pattern once #2915 is closed - const copy = token; self.pending_invalid_token = null; - return copy; + return token; } } From 6b74fd2e12b117e90197db5f4fa1ea51aa246248 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 16 Feb 2020 20:19:30 +0100 Subject: [PATCH 013/109] ir: Avoid invalidating the decl_table iterator Collect the declarations to resolve first and run resolve_top_level_decl on them later. Closes #4310 --- src/ir.cpp | 45 +++++++++++++++++++++++++++++------------ test/compile_errors.zig | 10 ++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index a29a5b6948..8544fe1758 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -23653,14 +23653,13 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown))) return err; - // Loop through our declarations once to figure out how many declarations we will generate info for. + // The unresolved declarations are collected in a separate queue to avoid + // modifying decl_table while iterating over it + ZigList resolve_decl_queue{}; + auto decl_it = decls_scope->decl_table.entry_iterator(); decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr; - int declaration_count = 0; - while ((curr_entry = decl_it.next()) != nullptr) { - // If the declaration is unresolved, force it to be resolved again. - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); if (curr_entry->value->resolution == TldResolutionInvalid) { return ErrorSemanticAnalyzeFail; } @@ -23670,18 +23669,38 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa return ErrorSemanticAnalyzeFail; } - // Skip comptime blocks and test functions. - if (curr_entry->value->id != TldIdCompTime) { - if (curr_entry->value->id == TldIdFn) { - ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; - if (fn_entry->is_test) - continue; - } + // If the declaration is unresolved, force it to be resolved again. + if (curr_entry->value->resolution == TldResolutionUnresolved) + resolve_decl_queue.append(curr_entry->value); + } - declaration_count += 1; + for (size_t i = 0; i < resolve_decl_queue.length; i++) { + Tld *decl = resolve_decl_queue.at(i); + resolve_top_level_decl(ira->codegen, decl, decl->source_node, false); + if (decl->resolution == TldResolutionInvalid) { + return ErrorSemanticAnalyzeFail; } } + resolve_decl_queue.deinit(); + + // Loop through our declarations once to figure out how many declarations we will generate info for. + int declaration_count = 0; + decl_it = decls_scope->decl_table.entry_iterator(); + while ((curr_entry = decl_it.next()) != nullptr) { + // Skip comptime blocks and test functions. + if (curr_entry->value->id == TldIdCompTime) + continue; + + if (curr_entry->value->id == TldIdFn) { + ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; + if (fn_entry->is_test) + continue; + } + + declaration_count += 1; + } + ZigValue *declaration_array = ira->codegen->pass1_arena->create(); declaration_array->special = ConstValSpecialStatic; declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 6d46afc979..febc936486 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,13 +3,13 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { - cases.addTest("access of undefined pointer to array", - \\const ram_u32: *[4096]u32 = undefined; - \\export fn entry() void { - \\ @ptrCast(*u32, &(ram_u32[0])) = &(ram_u32[0]); + cases.addTest("", + \\const A = B; + \\test "Crash" { + \\ _ = @typeInfo(@This()).Struct.decls; \\} , &[_][]const u8{ - "tmp.zig:3:29: error: use of undefined value here causes undefined behavior", + "tmp.zig:1:11: error: use of undeclared identifier 'B'", }); cases.addTest("duplicate field in anonymous struct literal", From 8173fbfb66132f0fca42a3c8415381ad9f5d632d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 17:10:43 -0500 Subject: [PATCH 014/109] implement os.faccessat for Windows --- lib/std/event/batch.zig | 4 ++-- lib/std/fs.zig | 31 ++++++++++++++++++++--------- lib/std/os.zig | 38 +++++++++++++++++++++++++++++++++--- lib/std/os/windows/ntdll.zig | 6 ++++++ 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig index 82dadb91be..af59b32490 100644 --- a/lib/std/event/batch.zig +++ b/lib/std/event/batch.zig @@ -109,13 +109,13 @@ pub fn Batch( test "std.event.Batch" { var count: usize = 0; - var batch = Batch(void, 2).init(); + var batch = Batch(void, 2, .auto_async).init(); batch.add(&async sleepALittle(&count)); batch.add(&async increaseByTen(&count)); batch.wait(); testing.expect(count == 11); - var another = Batch(anyerror!void, 2).init(); + var another = Batch(anyerror!void, 2, .auto_async).init(); another.add(&async somethingElse()); another.add(&async doSomethingThatFails()); testing.expectError(error.ItBroke, another.wait()); diff --git a/lib/std/fs.zig b/lib/std/fs.zig index c96aeeafc7..bc9ae6aa2d 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -818,6 +818,13 @@ pub const Dir = struct { ) File.OpenError!File { const w = os.windows; + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + return error.IsDir; + } + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + return error.IsDir; + } + var result = File{ .handle = undefined, .io_mode = .blocking, @@ -839,12 +846,6 @@ pub const Dir = struct { .SecurityDescriptor = null, .SecurityQualityOfService = null, }; - if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { - return error.IsDir; - } - if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { - return error.IsDir; - } var io: w.IO_STATUS_BLOCK = undefined; const rc = w.ntdll.NtCreateFile( &result.handle, @@ -1332,12 +1333,20 @@ pub const Dir = struct { /// For example, instead of testing if a file exists and then opening it, just /// open it and handle the error for file not found. pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void { + if (builtin.os == .windows) { + const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); + return self.accessW(&sub_path_w, flags); + } const path_c = try os.toPosixPath(sub_path); return self.accessZ(&path_c, flags); } /// Same as `access` except the path parameter is null-terminated. pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void { + if (builtin.os == .windows) { + const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path); + return self.accessW(&sub_path_w, flags); + } const os_mode = if (flags.write and flags.read) @as(u32, os.R_OK | os.W_OK) else if (flags.write) @@ -1351,9 +1360,13 @@ pub const Dir = struct { return result; } - /// Same as `access` except the parameter is null-terminated UTF16LE-encoded. - pub fn accessW(self: Dir, sub_path: [*:0]const u16, flags: File.OpenFlags) AccessError!void { - return os.faccessatW(self.fd, sub_path, 0, 0); + /// Same as `access` except asserts the target OS is Windows and the path parameter is + /// * WTF-16 encoded + /// * null-terminated + /// * NtDll prefixed + /// TODO currently this ignores `flags`. + pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void { + return os.faccessatW(self.fd, sub_path_w, 0, 0); } }; diff --git a/lib/std/os.zig b/lib/std/os.zig index fd85f8801b..ff2296d928 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2553,10 +2553,42 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces } /// Same as `faccessat` except asserts the target is Windows and the path parameter -/// is null-terminated WTF-16 encoded. +/// is NtDll-prefixed, null-terminated, WTF-16 encoded. /// TODO currently this ignores `mode` and `flags` -pub fn faccessatW(dirfd: fd_t, path: [*:0]const u16, mode: u32, flags: u32) AccessError!void { - @compileError("TODO implement faccessatW on Windows"); +pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32) AccessError!void { + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + return; + } + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + return; + } + + const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) { + error.Overflow => return error.NameTooLong, + }; + var nt_name = windows.UNICODE_STRING{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)), + }; + var attr = windows.OBJECT_ATTRIBUTES{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dirfd, + .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }; + var basic_info: windows.FILE_BASIC_INFORMATION = undefined; + switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { + .SUCCESS => return, + .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .INVALID_PARAMETER => unreachable, + .ACCESS_DENIED => return error.PermissionDenied, + .OBJECT_PATH_SYNTAX_BAD => unreachable, + else => |rc| return windows.unexpectedStatus(rc), + } } pub const PipeError = error{ diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig index 08f22386f9..e98a2e6a87 100644 --- a/lib/std/os/windows/ntdll.zig +++ b/lib/std/os/windows/ntdll.zig @@ -8,6 +8,12 @@ pub extern "NtDll" fn NtQueryInformationFile( Length: ULONG, FileInformationClass: FILE_INFORMATION_CLASS, ) callconv(.Stdcall) NTSTATUS; + +pub extern "NtDll" fn NtQueryAttributesFile( + ObjectAttributes: *OBJECT_ATTRIBUTES, + FileAttributes: *FILE_BASIC_INFORMATION, +) callconv(.Stdcall) NTSTATUS; + pub extern "NtDll" fn NtCreateFile( FileHandle: *HANDLE, DesiredAccess: ACCESS_MASK, From 39ee46a6c1b5a56129950953d304a1169b7ffa67 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 17:35:35 -0500 Subject: [PATCH 015/109] fix building zig0 -> zig on macos --- src/userland.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/userland.cpp b/src/userland.cpp index 539735f436..2be97f22d6 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -146,8 +146,19 @@ int stage2_cmd_targets(const char *zig_triple) { } enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { - const char *msg = "stage0 called stage2_libc_parse"; - stage2_panic(msg, strlen(msg)); + libc->include_dir = "/dummy/include"; + libc->include_dir_len = strlen(libc->include_dir); + libc->sys_include_dir = "/dummy/sys/include"; + libc->sys_include_dir_len = strlen(libc->sys_include_dir); + libc->crt_dir = ""; + libc->crt_dir_len = strlen(libc->crt_dir); + libc->static_crt_dir = ""; + libc->static_crt_dir_len = strlen(libc->static_crt_dir); + libc->msvc_lib_dir = ""; + libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); + libc->kernel32_lib_dir = ""; + libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); + return ErrorNone; } enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { From 7eb0a3edcef2ab752ff1e45e6f1316b633b29606 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 18:57:34 -0500 Subject: [PATCH 016/109] remove libc dependency of zig0 building libstage2 Rather than `zig0 build ...` the build now does `zig0 build-lib ...`, avoiding the requirement of linking the build script, and thus avoiding the requirement of finding native libc, for systems where libc is the system ABI. --- CMakeLists.txt | 63 +++++++++++++++++---------- build.zig | 27 ------------ cmake/install.cmake | 12 ++--- src-self-hosted/libc_installation.zig | 19 ++++---- src/main.cpp | 34 +++++++++++++-- src/userland.cpp | 15 +------ 6 files changed, 90 insertions(+), 80 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a4a6d3199..950aa70ce1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -604,28 +604,29 @@ else() set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(LIBUSERLAND_RELEASE_MODE "false") + set(LIBUSERLAND_RELEASE_ARG "") else() - set(LIBUSERLAND_RELEASE_MODE "true") + set(LIBUSERLAND_RELEASE_ARG "--release-fast --strip") +endif() +if(WIN32) + set(LIBUSERLAND_WINDOWS_ARGS "-lntdll") +else() + set(LIBUSERLAND_WINDOWS_ARGS "") endif() -set(BUILD_LIBUSERLAND_ARGS "build" +set(BUILD_LIBUSERLAND_ARGS "build-lib" --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" - "-Doutput-dir=${CMAKE_BINARY_DIR}" - "-Drelease=${LIBUSERLAND_RELEASE_MODE}" - "-Dlib-files-only" - --prefix "${CMAKE_INSTALL_PREFIX}" - libuserland + --cache on + --output-dir "${CMAKE_BINARY_DIR}" + ${LIBUSERLAND_RELEASE_ARG} + "src-self-hosted/stage1.zig" + --disable-gen-h + --bundle-compiler-rt + -fPIC + -lc + ${LIBUSERLAND_WINDOWS_ARGS} ) -# When using Visual Studio build system generator we default to libuserland install. -if(MSVC) - set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix") - if(NOT ZIG_SKIP_INSTALL_LIB_FILES) - set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install) - endif() -endif() - add_custom_target(zig_build_libuserland ALL COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} DEPENDS zig0 @@ -648,12 +649,30 @@ add_dependencies(zig zig_build_libuserland) install(TARGETS zig DESTINATION bin) -# CODE has no effect with Visual Studio build system generator. -if(NOT MSVC) - get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR) - install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")") - install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)") - install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")") +set(ZIG_INSTALL_ARGS "build" + --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" + "-Dlib-files-only" + --prefix "${CMAKE_INSTALL_PREFIX}" + install +) + +# CODE has no effect with Visual Studio build system generator, therefore +# when using Visual Studio build system generator we resort to running +# `zig build install` during the build phase. +if(MSVC) + set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL + "Windows-only: Disable copying lib/ files to install prefix during the build phase") + if(NOT ZIG_SKIP_INSTALL_LIB_FILES) + add_custom_target(zig_install_lib_files ALL + COMMAND zig ${ZIG_INSTALL_ARGS} + DEPENDS zig + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + ) + endif() +else() + get_target_property(zig_BINARY_DIR zig BINARY_DIR) + install(CODE "set(zig_EXE \"${zig_BINARY_DIR}/zig\")") + install(CODE "set(ZIG_INSTALL_ARGS \"${ZIG_INSTALL_ARGS}\")") install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")") install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake) endif() diff --git a/build.zig b/build.zig index 4567b63029..e1ae5cf3cd 100644 --- a/build.zig +++ b/build.zig @@ -64,8 +64,6 @@ pub fn build(b: *Builder) !void { try configureStage2(b, test_stage2, ctx); try configureStage2(b, exe, ctx); - addLibUserlandStep(b, mode); - const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; @@ -366,28 +364,3 @@ const Context = struct { dia_guids_lib: []const u8, llvm: LibraryDep, }; - -fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void { - const artifact = b.addStaticLibrary("userland", "src-self-hosted/stage1.zig"); - artifact.disable_gen_h = true; - artifact.bundle_compiler_rt = true; - artifact.setTarget(builtin.arch, builtin.os, builtin.abi); - artifact.setBuildMode(mode); - artifact.force_pic = true; - if (mode != .Debug) { - artifact.strip = true; - } - artifact.linkSystemLibrary("c"); - if (builtin.os == .windows) { - artifact.linkSystemLibrary("ntdll"); - } - const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1"); - libuserland_step.dependOn(&artifact.step); - - const output_dir = b.option( - []const u8, - "output-dir", - "For libuserland step, where to put the output", - ) orelse return; - artifact.setOutputDir(output_dir); -} diff --git a/cmake/install.cmake b/cmake/install.cmake index 415a088d6a..e485652a05 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -1,16 +1,16 @@ message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib") -if(NOT EXISTS ${zig0_EXE}) +if(NOT EXISTS ${zig_EXE}) message("::") message(":: ERROR: Executable not found") message(":: (execute_process)") message("::") - message(":: executable: ${zig0_EXE}") + message(":: executable: ${zig_EXE}") message("::") message(FATAL_ERROR) endif() -execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS} +execute_process(COMMAND ${zig_EXE} ${ZIG_INSTALL_ARGS} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} RESULT_VARIABLE _result ) @@ -19,11 +19,11 @@ if(_result) message(":: ERROR: ${_result}") message(":: (execute_process)") - string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}") + string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}") message("::") - message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install") + message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}") - set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}) + set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS}) list(LENGTH _args _len) math(EXPR _len "${_len} - 1") message("::") diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 8f62e91e38..d66f00c14e 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -204,14 +204,17 @@ pub const LibCInstallation = struct { } } } else { - var batch = Batch(FindError!void, 2, .auto_async).init(); - batch.add(&async self.findNativeIncludeDirPosix(allocator)); - if (is_freebsd or is_netbsd) { - self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib"); - } else if (is_linux or is_dragonfly) { - batch.add(&async self.findNativeCrtDirPosix(allocator)); - } - try batch.wait(); + try blk: { + var batch = Batch(FindError!void, 2, .auto_async).init(); + errdefer batch.wait() catch {}; + batch.add(&async self.findNativeIncludeDirPosix(allocator)); + if (is_freebsd or is_netbsd) { + self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib"); + } else if (is_linux or is_dragonfly) { + batch.add(&async self.findNativeCrtDirPosix(allocator)); + } + break :blk batch.wait(); + }; } return self; } diff --git a/src/main.cpp b/src/main.cpp index d5883d2bb3..4f5367be7b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1003,9 +1003,22 @@ static int main0(int argc, char **argv) { return main_exit(root_progress_node, EXIT_FAILURE); } + // If both output_dir and enable_cache are provided, and doing build-lib, we + // will just do a file copy at the end. This helps when bootstrapping zig from zig0 + // because we want to pass something like this: + // zig0 build-lib --cache on --output-dir ${CMAKE_BINARY_DIR} + // And we don't have access to `zig0 build` because that would require detecting native libc + // on systems where we are not able to build a libc from source for them. + // But that's the only reason this works, so otherwise we give an error here. + Buf *final_output_dir_step = nullptr; if (output_dir != nullptr && enable_cache == CacheOptOn) { - fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n"); - return print_error_usage(arg0); + if (cmd == CmdBuild && out_type == OutTypeLib) { + final_output_dir_step = output_dir; + output_dir = nullptr; + } else { + fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n"); + return print_error_usage(arg0); + } } if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) { @@ -1290,8 +1303,21 @@ static int main0(int argc, char **argv) { #if defined(ZIG_OS_WINDOWS) buf_replace(&g->output_file_path, '/', '\\'); #endif - if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) - return main_exit(root_progress_node, EXIT_FAILURE); + if (final_output_dir_step != nullptr) { + Buf *dest_basename = buf_alloc(); + os_path_split(&g->output_file_path, nullptr, dest_basename); + Buf *dest_path = buf_alloc(); + os_path_join(final_output_dir_step, dest_basename, dest_path); + + if ((err = os_copy_file(&g->output_file_path, dest_path))) { + fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path), + buf_ptr(dest_path), err_str(err)); + return main_exit(root_progress_node, EXIT_FAILURE); + } + } else { + if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) + return main_exit(root_progress_node, EXIT_FAILURE); + } } return main_exit(root_progress_node, EXIT_SUCCESS); } else { diff --git a/src/userland.cpp b/src/userland.cpp index 2be97f22d6..539735f436 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -146,19 +146,8 @@ int stage2_cmd_targets(const char *zig_triple) { } enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { - libc->include_dir = "/dummy/include"; - libc->include_dir_len = strlen(libc->include_dir); - libc->sys_include_dir = "/dummy/sys/include"; - libc->sys_include_dir_len = strlen(libc->sys_include_dir); - libc->crt_dir = ""; - libc->crt_dir_len = strlen(libc->crt_dir); - libc->static_crt_dir = ""; - libc->static_crt_dir_len = strlen(libc->static_crt_dir); - libc->msvc_lib_dir = ""; - libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); - libc->kernel32_lib_dir = ""; - libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); - return ErrorNone; + const char *msg = "stage0 called stage2_libc_parse"; + stage2_panic(msg, strlen(msg)); } enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { From c25742010d69e0e56f1fda99f1b986be52165e3b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 19:02:26 -0500 Subject: [PATCH 017/109] add the dummy libc paths back in --- CMakeLists.txt | 2 +- src/userland.cpp | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 950aa70ce1..b990261d08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -606,7 +606,7 @@ endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(LIBUSERLAND_RELEASE_ARG "") else() - set(LIBUSERLAND_RELEASE_ARG "--release-fast --strip") + set(LIBUSERLAND_RELEASE_ARG --release-fast --strip) endif() if(WIN32) set(LIBUSERLAND_WINDOWS_ARGS "-lntdll") diff --git a/src/userland.cpp b/src/userland.cpp index 539735f436..2be97f22d6 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -146,8 +146,19 @@ int stage2_cmd_targets(const char *zig_triple) { } enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { - const char *msg = "stage0 called stage2_libc_parse"; - stage2_panic(msg, strlen(msg)); + libc->include_dir = "/dummy/include"; + libc->include_dir_len = strlen(libc->include_dir); + libc->sys_include_dir = "/dummy/sys/include"; + libc->sys_include_dir_len = strlen(libc->sys_include_dir); + libc->crt_dir = ""; + libc->crt_dir_len = strlen(libc->crt_dir); + libc->static_crt_dir = ""; + libc->static_crt_dir_len = strlen(libc->static_crt_dir); + libc->msvc_lib_dir = ""; + libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); + libc->kernel32_lib_dir = ""; + libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); + return ErrorNone; } enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { From 20f3b0efff76cb3c611b72c1c1862490aef79b80 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 19:16:08 -0500 Subject: [PATCH 018/109] rename libuserland to libstage2 --- CMakeLists.txt | 34 +++++++++++----------- cmake/install.cmake | 4 +-- src-self-hosted/{stage1.zig => stage2.zig} | 0 src/cache_hash.cpp | 2 +- src/codegen.cpp | 2 +- src/codegen.hpp | 2 +- src/error.hpp | 2 +- src/main.cpp | 2 +- src/{userland.cpp => stage2.cpp} | 2 +- src/{userland.h => stage2.h} | 6 ++-- src/util.cpp | 2 +- src/zig_clang.h | 2 +- 12 files changed, 30 insertions(+), 30 deletions(-) rename src-self-hosted/{stage1.zig => stage2.zig} (100%) rename src/{userland.cpp => stage2.cpp} (99%) rename src/{userland.h => stage2.h} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b990261d08..a9dec50193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,8 +434,8 @@ find_package(Threads) # CMake doesn't let us create an empty executable, so we hang on to this one separately. set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") -# This is our shim which will be replaced by libuserland written in Zig. -set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") +# This is our shim which will be replaced by libstage2 written in Zig. +set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp") if(ZIG_ENABLE_MEM_PROFILE) set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp") @@ -599,38 +599,38 @@ set_target_properties(zig0 PROPERTIES target_link_libraries(zig0 compiler) if(MSVC) - set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/stage2.lib") else() - set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libstage2.a") endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(LIBUSERLAND_RELEASE_ARG "") + set(LIBSTAGE2_RELEASE_ARG "") else() - set(LIBUSERLAND_RELEASE_ARG --release-fast --strip) + set(LIBSTAGE2_RELEASE_ARG --release-fast --strip) endif() if(WIN32) - set(LIBUSERLAND_WINDOWS_ARGS "-lntdll") + set(LIBSTAGE2_WINDOWS_ARGS "-lntdll") else() - set(LIBUSERLAND_WINDOWS_ARGS "") + set(LIBSTAGE2_WINDOWS_ARGS "") endif() -set(BUILD_LIBUSERLAND_ARGS "build-lib" +set(BUILD_LIBSTAGE2_ARGS "build-lib" --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" --cache on --output-dir "${CMAKE_BINARY_DIR}" - ${LIBUSERLAND_RELEASE_ARG} - "src-self-hosted/stage1.zig" + ${LIBSTAGE2_RELEASE_ARG} + "src-self-hosted/stage2.zig" --disable-gen-h --bundle-compiler-rt -fPIC -lc - ${LIBUSERLAND_WINDOWS_ARGS} + ${LIBSTAGE2_WINDOWS_ARGS} ) -add_custom_target(zig_build_libuserland ALL - COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} +add_custom_target(zig_build_libstage2 ALL + COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS} DEPENDS zig0 - BYPRODUCTS "${LIBUSERLAND}" + BYPRODUCTS "${LIBSTAGE2}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) add_executable(zig "${ZIG_MAIN_SRC}") @@ -639,13 +639,13 @@ set_target_properties(zig PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) -target_link_libraries(zig compiler "${LIBUSERLAND}") +target_link_libraries(zig compiler "${LIBSTAGE2}") if(MSVC) target_link_libraries(zig ntdll.lib) elseif(MINGW) target_link_libraries(zig ntdll) endif() -add_dependencies(zig zig_build_libuserland) +add_dependencies(zig zig_build_libstage2) install(TARGETS zig DESTINATION bin) diff --git a/cmake/install.cmake b/cmake/install.cmake index e485652a05..386773e30c 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -19,9 +19,9 @@ if(_result) message(":: ERROR: ${_result}") message(":: (execute_process)") - string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}") + string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}") message("::") - message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}") + message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}") set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS}) list(LENGTH _args _len) diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage2.zig similarity index 100% rename from src-self-hosted/stage1.zig rename to src-self-hosted/stage2.zig diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 714b9b4c18..35b05a1ddf 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -5,7 +5,7 @@ * See http://opensource.org/licenses/MIT */ -#include "userland.h" +#include "stage2.h" #include "cache_hash.hpp" #include "all_types.hpp" #include "buffer.hpp" diff --git a/src/codegen.cpp b/src/codegen.cpp index 22d76c1372..0b5d2e82f1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -18,7 +18,7 @@ #include "target.hpp" #include "util.hpp" #include "zig_llvm.h" -#include "userland.h" +#include "stage2.h" #include "dump_analysis.hpp" #include "softfloat.hpp" #include "mem_profile.hpp" diff --git a/src/codegen.hpp b/src/codegen.hpp index 623ae12fef..f8be29494a 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -11,7 +11,7 @@ #include "parser.hpp" #include "errmsg.hpp" #include "target.hpp" -#include "userland.h" +#include "stage2.h" #include diff --git a/src/error.hpp b/src/error.hpp index 3ff36e1a5f..90772df108 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -8,7 +8,7 @@ #ifndef ERROR_HPP #define ERROR_HPP -#include "userland.h" +#include "stage2.h" const char *err_str(Error err); diff --git a/src/main.cpp b/src/main.cpp index 4f5367be7b..df6e07a5a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ #include "heap.hpp" #include "os.hpp" #include "target.hpp" -#include "userland.h" +#include "stage2.h" #include "glibc.hpp" #include "dump_analysis.hpp" #include "mem_profile.hpp" diff --git a/src/userland.cpp b/src/stage2.cpp similarity index 99% rename from src/userland.cpp rename to src/stage2.cpp index 2be97f22d6..db4f529c68 100644 --- a/src/userland.cpp +++ b/src/stage2.cpp @@ -1,7 +1,7 @@ // This file is a shim for zig1. The real implementations of these are in // src-self-hosted/stage1.zig -#include "userland.h" +#include "stage2.h" #include "util.hpp" #include "zig_llvm.h" #include diff --git a/src/userland.h b/src/stage2.h similarity index 98% rename from src/userland.h rename to src/stage2.h index 7903dc8fe4..f6bb17c884 100644 --- a/src/userland.h +++ b/src/stage2.h @@ -5,8 +5,8 @@ * See http://opensource.org/licenses/MIT */ -#ifndef ZIG_USERLAND_H -#define ZIG_USERLAND_H +#ifndef ZIG_STAGE2_H +#define ZIG_STAGE2_H #include #include @@ -25,7 +25,7 @@ #endif // ABI warning: the types and declarations in this file must match both those in -// userland.cpp and src-self-hosted/stage1.zig. +// stage2.cpp and src-self-hosted/stage2.zig. // ABI warning enum Error { diff --git a/src/util.cpp b/src/util.cpp index 56f1de9839..2de09df808 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6,7 +6,7 @@ */ #include "util.hpp" -#include "userland.h" +#include "stage2.h" #include #include diff --git a/src/zig_clang.h b/src/zig_clang.h index f7de9c2cee..2d9485ae9b 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -8,7 +8,7 @@ #ifndef ZIG_ZIG_CLANG_H #define ZIG_ZIG_CLANG_H -#include "userland.h" +#include "stage2.h" #include #include From 5c54d7bee7ca4d7d7948e2549fd67b61e2dcaf17 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 19:58:27 -0500 Subject: [PATCH 019/109] add missing implementations of libc installation to detect msvc paths --- lib/std/fs.zig | 1 - src-self-hosted/libc_installation.zig | 55 +++++++++++++++++++++++++-- src-self-hosted/stage2.zig | 2 + src/error.cpp | 1 + src/stage2.h | 1 + 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index bc9ae6aa2d..a00ba6a63f 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -96,7 +96,6 @@ pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus { /// atime, and mode of the source file so that the next call to `updateFile` will not need a copy. /// Returns the previous status of the file before updating. /// If any of the directories do not exist for dest_path, they are created. -/// TODO https://github.com/ziglang/zig/issues/2885 pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus { const my_cwd = cwd(); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index d66f00c14e..85d6fc61ed 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -36,6 +36,7 @@ pub const LibCInstallation = struct { LibCStdLibHeaderNotFound, LibCKernel32LibNotFound, UnsupportedArchitecture, + WindowsSdkNotFound, }; pub fn parse( @@ -174,7 +175,7 @@ pub const LibCInstallation = struct { } /// Finds the default, native libc. - pub fn findNative(allocator: *Allocator) !LibCInstallation { + pub fn findNative(allocator: *Allocator) FindError!LibCInstallation { var self: LibCInstallation = .{}; if (is_windows) { @@ -199,8 +200,8 @@ pub const LibCInstallation = struct { try batch.wait(); }, .OutOfMemory => return error.OutOfMemory, - .NotFound => return error.NotFound, - .PathTooLong => return error.NotFound, + .NotFound => return error.WindowsSdkNotFound, + .PathTooLong => return error.WindowsSdkNotFound, } } } else { @@ -311,7 +312,11 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) !void { + fn findNativeIncludeDirWindows( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -432,6 +437,48 @@ pub const LibCInstallation = struct { } return error.LibCKernel32LibNotFound; } + + fn findNativeMsvcIncludeDir( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { + const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCStdLibHeaderNotFound; + const msvc_lib_dir = msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]; + const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; + const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; + + var result_buf = try std.Buffer.init(allocator, up2); + defer result_buf.deinit(); + + try result_buf.append("\\include"); + + var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) { + error.FileNotFound, + error.NotDir, + error.NoDevice, + => return error.LibCStdLibHeaderNotFound, + + else => return error.FileSystem, + }; + defer dir.close(); + + dir.accessZ("vcruntime.h", .{}) catch |err| switch (err) { + error.FileNotFound => return error.LibCStdLibHeaderNotFound, + else => return error.FileSystem, + }; + + self.sys_include_dir = result_buf.toOwnedSlice(); + } + + fn findNativeMsvcLibDir( + self: *LibCInstallation, + allocator: *Allocator, + sdk: *ZigWindowsSDK, + ) FindError!void { + const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCRuntimeNotFound; + self.msvc_lib_dir = try std.mem.dupeZ(allocator, u8, msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); + } }; const default_cc_exe = if (is_windows) "cc.exe" else "cc"; diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 95719d47a9..897f2a3ed8 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -108,6 +108,7 @@ const Error = extern enum { LibCStdLibHeaderNotFound, LibCKernel32LibNotFound, UnsupportedArchitecture, + WindowsSdkNotFound, }; const FILE = std.c.FILE; @@ -985,6 +986,7 @@ export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, error.UnsupportedArchitecture => return .UnsupportedArchitecture, + error.WindowsSdkNotFound => return .WindowsSdkNotFound, }; stage1_libc.initFromStage2(libc); return .None; diff --git a/src/error.cpp b/src/error.cpp index 1e0267eb67..b7cc8e630a 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -79,6 +79,7 @@ const char *err_str(Error err) { case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found"; case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; + case ErrorWindowsSdkNotFound: return "Windows SDK not found"; } return "(invalid error)"; } diff --git a/src/stage2.h b/src/stage2.h index f6bb17c884..856a5c3df8 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -99,6 +99,7 @@ enum Error { ErrorLibCStdLibHeaderNotFound, ErrorLibCKernel32LibNotFound, ErrorUnsupportedArchitecture, + ErrorWindowsSdkNotFound, }; // ABI warning From a26800c0992b123b1ef16712ec1e56fb62b0caf9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 21:10:03 -0500 Subject: [PATCH 020/109] stage1: don't copy unchanged output files when both `--cache on` and `--output-dir` parameters are provided. This prevents re-linking `zig` with every `make` even when `libzigstage2.a` was unchanged. --- CMakeLists.txt | 23 +++---- src/main.cpp | 2 +- src/os.cpp | 163 ++++++++++++++++++++++++++++++++++++++----------- src/os.hpp | 7 ++- 4 files changed, 147 insertions(+), 48 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9dec50193..ab4607d230 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -565,12 +565,12 @@ set_target_properties(opt_c_util PROPERTIES COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}" ) -add_library(compiler STATIC ${ZIG_SOURCES}) -set_target_properties(compiler PROPERTIES +add_library(zigcompiler STATIC ${ZIG_SOURCES}) +set_target_properties(zigcompiler PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) -target_link_libraries(compiler LINK_PUBLIC +target_link_libraries(zigcompiler LINK_PUBLIC zig_cpp opt_c_util ${SOFTFLOAT_LIBRARIES} @@ -580,15 +580,15 @@ target_link_libraries(compiler LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT} ) if(NOT MSVC) - target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) + target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2}) endif() if(ZIG_DIA_GUIDS_LIB) - target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) + target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) endif() if(MSVC OR MINGW) - target_link_libraries(compiler LINK_PUBLIC version) + target_link_libraries(zigcompiler LINK_PUBLIC version) endif() add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}") @@ -596,12 +596,12 @@ set_target_properties(zig0 PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) -target_link_libraries(zig0 compiler) +target_link_libraries(zig0 zigcompiler) if(MSVC) - set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/stage2.lib") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/zigstage2.lib") else() - set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libstage2.a") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libzigstage2.a") endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(LIBSTAGE2_RELEASE_ARG "") @@ -615,11 +615,12 @@ else() endif() set(BUILD_LIBSTAGE2_ARGS "build-lib" + "src-self-hosted/stage2.zig" + --name zigstage2 --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" --cache on --output-dir "${CMAKE_BINARY_DIR}" ${LIBSTAGE2_RELEASE_ARG} - "src-self-hosted/stage2.zig" --disable-gen-h --bundle-compiler-rt -fPIC @@ -639,7 +640,7 @@ set_target_properties(zig PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) -target_link_libraries(zig compiler "${LIBSTAGE2}") +target_link_libraries(zig zigcompiler "${LIBSTAGE2}") if(MSVC) target_link_libraries(zig ntdll.lib) elseif(MINGW) diff --git a/src/main.cpp b/src/main.cpp index df6e07a5a7..cbaf6aeb70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1309,7 +1309,7 @@ static int main0(int argc, char **argv) { Buf *dest_path = buf_alloc(); os_path_join(final_output_dir_step, dest_basename, dest_path); - if ((err = os_copy_file(&g->output_file_path, dest_path))) { + if ((err = os_update_file(&g->output_file_path, dest_path))) { fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path), buf_ptr(dest_path), err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); diff --git a/src/os.cpp b/src/os.cpp index aa09166fc5..1df0cd8e80 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1029,6 +1029,110 @@ Error os_write_file(Buf *full_path, Buf *contents) { return ErrorNone; } +static Error copy_open_files(FILE *src_f, FILE *dest_f) { + static const size_t buf_size = 2048; + char buf[buf_size]; + for (;;) { + size_t amt_read = fread(buf, 1, buf_size, src_f); + if (amt_read != buf_size) { + if (ferror(src_f)) { + return ErrorFileSystem; + } + } + size_t amt_written = fwrite(buf, 1, amt_read, dest_f); + if (amt_written != amt_read) { + return ErrorFileSystem; + } + if (feof(src_f)) { + return ErrorNone; + } + } +} + +#if defined(ZIG_OS_WINDOWS) +static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) { + mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime; + mtime->nsec = 0; +} +static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) { + FILETIME result; + result.dwHighDateTime = mtime.sec >> 32; + result.dwLowDateTime = mtime.sec; + return result; +} +#endif + +static Error set_file_times(OsFile file, OsTimeStamp ts) { +#if defined(ZIG_OS_WINDOWS) + const atime_ft = windows.nanoSecondsToFileTime(atime); + const mtime_ft = windows.nanoSecondsToFileTime(mtime); + return SetFileTime(file, null, &atime_ft, &mtime_ft); +#else + struct timespec times[2] = { + { ts.sec, ts.nsec }, + { ts.sec, ts.nsec }, + }; + if (futimens(file, times) == -1) { + switch (errno) { + case EBADF: + zig_panic("futimens EBADF"); + default: + return ErrorUnexpected; + } + } + return ErrorNone; +#endif +} + +Error os_update_file(Buf *src_path, Buf *dst_path) { + Error err; + + OsFile src_file; + OsFileAttr src_attr; + if ((err = os_file_open_r(src_path, &src_file, &src_attr))) { + return err; + } + + OsFile dst_file; + OsFileAttr dst_attr; + if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) { + os_file_close(&src_file); + return err; + } + + if (src_attr.mtime.sec == dst_attr.mtime.sec && + src_attr.mtime.nsec == dst_attr.mtime.nsec && + src_attr.mode == dst_attr.mode) + { + os_file_close(&src_file); + os_file_close(&dst_file); + return ErrorNone; + } + + FILE *src_libc_file = fdopen(src_file, "rb"); + FILE *dst_libc_file = fdopen(dst_file, "wb"); + assert(src_libc_file); + assert(dst_libc_file); + if (ftruncate(dst_file, 0) == -1) { + return ErrorUnexpected; + } + if ((err = copy_open_files(src_libc_file, dst_libc_file))) { + fclose(src_libc_file); + fclose(dst_libc_file); + return err; + } + if (fflush(src_libc_file) == -1) { + return ErrorUnexpected; + } + if (fflush(dst_libc_file) == -1) { + return ErrorUnexpected; + } + err = set_file_times(dst_file, src_attr.mtime); + fclose(src_libc_file); + fclose(dst_libc_file); + return err; +} + Error os_copy_file(Buf *src_path, Buf *dest_path) { FILE *src_f = fopen(buf_ptr(src_path), "rb"); if (!src_f) { @@ -1055,30 +1159,10 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) { return ErrorFileSystem; } } - - static const size_t buf_size = 2048; - char buf[buf_size]; - for (;;) { - size_t amt_read = fread(buf, 1, buf_size, src_f); - if (amt_read != buf_size) { - if (ferror(src_f)) { - fclose(src_f); - fclose(dest_f); - return ErrorFileSystem; - } - } - size_t amt_written = fwrite(buf, 1, amt_read, dest_f); - if (amt_written != amt_read) { - fclose(src_f); - fclose(dest_f); - return ErrorFileSystem; - } - if (feof(src_f)) { - fclose(src_f); - fclose(dest_f); - return ErrorNone; - } - } + Error err = copy_open_files(src_f, dest_f); + fclose(src_f); + fclose(dest_f); + return err; } Error os_fetch_file_path(Buf *full_path, Buf *out_contents) { @@ -1218,13 +1302,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) { return ErrorNone; } -#if defined(ZIG_OS_WINDOWS) -static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) { - mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime; - mtime->nsec = 0; -} -#endif - OsTimeStamp os_timestamp_calendar(void) { OsTimeStamp result; #if defined(ZIG_OS_WINDOWS) @@ -1733,10 +1810,15 @@ Error os_self_exe_shared_libs(ZigList &paths) { #endif } -Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { +Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) { #if defined(ZIG_OS_WINDOWS) // TODO use CreateFileW - HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + HANDLE result = CreateFileA(buf_ptr(full_path), + need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, + need_write ? 0 : FILE_SHARE_READ, + nullptr, + need_write ? OPEN_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, nullptr); if (result == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); @@ -1769,12 +1851,14 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { } windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime); attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow; + attr->mode = 0; } return ErrorNone; #else for (;;) { - int fd = open(buf_ptr(full_path), O_RDONLY|O_CLOEXEC); + int fd = open(buf_ptr(full_path), + need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode); if (fd == -1) { switch (errno) { case EINTR: @@ -1784,6 +1868,7 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { case EFAULT: zig_unreachable(); case EACCES: + case EPERM: return ErrorAccess; case EISDIR: return ErrorIsDir; @@ -1813,12 +1898,21 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { attr->mtime.sec = statbuf.st_mtim.tv_sec; attr->mtime.nsec = statbuf.st_mtim.tv_nsec; #endif + attr->mode = statbuf.st_mode; } return ErrorNone; } #endif } +Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) { + return os_file_open_rw(full_path, out_file, attr, false, 0); +} + +Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) { + return os_file_open_rw(full_path, out_file, attr, true, mode); +} + Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { #if defined(ZIG_OS_WINDOWS) for (;;) { @@ -1864,6 +1958,7 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { case EFAULT: zig_unreachable(); case EACCES: + case EPERM: return ErrorAccess; case EISDIR: return ErrorIsDir; diff --git a/src/os.hpp b/src/os.hpp index 6823d901b5..c8e098b333 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -93,13 +93,14 @@ struct Termination { #endif struct OsTimeStamp { - uint64_t sec; - uint64_t nsec; + int64_t sec; + int64_t nsec; }; struct OsFileAttr { OsTimeStamp mtime; uint64_t inode; + uint32_t mode; }; int os_init(void); @@ -121,6 +122,7 @@ Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr); +Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode); Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file); Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len); Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); @@ -129,6 +131,7 @@ void os_file_close(OsFile *file); Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents); Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path); +Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path); Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents); Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents); From 364a284eb3b5e90a9ec0ea6b29be8b74d2a92fa5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 21:35:12 -0500 Subject: [PATCH 021/109] stage1 os: handle errors from read/write not sure why the CI is complaining about these now and not in master branch. but this is a slight code improvement anyway --- src/os.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 1df0cd8e80..65e1b79524 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -826,7 +826,9 @@ static Error os_exec_process_posix(ZigList &args, if (errno == ENOENT) { report_err = ErrorFileNotFound; } - write(err_pipe[1], &report_err, sizeof(Error)); + if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) { + zig_panic("write failed"); + } exit(1); } else { // parent @@ -851,9 +853,13 @@ static Error os_exec_process_posix(ZigList &args, if (err2) return err2; Error child_err = ErrorNone; - write(err_pipe[1], &child_err, sizeof(Error)); + if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) { + zig_panic("write failed"); + } close(err_pipe[1]); - read(err_pipe[0], &child_err, sizeof(Error)); + if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) { + zig_panic("write failed"); + } close(err_pipe[0]); return child_err; } From d5860cbade79141c4c547a3411befb8448dd56ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 22:34:40 -0500 Subject: [PATCH 022/109] fix os_update_file implementation on Windows --- src/os.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 65e1b79524..48bf78e1cb 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1070,9 +1070,11 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) { static Error set_file_times(OsFile file, OsTimeStamp ts) { #if defined(ZIG_OS_WINDOWS) - const atime_ft = windows.nanoSecondsToFileTime(atime); - const mtime_ft = windows.nanoSecondsToFileTime(mtime); - return SetFileTime(file, null, &atime_ft, &mtime_ft); + FILETIME ft = windows_os_timestamp_to_filetime(ts); + if (SetFileTime(file, nullptr, &ft, &ft) == 0) { + return ErrorUnexpected; + } + return ErrorNone; #else struct timespec times[2] = { { ts.sec, ts.nsec }, @@ -1114,14 +1116,25 @@ Error os_update_file(Buf *src_path, Buf *dst_path) { os_file_close(&dst_file); return ErrorNone; } - - FILE *src_libc_file = fdopen(src_file, "rb"); - FILE *dst_libc_file = fdopen(dst_file, "wb"); - assert(src_libc_file); - assert(dst_libc_file); +#if defined(ZIG_OS_WINDOWS) + if (SetEndOfFile(dst_file) == 0) { + return ErrorUnexpected; + } +#else if (ftruncate(dst_file, 0) == -1) { return ErrorUnexpected; } +#endif +#if defined(ZIG_OS_WINDOWS) + FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb"); + FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb"); +#else + FILE *src_libc_file = fdopen(src_file, "rb"); + FILE *dst_libc_file = fdopen(dst_file, "wb"); +#endif + assert(src_libc_file); + assert(dst_libc_file); + if ((err = copy_open_files(src_libc_file, dst_libc_file))) { fclose(src_libc_file); fclose(dst_libc_file); From a5d47be5adc7c493ff7e87fc47241a84e268a3f0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Feb 2020 22:49:28 -0500 Subject: [PATCH 023/109] stage1 os_update_file additionally compares src and dest size prevents problems when source is created and then immediately copied to dest. --- src/os.cpp | 9 ++++++--- src/os.hpp | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/os.cpp b/src/os.cpp index 48bf78e1cb..5e2c986e43 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1108,9 +1108,10 @@ Error os_update_file(Buf *src_path, Buf *dst_path) { return err; } - if (src_attr.mtime.sec == dst_attr.mtime.sec && - src_attr.mtime.nsec == dst_attr.mtime.nsec && - src_attr.mode == dst_attr.mode) + if (src_attr.size == dst_attr.size && + src_attr.mode == dst_attr.mode && + src_attr.mtime.sec == dst_attr.mtime.sec && + src_attr.mtime.nsec == dst_attr.mtime.nsec) { os_file_close(&src_file); os_file_close(&dst_file); @@ -1871,6 +1872,7 @@ Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool n windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime); attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow; attr->mode = 0; + attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow; } return ErrorNone; @@ -1918,6 +1920,7 @@ Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool n attr->mtime.nsec = statbuf.st_mtim.tv_nsec; #endif attr->mode = statbuf.st_mode; + attr->size = statbuf.st_size; } return ErrorNone; } diff --git a/src/os.hpp b/src/os.hpp index c8e098b333..c26d6c8df5 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -99,6 +99,7 @@ struct OsTimeStamp { struct OsFileAttr { OsTimeStamp mtime; + uint64_t size; uint64_t inode; uint32_t mode; }; From 44c14749a1063e5525b3249cddca6435d0654df4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 00:58:30 -0500 Subject: [PATCH 024/109] expand argv[0] when spawning system C compiler Some C compilers, such as Clang, are known to rely on argv[0] to find the path to their own executable, without even bothering to resolve PATH. This results in the message: error: unable to execute command: Executable "" doesn't exist! So we tell ChildProcess to expand argv[0] to the absolute path to give them a helping hand. --- lib/std/child_process.zig | 51 +++++++++++++----- lib/std/os.zig | 77 ++++++++++++++++++++++----- src-self-hosted/libc_installation.zig | 24 +++++++-- 3 files changed, 122 insertions(+), 30 deletions(-) diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index f3626f5249..171a330bac 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -49,6 +49,10 @@ pub const ChildProcess = struct { err_pipe: if (builtin.os == .windows) void else [2]os.fd_t, + expand_arg0: Arg0Expand, + + pub const Arg0Expand = os.Arg0Expand; + pub const SpawnError = error{ OutOfMemory, @@ -100,6 +104,7 @@ pub const ChildProcess = struct { .stdin_behavior = StdIo.Inherit, .stdout_behavior = StdIo.Inherit, .stderr_behavior = StdIo.Inherit, + .expand_arg0 = .no_expand, }; errdefer allocator.destroy(child); return child; @@ -172,34 +177,56 @@ pub const ChildProcess = struct { /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. /// If it succeeds, the caller owns result.stdout and result.stderr memory. + /// TODO deprecate in favor of exec2 pub fn exec( allocator: *mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?*const BufMap, - max_output_size: usize, + max_output_bytes: usize, ) !ExecResult { - const child = try ChildProcess.init(argv, allocator); + return exec2(.{ + .allocator = allocator, + .argv = argv, + .cwd = cwd, + .env_map = env_map, + .max_output_bytes = max_output_bytes, + }); + } + + /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. + /// If it succeeds, the caller owns result.stdout and result.stderr memory. + /// TODO rename to exec + pub fn exec2(args: struct { + allocator: *mem.Allocator, + argv: []const []const u8, + cwd: ?[]const u8 = null, + env_map: ?*const BufMap = null, + max_output_bytes: usize = 50 * 1024, + expand_arg0: Arg0Expand = .no_expand, + }) !ExecResult { + const child = try ChildProcess.init(args.argv, args.allocator); defer child.deinit(); - child.stdin_behavior = ChildProcess.StdIo.Ignore; - child.stdout_behavior = ChildProcess.StdIo.Pipe; - child.stderr_behavior = ChildProcess.StdIo.Pipe; - child.cwd = cwd; - child.env_map = env_map; + child.stdin_behavior = .Ignore; + child.stdout_behavior = .Pipe; + child.stderr_behavior = .Pipe; + child.cwd = args.cwd; + child.env_map = args.env_map; + child.expand_arg0 = args.expand_arg0; try child.spawn(); - var stdout = Buffer.initNull(allocator); - var stderr = Buffer.initNull(allocator); + var stdout = Buffer.initNull(args.allocator); + var stderr = Buffer.initNull(args.allocator); defer Buffer.deinit(&stdout); defer Buffer.deinit(&stderr); var stdout_file_in_stream = child.stdout.?.inStream(); var stderr_file_in_stream = child.stderr.?.inStream(); - try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); - try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size); + try stdout_file_in_stream.stream.readAllBuffer(&stdout, args.max_output_bytes); + try stderr_file_in_stream.stream.readAllBuffer(&stderr, args.max_output_bytes); return ExecResult{ .term = try child.wait(), @@ -418,7 +445,7 @@ pub const ChildProcess = struct { os.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); } - const err = os.execvpe(self.allocator, self.argv, env_map); + const err = os.execvpe_expandArg0(self.allocator, self.expand_arg0, self.argv, env_map); forkChildErrReport(err_pipe[1], err); } diff --git a/lib/std/os.zig b/lib/std/os.zig index ff2296d928..c5fdc41d83 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -916,10 +916,13 @@ pub const ExecveError = error{ NameTooLong, } || UnexpectedError; +/// Deprecated in favor of `execveZ`. +pub const execveC = execveZ; + /// Like `execve` except the parameters are null-terminated, /// matching the syscall API on all targets. This removes the need for an allocator. -/// This function ignores PATH environment variable. See `execvpeC` for that. -pub fn execveC(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { +/// This function ignores PATH environment variable. See `execvpeZ` for that. +pub fn execveZ(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { switch (errno(system.execve(path, child_argv, envp))) { 0 => unreachable, EFAULT => unreachable, @@ -942,11 +945,25 @@ pub fn execveC(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, en } } -/// Like `execvpe` except the parameters are null-terminated, -/// matching the syscall API on all targets. This removes the need for an allocator. -/// This function also uses the PATH environment variable to get the full path to the executable. -/// If `file` is an absolute path, this is the same as `execveC`. -pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { +/// Deprecated in favor of `execvpeZ`. +pub const execvpeC = execvpeZ; + +pub const Arg0Expand = enum { + expand, + no_expand, +}; + +/// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable, +/// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall. +pub fn execvpeZ_expandArg0( + comptime arg0_expand: Arg0Expand, + file: [*:0]const u8, + child_argv: switch (arg0_expand) { + .expand => [*:null]?[*:0]const u8, + .no_expand => [*:null]const ?[*:0]const u8, + }, + envp: [*:null]const ?[*:0]const u8, +) ExecveError { const file_slice = mem.toSliceConst(u8, file); if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp); @@ -962,7 +979,12 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice); const path_len = search_path.len + file_slice.len + 1; path_buf[path_len] = 0; - err = execveC(path_buf[0..path_len :0].ptr, child_argv, envp); + const full_path = path_buf[0..path_len :0].ptr; + switch (arg0_expand) { + .expand => child_argv[0] = full_path, + .no_expand => {}, + } + err = execveC(full_path, child_argv, envp); switch (err) { error.AccessDenied => seen_eacces = true, error.FileNotFound, error.NotDir => {}, @@ -973,13 +995,24 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e return err; } -/// This function must allocate memory to add a null terminating bytes on path and each arg. -/// It must also convert to KEY=VALUE\0 format for environment variables, and include null -/// pointers after the args and after the environment variables. -/// `argv_slice[0]` is the executable path. +/// Like `execvpe` except the parameters are null-terminated, +/// matching the syscall API on all targets. This removes the need for an allocator. /// This function also uses the PATH environment variable to get the full path to the executable. -pub fn execvpe( +/// If `file` is an absolute path, this is the same as `execveC`. +pub fn execvpeZ( + file: [*:0]const u8, + argv: [*:null]const ?[*:0]const u8, + envp: [*:null]const ?[*:0]const u8, +) ExecveError { + return execvpeZ_expandArg0(.no_expand, file, argv, envp); +} + +/// This is the same as `execvpe` except if the `arg0_expand` parameter is set to `.expand`, +/// then argv[0] will be replaced with the expanded version of it, after resolving in accordance +/// with the PATH environment variable. +pub fn execvpe_expandArg0( allocator: *mem.Allocator, + arg0_expand: Arg0Expand, argv_slice: []const []const u8, env_map: *const std.BufMap, ) (ExecveError || error{OutOfMemory}) { @@ -1004,7 +1037,23 @@ pub fn execvpe( const envp_buf = try createNullDelimitedEnvMap(allocator, env_map); defer freeNullDelimitedEnvMap(allocator, envp_buf); - return execvpeC(argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr); + switch (arg0_expand) { + .expand => return execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr), + .no_expand => return execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr), + } +} + +/// This function must allocate memory to add a null terminating bytes on path and each arg. +/// It must also convert to KEY=VALUE\0 format for environment variables, and include null +/// pointers after the args and after the environment variables. +/// `argv_slice[0]` is the executable path. +/// This function also uses the PATH environment variable to get the full path to the executable. +pub fn execvpe( + allocator: *mem.Allocator, + argv_slice: []const []const u8, + env_map: *const std.BufMap, +) (ExecveError || error{OutOfMemory}) { + return execvpe_expandArg0(allocator, .no_expand, argv_slice, env_map); } pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![:null]?[*:0]u8 { diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 85d6fc61ed..08d7571cec 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -241,8 +241,16 @@ pub const LibCInstallation = struct { "-xc", dev_null, }; - const max_bytes = 1024 * 1024; - const exec_res = std.ChildProcess.exec(allocator, &argv, null, null, max_bytes) catch |err| switch (err) { + const exec_res = std.ChildProcess.exec2(.{ + .allocator = allocator, + .argv = &argv, + .max_output_bytes = 1024 * 1024, + // Some C compilers, such as Clang, are known to rely on argv[0] to find the path + // to their own executable, without even bothering to resolve PATH. This results in the message: + // error: unable to execute command: Executable "" doesn't exist! + // So we use the expandArg0 variant of ChildProcess to give them a helping hand. + .expand_arg0 = .expand, + }) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => return error.UnableToSpawnCCompiler, }; @@ -494,8 +502,16 @@ pub fn ccPrintFileName( defer allocator.free(arg1); const argv = [_][]const u8{ cc_exe, arg1 }; - const max_bytes = 1024 * 1024; - const exec_res = std.ChildProcess.exec(allocator, &argv, null, null, max_bytes) catch |err| switch (err) { + const exec_res = std.ChildProcess.exec2(.{ + .allocator = allocator, + .argv = &argv, + .max_output_bytes = 1024 * 1024, + // Some C compilers, such as Clang, are known to rely on argv[0] to find the path + // to their own executable, without even bothering to resolve PATH. This results in the message: + // error: unable to execute command: Executable "" doesn't exist! + // So we use the expandArg0 variant of ChildProcess to give them a helping hand. + .expand_arg0 = .expand, + }) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => return error.UnableToSpawnCCompiler, }; From c784c52819e505620fb1fcb48e59a48c6d8f487e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 01:15:43 -0500 Subject: [PATCH 025/109] fix backwards warning of `zig libc` crt_dir is only not required for darwin --- src-self-hosted/libc_installation.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 08d7571cec..f97850bb68 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -98,7 +98,7 @@ pub const LibCInstallation = struct { try stderr.print("sys_include_dir may not be empty\n", .{}); return error.ParseError; } - if (self.crt_dir == null and is_darwin) { + if (self.crt_dir == null and !is_darwin) { try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.getOs())}); return error.ParseError; } @@ -153,7 +153,7 @@ pub const LibCInstallation = struct { \\ \\# The directory that contains `crtbegin.o`. \\# On POSIX, can be found with `cc -print-file-name=crtbegin.o`. - \\# Not needed when targeting MacOS. + \\# Only needed when targeting MinGW-w64 on Windows. \\static_crt_dir={} \\ \\# The directory that contains `vcruntime.lib`. From 2f9c5c0644dd516ec0d96f33333a35e6b4deea91 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 15:23:59 -0500 Subject: [PATCH 026/109] self-host dynamic linker detection --- lib/std/os.zig | 32 ++-- lib/std/process.zig | 56 +++++++ lib/std/target.zig | 137 +++++++++++++++++ src-self-hosted/introspect.zig | 8 + src-self-hosted/libc_installation.zig | 39 ++++- src-self-hosted/stage2.zig | 103 +++++++++++-- src-self-hosted/util.zig | 137 ----------------- src/codegen.cpp | 52 ++----- src/compiler.cpp | 34 ----- src/compiler.hpp | 1 - src/error.cpp | 1 + src/os.cpp | 18 --- src/os.hpp | 4 - src/stage2.cpp | 6 +- src/stage2.h | 69 ++++++++- src/target.cpp | 203 -------------------------- src/target.hpp | 62 +------- 17 files changed, 430 insertions(+), 532 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index c5fdc41d83..0f492a25f2 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2974,18 +2974,26 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void { } pub fn dl_iterate_phdr( - comptime T: type, - callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, - data: ?*T, -) isize { + context: var, + comptime Error: type, + comptime callback: fn (info: *dl_phdr_info, size: usize, context: @TypeOf(context)) Error!void, +) Error!void { + const Context = @TypeOf(context); + if (builtin.object_format != .elf) @compileError("dl_iterate_phdr is not available for this target"); if (builtin.link_libc) { - return system.dl_iterate_phdr( - @ptrCast(std.c.dl_iterate_phdr_callback, callback), - @ptrCast(?*c_void, data), - ); + switch (system.dl_iterate_phdr(struct { + fn callbackC(info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int { + const context_ptr = @ptrCast(*const Context, @alignCast(@alignOf(*const Context), data)); + callback(info, size, context_ptr.*) catch |err| return @errorToInt(err); + return 0; + } + }.callbackC, @intToPtr(?*c_void, @ptrToInt(&context)))) { + 0 => return, + else => |err| return @errSetCast(Error, @intToError(@intCast(u16, err))), // TODO don't hardcode u16 + } } const elf_base = std.process.getBaseAddress(); @@ -3007,11 +3015,10 @@ pub fn dl_iterate_phdr( .dlpi_phnum = ehdr.e_phnum, }; - return callback(&info, @sizeOf(dl_phdr_info), data); + return callback(&info, @sizeOf(dl_phdr_info), context); } // Last return value from the callback function - var last_r: isize = 0; while (it.next()) |entry| { var dlpi_phdr: [*]elf.Phdr = undefined; var dlpi_phnum: u16 = undefined; @@ -3033,11 +3040,8 @@ pub fn dl_iterate_phdr( .dlpi_phnum = dlpi_phnum, }; - last_r = callback(&info, @sizeOf(dl_phdr_info), data); - if (last_r != 0) break; + try callback(&info, @sizeOf(dl_phdr_info), context); } - - return last_r; } pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; diff --git a/lib/std/process.zig b/lib/std/process.zig index 0178f6fa91..ddae0bffbb 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -613,3 +613,59 @@ pub fn getBaseAddress() usize { else => @compileError("Unsupported OS"), } } + +/// Caller owns the result value and each inner slice. +pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]u8 { + switch (builtin.link_mode) { + .Static => return &[_][:0]u8{}, + .Dynamic => {}, + } + const List = std.ArrayList([:0]u8); + switch (builtin.os) { + .linux, + .freebsd, + .netbsd, + .dragonfly, + => { + var paths = List.init(allocator); + errdefer { + const slice = paths.toOwnedSlice(); + for (slice) |item| { + allocator.free(item); + } + allocator.free(slice); + } + try os.dl_iterate_phdr(&paths, error{OutOfMemory}, struct { + fn callback(info: *os.dl_phdr_info, size: usize, list: *List) !void { + const name = info.dlpi_name orelse return; + if (name[0] == '/') { + const item = try mem.dupeZ(list.allocator, u8, mem.toSliceConst(u8, name)); + errdefer list.allocator.free(item); + try list.append(item); + } + } + }.callback); + return paths.toOwnedSlice(); + }, + .macosx, .ios, .watchos, .tvos => { + var paths = List.init(allocator); + errdefer { + const slice = paths.toOwnedSlice(); + for (slice) |item| { + allocator.free(item); + } + allocator.free(slice); + } + const img_count = std.c._dyld_image_count(); + var i: u32 = 0; + while (i < img_count) : (i += 1) { + const name = std.c._dyld_get_image_name(i); + const item = try mem.dupeZ(allocator, u8, mem.toSliceConst(u8, name)); + errdefer allocator.free(item); + try paths.append(item); + } + return paths.toOwnedSlice(); + }, + else => return error.UnimplementedSelfExeSharedPaths, + } +} diff --git a/lib/std/target.zig b/lib/std/target.zig index fb3fe96075..af8d6474ed 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1037,6 +1037,13 @@ pub const Target = union(enum) { }; } + pub fn isAndroid(self: Target) bool { + return switch (self.getAbi()) { + .android => true, + else => false, + }; + } + pub fn isDragonFlyBSD(self: Target) bool { return switch (self.getOs()) { .dragonfly => true, @@ -1196,6 +1203,136 @@ pub const Target = union(enum) { return .unavailable; } + + pub const FloatAbi = enum { + hard, + soft, + soft_fp, + }; + + pub fn getFloatAbi(self: Target) FloatAbi { + return switch (self.getAbi()) { + .gnueabihf, + .eabihf, + .musleabihf, + => .hard, + else => .soft, + }; + } + + /// Caller owns returned memory. + pub fn getStandardDynamicLinkerPath( + self: Target, + allocator: *mem.Allocator, + ) error{ + OutOfMemory, + UnknownDynamicLinkerPath, + }![:0]u8 { + const a = allocator; + if (self.isAndroid()) { + return mem.dupeZ(a, u8, if (self.getArchPtrBitWidth() == 64) + "/system/bin/linker64" + else + "/system/bin/linker"); + } + + if (self.isMusl()) { + var result = try std.Buffer.init(allocator, "/lib/ld-musl-"); + defer result.deinit(); + + var is_arm = false; + switch (self.getArch()) { + .arm, .thumb => { + try result.append("arm"); + is_arm = true; + }, + .armeb, .thumbeb => { + try result.append("armeb"); + is_arm = true; + }, + else => |arch| try result.append(@tagName(arch)), + } + if (is_arm and self.getFloatAbi() == .hard) { + try result.append("hf"); + } + try result.append(".so.1"); + return result.toOwnedSlice(); + } + + switch (self.getOs()) { + .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"), + .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"), + .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"), + .linux => switch (self.getArch()) { + .i386, + .sparc, + .sparcel, + => return mem.dupeZ(a, u8, "/lib/ld-linux.so.2"), + + .aarch64 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64.so.1"), + .aarch64_be => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_be.so.1"), + .aarch64_32 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_32.so.1"), + + .arm, + .armeb, + .thumb, + .thumbeb, + => return mem.dupeZ(a, u8, switch (self.getFloatAbi()) { + .hard => "/lib/ld-linux-armhf.so.3", + else => "/lib/ld-linux.so.3", + }), + + .mips, + .mipsel, + .mips64, + .mips64el, + => return error.UnknownDynamicLinkerPath, + + .powerpc => return mem.dupeZ(a, u8, "/lib/ld.so.1"), + .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"), + .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"), + .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"), + .x86_64 => return mem.dupeZ(a, u8, switch (self.getAbi()) { + .gnux32 => "/libx32/ld-linux-x32.so.2", + else => "/lib64/ld-linux-x86-64.so.2", + }), + + .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"), + .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"), + + .arc, + .avr, + .bpfel, + .bpfeb, + .hexagon, + .msp430, + .r600, + .amdgcn, + .tce, + .tcele, + .xcore, + .nvptx, + .nvptx64, + .le32, + .le64, + .amdil, + .amdil64, + .hsail, + .hsail64, + .spir, + .spir64, + .kalimba, + .shave, + .lanai, + .wasm32, + .wasm64, + .renderscript32, + .renderscript64, + => return error.UnknownDynamicLinkerPath, + }, + else => return error.UnknownDynamicLinkerPath, + } + } }; test "parseCpuFeatureSet" { diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig index 3cf18ab363..11838e7e63 100644 --- a/src-self-hosted/introspect.zig +++ b/src-self-hosted/introspect.zig @@ -6,6 +6,14 @@ const fs = std.fs; const warn = std.debug.warn; +pub fn detectDynamicLinker(allocator: *mem.Allocator, target: std.Target) ![:0]u8 { + if (target == .Native) { + return @import("libc_installation.zig").detectNativeDynamicLinker(allocator); + } else { + return target.getStandardDynamicLinkerPath(allocator); + } +} + /// Caller must free result pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { const test_zig_dir = try fs.path.join(allocator, &[_][]const u8{ test_path, "lib", "zig" }); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index f97850bb68..1fec40c516 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -492,7 +492,7 @@ pub const LibCInstallation = struct { const default_cc_exe = if (is_windows) "cc.exe" else "cc"; /// caller owns returned memory -pub fn ccPrintFileName( +fn ccPrintFileName( allocator: *Allocator, o_file: []const u8, want_dirname: enum { full_path, only_dir }, @@ -535,6 +535,43 @@ pub fn ccPrintFileName( } } +/// Caller owns returned memory. +pub fn detectNativeDynamicLinker(allocator: *Allocator) ![:0]u8 { + const standard_ld_path = try std.Target.current.getStandardDynamicLinkerPath(allocator); + var standard_ld_path_resource: ?[:0]u8 = standard_ld_path; // Set to null to avoid freeing it. + defer if (standard_ld_path_resource) |s| allocator.free(s); + + const standard_ld_basename = fs.path.basename(standard_ld_path); + + { + // Best case scenario: the current executable is dynamically linked, and we can iterate + // over our own shared objects and find a dynamic linker. + const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator); + defer allocator.free(lib_paths); + + for (lib_paths) |lib_path| { + if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) { + return std.mem.dupeZ(allocator, u8, lib_path); + } + } + } + + // If Zig is statically linked, such as via distributed binary static builds, the above + // trick won't work. What are we left with? Try to run the system C compiler and get + // it to tell us the dynamic linker path. + return ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.LibCRuntimeNotFound, + error.CCompilerExitCode, + error.CCompilerCrashed, + error.UnableToSpawnCCompiler, + => { + standard_ld_path_resource = null; // Prevent freeing standard_ld_path. + return standard_ld_path; + }, + }; +} + const Search = struct { path: []const u8, version: []const u8, diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 897f2a3ed8..02269a8c4f 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -109,6 +109,7 @@ const Error = extern enum { LibCKernel32LibNotFound, UnsupportedArchitecture, WindowsSdkNotFound, + UnknownDynamicLinkerPath, }; const FILE = std.c.FILE; @@ -1012,24 +1013,100 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: } // ABI warning -export fn stage2_libc_cc_print_file_name( - out_ptr: *[*:0]u8, - out_len: *usize, - o_file: [*:0]const u8, - want_dirname: bool, -) Error { - const result = @import("libc_installation.zig").ccPrintFileName( +const Stage2Target = extern struct { + arch: c_int, + sub_arch: c_int, + vendor: c_int, + os: c_int, + abi: c_int, + glibc_version: ?*Stage2GLibCVersion, // null means default + cpu_features: *Stage2CpuFeatures, + is_native: bool, +}; + +// ABI warning +const Stage2GLibCVersion = extern struct { + major: u32, + minor: u32, + patch: u32, +}; + +// ABI warning +export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error { + const target: Target = if (in_target.is_native) .Native else .{ + .Cross = .{ + .arch = switch (enumInt(@TagType(Target.Arch), in_target.arch)) { + .arm => .{ .arm = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .armeb => .{ .armeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .thumb => .{ .thumb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .thumbeb => .{ .thumbeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + + .aarch64 => .{ .aarch64 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + .aarch64_be => .{ .aarch64_be = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + .aarch64_32 => .{ .aarch64_32 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + + .kalimba => .{ .kalimba = enumInt(Target.Arch.Kalimba, in_target.sub_arch) }, + + .arc => .arc, + .avr => .avr, + .bpfel => .bpfel, + .bpfeb => .bpfeb, + .hexagon => .hexagon, + .mips => .mips, + .mipsel => .mipsel, + .mips64 => .mips64, + .mips64el => .mips64el, + .msp430 => .msp430, + .powerpc => .powerpc, + .powerpc64 => .powerpc64, + .powerpc64le => .powerpc64le, + .r600 => .r600, + .amdgcn => .amdgcn, + .riscv32 => .riscv32, + .riscv64 => .riscv64, + .sparc => .sparc, + .sparcv9 => .sparcv9, + .sparcel => .sparcel, + .s390x => .s390x, + .tce => .tce, + .tcele => .tcele, + .i386 => .i386, + .x86_64 => .x86_64, + .xcore => .xcore, + .nvptx => .nvptx, + .nvptx64 => .nvptx64, + .le32 => .le32, + .le64 => .le64, + .amdil => .amdil, + .amdil64 => .amdil64, + .hsail => .hsail, + .hsail64 => .hsail64, + .spir => .spir, + .spir64 => .spir64, + .shave => .shave, + .lanai => .lanai, + .wasm32 => .wasm32, + .wasm64 => .wasm64, + .renderscript32 => .renderscript32, + .renderscript64 => .renderscript64, + }, + .os = enumInt(Target.Os, in_target.os), + .abi = enumInt(Target.Abi, in_target.abi), + .cpu_features = in_target.cpu_features.cpu_features, + }, + }; + const result = @import("introspect.zig").detectDynamicLinker( std.heap.c_allocator, - mem.toSliceConst(u8, o_file), - if (want_dirname) .only_dir else .full_path, + target, ) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, - error.LibCRuntimeNotFound => return .FileNotFound, - error.CCompilerExitCode => return .CCompilerExitCode, - error.CCompilerCrashed => return .CCompilerCrashed, - error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath, }; out_ptr.* = result.ptr; out_len.* = result.len; return .None; } + +fn enumInt(comptime Enum: type, int: c_int) Enum { + return @intToEnum(Enum, @intCast(@TagType(Enum), int)); +} diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig index 95bc72469d..04c5420d26 100644 --- a/src-self-hosted/util.zig +++ b/src-self-hosted/util.zig @@ -2,143 +2,6 @@ const std = @import("std"); const Target = std.Target; const llvm = @import("llvm.zig"); -pub const FloatAbi = enum { - Hard, - Soft, - SoftFp, -}; - -/// TODO expose the arch and subarch separately -pub fn isArmOrThumb(self: Target) bool { - return switch (self.getArch()) { - .arm, - .armeb, - .aarch64, - .aarch64_be, - .thumb, - .thumbeb, - => true, - else => false, - }; -} - -pub fn getFloatAbi(self: Target) FloatAbi { - return switch (self.getAbi()) { - .gnueabihf, - .eabihf, - .musleabihf, - => .Hard, - else => .Soft, - }; -} - -pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { - const env = self.getAbi(); - const arch = self.getArch(); - const os = self.getOs(); - switch (os) { - .freebsd => { - return "/libexec/ld-elf.so.1"; - }, - .linux => { - switch (env) { - .android => { - if (self.getArchPtrBitWidth() == 64) { - return "/system/bin/linker64"; - } else { - return "/system/bin/linker"; - } - }, - .gnux32 => { - if (arch == .x86_64) { - return "/libx32/ld-linux-x32.so.2"; - } - }, - .musl, - .musleabi, - .musleabihf, - => { - if (arch == .x86_64) { - return "/lib/ld-musl-x86_64.so.1"; - } - }, - else => {}, - } - switch (arch) { - .i386, - .sparc, - .sparcel, - => return "/lib/ld-linux.so.2", - - .aarch64 => return "/lib/ld-linux-aarch64.so.1", - - .aarch64_be => return "/lib/ld-linux-aarch64_be.so.1", - - .arm, - .thumb, - => return switch (getFloatAbi(self)) { - .Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - .armeb, - .thumbeb, - => return switch (getFloatAbi(self)) { - .Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - .mips, - .mipsel, - .mips64, - .mips64el, - => return null, - - .powerpc => return "/lib/ld.so.1", - .powerpc64 => return "/lib64/ld64.so.2", - .powerpc64le => return "/lib64/ld64.so.2", - .s390x => return "/lib64/ld64.so.1", - .sparcv9 => return "/lib64/ld-linux.so.2", - .x86_64 => return "/lib64/ld-linux-x86-64.so.2", - - .arc, - .avr, - .bpfel, - .bpfeb, - .hexagon, - .msp430, - .r600, - .amdgcn, - .riscv32, - .riscv64, - .tce, - .tcele, - .xcore, - .nvptx, - .nvptx64, - .le32, - .le64, - .amdil, - .amdil64, - .hsail, - .hsail64, - .spir, - .spir64, - .kalimba, - .shave, - .lanai, - .wasm32, - .wasm64, - .renderscript32, - .renderscript64, - .aarch64_32, - => return null, - } - }, - else => return null, - } -} - pub fn getDarwinArchString(self: Target) [:0]const u8 { const arch = self.getArch(); switch (arch) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 0b5d2e82f1..f0640c871c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8624,7 +8624,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { break; } buf_appendf(contents, "pub const output_mode = OutputMode.%s;\n", out_type); - const char *link_type = g->is_dynamic ? "Dynamic" : "Static"; + const char *link_type = g->have_dynamic_link ? "Dynamic" : "Static"; buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", link_type); buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); @@ -8731,7 +8731,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->build_mode); cache_bool(&cache_hash, g->strip_debug_symbols); cache_int(&cache_hash, g->out_type); - cache_bool(&cache_hash, g->is_dynamic); + cache_bool(&cache_hash, detect_dynamic_link(g)); cache_bool(&cache_hash, g->is_test_build); cache_bool(&cache_hash, g->is_single_threaded); cache_bool(&cache_hash, g->test_is_evented); @@ -8957,6 +8957,8 @@ static void init(CodeGen *g) { } static void detect_dynamic_linker(CodeGen *g) { + Error err; + if (g->dynamic_linker_path != nullptr) return; if (!g->have_dynamic_link) @@ -8964,45 +8966,15 @@ static void detect_dynamic_linker(CodeGen *g) { if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic)) return; - const char *standard_ld_path = target_dynamic_linker(g->zig_target); - if (standard_ld_path == nullptr) - return; - - if (g->zig_target->is_native) { - // target_dynamic_linker is usually correct. However on some systems, such as NixOS - // it will be incorrect. See if we can do better by looking at what zig's own - // dynamic linker path is. - g->dynamic_linker_path = get_self_dynamic_linker_path(); - if (g->dynamic_linker_path != nullptr) - return; - - // If Zig is statically linked, such as via distributed binary static builds, the above - // trick won't work. What are we left with? Try to run the system C compiler and get - // it to tell us the dynamic linker path -#if defined(ZIG_OS_LINUX) - { - Error err; - for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) { - const char *lib_name = possible_ld_names[i]; - char *result_ptr; - size_t result_len; - if ((err = stage2_libc_cc_print_file_name(&result_ptr, &result_len, lib_name, false))) { - if (err != ErrorCCompilerCannotFindFile && err != ErrorNoCCompilerInstalled) { - fprintf(stderr, "Unable to detect native dynamic linker: %s\n", err_str(err)); - exit(1); - } - continue; - } - g->dynamic_linker_path = buf_create_from_mem(result_ptr, result_len); - // Skips heap::c_allocator because the memory is allocated by stage2 library. - free(result_ptr); - return; - } - } -#endif + char *dynamic_linker_ptr; + size_t dynamic_linker_len; + if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) { + fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err)); + exit(1); } - - g->dynamic_linker_path = buf_create_from_str(standard_ld_path); + g->dynamic_linker_path = buf_create_from_mem(dynamic_linker_ptr, dynamic_linker_len); + // Skips heap::c_allocator because the memory is allocated by stage2 library. + free(dynamic_linker_ptr); } static void detect_libc(CodeGen *g) { diff --git a/src/compiler.cpp b/src/compiler.cpp index 484a4ca089..31bac4ee24 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4,20 +4,6 @@ #include -static Buf saved_dynamic_linker_path = BUF_INIT; -static bool searched_for_dyn_linker = false; - -static void detect_dynamic_linker(Buf *lib_path) { -#if defined(ZIG_OS_LINUX) - for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) { - if (buf_ends_with_str(lib_path, possible_ld_names[i])) { - buf_init_from_buf(&saved_dynamic_linker_path, lib_path); - break; - } - } -#endif -} - Buf *get_self_libc_path(void) { static Buf saved_libc_path = BUF_INIT; static bool searched_for_libc = false; @@ -43,25 +29,6 @@ Buf *get_self_libc_path(void) { } } -Buf *get_self_dynamic_linker_path(void) { - for (;;) { - if (saved_dynamic_linker_path.list.length != 0) { - return &saved_dynamic_linker_path; - } - if (searched_for_dyn_linker) - return nullptr; - ZigList lib_paths = {}; - Error err; - if ((err = os_self_exe_shared_libs(lib_paths))) - return nullptr; - for (size_t i = 0; i < lib_paths.length; i += 1) { - Buf *lib_path = lib_paths.at(i); - detect_dynamic_linker(lib_path); - } - searched_for_dyn_linker = true; - } -} - Error get_compiler_id(Buf **result) { static Buf saved_compiler_id = BUF_INIT; @@ -98,7 +65,6 @@ Error get_compiler_id(Buf **result) { return err; for (size_t i = 0; i < lib_paths.length; i += 1) { Buf *lib_path = lib_paths.at(i); - detect_dynamic_linker(lib_path); if ((err = cache_add_file(ch, lib_path))) return err; } diff --git a/src/compiler.hpp b/src/compiler.hpp index ee9c4ab4fc..4a1699b782 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -12,7 +12,6 @@ #include "error.hpp" Error get_compiler_id(Buf **result); -Buf *get_self_dynamic_linker_path(void); Buf *get_self_libc_path(void); Buf *get_zig_lib_dir(void); diff --git a/src/error.cpp b/src/error.cpp index b7cc8e630a..af1359f9ee 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -80,6 +80,7 @@ const char *err_str(Error err) { case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; case ErrorWindowsSdkNotFound: return "Windows SDK not found"; + case ErrorUnknownDynamicLinkerPath: return "Windows SDK not found"; } return "(invalid error)"; } diff --git a/src/os.cpp b/src/os.cpp index 5e2c986e43..268e812050 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -2129,21 +2129,3 @@ void os_file_close(OsFile *file) { *file = -1; #endif } - -#ifdef ZIG_OS_LINUX -const char *possible_ld_names[] = { -#if defined(ZIG_ARCH_X86_64) - "ld-linux-x86-64.so.2", - "ld-musl-x86_64.so.1", -#elif defined(ZIG_ARCH_ARM64) - "ld-linux-aarch64.so.1", - "ld-musl-aarch64.so.1", -#elif defined(ZIG_ARCH_ARM) - "ld-linux-armhf.so.3", - "ld-musl-armhf.so.1", - "ld-linux.so.3", - "ld-musl-arm.so.1", -#endif - NULL, -}; -#endif diff --git a/src/os.hpp b/src/os.hpp index c26d6c8df5..116861e8b5 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -43,10 +43,6 @@ #define ZIG_ARCH_UNKNOWN #endif -#ifdef ZIG_OS_LINUX -extern const char *possible_ld_names[]; -#endif - #if defined(ZIG_OS_WINDOWS) #define ZIG_PRI_usize "I64u" #define ZIG_PRI_i64 "I64d" diff --git a/src/stage2.cpp b/src/stage2.cpp index db4f529c68..7f68321752 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -171,9 +171,7 @@ enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { stage2_panic(msg, strlen(msg)); } -enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname) -{ - const char *msg = "stage0 called stage2_libc_cc_print_file_name"; +enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len) { + const char *msg = "stage0 called stage2_detect_dynamic_linker"; stage2_panic(msg, strlen(msg)); } diff --git a/src/stage2.h b/src/stage2.h index 856a5c3df8..15a66379a7 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -12,6 +12,8 @@ #include #include +#include "zig_llvm.h" + #ifdef __cplusplus #define ZIG_EXTERN_C extern "C" #else @@ -100,6 +102,7 @@ enum Error { ErrorLibCKernel32LibNotFound, ErrorUnsupportedArchitecture, ErrorWindowsSdkNotFound, + ErrorUnknownDynamicLinkerPath, }; // ABI warning @@ -242,8 +245,70 @@ ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, c ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); // ABI warning ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); + // ABI warning -ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname); +// Synchronize with target.cpp::os_list +enum Os { + OsFreestanding, + OsAnanas, + OsCloudABI, + OsDragonFly, + OsFreeBSD, + OsFuchsia, + OsIOS, + OsKFreeBSD, + OsLinux, + OsLv2, // PS3 + OsMacOSX, + OsNetBSD, + OsOpenBSD, + OsSolaris, + OsWindows, + OsHaiku, + OsMinix, + OsRTEMS, + OsNaCl, // Native Client + OsCNK, // BG/P Compute-Node Kernel + OsAIX, + OsCUDA, // NVIDIA CUDA + OsNVCL, // NVIDIA OpenCL + OsAMDHSA, // AMD HSA Runtime + OsPS4, + OsELFIAMCU, + OsTvOS, // Apple tvOS + OsWatchOS, // Apple watchOS + OsMesa3D, + OsContiki, + OsAMDPAL, + OsHermitCore, + OsHurd, + OsWASI, + OsEmscripten, + OsUefi, + OsOther, +}; + +// ABI warning +struct ZigGLibCVersion { + uint32_t major; // always 2 + uint32_t minor; + uint32_t patch; +}; + +// ABI warning +struct ZigTarget { + enum ZigLLVM_ArchType arch; + enum ZigLLVM_SubArchType sub_arch; + enum ZigLLVM_VendorType vendor; + Os os; + enum ZigLLVM_EnvironmentType abi; + struct ZigGLibCVersion *glibc_version; // null means default + struct Stage2CpuFeatures *cpu_features; + bool is_native; +}; + +// ABI warning +ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, + char **out_ptr, size_t *out_len); #endif diff --git a/src/target.cpp b/src/target.cpp index b8979d0214..209b42f3c9 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1204,213 +1204,10 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static, } } -enum FloatAbi { - FloatAbiHard, - FloatAbiSoft, - FloatAbiSoftFp, -}; - -static FloatAbi get_float_abi(const ZigTarget *target) { - const ZigLLVM_EnvironmentType env = target->abi; - if (env == ZigLLVM_GNUEABIHF || - env == ZigLLVM_EABIHF || - env == ZigLLVM_MuslEABIHF) - { - return FloatAbiHard; - } else { - return FloatAbiSoft; - } -} - -static bool is_64_bit(ZigLLVM_ArchType arch) { - return target_arch_pointer_bit_width(arch) == 64; -} - bool target_is_android(const ZigTarget *target) { return target->abi == ZigLLVM_Android; } -const char *target_dynamic_linker(const ZigTarget *target) { - if (target_is_android(target)) { - return is_64_bit(target->arch) ? "/system/bin/linker64" : "/system/bin/linker"; - } - - if (target_is_musl(target)) { - Buf buf = BUF_INIT; - buf_init_from_str(&buf, "/lib/ld-musl-"); - bool is_arm = false; - switch (target->arch) { - case ZigLLVM_arm: - case ZigLLVM_thumb: - buf_append_str(&buf, "arm"); - is_arm = true; - break; - case ZigLLVM_armeb: - case ZigLLVM_thumbeb: - buf_append_str(&buf, "armeb"); - is_arm = true; - break; - default: - buf_append_str(&buf, target_arch_name(target->arch)); - } - if (is_arm && get_float_abi(target) == FloatAbiHard) { - buf_append_str(&buf, "hf"); - } - buf_append_str(&buf, ".so.1"); - return buf_ptr(&buf); - } - - switch (target->os) { - case OsFreeBSD: - return "/libexec/ld-elf.so.1"; - case OsNetBSD: - return "/libexec/ld.elf_so"; - case OsDragonFly: - return "/libexec/ld-elf.so.2"; - case OsLinux: { - const ZigLLVM_EnvironmentType abi = target->abi; - switch (target->arch) { - case ZigLLVM_UnknownArch: - zig_unreachable(); - case ZigLLVM_x86: - case ZigLLVM_sparc: - case ZigLLVM_sparcel: - return "/lib/ld-linux.so.2"; - - case ZigLLVM_aarch64: - return "/lib/ld-linux-aarch64.so.1"; - - case ZigLLVM_aarch64_be: - return "/lib/ld-linux-aarch64_be.so.1"; - - case ZigLLVM_aarch64_32: - return "/lib/ld-linux-aarch64_32.so.1"; - - case ZigLLVM_arm: - case ZigLLVM_thumb: - if (get_float_abi(target) == FloatAbiHard) { - return "/lib/ld-linux-armhf.so.3"; - } else { - return "/lib/ld-linux.so.3"; - } - - case ZigLLVM_armeb: - case ZigLLVM_thumbeb: - if (get_float_abi(target) == FloatAbiHard) { - return "/lib/ld-linux-armhf.so.3"; - } else { - return "/lib/ld-linux.so.3"; - } - - case ZigLLVM_mips: - case ZigLLVM_mipsel: - case ZigLLVM_mips64: - case ZigLLVM_mips64el: - zig_panic("TODO implement target_dynamic_linker for mips"); - - case ZigLLVM_ppc: - return "/lib/ld.so.1"; - - case ZigLLVM_ppc64: - return "/lib64/ld64.so.2"; - - case ZigLLVM_ppc64le: - return "/lib64/ld64.so.2"; - - case ZigLLVM_systemz: - return "/lib64/ld64.so.1"; - - case ZigLLVM_sparcv9: - return "/lib64/ld-linux.so.2"; - - case ZigLLVM_x86_64: - if (abi == ZigLLVM_GNUX32) { - return "/libx32/ld-linux-x32.so.2"; - } - if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) { - return "/lib/ld-musl-x86_64.so.1"; - } - return "/lib64/ld-linux-x86-64.so.2"; - - case ZigLLVM_wasm32: - case ZigLLVM_wasm64: - return nullptr; - - case ZigLLVM_riscv32: - return "/lib/ld-linux-riscv32-ilp32.so.1"; - case ZigLLVM_riscv64: - return "/lib/ld-linux-riscv64-lp64.so.1"; - - case ZigLLVM_arc: - case ZigLLVM_avr: - case ZigLLVM_bpfel: - case ZigLLVM_bpfeb: - case ZigLLVM_hexagon: - case ZigLLVM_msp430: - case ZigLLVM_r600: - case ZigLLVM_amdgcn: - case ZigLLVM_tce: - case ZigLLVM_tcele: - case ZigLLVM_xcore: - case ZigLLVM_nvptx: - case ZigLLVM_nvptx64: - case ZigLLVM_le32: - case ZigLLVM_le64: - case ZigLLVM_amdil: - case ZigLLVM_amdil64: - case ZigLLVM_hsail: - case ZigLLVM_hsail64: - case ZigLLVM_spir: - case ZigLLVM_spir64: - case ZigLLVM_kalimba: - case ZigLLVM_shave: - case ZigLLVM_lanai: - case ZigLLVM_renderscript32: - case ZigLLVM_renderscript64: - zig_panic("TODO implement target_dynamic_linker for this arch"); - } - zig_unreachable(); - } - case OsFreestanding: - case OsIOS: - case OsTvOS: - case OsWatchOS: - case OsMacOSX: - case OsUefi: - case OsWindows: - case OsEmscripten: - case OsOther: - return nullptr; - - case OsAnanas: - case OsCloudABI: - case OsFuchsia: - case OsKFreeBSD: - case OsLv2: - case OsOpenBSD: - case OsSolaris: - case OsHaiku: - case OsMinix: - case OsRTEMS: - case OsNaCl: - case OsCNK: - case OsAIX: - case OsCUDA: - case OsNVCL: - case OsAMDHSA: - case OsPS4: - case OsELFIAMCU: - case OsMesa3D: - case OsContiki: - case OsAMDPAL: - case OsHermitCore: - case OsHurd: - case OsWASI: - zig_panic("TODO implement target_dynamic_linker for this OS"); - } - zig_unreachable(); -} - bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) { assert(host_target != nullptr); diff --git a/src/target.hpp b/src/target.hpp index 3e984e1269..4344749719 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -8,51 +8,10 @@ #ifndef ZIG_TARGET_HPP #define ZIG_TARGET_HPP -#include +#include "stage2.h" struct Buf; -// Synchronize with target.cpp::os_list -enum Os { - OsFreestanding, - OsAnanas, - OsCloudABI, - OsDragonFly, - OsFreeBSD, - OsFuchsia, - OsIOS, - OsKFreeBSD, - OsLinux, - OsLv2, // PS3 - OsMacOSX, - OsNetBSD, - OsOpenBSD, - OsSolaris, - OsWindows, - OsHaiku, - OsMinix, - OsRTEMS, - OsNaCl, // Native Client - OsCNK, // BG/P Compute-Node Kernel - OsAIX, - OsCUDA, // NVIDIA CUDA - OsNVCL, // NVIDIA OpenCL - OsAMDHSA, // AMD HSA Runtime - OsPS4, - OsELFIAMCU, - OsTvOS, // Apple tvOS - OsWatchOS, // Apple watchOS - OsMesa3D, - OsContiki, - OsAMDPAL, - OsHermitCore, - OsHurd, - OsWASI, - OsEmscripten, - OsUefi, - OsOther, -}; - // Synchronize with target.cpp::subarch_list_list enum SubArchList { SubArchListNone, @@ -78,23 +37,6 @@ enum TargetSubsystem { TargetSubsystemAuto }; -struct ZigGLibCVersion { - uint32_t major; // always 2 - uint32_t minor; - uint32_t patch; -}; - -struct ZigTarget { - ZigLLVM_ArchType arch; - ZigLLVM_SubArchType sub_arch; - ZigLLVM_VendorType vendor; - Os os; - ZigLLVM_EnvironmentType abi; - ZigGLibCVersion *glibc_version; // null means default - Stage2CpuFeatures *cpu_features; - bool is_native; -}; - enum CIntType { CIntTypeShort, CIntTypeUShort, @@ -168,8 +110,6 @@ const char *target_lib_file_prefix(const ZigTarget *target); const char *target_lib_file_ext(const ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch); -const char *target_dynamic_linker(const ZigTarget *target); - bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); ZigLLVM_OSType get_llvm_os_type(Os os_type); From e26f063b22893f50dd7eb02a01585f4d52849ede Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 15:46:53 -0500 Subject: [PATCH 027/109] support the concept of a target not having a dynamic linker --- lib/std/target.zig | 19 +++++++++++++++++-- src-self-hosted/stage2.zig | 2 ++ src/codegen.cpp | 1 + src/error.cpp | 3 ++- src/stage2.h | 1 + 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index af8d6474ed..d3f487e9ff 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1227,6 +1227,7 @@ pub const Target = union(enum) { ) error{ OutOfMemory, UnknownDynamicLinkerPath, + TargetHasNoDynamicLinker, }![:0]u8 { const a = allocator; if (self.isAndroid()) { @@ -1300,6 +1301,10 @@ pub const Target = union(enum) { .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"), .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"), + .wasm32, + .wasm64, + => return error.TargetHasNoDynamicLinker, + .arc, .avr, .bpfel, @@ -1324,12 +1329,22 @@ pub const Target = union(enum) { .kalimba, .shave, .lanai, - .wasm32, - .wasm64, .renderscript32, .renderscript64, => return error.UnknownDynamicLinkerPath, }, + + .freestanding, + .ios, + .tvos, + .watchos, + .macosx, + .uefi, + .windows, + .emscripten, + .other, + => return error.TargetHasNoDynamicLinker, + else => return error.UnknownDynamicLinkerPath, } } diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 02269a8c4f..5b918f9514 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -110,6 +110,7 @@ const Error = extern enum { UnsupportedArchitecture, WindowsSdkNotFound, UnknownDynamicLinkerPath, + TargetHasNoDynamicLinker, }; const FILE = std.c.FILE; @@ -1101,6 +1102,7 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: ) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath, + error.TargetHasNoDynamicLinker => return .TargetHasNoDynamicLinker, }; out_ptr.* = result.ptr; out_len.* = result.len; diff --git a/src/codegen.cpp b/src/codegen.cpp index f0640c871c..225e39989c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8969,6 +8969,7 @@ static void detect_dynamic_linker(CodeGen *g) { char *dynamic_linker_ptr; size_t dynamic_linker_len; if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) { + if (err == ErrorTargetHasNoDynamicLinker) return; fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err)); exit(1); } diff --git a/src/error.cpp b/src/error.cpp index af1359f9ee..c633e2fe67 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -80,7 +80,8 @@ const char *err_str(Error err) { case ErrorLibCKernel32LibNotFound: return "kernel32 library not found"; case ErrorUnsupportedArchitecture: return "unsupported architecture"; case ErrorWindowsSdkNotFound: return "Windows SDK not found"; - case ErrorUnknownDynamicLinkerPath: return "Windows SDK not found"; + case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path"; + case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker"; } return "(invalid error)"; } diff --git a/src/stage2.h b/src/stage2.h index 15a66379a7..b6e4cebbaf 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -103,6 +103,7 @@ enum Error { ErrorUnsupportedArchitecture, ErrorWindowsSdkNotFound, ErrorUnknownDynamicLinkerPath, + ErrorTargetHasNoDynamicLinker, }; // ABI warning From 4b91e4c91fae760f30becbafaf28befef832ecf5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 16:03:01 -0500 Subject: [PATCH 028/109] fix dynamic linker detection on windows (where there isn't one) --- lib/std/process.zig | 2 +- lib/std/target.zig | 22 ++++++++++++++++++++++ src-self-hosted/libc_installation.zig | 6 +++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index ddae0bffbb..89307b44da 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -666,6 +666,6 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0] } return paths.toOwnedSlice(); }, - else => return error.UnimplementedSelfExeSharedPaths, + else => @compileError("getSelfExeSharedLibPaths unimplemented for this target"), } } diff --git a/lib/std/target.zig b/lib/std/target.zig index d3f487e9ff..bc78b2dce5 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1220,6 +1220,28 @@ pub const Target = union(enum) { }; } + pub fn hasDynamicLinker(self: Target) bool { + switch (self.getArch()) { + .wasm32, + .wasm64, + => return false, + else => {}, + } + switch (self.getOs()) { + .freestanding, + .ios, + .tvos, + .watchos, + .macosx, + .uefi, + .windows, + .emscripten, + .other, + => return false, + else => return true, + } + } + /// Caller owns returned memory. pub fn getStandardDynamicLinkerPath( self: Target, diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 1fec40c516..fbb7b010c4 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -536,7 +536,11 @@ fn ccPrintFileName( } /// Caller owns returned memory. -pub fn detectNativeDynamicLinker(allocator: *Allocator) ![:0]u8 { +pub fn detectNativeDynamicLinker(allocator: *Allocator) error{OutOfMemory, TargetHasNoDynamicLinker, UnknownDynamicLinkerPath}![:0]u8 { + if (!comptime Target.current.hasDynamicLinker()) { + return error.TargetHasNoDynamicLinker; + } + const standard_ld_path = try std.Target.current.getStandardDynamicLinkerPath(allocator); var standard_ld_path_resource: ?[:0]u8 = standard_ld_path; // Set to null to avoid freeing it. defer if (standard_ld_path_resource) |s| allocator.free(s); From a959e98273110fb656a96b1ce22ef400fdcc3c0e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 16:16:58 -0500 Subject: [PATCH 029/109] target requiring PIC does not imply dynamic linking Related: #3237 --- src/codegen.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 225e39989c..b959d03549 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8375,8 +8375,6 @@ static bool detect_dynamic_link(CodeGen *g) { return true; if (g->zig_target->os == OsFreestanding) return false; - if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr)) - return true; // If there are no dynamic libraries then we can disable PIC for (size_t i = 0; i < g->link_libs_list.length; i += 1) { LinkLib *link_lib = g->link_libs_list.at(i); From 9b02cab3dacc40fdda2b0bd493f33bc7d17b326d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 16:37:22 -0500 Subject: [PATCH 030/109] fix glibc not forcing dynamic link --- src/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b959d03549..12b49ab2ae 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8375,7 +8375,9 @@ static bool detect_dynamic_link(CodeGen *g) { return true; if (g->zig_target->os == OsFreestanding) return false; - // If there are no dynamic libraries then we can disable PIC + if (g->libc_link_lib != nullptr && target_is_glibc(g->zig_target)) + return true; + // If there are no dynamic libraries then we can disable dynamic linking. for (size_t i = 0; i < g->link_libs_list.length; i += 1) { LinkLib *link_lib = g->link_libs_list.at(i); if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) From 8fe636dafdc0e4dfeb0e3913148b21df8c066443 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 16:49:30 -0500 Subject: [PATCH 031/109] fix ABI mismatch of ZigTarget in stage2 glue code --- src-self-hosted/stage2.zig | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 5b918f9514..37816464a1 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -1034,19 +1034,23 @@ const Stage2GLibCVersion = extern struct { // ABI warning export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error { + const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch + const in_sub_arch = in_target.sub_arch - 1; // skip over ZigLLVM_NoSubArch + const in_os = in_target.os; + const in_abi = in_target.abi - 1; // skip over ZigLLVM_UnknownEnvironment const target: Target = if (in_target.is_native) .Native else .{ .Cross = .{ - .arch = switch (enumInt(@TagType(Target.Arch), in_target.arch)) { - .arm => .{ .arm = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, - .armeb => .{ .armeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, - .thumb => .{ .thumb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, - .thumbeb => .{ .thumbeb = enumInt(Target.Arch.Arm32, in_target.sub_arch) }, + .arch = switch (enumInt(@TagType(Target.Arch), in_arch)) { + .arm => .{ .arm = enumInt(Target.Arch.Arm32, in_sub_arch) }, + .armeb => .{ .armeb = enumInt(Target.Arch.Arm32, in_sub_arch) }, + .thumb => .{ .thumb = enumInt(Target.Arch.Arm32, in_sub_arch) }, + .thumbeb => .{ .thumbeb = enumInt(Target.Arch.Arm32, in_sub_arch) }, - .aarch64 => .{ .aarch64 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, - .aarch64_be => .{ .aarch64_be = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, - .aarch64_32 => .{ .aarch64_32 = enumInt(Target.Arch.Arm64, in_target.sub_arch) }, + .aarch64 => .{ .aarch64 = enumInt(Target.Arch.Arm64, in_sub_arch) }, + .aarch64_be => .{ .aarch64_be = enumInt(Target.Arch.Arm64, in_sub_arch) }, + .aarch64_32 => .{ .aarch64_32 = enumInt(Target.Arch.Arm64, in_sub_arch) }, - .kalimba => .{ .kalimba = enumInt(Target.Arch.Kalimba, in_target.sub_arch) }, + .kalimba => .{ .kalimba = enumInt(Target.Arch.Kalimba, in_sub_arch) }, .arc => .arc, .avr => .avr, @@ -1091,8 +1095,8 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: .renderscript32 => .renderscript32, .renderscript64 => .renderscript64, }, - .os = enumInt(Target.Os, in_target.os), - .abi = enumInt(Target.Abi, in_target.abi), + .os = enumInt(Target.Os, in_os), + .abi = enumInt(Target.Abi, in_abi), .cpu_features = in_target.cpu_features.cpu_features, }, }; From b53afc510c763f5da57bc654a6cc42a233304938 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 17:22:32 -0500 Subject: [PATCH 032/109] update dl_iterate_phdr test case to new API --- lib/std/os/test.zig | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 9ca4044a75..055d049f69 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -165,16 +165,19 @@ test "sigaltstack" { // analyzed const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void; -fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) callconv(.C) i32 { - if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx) - return 0; +const IterFnError = error{ + MissingPtLoadSegment, + MissingLoad, + BadElfMagic, + FailedConsistencyCheck, +}; - var counter = data.?; +fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { // Count how many libraries are loaded counter.* += @as(usize, 1); // The image should contain at least a PT_LOAD segment - if (info.dlpi_phnum < 1) return -1; + if (info.dlpi_phnum < 1) return error.MissingPtLoadSegment; // Quick & dirty validation of the phdr pointers, make sure we're not // pointing to some random gibberish @@ -189,17 +192,15 @@ fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) callconv(.C) i32 { // Find the ELF header const elf_header = @intToPtr(*elf.Ehdr, reloc_addr - phdr.p_offset); // Validate the magic - if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1; + if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return error.BadElfMagic; // Consistency check - if (elf_header.e_phnum != info.dlpi_phnum) return -1; + if (elf_header.e_phnum != info.dlpi_phnum) return error.FailedConsistencyCheck; found_load = true; break; } - if (!found_load) return -1; - - return 42; + if (!found_load) return error.MissingLoad; } test "dl_iterate_phdr" { @@ -207,7 +208,7 @@ test "dl_iterate_phdr" { return error.SkipZigTest; var counter: usize = 0; - expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0); + try os.dl_iterate_phdr(&counter, IterFnError, iter_fn); expect(counter != 0); } From 5a4e8c779a713d7b07cec262b07afd6883684c98 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 19:26:32 -0500 Subject: [PATCH 033/109] smarter detectNativeDynamicLinker logic The current target's ABI cannot be relied on for this. For example, we may build the zig compiler for target riscv64-linux-musl and provide a tarball for users to download. A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined and supported by Zig. But that means that we must detect the system ABI here rather than relying on `std.Target.current`. --- src-self-hosted/libc_installation.zig | 97 +++++++++++++++++++++------ 1 file changed, 77 insertions(+), 20 deletions(-) diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index fbb7b010c4..fd920ad291 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -526,6 +526,9 @@ fn ccPrintFileName( var it = std.mem.tokenize(exec_res.stdout, "\n\r"); const line = it.next() orelse return error.LibCRuntimeNotFound; + // When this command fails, it returns exit code 0 and duplicates the input file name. + // So we detect failure by checking if the output matches exactly the input. + if (std.mem.eql(u8, line, o_file)) return error.LibCRuntimeNotFound; switch (want_dirname) { .full_path => return std.mem.dupeZ(allocator, u8, line), .only_dir => { @@ -536,26 +539,74 @@ fn ccPrintFileName( } /// Caller owns returned memory. -pub fn detectNativeDynamicLinker(allocator: *Allocator) error{OutOfMemory, TargetHasNoDynamicLinker, UnknownDynamicLinkerPath}![:0]u8 { +pub fn detectNativeDynamicLinker(allocator: *Allocator) error{ + OutOfMemory, + TargetHasNoDynamicLinker, + UnknownDynamicLinkerPath, +}![:0]u8 { if (!comptime Target.current.hasDynamicLinker()) { return error.TargetHasNoDynamicLinker; } - const standard_ld_path = try std.Target.current.getStandardDynamicLinkerPath(allocator); - var standard_ld_path_resource: ?[:0]u8 = standard_ld_path; // Set to null to avoid freeing it. - defer if (standard_ld_path_resource) |s| allocator.free(s); + // The current target's ABI cannot be relied on for this. For example, we may build the zig + // compiler for target riscv64-linux-musl and provide a tarball for users to download. + // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined + // and supported by Zig. But that means that we must detect the system ABI here rather than + // relying on `std.Target.current`. - const standard_ld_basename = fs.path.basename(standard_ld_path); + const LdInfo = struct { + ld_path: []u8, + abi: Target.Abi, + }; + var ld_info_list = std.ArrayList(LdInfo).init(allocator); + defer { + for (ld_info_list.toSlice()) |ld_info| allocator.free(ld_info.ld_path); + ld_info_list.deinit(); + } + const all_abis = comptime blk: { + const fields = std.meta.fields(Target.Abi); + var array: [fields.len]Target.Abi = undefined; + inline for (fields) |field, i| { + array[i] = @field(Target.Abi, field.name); + } + break :blk array; + }; + for (all_abis) |abi| { + // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and + // skip adding it to `ld_info_list`. + const target: Target = .{ + .Cross = .{ + .arch = Target.current.getArch(), + .os = Target.current.getOs(), + .abi = abi, + .cpu_features = Target.current.getArch().getBaselineCpuFeatures(), + }, + }; + const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => continue, + }; + errdefer allocator.free(standard_ld_path); + try ld_info_list.append(.{ + .ld_path = standard_ld_path, + .abi = abi, + }); + } + + // Best case scenario: the zig compiler is dynamically linked, and we can iterate + // over our own shared objects and find a dynamic linker. { - // Best case scenario: the current executable is dynamically linked, and we can iterate - // over our own shared objects and find a dynamic linker. const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator); defer allocator.free(lib_paths); + // This is O(N^M) but typical case here is N=2 and M=10. for (lib_paths) |lib_path| { - if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) { - return std.mem.dupeZ(allocator, u8, lib_path); + for (ld_info_list.toSlice()) |ld_info| { + const standard_ld_basename = fs.path.basename(ld_info.ld_path); + if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) { + return std.mem.dupeZ(allocator, u8, lib_path); + } } } } @@ -563,17 +614,23 @@ pub fn detectNativeDynamicLinker(allocator: *Allocator) error{OutOfMemory, Targe // If Zig is statically linked, such as via distributed binary static builds, the above // trick won't work. What are we left with? Try to run the system C compiler and get // it to tell us the dynamic linker path. - return ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.LibCRuntimeNotFound, - error.CCompilerExitCode, - error.CCompilerCrashed, - error.UnableToSpawnCCompiler, - => { - standard_ld_path_resource = null; // Prevent freeing standard_ld_path. - return standard_ld_path; - }, - }; + // TODO: instead of this, look at the shared libs of /usr/bin/env. + for (ld_info_list.toSlice()) |ld_info| { + const standard_ld_basename = fs.path.basename(ld_info.ld_path); + + const full_ld_path = ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.LibCRuntimeNotFound, + error.CCompilerExitCode, + error.CCompilerCrashed, + error.UnableToSpawnCCompiler, + => continue, + }; + return full_ld_path; + } + + // Finally, we fall back on the standard path. + return Target.current.getStandardDynamicLinkerPath(allocator); } const Search = struct { From 99520c4e6936b69e7489262bc35a70300366d395 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 19:49:19 -0500 Subject: [PATCH 034/109] target_os_requires_libc implies dynamic linking --- src/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 12b49ab2ae..41a353ef14 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8375,6 +8375,8 @@ static bool detect_dynamic_link(CodeGen *g) { return true; if (g->zig_target->os == OsFreestanding) return false; + if (target_os_requires_libc(g->zig_target->os)) + return true; if (g->libc_link_lib != nullptr && target_is_glibc(g->zig_target)) return true; // If there are no dynamic libraries then we can disable dynamic linking. From 35f0cb049e6a46c8037bab15a9debc21ad1a979e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Feb 2020 20:25:02 -0500 Subject: [PATCH 035/109] stage2: fix invalid iteration code in std.ast.Node.Asm closes #4480 --- lib/std/zig/ast.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index e01d406530..f96428a6bc 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -2183,10 +2183,10 @@ pub const Node = struct { pub fn iterate(self: *Asm, index: usize) ?*Node { var i = index; - if (i < self.outputs.len) return &self.outputs.at(index).*.base; + if (i < self.outputs.len) return &self.outputs.at(i).*.base; i -= self.outputs.len; - if (i < self.inputs.len) return &self.inputs.at(index).*.base; + if (i < self.inputs.len) return &self.inputs.at(i).*.base; i -= self.inputs.len; return null; From 7560fc716d968f2448bed370affd6162d1e784c4 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Tue, 11 Feb 2020 23:14:08 +0100 Subject: [PATCH 036/109] Makes the declaration slice resolve lazely when using `@typeInfo` This way all the declarations in a container won't be resolved untill the user actually uses the decls slice in the builtin TypeInfo union. --- src/all_types.hpp | 10 +++++++++ src/analyze.cpp | 6 ++++++ src/ir.cpp | 45 +++++++++++++++++++++++++++++++++++++---- test/compile_errors.zig | 23 +++------------------ 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index c5804a3dc4..fbe24c918b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -369,12 +369,22 @@ enum LazyValueId { LazyValueIdFnType, LazyValueIdErrUnionType, LazyValueIdArrayType, + LazyValueIdTypeInfoDecls, }; struct LazyValue { LazyValueId id; }; +struct LazyValueTypeInfoDecls { + LazyValue base; + + IrAnalyze *ira; + + ScopeDecls *decls_scope; + IrInst *source_instr; +}; + struct LazyValueAlignOf { LazyValue base; diff --git a/src/analyze.cpp b/src/analyze.cpp index 98366bc87d..95b2c77129 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1150,6 +1150,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdPtrType: { LazyValuePtrType *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); @@ -1209,6 +1210,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdSliceType: case LazyValueIdPtrType: @@ -1230,6 +1232,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdSliceType: { LazyValueSliceType *lazy_slice_type = reinterpret_cast(type_val->data.x_lazy); @@ -1303,6 +1306,7 @@ start_over: case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdSliceType: { LazyValueSliceType *lazy_slice_type = reinterpret_cast(type_val->data.x_lazy); @@ -1370,6 +1374,7 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdSliceType: case LazyValueIdPtrType: @@ -1412,6 +1417,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV case LazyValueIdInvalid: case LazyValueIdAlignOf: case LazyValueIdSizeOf: + case LazyValueIdTypeInfoDecls: zig_unreachable(); case LazyValueIdSliceType: // it has the len field case LazyValueIdOptType: // it has the optional bit diff --git a/src/ir.cpp b/src/ir.cpp index c87424b25e..7f67c317b0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21221,6 +21221,13 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins return ira->codegen->invalid_inst_gen; if (type_is_invalid(struct_val->type)) return ira->codegen->invalid_inst_gen; + + // This to allow lazy values to be resolved. + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + source_instr->source_node, struct_val, UndefOk))) + { + return ira->codegen->invalid_inst_gen; + } if (initializing && struct_val->special == ConstValSpecialUndef) { struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; @@ -23626,7 +23633,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig } static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val, - ScopeDecls *decls_scope) + ScopeDecls *decls_scope, bool resolve_types) { Error err; ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr); @@ -23637,6 +23644,24 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa ensure_field_index(type_info_declaration_type, "is_pub", 1); ensure_field_index(type_info_declaration_type, "data", 2); + if (!resolve_types) { + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, type_info_declaration_type, + false, false, PtrLenUnknown, 0, 0, 0, false); + + out_val->special = ConstValSpecialLazy; + out_val->type = get_slice_type(ira->codegen, ptr_type); + + LazyValueTypeInfoDecls *lazy_type_info_decls = heap::c_allocator.create(); + lazy_type_info_decls->ira = ira; ira_ref(ira); + out_val->data.x_lazy = &lazy_type_info_decls->base; + lazy_type_info_decls->base.id = LazyValueIdTypeInfoDecls; + + lazy_type_info_decls->source_instr = source_instr; + lazy_type_info_decls->decls_scope = decls_scope; + + return ErrorNone; + } + ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type); if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown))) return err; @@ -24189,7 +24214,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], - type_entry->data.enumeration.decls_scope))) + type_entry->data.enumeration.decls_scope, false))) { return err; } @@ -24361,7 +24386,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], - type_entry->data.unionation.decls_scope))) + type_entry->data.unionation.decls_scope, false))) { return err; } @@ -24453,7 +24478,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 2); if ((err = ir_make_type_info_decls(ira, source_instr, fields[2], - type_entry->data.structure.decls_scope))) + type_entry->data.structure.decls_scope, false))) { return err; } @@ -30391,6 +30416,18 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { switch (val->data.x_lazy->id) { case LazyValueIdInvalid: zig_unreachable(); + case LazyValueIdTypeInfoDecls: { + LazyValueTypeInfoDecls *type_info_decls = reinterpret_cast(val->data.x_lazy); + IrAnalyze *ira = type_info_decls->ira; + + if ((err = ir_make_type_info_decls(ira, type_info_decls->source_instr, val, type_info_decls->decls_scope, true))) + { + return err; + }; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. + return ErrorNone; + } case LazyValueIdAlignOf: { LazyValueAlignOf *lazy_align_of = reinterpret_cast(val->data.x_lazy); IrAnalyze *ira = lazy_align_of->ira; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index cc2863a046..240980efba 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -30,10 +30,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'", }); - cases.addTest("dependency loop in top-level decl with @TypeInfo", - \\export const foo = @typeInfo(@This()); + cases.addTest("dependency loop in top-level decl with @TypeInfo when accessing the decls", + \\export const foo = @typeInfo(@This()).Struct.decls; , &[_][]const u8{ "tmp.zig:1:20: error: dependency loop detected", + "tmp.zig:1:45: note: referenced here", }); cases.add("function call assigned to incorrect type", @@ -1346,24 +1347,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:8:28: note: referenced here", }); - cases.add("@typeInfo causing depend on itself compile error", - \\const start = struct { - \\ fn crash() bug() { - \\ return bug; - \\ } - \\}; - \\fn bug() void { - \\ _ = @typeInfo(start).Struct; - \\} - \\export fn entry() void { - \\ var boom = start.crash(); - \\} - , &[_][]const u8{ - "tmp.zig:7:9: error: dependency loop detected", - "tmp.zig:2:19: note: referenced here", - "tmp.zig:10:21: note: referenced here", - }); - cases.add("enum field value references enum", \\pub const Foo = extern enum { \\ A = Foo.B, From dd58278dbe8ac89a9e685a966b5f05f80f463798 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 15:28:14 -0500 Subject: [PATCH 037/109] add behavior test for previous commit --- test/stage1/behavior/type_info.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig index 9d577ec0b4..a3988cba6d 100644 --- a/test/stage1/behavior/type_info.zig +++ b/test/stage1/behavior/type_info.zig @@ -375,3 +375,14 @@ test "sentinel of opaque pointer type" { const c_void_info = @typeInfo(*c_void); expect(c_void_info.Pointer.sentinel == null); } + +test "@typeInfo does not force declarations into existence" { + const S = struct { + x: i32, + + fn doNotReferenceMe() void { + @compileError("test failed"); + } + }; + comptime expect(@typeInfo(S).Struct.fields.len == 1); +} From d056c7732b87633ace03dd15668a88eac76b62a5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 15:34:13 -0500 Subject: [PATCH 038/109] fix std.meta.refAllDecls --- lib/std/meta.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 9c83b8304d..300bca3d0e 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -437,7 +437,7 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { }, .Pointer => |info| { return switch (info.size) { - .One, .Many, .C, => a == b, + .One, .Many, .C => a == b, .Slice => a.ptr == b.ptr and a.len == b.len, }; }, @@ -559,7 +559,9 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int { /// Given a type, reference all the declarations inside, so that the semantic analyzer sees them. pub fn refAllDecls(comptime T: type) void { if (!builtin.is_test) return; - _ = declarations(T); + inline for (declarations(T)) |decl| { + _ = decl; + } } /// Returns a slice of pointers to public declarations of a namespace. From bdff2f43bdc112cb02e36678d079e82fd5a96605 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 11 Nov 2019 02:49:35 +1100 Subject: [PATCH 039/109] std: use LinearFifo to implement io.BufferedInStreamCustom --- lib/std/io.zig | 67 +++++++++++--------------------------------------- 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 16bfffdcad..7baa383001 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -121,76 +121,37 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) unbuffered_in_stream: *Stream, - buffer: [buffer_size]u8, - start_index: usize, - end_index: usize, + const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size }); + fifo: FifoType, pub fn init(unbuffered_in_stream: *Stream) Self { return Self{ .unbuffered_in_stream = unbuffered_in_stream, - .buffer = undefined, - - // Initialize these two fields to buffer_size so that - // in `readFn` we treat the state as being able to read - // more from the unbuffered stream. If we set them to 0 - // and 0, the code would think we already hit EOF. - .start_index = buffer_size, - .end_index = buffer_size, - + .fifo = FifoType.init(), .stream = Stream{ .readFn = readFn }, }; } fn readFn(in_stream: *Stream, dest: []u8) !usize { const self = @fieldParentPtr(Self, "stream", in_stream); - - // Hot path for one byte reads - if (dest.len == 1 and self.end_index > self.start_index) { - dest[0] = self.buffer[self.start_index]; - self.start_index += 1; - return 1; - } - var dest_index: usize = 0; - while (true) { - const dest_space = dest.len - dest_index; - if (dest_space == 0) { - return dest_index; - } - const amt_buffered = self.end_index - self.start_index; - if (amt_buffered == 0) { - assert(self.end_index <= buffer_size); - // Make sure the last read actually gave us some data - if (self.end_index == 0) { + while (dest_index < dest.len) { + const written = self.fifo.read(dest[dest_index..]); + if (written == 0) { + // fifo empty, fill it + const writable = self.fifo.writableSlice(0); + assert(writable.len > 0); + const n = try self.unbuffered_in_stream.read(writable); + if (n == 0) { // reading from the unbuffered stream returned nothing // so we have nothing left to read. return dest_index; } - // we can read more data from the unbuffered stream - if (dest_space < buffer_size) { - self.start_index = 0; - self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); - - // Shortcut - if (self.end_index >= dest_space) { - mem.copy(u8, dest[dest_index..], self.buffer[0..dest_space]); - self.start_index = dest_space; - return dest.len; - } - } else { - // asking for so much data that buffering is actually less efficient. - // forward the request directly to the unbuffered stream - const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); - return dest_index + amt_read; - } + self.fifo.update(n); } - - const copy_amount = math.min(dest_space, amt_buffered); - const copy_end_index = self.start_index + copy_amount; - mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]); - self.start_index = copy_end_index; - dest_index += copy_amount; + dest_index += written; } + return dest.len; } }; } From 38ad7daebb42d562946c092a59cfbbf94e75870a Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 11 Nov 2019 03:07:57 +1100 Subject: [PATCH 040/109] std: use LinearFifo to implement io.PeekStream --- lib/std/io.zig | 46 +++++++++++++-------------------------------- lib/std/io/test.zig | 8 ++++---- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 7baa383001..018c863bbd 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -196,7 +196,7 @@ test "io.BufferedInStream" { /// Creates a stream which supports 'un-reading' data, so that it can be read again. /// This makes look-ahead style parsing much easier. -pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { +pub fn PeekStream(comptime buffer_type: usize, comptime InStreamError: type) type { return struct { const Self = @This(); pub const Error = InStreamError; @@ -207,55 +207,35 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ // Right now the look-ahead space is statically allocated, but a version with dynamic allocation // is not too difficult to derive from this. - buffer: [buffer_size]u8, - index: usize, - at_end: bool, + const FifoType = std.fifo.LinearFifo(u8, .{ .Static = buffer_size }); + fifo: FifoType, pub fn init(base: *Stream) Self { - return Self{ + return .{ .base = base, - .buffer = undefined, - .index = 0, - .at_end = false, + .fifo = FifoType.init(), .stream = Stream{ .readFn = readFn }, }; } - pub fn putBackByte(self: *Self, byte: u8) void { - self.buffer[self.index] = byte; - self.index += 1; + pub fn putBackByte(self: *Self, byte: u8) !void { + try self.putBack(@ptrCast([*]const u8, &byte)[0..1]); } - pub fn putBack(self: *Self, bytes: []const u8) void { - var pos = bytes.len; - while (pos != 0) { - pos -= 1; - self.putBackByte(bytes[pos]); - } + pub fn putBack(self: *Self, bytes: []const u8) !void { + try self.fifo.unget(bytes); } fn readFn(in_stream: *Stream, dest: []u8) Error!usize { const self = @fieldParentPtr(Self, "stream", in_stream); // copy over anything putBack()'d - var pos: usize = 0; - while (pos < dest.len and self.index != 0) { - dest[pos] = self.buffer[self.index - 1]; - self.index -= 1; - pos += 1; - } - - if (pos == dest.len or self.at_end) { - return pos; - } + var dest_index = self.fifo.read(dest); + if (dest_index == dest.len) return dest_index; // ask the backing stream for more - const left = dest.len - pos; - const read = try self.base.read(dest[pos..]); - assert(read <= left); - - self.at_end = (read < left); - return pos + read; + dest_index += try self.base.read(dest[dest_index..]); + return dest_index; } }; } diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index c4e9a1fc06..b2f8307310 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -97,8 +97,8 @@ test "PeekStream" { var dest: [4]u8 = undefined; - ps.putBackByte(9); - ps.putBackByte(10); + try ps.putBackByte(9); + try ps.putBackByte(10); var read = try ps.stream.read(dest[0..4]); expect(read == 4); @@ -114,8 +114,8 @@ test "PeekStream" { expect(read == 2); expect(mem.eql(u8, dest[0..2], bytes[6..8])); - ps.putBackByte(11); - ps.putBackByte(12); + try ps.putBackByte(11); + try ps.putBackByte(12); read = try ps.stream.read(dest[0..4]); expect(read == 2); From dd75cc214d087e0d3a68a76ced3a707aa456d887 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sat, 16 Nov 2019 22:34:27 +1100 Subject: [PATCH 041/109] std: let PeekStream have static/dynamic variants This completes a TODO in the existing implementation --- lib/std/io.zig | 42 +++++++++++++++++++++++++++++++----------- lib/std/io/test.zig | 2 +- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 018c863bbd..2ebf8c3b87 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -196,7 +196,7 @@ test "io.BufferedInStream" { /// Creates a stream which supports 'un-reading' data, so that it can be read again. /// This makes look-ahead style parsing much easier. -pub fn PeekStream(comptime buffer_type: usize, comptime InStreamError: type) type { +pub fn PeekStream(comptime buffer_type: std.fifo.LinearFifoBufferType, comptime InStreamError: type) type { return struct { const Self = @This(); pub const Error = InStreamError; @@ -205,18 +205,38 @@ pub fn PeekStream(comptime buffer_type: usize, comptime InStreamError: type) typ stream: Stream, base: *Stream, - // Right now the look-ahead space is statically allocated, but a version with dynamic allocation - // is not too difficult to derive from this. - const FifoType = std.fifo.LinearFifo(u8, .{ .Static = buffer_size }); + const FifoType = std.fifo.LinearFifo(u8, buffer_type); fifo: FifoType, - pub fn init(base: *Stream) Self { - return .{ - .base = base, - .fifo = FifoType.init(), - .stream = Stream{ .readFn = readFn }, - }; - } + pub usingnamespace switch (buffer_type) { + .Static => struct { + pub fn init(base: *Stream) Self { + return .{ + .base = base, + .fifo = FifoType.init(), + .stream = Stream{ .readFn = readFn }, + }; + } + }, + .Slice => struct { + pub fn init(base: *Stream, buf: []u8) Self { + return .{ + .base = base, + .fifo = FifoType.init(buf), + .stream = Stream{ .readFn = readFn }, + }; + } + }, + .Dynamic => struct { + pub fn init(base: *Stream, allocator: *mem.Allocator) Self { + return .{ + .base = base, + .fifo = FifoType.init(allocator), + .stream = Stream{ .readFn = readFn }, + }; + } + }, + }; pub fn putBackByte(self: *Self, byte: u8) !void { try self.putBack(@ptrCast([*]const u8, &byte)[0..1]); diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index b2f8307310..6c194b0f3d 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -93,7 +93,7 @@ test "SliceInStream" { test "PeekStream" { const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; var ss = io.SliceInStream.init(&bytes); - var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream); + var ps = io.PeekStream(.{ .Static = 2 }, io.SliceInStream.Error).init(&ss.stream); var dest: [4]u8 = undefined; From 3632f31ec2991005f2269eac955cd5ef589fe5ed Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 11 Nov 2019 03:22:42 +1100 Subject: [PATCH 042/109] std: use LinearFifo to implement io.BufferedOutStreamCustom --- lib/std/io.zig | 41 +++++++++++------------------------------ lib/std/io/test.zig | 5 +++-- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 2ebf8c3b87..4618db95e4 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -568,52 +568,33 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr unbuffered_out_stream: *Stream, - buffer: [buffer_size]u8, - index: usize, + const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size }); + fifo: FifoType, pub fn init(unbuffered_out_stream: *Stream) Self { return Self{ .unbuffered_out_stream = unbuffered_out_stream, - .buffer = undefined, - .index = 0, + .fifo = FifoType.init(), .stream = Stream{ .writeFn = writeFn }, }; } pub fn flush(self: *Self) !void { - try self.unbuffered_out_stream.write(self.buffer[0..self.index]); - self.index = 0; + while (true) { + const slice = self.fifo.readableSlice(0); + if (slice.len == 0) break; + try self.unbuffered_out_stream.write(slice); + self.fifo.discard(slice.len); + } } fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void { const self = @fieldParentPtr(Self, "stream", out_stream); - - if (bytes.len == 1) { - // This is not required logic but a shorter path - // for single byte writes - self.buffer[self.index] = bytes[0]; - self.index += 1; - if (self.index == buffer_size) { - try self.flush(); - } - return; - } else if (bytes.len >= self.buffer.len) { + if (bytes.len >= self.fifo.writableLength()) { try self.flush(); return self.unbuffered_out_stream.write(bytes); } - var src_index: usize = 0; - - while (src_index < bytes.len) { - const dest_space_left = self.buffer.len - self.index; - const copy_amt = math.min(dest_space_left, bytes.len - src_index); - mem.copy(u8, self.buffer[self.index..], bytes[src_index .. src_index + copy_amt]); - self.index += copy_amt; - assert(self.index <= self.buffer.len); - if (self.index == self.buffer.len) { - try self.flush(); - } - src_index += copy_amt; - } + self.fifo.writeAssumeCapacity(bytes); } }; } diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 6c194b0f3d..7716e603a0 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -5,6 +5,7 @@ const meta = std.meta; const trait = std.trait; const DefaultPrng = std.rand.DefaultPrng; const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; const expectError = std.testing.expectError; const mem = std.mem; const fs = std.fs; @@ -44,8 +45,8 @@ test "write a file, read it, then delete it" { defer file.close(); const file_size = try file.getEndPos(); - const expected_file_size = "begin".len + data.len + "end".len; - expect(file_size == expected_file_size); + const expected_file_size: u64 = "begin".len + data.len + "end".len; + expectEqual(expected_file_size, file_size); var file_in_stream = file.inStream(); var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream); From a8d7652001525881fe17ddf42f5f86671d706b4b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 16:48:26 -0500 Subject: [PATCH 043/109] avoid a `@ptrCast` with an array literal --- lib/std/io.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 4618db95e4..22ba0b9bf4 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -239,7 +239,7 @@ pub fn PeekStream(comptime buffer_type: std.fifo.LinearFifoBufferType, comptime }; pub fn putBackByte(self: *Self, byte: u8) !void { - try self.putBack(@ptrCast([*]const u8, &byte)[0..1]); + try self.putBack(&[_]u8{byte}); } pub fn putBack(self: *Self, bytes: []const u8) !void { From 95a71e29f84573ce72b16406eaf1a6dff96de35f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 18 Feb 2020 22:39:19 +0100 Subject: [PATCH 044/109] zig fmt: Fix callconv rewriting for extern + string Closes #4473 --- lib/std/zig/parser_test.zig | 2 ++ lib/std/zig/render.zig | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 28bf0c9ed5..5f28dd3b06 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -92,10 +92,12 @@ test "zig fmt: convert extern/nakedcc/stdcallcc into callconv(...)" { \\nakedcc fn foo1() void {} \\stdcallcc fn foo2() void {} \\extern fn foo3() void {} + \\extern "mylib" fn foo4() void {} , \\fn foo1() callconv(.Naked) void {} \\fn foo2() callconv(.Stdcall) void {} \\fn foo3() callconv(.C) void {} + \\fn foo4() callconv(.C) void {} \\ ); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index e322a91dc4..069635d42e 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1396,6 +1396,7 @@ fn renderExpression( try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export } else { cc_rewrite_str = ".C"; + fn_proto.lib_name = null; } } From a6b74cdd38a2aac25275c97c00133ec7134aacd2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 18 Feb 2020 22:53:03 +0100 Subject: [PATCH 045/109] stage1: Make the parser reject extern fn with body --- src/parser.cpp | 3 +++ test/compile_errors.zig | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/parser.cpp b/src/parser.cpp index c8c53e81b7..275fa90167 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -689,6 +689,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B AstNode *res = fn_proto; if (body != nullptr) { + if (fn_proto->data.fn_proto.is_extern) { + ast_error(pc, first, "Extern functions have no body"); + } res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); res->data.fn_def.fn_proto = fn_proto; res->data.fn_def.body = body; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 2c52ee2c67..dd688e6c10 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -12,6 +12,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:11: error: use of undeclared identifier 'B'", }); + cases.addTest("reject extern function definitions with body", + \\extern "c" fn definitelyNotInLibC(a: i32, b: i32) i32 { + \\ return a + b; + \\} + , &[_][]const u8{ + "tmp.zig:1:1: error: Extern functions have no body", + }); + cases.addTest("duplicate field in anonymous struct literal", \\export fn entry() void { \\ const anon = .{ From eb5e6259aa21774e3dffba9518a94cb904285f8a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 18 Feb 2020 23:35:08 +0100 Subject: [PATCH 046/109] docs: Fix wrong extern fn definition --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 47f13f9e05..71f97b3f06 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7399,7 +7399,7 @@ comptime { @export(internalName, .{ .name = "foo", .linkage = .Strong }); } -extern fn internalName() void {} +fn internalName() callconv(.C) void {} {#code_end#}

This is equivalent to:

{#code_begin|obj#} From 30194f27fb5521b11442f1d13474eac3915051d7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 18:27:18 -0500 Subject: [PATCH 047/109] update new test case to take into account lazy `@typeInfo` --- test/compile_errors.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index dd688e6c10..c5f5b6f9da 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,10 +3,10 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { - cases.addTest("", + cases.addTest("access invalid @typeInfo decl", \\const A = B; \\test "Crash" { - \\ _ = @typeInfo(@This()).Struct.decls; + \\ _ = @typeInfo(@This()).Struct.decls[0]; \\} , &[_][]const u8{ "tmp.zig:1:11: error: use of undeclared identifier 'B'", From 2502cb242a0da5112c2cf9b0974ffd68aa27ecc8 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Sun, 9 Feb 2020 19:52:50 -0500 Subject: [PATCH 048/109] Improve support for generating LLVM IR/asm files --- lib/std/build.zig | 10 +++ src/all_types.hpp | 9 +-- src/codegen.cpp | 173 ++++++++++++++++++++++------------------------ src/codegen.hpp | 4 +- src/main.cpp | 35 +++++++--- 5 files changed, 122 insertions(+), 109 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 6cab29eb41..d81b660a5b 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,6 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, + produce_ir: bool, + produce_asm: bool, + produce_bin: bool, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1285,6 +1288,9 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, + .produce_ir = false, + .produce_asm = false, + .produce_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1941,6 +1947,10 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; + try zig_args.append(if (self.produce_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); + try zig_args.append(if (self.produce_asm) "-femit-asm" else "-fno-emit-asm"); + try zig_args.append(if (self.produce_bin) "-femit-bin" else "-fno-emit-bin"); + if (self.strip) { try zig_args.append("--strip"); } diff --git a/src/all_types.hpp b/src/all_types.hpp index fbe24c918b..eb57a6e618 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1966,12 +1966,6 @@ enum CodeModel { CodeModelLarge, }; -enum EmitFileType { - EmitFileTypeBinary, - EmitFileTypeAssembly, - EmitFileTypeLLVMIr, -}; - struct LinkLib { Buf *name; Buf *path; @@ -2204,6 +2198,8 @@ struct CodeGen { bool verbose_cimport; bool verbose_cc; bool verbose_llvm_cpu_features; + bool emit_asm; + bool emit_llvm_ir; bool error_during_imports; bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir @@ -2236,7 +2232,6 @@ struct CodeGen { size_t version_patch; const char *linker_script; - EmitFileType emit_file_type; BuildMode build_mode; OutType out_type; const ZigTarget *zig_target; diff --git a/src/codegen.cpp b/src/codegen.cpp index 41a353ef14..84753e1053 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -121,10 +121,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc g->version_patch = patch; } -void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { - g->emit_file_type = emit_file_type; -} - void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) { g->each_lib_rpath = each_lib_rpath; } @@ -7919,6 +7915,14 @@ static void do_code_gen(CodeGen *g) { } } +void codegen_set_emit_asm(CodeGen *g, bool emit) { + g->emit_asm = emit; +} + +void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) { + g->emit_llvm_ir = emit; +} + static void zig_llvm_emit_output(CodeGen *g) { g->pass1_arena->destruct(&heap::c_allocator); g->pass1_arena = nullptr; @@ -7927,48 +7931,40 @@ static void zig_llvm_emit_output(CodeGen *g) { Buf *output_path = &g->o_file_output_path; char *err_msg = nullptr; - switch (g->emit_file_type) { - case EmitFileTypeBinary: - if (g->disable_bin_generation) - return; - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - g->link_objects.append(output_path); - if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || - (g->out_type == OutTypeLib && !g->is_dynamic))) - { - zig_link_add_compiler_rt(g, g->sub_progress_node); - } - break; - - case EmitFileTypeAssembly: - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - break; - - case EmitFileTypeLLVMIr: - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - break; - - default: - zig_unreachable(); + if (!g->disable_bin_generation) { + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), + ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, + g->enable_time_report)) + { + zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); + } + validate_inline_fns(g); + g->link_objects.append(output_path); + if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || + (g->out_type == OutTypeLib && !g->is_dynamic))) + { + zig_link_add_compiler_rt(g, g->sub_progress_node); + } } + if (g->emit_asm) { + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), + ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small, + g->enable_time_report)) + { + zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); + } + validate_inline_fns(g); + } + if (g->emit_llvm_ir) { + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), + ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small, + g->enable_time_report)) + { + zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); + } + validate_inline_fns(g); + } + LLVMDisposeModule(g->module); g->module = nullptr; LLVMDisposeTargetData(g->target_data_ref); @@ -10497,53 +10493,48 @@ static void resolve_out_paths(CodeGen *g) { Buf *out_basename = buf_create_from_buf(g->root_out_name); Buf *o_basename = buf_create_from_buf(g->root_out_name); - switch (g->emit_file_type) { - case EmitFileTypeBinary: { - switch (g->out_type) { - case OutTypeUnknown: - zig_unreachable(); - case OutTypeObj: - if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { - buf_init_from_buf(&g->output_file_path, g->link_objects.at(0)); - return; - } - if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && - buf_eql_buf(o_basename, out_basename)) - { - // make it not collide with main output object - buf_append_str(o_basename, ".root"); - } - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_append_str(out_basename, target_o_file_ext(g->zig_target)); - break; - case OutTypeExe: - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_append_str(out_basename, target_exe_file_ext(g->zig_target)); - break; - case OutTypeLib: - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_resize(out_basename, 0); - buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); - buf_append_buf(out_basename, g->root_out_name); - buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, - g->version_major, g->version_minor, g->version_patch)); - break; - } - break; - } - case EmitFileTypeAssembly: { - const char *asm_ext = target_asm_file_ext(g->zig_target); - buf_append_str(o_basename, asm_ext); - buf_append_str(out_basename, asm_ext); - break; - } - case EmitFileTypeLLVMIr: { - const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); - buf_append_str(o_basename, llvm_ir_ext); - buf_append_str(out_basename, llvm_ir_ext); - break; + if (!g->disable_bin_generation) { + switch (g->out_type) { + case OutTypeUnknown: + zig_unreachable(); + case OutTypeObj: + if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { + buf_init_from_buf(&g->output_file_path, g->link_objects.at(0)); + return; + } + if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && + buf_eql_buf(o_basename, out_basename)) + { + // make it not collide with main output object + buf_append_str(o_basename, ".root"); + } + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_append_str(out_basename, target_o_file_ext(g->zig_target)); + break; + case OutTypeExe: + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_append_str(out_basename, target_exe_file_ext(g->zig_target)); + break; + case OutTypeLib: + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_resize(out_basename, 0); + buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); + buf_append_buf(out_basename, g->root_out_name); + buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, + g->version_major, g->version_minor, g->version_patch)); + break; } } + else if (g->emit_asm) { + const char *asm_ext = target_asm_file_ext(g->zig_target); + buf_append_str(o_basename, asm_ext); + buf_append_str(out_basename, asm_ext); + } + else if (g->emit_llvm_ir) { + const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); + buf_append_str(o_basename, llvm_ir_ext); + buf_append_str(out_basename, llvm_ir_ext); + } os_path_join(g->output_dir, o_basename, &g->o_file_output_path); os_path_join(g->output_dir, out_basename, &g->output_file_path); @@ -10708,7 +10699,7 @@ void codegen_build_and_link(CodeGen *g) { // If there is more than one object, we have to link them (with -r). // Finally, if we didn't make an object from zig source, and we don't have caching enabled, // then we have an object from C source that we must copy to the output dir which we do with a -r link. - if (!g->disable_bin_generation && g->emit_file_type == EmitFileTypeBinary && + if (!g->disable_bin_generation && (g->out_type != OutTypeObj || g->link_objects.length > 1 || (!need_llvm_module(g) && !g->enable_cache))) { diff --git a/src/codegen.hpp b/src/codegen.hpp index f8be29494a..1e99cf220f 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -26,7 +26,9 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); -void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); +void codegen_set_emit_asm(CodeGen *codegen, bool emit); +void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit); + void codegen_set_strip(CodeGen *codegen, bool strip); void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); void codegen_set_out_name(CodeGen *codegen, Buf *out_name); diff --git a/src/main.cpp b/src/main.cpp index cbaf6aeb70..2a279e80ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -376,7 +376,6 @@ static int main0(int argc, char **argv) { } Cmd cmd = CmdNone; - EmitFileType emit_file_type = EmitFileTypeBinary; const char *in_file = nullptr; Buf *output_dir = nullptr; bool strip = false; @@ -425,6 +424,8 @@ static int main0(int argc, char **argv) { bool enable_dump_analysis = false; bool enable_doc_generation = false; bool disable_bin_generation = false; + bool emit_asm = false; + bool emit_llvm_ir = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = heap::c_allocator.create(); BuildMode build_mode = BuildModeDebug; @@ -701,6 +702,18 @@ static int main0(int argc, char **argv) { function_sections = true; } else if (strcmp(arg, "--test-evented-io") == 0) { test_evented_io = true; + } else if (strcmp(arg, "-femit-bin") == 0) { + disable_bin_generation = false; + } else if (strcmp(arg, "-fno-emit-bin") == 0) { + disable_bin_generation = true; + } else if (strcmp(arg, "-femit-asm") == 0) { + emit_asm = true; + } else if (strcmp(arg, "-fno-emit-asm") == 0) { + emit_asm = false; + } else if (strcmp(arg, "-femit-llvm-ir") == 0) { + emit_llvm_ir = true; + } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) { + emit_llvm_ir = false; } else if (i + 1 >= argc) { fprintf(stderr, "Expected another argument after %s\n", arg); return print_error_usage(arg0); @@ -732,11 +745,11 @@ static int main0(int argc, char **argv) { } } else if (strcmp(arg, "--emit") == 0) { if (strcmp(argv[i], "asm") == 0) { - emit_file_type = EmitFileTypeAssembly; + emit_asm = true; } else if (strcmp(argv[i], "bin") == 0) { - emit_file_type = EmitFileTypeBinary; + disable_bin_generation = false; } else if (strcmp(argv[i], "llvm-ir") == 0) { - emit_file_type = EmitFileTypeLLVMIr; + emit_llvm_ir = true; } else { fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); return print_error_usage(arg0); @@ -1026,8 +1039,8 @@ static int main0(int argc, char **argv) { return print_error_usage(arg0); } - if (emit_file_type != EmitFileTypeBinary && in_file == nullptr) { - fprintf(stderr, "A root source file is required when using `--emit asm` or `--emit llvm-ir`\n"); + if ((emit_asm || emit_llvm_ir) && in_file == nullptr) { + fprintf(stderr, "A root source file is required when using `-femit-asm` or `-femit-llvm-ir`\n"); return print_error_usage(arg0); } @@ -1098,7 +1111,7 @@ static int main0(int argc, char **argv) { { fprintf(stderr, "Expected source file argument.\n"); return print_error_usage(arg0); - } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) { + } else if (cmd == CmdRun && disable_bin_generation) { fprintf(stderr, "Cannot run non-executable file.\n"); return print_error_usage(arg0); } @@ -1262,7 +1275,8 @@ static int main0(int argc, char **argv) { if (cmd == CmdBuild || cmd == CmdRun) { - codegen_set_emit_file_type(g, emit_file_type); + codegen_set_emit_asm(g, emit_asm); + codegen_set_emit_llvm_ir(g, emit_llvm_ir); g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun); codegen_build_and_link(g); @@ -1330,7 +1344,8 @@ static int main0(int argc, char **argv) { codegen_print_timing_report(g, stderr); return main_exit(root_progress_node, EXIT_SUCCESS); } else if (cmd == CmdTest) { - codegen_set_emit_file_type(g, emit_file_type); + codegen_set_emit_asm(g, emit_asm); + codegen_set_emit_llvm_ir(g, emit_llvm_ir); ZigTarget native; get_native_target(&native); @@ -1359,7 +1374,7 @@ static int main0(int argc, char **argv) { Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); - if (emit_file_type != EmitFileTypeBinary) { + if (disable_bin_generation) { fprintf(stderr, "Created %s but skipping execution because it is non executable.\n", buf_ptr(test_exe_path)); return main_exit(root_progress_node, EXIT_SUCCESS); From 9c98c73e7359bdf54b3c6b1e82354b0e987c2715 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Sun, 9 Feb 2020 20:33:35 -0500 Subject: [PATCH 049/109] Disable binary generation when deprecated `--emit` is used --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 2a279e80ac..c8c2f1b4a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -746,10 +746,12 @@ static int main0(int argc, char **argv) { } else if (strcmp(arg, "--emit") == 0) { if (strcmp(argv[i], "asm") == 0) { emit_asm = true; + disable_bin_generation = true; } else if (strcmp(argv[i], "bin") == 0) { disable_bin_generation = false; } else if (strcmp(argv[i], "llvm-ir") == 0) { emit_llvm_ir = true; + disable_bin_generation = true; } else { fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); return print_error_usage(arg0); From dba12cd693495009ae624393337a04e80b0ea565 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Mon, 10 Feb 2020 00:23:10 -0500 Subject: [PATCH 050/109] Rename produce_* bools to emit_* to match CLI --- lib/std/build.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index d81b660a5b..38031e2672 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, - produce_ir: bool, - produce_asm: bool, - produce_bin: bool, + emit_ir: bool, + emit_asm: bool, + emit_bin: bool, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1288,9 +1288,9 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, - .produce_ir = false, - .produce_asm = false, - .produce_bin = true, + .emit_ir = false, + .emit_asm = false, + .emit_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1947,9 +1947,9 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; - try zig_args.append(if (self.produce_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); - try zig_args.append(if (self.produce_asm) "-femit-asm" else "-fno-emit-asm"); - try zig_args.append(if (self.produce_bin) "-femit-bin" else "-fno-emit-bin"); + try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); + try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm"); + try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin"); if (self.strip) { try zig_args.append("--strip"); From d7968c6d33b054a8293edd89ce248f385e108469 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 21:59:43 -0500 Subject: [PATCH 051/109] improvements which allow zig to emit multiple things at once example: zig build-obj test.zig -femit-llvm-ir -femit-asm this will generate all three: test.o test.s test.ll --- lib/std/build.zig | 15 +++---- src/all_types.hpp | 10 +++-- src/codegen.cpp | 102 +++++++++++++++++++++++----------------------- src/codegen.hpp | 3 -- src/link.cpp | 38 ++++++++--------- src/main.cpp | 63 ++++++++++++++-------------- src/zig_llvm.cpp | 101 ++++++++++++++++++++++++++------------------- src/zig_llvm.h | 13 ++---- 8 files changed, 174 insertions(+), 171 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 38031e2672..5d13a9923a 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, - emit_ir: bool, - emit_asm: bool, - emit_bin: bool, + emit_llvm_ir: bool = false, + emit_asm: bool = false, + emit_bin: bool = true, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1288,9 +1288,6 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, - .emit_ir = false, - .emit_asm = false, - .emit_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1947,9 +1944,9 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; - try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); - try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm"); - try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin"); + if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir"); + if (self.emit_asm) try zig_args.append("-femit-asm"); + if (!self.emit_bin) try zig_args.append("-fno-emit-bin"); if (self.strip) { try zig_args.append("--strip"); diff --git a/src/all_types.hpp b/src/all_types.hpp index eb57a6e618..c1348d3abd 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2136,8 +2136,10 @@ struct CodeGen { Buf llvm_triple_str; Buf global_asm; - Buf output_file_path; Buf o_file_output_path; + Buf bin_file_output_path; + Buf asm_file_output_path; + Buf llvm_ir_file_output_path; Buf *cache_dir; // As an input parameter, mutually exclusive with enable_cache. But it gets // populated in codegen_build_and_link. @@ -2198,8 +2200,6 @@ struct CodeGen { bool verbose_cimport; bool verbose_cc; bool verbose_llvm_cpu_features; - bool emit_asm; - bool emit_llvm_ir; bool error_during_imports; bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir @@ -2253,7 +2253,9 @@ struct CodeGen { bool function_sections; bool enable_dump_analysis; bool enable_doc_generation; - bool disable_bin_generation; + bool emit_bin; + bool emit_asm; + bool emit_llvm_ir; bool test_is_evented; CodeModel code_model; diff --git a/src/codegen.cpp b/src/codegen.cpp index 84753e1053..a28d2d469d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7915,55 +7915,49 @@ static void do_code_gen(CodeGen *g) { } } -void codegen_set_emit_asm(CodeGen *g, bool emit) { - g->emit_asm = emit; -} - -void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) { - g->emit_llvm_ir = emit; -} - static void zig_llvm_emit_output(CodeGen *g) { g->pass1_arena->destruct(&heap::c_allocator); g->pass1_arena = nullptr; bool is_small = g->build_mode == BuildModeSmallRelease; - Buf *output_path = &g->o_file_output_path; char *err_msg = nullptr; - if (!g->disable_bin_generation) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) + const char *asm_filename = nullptr; + const char *bin_filename = nullptr; + const char *llvm_ir_filename = nullptr; + + if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path); + if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path); + if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path); + + // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire + // pipeline multiple times if this is requested. + if (asm_filename != nullptr && bin_filename != nullptr) { + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug, + is_small, g->enable_time_report, nullptr, bin_filename, llvm_ir_filename)) { - zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); + fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); + exit(1); } - validate_inline_fns(g); - g->link_objects.append(output_path); - if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || - (g->out_type == OutTypeLib && !g->is_dynamic))) - { + bin_filename = nullptr; + llvm_ir_filename = nullptr; + } + + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug, + is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename)) + { + fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); + exit(1); + } + + validate_inline_fns(g); + + if (g->emit_bin) { + g->link_objects.append(&g->o_file_output_path); + if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) { zig_link_add_compiler_rt(g, g->sub_progress_node); } } - if (g->emit_asm) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - } - if (g->emit_llvm_ir) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - } LLVMDisposeModule(g->module); g->module = nullptr; @@ -10446,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->function_sections); cache_bool(ch, g->enable_dump_analysis); cache_bool(ch, g->enable_doc_generation); - cache_bool(ch, g->disable_bin_generation); + cache_bool(ch, g->emit_bin); + cache_bool(ch, g->emit_llvm_ir); + cache_bool(ch, g->emit_asm); cache_buf_opt(ch, g->mmacosx_version_min); cache_buf_opt(ch, g->mios_version_min); cache_usize(ch, g->version_major); @@ -10491,15 +10487,15 @@ static void resolve_out_paths(CodeGen *g) { assert(g->output_dir != nullptr); assert(g->root_out_name != nullptr); - Buf *out_basename = buf_create_from_buf(g->root_out_name); - Buf *o_basename = buf_create_from_buf(g->root_out_name); - if (!g->disable_bin_generation) { + if (g->emit_bin) { + Buf *out_basename = buf_create_from_buf(g->root_out_name); + Buf *o_basename = buf_create_from_buf(g->root_out_name); switch (g->out_type) { case OutTypeUnknown: zig_unreachable(); case OutTypeObj: if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { - buf_init_from_buf(&g->output_file_path, g->link_objects.at(0)); + buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0)); return; } if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && @@ -10524,20 +10520,21 @@ static void resolve_out_paths(CodeGen *g) { g->version_major, g->version_minor, g->version_patch)); break; } + os_path_join(g->output_dir, o_basename, &g->o_file_output_path); + os_path_join(g->output_dir, out_basename, &g->bin_file_output_path); } - else if (g->emit_asm) { + if (g->emit_asm) { + Buf *asm_basename = buf_create_from_buf(g->root_out_name); const char *asm_ext = target_asm_file_ext(g->zig_target); - buf_append_str(o_basename, asm_ext); - buf_append_str(out_basename, asm_ext); + buf_append_str(asm_basename, asm_ext); + os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path); } - else if (g->emit_llvm_ir) { + if (g->emit_llvm_ir) { + Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name); const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); - buf_append_str(o_basename, llvm_ir_ext); - buf_append_str(out_basename, llvm_ir_ext); + buf_append_str(llvm_ir_basename, llvm_ir_ext); + os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path); } - - os_path_join(g->output_dir, o_basename, &g->o_file_output_path); - os_path_join(g->output_dir, out_basename, &g->output_file_path); } void codegen_build_and_link(CodeGen *g) { @@ -10699,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) { // If there is more than one object, we have to link them (with -r). // Finally, if we didn't make an object from zig source, and we don't have caching enabled, // then we have an object from C source that we must copy to the output dir which we do with a -r link. - if (!g->disable_bin_generation && + if (g->emit_bin && (g->out_type != OutTypeObj || g->link_objects.length > 1 || (!need_llvm_module(g) && !g->enable_cache))) { @@ -10777,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) { CodeGen *g = heap::c_allocator.create(); + g->emit_bin = true; g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); g->main_progress_node = progress_node; diff --git a/src/codegen.hpp b/src/codegen.hpp index 1e99cf220f..6329c59a5e 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -26,9 +26,6 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); -void codegen_set_emit_asm(CodeGen *codegen, bool emit); -void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit); - void codegen_set_strip(CodeGen *codegen, bool strip); void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); void codegen_set_out_name(CodeGen *codegen, Buf *out_name); diff --git a/src/link.cpp b/src/link.cpp index 8b31b2519e..901390feae 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil c_source_files.append(c_file); child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) { @@ -682,7 +682,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress } child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) { @@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { @@ -1253,7 +1253,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr child_gen->c_source_files.append(c_file); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "msvcrt-os.lib") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); @@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "mingwex.lib") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); @@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr zig_unreachable(); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else { zig_unreachable(); } @@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr codegen_add_object(child_gen, buf_create_from_str(start_os)); codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "libc_nonshared.a") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); { @@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr build_libc_object(parent, deps[i].name, c_file, progress_node))); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else { zig_unreachable(); } @@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, child_gen->want_stack_check = WantStackCheckDisabled; codegen_build_and_link(child_gen); - return &child_gen->output_file_path; + return &child_gen->bin_file_output_path; } static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { @@ -1681,7 +1681,7 @@ static void construct_linker_job_elf(LinkJob *lj) { } else if (is_dyn_lib) { lj->args.append("-shared"); - assert(buf_len(&g->output_file_path) != 0); + assert(buf_len(&g->bin_file_output_path) != 0); soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); } @@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) { } lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); if (lj->link_in_crt) { const char *crt1o; @@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) { } lj->args.append("--allow-undefined"); lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); // .o files for (size_t i = 0; i < g->link_objects.length; i += 1) { @@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append("-DLL"); } - lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); + lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path)))); if (g->libc_link_lib != nullptr && g->libc != nullptr) { lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); @@ -2501,7 +2501,7 @@ static void construct_linker_job_macho(LinkJob *lj) { //lj->args.append("-install_name"); //lj->args.append(buf_ptr(dylib_install_name)); - assert(buf_len(&g->output_file_path) != 0); + assert(buf_len(&g->bin_file_output_path) != 0); } lj->args.append("-arch"); @@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) { } lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); for (size_t i = 0; i < g->rpath_list.length; i += 1) { Buf *rpath = g->rpath_list.at(i); add_rpath(lj, rpath); } if (is_dyn_lib) { - add_rpath(lj, &g->output_file_path); + add_rpath(lj, &g->bin_file_output_path); } if (is_dyn_lib) { @@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) { progress_name, strlen(progress_name), 0)); } if (g->verbose_link) { - fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path)); + fprintf(stderr, "ar rcs %s", buf_ptr(&g->bin_file_output_path)); for (size_t i = 0; i < file_names.length; i += 1) { fprintf(stderr, " %s", file_names.at(i)); } fprintf(stderr, "\n"); } - if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) { - fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path)); + if (ZigLLVMWriteArchive(buf_ptr(&g->bin_file_output_path), file_names.items, file_names.length, os_type)) { + fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path)); exit(1); } return; diff --git a/src/main.cpp b/src/main.cpp index c8c2f1b4a2..5117348e34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -fno-stack-check disable stack probing in safe builds\n" " -fsanitize-c enable C undefined behavior detection in unsafe builds\n" " -fno-sanitize-c disable C undefined behavior detection in safe builds\n" - " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" + " --emit [asm|bin|llvm-ir] (deprecated) emit a specific file format as compilation output\n" " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" " -ftime-report print timing diagnostics\n" " -fstack-report print stack size diagnostics\n" -#ifdef ZIG_ENABLE_MEM_PROFILE " -fmem-report print memory usage diagnostics\n" -#endif " -fdump-analysis write analysis.json file with type information\n" " -femit-docs create a docs/ dir with html documentation\n" - " -fno-emit-bin skip emitting machine code\n" + " -fno-emit-docs do not produce docs/ dir with html documentation\n" + " -femit-bin (default) output machine code\n" + " -fno-emit-bin do not output machine code\n" + " -femit-asm output .s (assembly code)\n" + " -fno-emit-asm (default) do not output .s (assembly code)\n" + " -femit-llvm-ir produce a .ll file with LLVM IR\n" + " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" @@ -423,7 +427,7 @@ static int main0(int argc, char **argv) { bool stack_report = false; bool enable_dump_analysis = false; bool enable_doc_generation = false; - bool disable_bin_generation = false; + bool emit_bin = true; bool emit_asm = false; bool emit_llvm_ir = false; const char *cache_dir = nullptr; @@ -553,7 +557,7 @@ static int main0(int argc, char **argv) { } Termination term; - args.items[0] = buf_ptr(&g->output_file_path); + args.items[0] = buf_ptr(&g->bin_file_output_path); os_spawn_process(args, &term); if (term.how != TerminationIdClean || term.code != 0) { fprintf(stderr, "\nBuild failed. The following command failed:\n"); @@ -632,8 +636,6 @@ static int main0(int argc, char **argv) { enable_dump_analysis = true; } else if (strcmp(arg, "-femit-docs") == 0) { enable_doc_generation = true; - } else if (strcmp(arg, "-fno-emit-bin") == 0) { - disable_bin_generation = true; } else if (strcmp(arg, "--enable-valgrind") == 0) { valgrind_support = ValgrindSupportEnabled; } else if (strcmp(arg, "--disable-valgrind") == 0) { @@ -703,9 +705,9 @@ static int main0(int argc, char **argv) { } else if (strcmp(arg, "--test-evented-io") == 0) { test_evented_io = true; } else if (strcmp(arg, "-femit-bin") == 0) { - disable_bin_generation = false; + emit_bin = true; } else if (strcmp(arg, "-fno-emit-bin") == 0) { - disable_bin_generation = true; + emit_bin = false; } else if (strcmp(arg, "-femit-asm") == 0) { emit_asm = true; } else if (strcmp(arg, "-fno-emit-asm") == 0) { @@ -746,12 +748,12 @@ static int main0(int argc, char **argv) { } else if (strcmp(arg, "--emit") == 0) { if (strcmp(argv[i], "asm") == 0) { emit_asm = true; - disable_bin_generation = true; + emit_bin = false; } else if (strcmp(argv[i], "bin") == 0) { - disable_bin_generation = false; + emit_bin = true; } else if (strcmp(argv[i], "llvm-ir") == 0) { emit_llvm_ir = true; - disable_bin_generation = true; + emit_bin = false; } else { fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); return print_error_usage(arg0); @@ -1113,8 +1115,8 @@ static int main0(int argc, char **argv) { { fprintf(stderr, "Expected source file argument.\n"); return print_error_usage(arg0); - } else if (cmd == CmdRun && disable_bin_generation) { - fprintf(stderr, "Cannot run non-executable file.\n"); + } else if (cmd == CmdRun && !emit_bin) { + fprintf(stderr, "Cannot run without emitting a binary file.\n"); return print_error_usage(arg0); } @@ -1191,7 +1193,10 @@ static int main0(int argc, char **argv) { g->enable_stack_report = stack_report; g->enable_dump_analysis = enable_dump_analysis; g->enable_doc_generation = enable_doc_generation; - g->disable_bin_generation = disable_bin_generation; + g->emit_bin = emit_bin; + g->emit_asm = emit_asm; + g->emit_llvm_ir = emit_llvm_ir; + codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); g->want_single_threaded = want_single_threaded; @@ -1277,9 +1282,6 @@ static int main0(int argc, char **argv) { if (cmd == CmdBuild || cmd == CmdRun) { - codegen_set_emit_asm(g, emit_asm); - codegen_set_emit_llvm_ir(g, emit_llvm_ir); - g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun); codegen_build_and_link(g); if (root_progress_node != nullptr) { @@ -1297,7 +1299,7 @@ static int main0(int argc, char **argv) { mem::print_report(); #endif - const char *exec_path = buf_ptr(&g->output_file_path); + const char *exec_path = buf_ptr(&g->bin_file_output_path); ZigList args = {0}; args.append(exec_path); @@ -1317,21 +1319,21 @@ static int main0(int argc, char **argv) { } else if (cmd == CmdBuild) { if (g->enable_cache) { #if defined(ZIG_OS_WINDOWS) - buf_replace(&g->output_file_path, '/', '\\'); + buf_replace(&g->bin_file_output_path, '/', '\\'); #endif if (final_output_dir_step != nullptr) { Buf *dest_basename = buf_alloc(); - os_path_split(&g->output_file_path, nullptr, dest_basename); + os_path_split(&g->bin_file_output_path, nullptr, dest_basename); Buf *dest_path = buf_alloc(); os_path_join(final_output_dir_step, dest_basename, dest_path); - if ((err = os_update_file(&g->output_file_path, dest_path))) { - fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path), + if ((err = os_update_file(&g->bin_file_output_path, dest_path))) { + fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path), buf_ptr(dest_path), err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); } } else { - if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) + if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0) return main_exit(root_progress_node, EXIT_FAILURE); } } @@ -1346,9 +1348,6 @@ static int main0(int argc, char **argv) { codegen_print_timing_report(g, stderr); return main_exit(root_progress_node, EXIT_SUCCESS); } else if (cmd == CmdTest) { - codegen_set_emit_asm(g, emit_asm); - codegen_set_emit_llvm_ir(g, emit_llvm_ir); - ZigTarget native; get_native_target(&native); @@ -1367,17 +1366,17 @@ static int main0(int argc, char **argv) { zig_print_stack_report(g, stdout); } - if (g->disable_bin_generation) { + if (!g->emit_bin) { fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n"); return main_exit(root_progress_node, EXIT_SUCCESS); } - Buf *test_exe_path_unresolved = &g->output_file_path; + Buf *test_exe_path_unresolved = &g->bin_file_output_path; Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); - if (disable_bin_generation) { - fprintf(stderr, "Created %s but skipping execution because it is non executable.\n", + if (!g->emit_bin) { + fprintf(stderr, "Created %s but skipping execution because no binary generated.\n", buf_ptr(test_exe_path)); return main_exit(root_progress_node, EXIT_SUCCESS); } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 614d31dc5a..64706500d5 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { } bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, - bool is_small, bool time_report) + char **error_message, bool is_debug, + bool is_small, bool time_report, + const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename) { TimePassesIsEnabled = time_report; - std::error_code EC; - raw_fd_ostream dest(filename, EC, sys::fs::F_None); - if (EC) { - *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); - return true; + raw_fd_ostream *dest_asm = nullptr; + raw_fd_ostream *dest_bin = nullptr; + + if (asm_filename) { + std::error_code EC; + dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); + if (EC) { + *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); + return true; + } } + if (bin_filename) { + std::error_code EC; + dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); + if (EC) { + *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); + return true; + } + } + TargetMachine* target_machine = reinterpret_cast(targ_machine_ref); target_machine->setO0WantsFastISel(true); @@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM } PMBuilder->populateFunctionPassManager(FPM); - // Set up the per-module pass manager. - legacy::PassManager MPM; - MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); - PMBuilder->populateModulePassManager(MPM); + { + // Set up the per-module pass manager. + legacy::PassManager MPM; + MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); + PMBuilder->populateModulePassManager(MPM); - // Set output pass. - TargetMachine::CodeGenFileType ft; - if (output_type != ZigLLVM_EmitLLVMIr) { - switch (output_type) { - case ZigLLVM_EmitAssembly: - ft = TargetMachine::CGFT_AssemblyFile; - break; - case ZigLLVM_EmitBinary: - ft = TargetMachine::CGFT_ObjectFile; - break; - default: - abort(); + // Set output passes. + if (dest_bin) { + if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, TargetMachine::CGFT_ObjectFile)) { + *error_message = strdup("TargetMachine can't emit an object file"); + return true; + } + } + if (dest_asm) { + if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, TargetMachine::CGFT_AssemblyFile)) { + *error_message = strdup("TargetMachine can't emit an assembly file"); + return true; + } } - if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) { - *error_message = strdup("TargetMachine can't emit a file of this type"); - return true; + // run per function optimization passes + FPM.doInitialization(); + for (Function &F : *module) + if (!F.isDeclaration()) + FPM.run(F); + FPM.doFinalization(); + + MPM.run(*module); + + if (llvm_ir_filename) { + if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { + return true; + } } - } - // run per function optimization passes - FPM.doInitialization(); - for (Function &F : *module) - if (!F.isDeclaration()) - FPM.run(F); - FPM.doFinalization(); - - MPM.run(*module); - - if (output_type == ZigLLVM_EmitLLVMIr) { - if (LLVMPrintModuleToFile(module_ref, filename, error_message)) { - return true; + if (time_report) { + TimerGroup::printAll(errs()); } + + // MPM goes out of scope and writes to the out streams } - if (time_report) { - TimerGroup::printAll(errs()); - } + delete dest_asm; + delete dest_bin; + return false; } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index ba9816b4f8..95751cd08a 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); -// We use a custom enum here since LLVM does not expose LLVMIr as an emit -// output through the same mechanism as assembly/binary. -enum ZigLLVM_EmitOutputType { - ZigLLVM_EmitAssembly, - ZigLLVM_EmitBinary, - ZigLLVM_EmitLLVMIr, -}; - ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, - bool is_small, bool time_report); + char **error_message, bool is_debug, + bool is_small, bool time_report, + const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename); ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, From 63383a8af8bf45b2de78967a2fe8773a5639d36b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 01:24:19 -0500 Subject: [PATCH 052/109] consistent capitalization of error message --- src/parser.cpp | 2 +- test/compile_errors.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 275fa90167..3a3e13f1d8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -690,7 +690,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B AstNode *res = fn_proto; if (body != nullptr) { if (fn_proto->data.fn_proto.is_extern) { - ast_error(pc, first, "Extern functions have no body"); + ast_error(pc, first, "extern functions have no body"); } res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); res->data.fn_def.fn_proto = fn_proto; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index c5f5b6f9da..9f2b3716b0 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -17,7 +17,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return a + b; \\} , &[_][]const u8{ - "tmp.zig:1:1: error: Extern functions have no body", + "tmp.zig:1:1: error: extern functions have no body", }); cases.addTest("duplicate field in anonymous struct literal", From c664692bdd62765ab444a79a8704d2161c1809f1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 01:24:34 -0500 Subject: [PATCH 053/109] make the CLI support depending on system headers and libraries (include and lib search paths) The detection of native system paths is self-hosted. closes #2041 --- lib/std/build.zig | 123 ------------------------------ lib/std/zig.zig | 1 + lib/std/zig/system.zig | 152 +++++++++++++++++++++++++++++++++++++ src-self-hosted/stage2.zig | 38 ++++++++++ src/main.cpp | 28 ++++++- src/stage2.cpp | 16 ++++ src/stage2.h | 16 ++++ 7 files changed, 250 insertions(+), 124 deletions(-) create mode 100644 lib/std/zig/system.zig diff --git a/lib/std/build.zig b/lib/std/build.zig index 5d13a9923a..f6e8474701 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -27,9 +27,6 @@ pub const Builder = struct { install_tls: TopLevelStep, uninstall_tls: TopLevelStep, allocator: *Allocator, - native_system_lib_paths: ArrayList([]const u8), - native_system_include_dirs: ArrayList([]const u8), - native_system_rpaths: ArrayList([]const u8), user_input_options: UserInputOptionsMap, available_options_map: AvailableOptionsMap, available_options_list: ArrayList(AvailableOption), @@ -139,9 +136,6 @@ pub const Builder = struct { .verbose_cimport = false, .invalid_user_input = false, .allocator = allocator, - .native_system_lib_paths = ArrayList([]const u8).init(allocator), - .native_system_include_dirs = ArrayList([]const u8).init(allocator), - .native_system_rpaths = ArrayList([]const u8).init(allocator), .user_input_options = UserInputOptionsMap.init(allocator), .available_options_map = AvailableOptionsMap.init(allocator), .available_options_list = ArrayList(AvailableOption).init(allocator), @@ -172,15 +166,11 @@ pub const Builder = struct { }; try self.top_level_steps.append(&self.install_tls); try self.top_level_steps.append(&self.uninstall_tls); - self.detectNativeSystemPaths(); self.default_step = &self.install_tls.step; return self; } pub fn destroy(self: *Builder) void { - self.native_system_lib_paths.deinit(); - self.native_system_include_dirs.deinit(); - self.native_system_rpaths.deinit(); self.env_map.deinit(); self.top_level_steps.deinit(); self.allocator.destroy(self); @@ -347,18 +337,6 @@ pub const Builder = struct { }; } - pub fn addNativeSystemIncludeDir(self: *Builder, path: []const u8) void { - self.native_system_include_dirs.append(path) catch unreachable; - } - - pub fn addNativeSystemRPath(self: *Builder, path: []const u8) void { - self.native_system_rpaths.append(path) catch unreachable; - } - - pub fn addNativeSystemLibPath(self: *Builder, path: []const u8) void { - self.native_system_lib_paths.append(path) catch unreachable; - } - pub fn make(self: *Builder, step_names: []const []const u8) !void { try self.makePath(self.cache_root); @@ -433,87 +411,6 @@ pub const Builder = struct { return error.InvalidStepName; } - fn detectNativeSystemPaths(self: *Builder) void { - var is_nixos = false; - if (process.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { - is_nixos = true; - var it = mem.tokenize(nix_cflags_compile, " "); - while (true) { - const word = it.next() orelse break; - if (mem.eql(u8, word, "-isystem")) { - const include_path = it.next() orelse { - warn("Expected argument after -isystem in NIX_CFLAGS_COMPILE\n", .{}); - break; - }; - self.addNativeSystemIncludeDir(include_path); - } else { - warn("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}\n", .{word}); - break; - } - } - } else |err| { - assert(err == error.EnvironmentVariableNotFound); - } - if (process.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| { - is_nixos = true; - var it = mem.tokenize(nix_ldflags, " "); - while (true) { - const word = it.next() orelse break; - if (mem.eql(u8, word, "-rpath")) { - const rpath = it.next() orelse { - warn("Expected argument after -rpath in NIX_LDFLAGS\n", .{}); - break; - }; - self.addNativeSystemRPath(rpath); - } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') { - const lib_path = word[2..]; - self.addNativeSystemLibPath(lib_path); - } else { - warn("Unrecognized C flag from NIX_LDFLAGS: {}\n", .{word}); - break; - } - } - } else |err| { - assert(err == error.EnvironmentVariableNotFound); - } - if (is_nixos) return; - switch (builtin.os) { - .windows => {}, - else => { - const triple = (Target{ - .Cross = CrossTarget{ - .arch = builtin.arch, - .os = builtin.os, - .abi = builtin.abi, - .cpu_features = builtin.cpu_features, - }, - }).linuxTriple(self.allocator); - - // TODO: $ ld --verbose | grep SEARCH_DIR - // the output contains some paths that end with lib64, maybe include them too? - // also, what is the best possible order of things? - - self.addNativeSystemIncludeDir("/usr/local/include"); - self.addNativeSystemLibPath("/usr/local/lib"); - self.addNativeSystemLibPath("/usr/local/lib64"); - - self.addNativeSystemIncludeDir(self.fmt("/usr/include/{}", .{triple})); - self.addNativeSystemLibPath(self.fmt("/usr/lib/{}", .{triple})); - - self.addNativeSystemIncludeDir("/usr/include"); - self.addNativeSystemLibPath("/lib"); - self.addNativeSystemLibPath("/lib64"); - self.addNativeSystemLibPath("/usr/lib"); - self.addNativeSystemLibPath("/usr/lib64"); - - // example: on a 64-bit debian-based linux distro, with zlib installed from apt: - // zlib.h is in /usr/include (added above) - // libz.so.1 is in /lib/x86_64-linux-gnu (added here) - self.addNativeSystemLibPath(self.fmt("/lib/{}", .{triple})); - }, - } - } - pub fn option(self: *Builder, comptime T: type, name: []const u8, description: []const u8) ?T { const type_id = comptime typeToEnum(T); const available_option = AvailableOption{ @@ -1185,7 +1082,6 @@ pub const LibExeObjStep = struct { include_dirs: ArrayList(IncludeDir), c_macros: ArrayList([]const u8), output_dir: ?[]const u8, - need_system_paths: bool, is_linking_libc: bool = false, vcpkg_bin_path: ?[]const u8 = null, @@ -1323,7 +1219,6 @@ pub const LibExeObjStep = struct { .disable_stack_probing = false, .disable_sanitize_c = false, .output_dir = null, - .need_system_paths = false, .single_threaded = false, .installed_path = null, .install_step = null, @@ -1499,7 +1394,6 @@ pub const LibExeObjStep = struct { /// Prefer to use `linkSystemLibrary` instead. pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void { self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable; - self.need_system_paths = true; } /// This links against a system library, exclusively using pkg-config to find the library. @@ -2159,23 +2053,6 @@ pub const LibExeObjStep = struct { try zig_args.append(lib_path); } - if (self.need_system_paths and self.target == Target.Native) { - for (builder.native_system_include_dirs.toSliceConst()) |include_path| { - zig_args.append("-isystem") catch unreachable; - zig_args.append(builder.pathFromRoot(include_path)) catch unreachable; - } - - for (builder.native_system_rpaths.toSliceConst()) |rpath| { - zig_args.append("-rpath") catch unreachable; - zig_args.append(rpath) catch unreachable; - } - - for (builder.native_system_lib_paths.toSliceConst()) |lib_path| { - zig_args.append("--library-path") catch unreachable; - zig_args.append(lib_path) catch unreachable; - } - } - for (self.c_macros.toSliceConst()) |c_macro| { try zig_args.append("-D"); try zig_args.append(c_macro); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 494c9d0057..d76ed9dfd2 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -5,6 +5,7 @@ pub const parse = @import("zig/parse.zig").parse; pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStringLiteral; pub const render = @import("zig/render.zig").render; pub const ast = @import("zig/ast.zig"); +pub const system = @import("zig/system.zig"); test "std.zig tests" { _ = @import("zig/ast.zig"); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig new file mode 100644 index 0000000000..74a9ffdc70 --- /dev/null +++ b/lib/std/zig/system.zig @@ -0,0 +1,152 @@ +const std = @import("../std.zig"); +const mem = std.mem; +const Allocator = std.mem.Allocator; +const ArrayList = std.ArrayList; +const assert = std.debug.assert; +const process = std.process; + +pub const NativePaths = struct { + include_dirs: ArrayList([:0]u8), + lib_dirs: ArrayList([:0]u8), + rpaths: ArrayList([:0]u8), + warnings: ArrayList([:0]u8), + + pub fn detect(allocator: *Allocator) !NativePaths { + var self: NativePaths = .{ + .include_dirs = ArrayList([:0]u8).init(allocator), + .lib_dirs = ArrayList([:0]u8).init(allocator), + .rpaths = ArrayList([:0]u8).init(allocator), + .warnings = ArrayList([:0]u8).init(allocator), + }; + errdefer self.deinit(); + + var is_nix = false; + if (std.os.getenvZ("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { + is_nix = true; + var it = mem.tokenize(nix_cflags_compile, " "); + while (true) { + const word = it.next() orelse break; + if (mem.eql(u8, word, "-isystem")) { + const include_path = it.next() orelse { + try self.addWarning("Expected argument after -isystem in NIX_CFLAGS_COMPILE"); + break; + }; + try self.addIncludeDir(include_path); + } else { + try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}", .{word}); + break; + } + } + } + if (std.os.getenvZ("NIX_LDFLAGS")) |nix_ldflags| { + is_nix = true; + var it = mem.tokenize(nix_ldflags, " "); + while (true) { + const word = it.next() orelse break; + if (mem.eql(u8, word, "-rpath")) { + const rpath = it.next() orelse { + try self.addWarning("Expected argument after -rpath in NIX_LDFLAGS"); + break; + }; + try self.addRPath(rpath); + } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') { + const lib_path = word[2..]; + try self.addLibDir(lib_path); + } else { + try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {}", .{word}); + break; + } + } + } + if (is_nix) { + return self; + } + + switch (std.builtin.os) { + .windows => {}, + else => { + const triple = try std.Target.current.linuxTriple(allocator); + + // TODO: $ ld --verbose | grep SEARCH_DIR + // the output contains some paths that end with lib64, maybe include them too? + // TODO: what is the best possible order of things? + // TODO: some of these are suspect and should only be added on some systems. audit needed. + + try self.addIncludeDir("/usr/local/include"); + try self.addLibDir("/usr/local/lib"); + try self.addLibDir("/usr/local/lib64"); + + try self.addIncludeDirFmt("/usr/include/{}", .{triple}); + try self.addLibDirFmt("/usr/lib/{}", .{triple}); + + try self.addIncludeDir("/usr/include"); + try self.addLibDir("/lib"); + try self.addLibDir("/lib64"); + try self.addLibDir("/usr/lib"); + try self.addLibDir("/usr/lib64"); + + // example: on a 64-bit debian-based linux distro, with zlib installed from apt: + // zlib.h is in /usr/include (added above) + // libz.so.1 is in /lib/x86_64-linux-gnu (added here) + try self.addLibDirFmt("/lib/{}", .{triple}); + }, + } + + return self; + } + + pub fn deinit(self: *NativePaths) void { + deinitArray(&self.include_dirs); + deinitArray(&self.lib_dirs); + deinitArray(&self.rpaths); + deinitArray(&self.warnings); + self.* = undefined; + } + + fn deinitArray(array: *ArrayList([:0]u8)) void { + for (array.toSlice()) |item| { + array.allocator.free(item); + } + array.deinit(); + } + + pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void { + return self.appendArray(&self.include_dirs, s); + } + + pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { + const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args); + errdefer self.include_dirs.allocator.free(item); + try self.include_dirs.append(item); + } + + pub fn addLibDir(self: *NativePaths, s: []const u8) !void { + return self.appendArray(&self.lib_dirs, s); + } + + pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { + const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args); + errdefer self.lib_dirs.allocator.free(item); + try self.lib_dirs.append(item); + } + + pub fn addWarning(self: *NativePaths, s: []const u8) !void { + return self.appendArray(&self.warnings, s); + } + + pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { + const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args); + errdefer self.warnings.allocator.free(item); + try self.warnings.append(item); + } + + pub fn addRPath(self: *NativePaths, s: []const u8) !void { + return self.appendArray(&self.rpaths, s); + } + + fn appendArray(self: *NativePaths, array: *ArrayList([:0]u8), s: []const u8) !void { + const item = try std.mem.dupeZ(array.allocator, u8, s); + errdefer array.allocator.free(item); + try array.append(item); + } +}; diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 37816464a1..b278bb9f75 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -1116,3 +1116,41 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: fn enumInt(comptime Enum: type, int: c_int) Enum { return @intToEnum(Enum, @intCast(@TagType(Enum), int)); } + +// ABI warning +const Stage2NativePaths = extern struct { + include_dirs_ptr: [*][*:0]u8, + include_dirs_len: usize, + lib_dirs_ptr: [*][*:0]u8, + lib_dirs_len: usize, + rpaths_ptr: [*][*:0]u8, + rpaths_len: usize, + warnings_ptr: [*][*:0]u8, + warnings_len: usize, +}; +// ABI warning +export fn stage2_detect_native_paths(stage1_paths: *Stage2NativePaths) Error { + stage2DetectNativePaths(stage1_paths) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + }; + return .None; +} + +fn stage2DetectNativePaths(stage1_paths: *Stage2NativePaths) !void { + var paths = try std.zig.system.NativePaths.detect(std.heap.c_allocator); + errdefer paths.deinit(); + + try convertSlice(paths.include_dirs.toSlice(), &stage1_paths.include_dirs_ptr, &stage1_paths.include_dirs_len); + try convertSlice(paths.lib_dirs.toSlice(), &stage1_paths.lib_dirs_ptr, &stage1_paths.lib_dirs_len); + try convertSlice(paths.rpaths.toSlice(), &stage1_paths.rpaths_ptr, &stage1_paths.rpaths_len); + try convertSlice(paths.warnings.toSlice(), &stage1_paths.warnings_ptr, &stage1_paths.warnings_len); +} + +fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void { + len.* = slice.len; + const new_slice = try std.heap.c_allocator.alloc([*:0]u8, slice.len); + for (slice) |item, i| { + new_slice[i] = item.ptr; + } + ptr.* = new_slice.ptr; +} diff --git a/src/main.cpp b/src/main.cpp index 5117348e34..d7f5e5b7b0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1120,6 +1120,33 @@ static int main0(int argc, char **argv) { return print_error_usage(arg0); } + if (target.is_native && link_libs.length != 0) { + Error err; + Stage2NativePaths paths; + if ((err = stage2_detect_native_paths(&paths))) { + fprintf(stderr, "unable to detect native system paths: %s\n", err_str(err)); + exit(1); + } + for (size_t i = 0; i < paths.warnings_len; i += 1) { + const char *warning = paths.warnings_ptr[i]; + fprintf(stderr, "warning: %s\n", warning); + } + for (size_t i = 0; i < paths.include_dirs_len; i += 1) { + const char *include_dir = paths.include_dirs_ptr[i]; + clang_argv.append("-I"); + clang_argv.append(include_dir); + } + for (size_t i = 0; i < paths.lib_dirs_len; i += 1) { + const char *lib_dir = paths.lib_dirs_ptr[i]; + lib_dirs.append(lib_dir); + } + for (size_t i = 0; i < paths.rpaths_len; i += 1) { + const char *rpath = paths.rpaths_ptr[i]; + rpath_list.append(rpath); + } + } + + assert(cmd != CmdBuild || out_type != OutTypeUnknown); bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC); @@ -1226,7 +1253,6 @@ static int main0(int argc, char **argv) { g->function_sections = function_sections; g->code_model = code_model; - for (size_t i = 0; i < lib_dirs.length; i += 1) { codegen_add_lib_dir(g, lib_dirs.at(i)); } diff --git a/src/stage2.cpp b/src/stage2.cpp index 7f68321752..c3abe54d77 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -175,3 +175,19 @@ enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **o const char *msg = "stage0 called stage2_detect_dynamic_linker"; stage2_panic(msg, strlen(msg)); } + +enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) { + native_paths->include_dirs_ptr = nullptr; + native_paths->include_dirs_len = 0; + + native_paths->lib_dirs_ptr = nullptr; + native_paths->lib_dirs_len = 0; + + native_paths->rpaths_ptr = nullptr; + native_paths->rpaths_len = 0; + + native_paths->warnings_ptr = nullptr; + native_paths->warnings_len = 0; + + return ErrorNone; +} diff --git a/src/stage2.h b/src/stage2.h index b6e4cebbaf..302cffafc6 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -312,4 +312,20 @@ struct ZigTarget { ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len); + + +// ABI warning +struct Stage2NativePaths { + const char **include_dirs_ptr; + size_t include_dirs_len; + const char **lib_dirs_ptr; + size_t lib_dirs_len; + const char **rpaths_ptr; + size_t rpaths_len; + const char **warnings_ptr; + size_t warnings_len; +}; +// ABI warning +ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths); + #endif From 5a2060482042129e64af2b6281f8e4bbf1f2fe6e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 30 Dec 2019 22:35:11 +1100 Subject: [PATCH 054/109] std: add json.stringify to encode arbitrary values to JSON --- lib/std/json.zig | 266 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) diff --git a/lib/std/json.zig b/lib/std/json.zig index b04861eaae..37ee20f2a2 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1686,3 +1686,269 @@ test "string copy option" { } testing.expect(found_nocopy); } + +pub const StringifyOptions = struct { + // TODO: indentation options? + // TODO: make escaping '/' in strings optional? + // TODO: allow picking if []u8 is string or array? +}; + +pub fn stringify( + value: var, + options: StringifyOptions, + context: var, + comptime Errors: type, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, +) Errors!void { + const T = @TypeOf(value); + switch (@typeInfo(T)) { + .Float, .ComptimeFloat => { + return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output); + }, + .Int, .ComptimeInt => { + return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output); + }, + .Bool => { + return output(context, if (value) "true" else "false"); + }, + .Optional => { + if (value) |payload| { + return try stringify(payload, options, context, Errors, output); + } else { + return output(context, "null"); + } + }, + .Enum => { + if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { + return value.jsonStringify(options, context, Errors, output); + } + + @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'"); + }, + .Union => { + if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { + return value.jsonStringify(options, context, Errors, output); + } + + const info = @typeInfo(T).Union; + if (info.tag_type) |UnionTagType| { + inline for (info.fields) |u_field| { + if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { + return try stringify(@field(value, u_field.name), options, context, Errors, output); + } + } + } else { + @compileError("Unable to stringify untagged union '" ++ @typeName(T) ++ "'"); + } + }, + .Struct => |S| { + if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { + return value.jsonStringify(options, context, Errors, output); + } + + try output(context, "{"); + comptime var field_output = false; + inline for (S.fields) |Field, field_i| { + // don't include void fields + if (Field.field_type == void) continue; + + if (!field_output) { + field_output = true; + } else { + try output(context, ","); + } + + try stringify(Field.name, options, context, Errors, output); + try output(context, ":"); + try stringify(@field(value, Field.name), options, context, Errors, output); + } + try output(context, "}"); + return; + }, + .Pointer => |ptr_info| switch (ptr_info.size) { + .One => { + // TODO: avoid loops? + return try stringify(value.*, options, context, Errors, output); + }, + // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) + .Slice => { + if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) { + try output(context, "\""); + var i: usize = 0; + while (i < value.len) : (i += 1) { + switch (value[i]) { + // normal ascii characters + 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]), + // control characters with short escapes + '\\' => try output(context, "\\\\"), + '\"' => try output(context, "\\\""), + '/' => try output(context, "\\/"), + 0x8 => try output(context, "\\b"), + 0xC => try output(context, "\\f"), + '\n' => try output(context, "\\n"), + '\r' => try output(context, "\\r"), + '\t' => try output(context, "\\t"), + else => { + const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; + const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; + if (codepoint <= 0xFFFF) { + // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), + // then it may be represented as a six-character sequence: a reverse solidus, followed + // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. + try output(context, "\\u"); + try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); + } else { + // To escape an extended character that is not in the Basic Multilingual Plane, + // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair. + const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800; + const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00; + try output(context, "\\u"); + try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); + try output(context, "\\u"); + try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); + } + i += ulen - 1; + }, + } + } + try output(context, "\""); + return; + } + + try output(context, "["); + for (value) |x, i| { + if (i != 0) { + try output(context, ","); + } + try stringify(x, options, context, Errors, output); + } + try output(context, "]"); + return; + }, + else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), + }, + .Array => |info| { + return try stringify(value[0..], options, context, Errors, output); + }, + else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), + } + unreachable; +} + +fn teststringify(expected: []const u8, value: var) !void { + const TestStringifyContext = struct { + expected_remaining: []const u8, + fn testStringifyWrite(context: *@This(), bytes: []const u8) !void { + if (context.expected_remaining.len < bytes.len) { + std.debug.warn( + \\====== expected this output: ========= + \\{} + \\======== instead found this: ========= + \\{} + \\====================================== + , .{ + context.expected_remaining, + bytes, + }); + return error.TooMuchData; + } + if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) { + std.debug.warn( + \\====== expected this output: ========= + \\{} + \\======== instead found this: ========= + \\{} + \\====================================== + , .{ + context.expected_remaining[0..bytes.len], + bytes, + }); + return error.DifferentData; + } + context.expected_remaining = context.expected_remaining[bytes.len..]; + } + }; + var buf: [100]u8 = undefined; + var context = TestStringifyContext{ .expected_remaining = expected }; + try stringify(value, StringifyOptions{}, &context, error{ + TooMuchData, + DifferentData, + }, TestStringifyContext.testStringifyWrite); + if (context.expected_remaining.len > 0) return error.NotEnoughData; +} + +test "stringify basic types" { + try teststringify("false", false); + try teststringify("true", true); + try teststringify("null", @as(?u8, null)); + try teststringify("null", @as(?*u32, null)); + try teststringify("42", 42); + try teststringify("4.2e+01", 42.0); + try teststringify("42", @as(u8, 42)); + try teststringify("42", @as(u128, 42)); + try teststringify("4.2e+01", @as(f32, 42)); + try teststringify("4.2e+01", @as(f64, 42)); +} + +test "stringify string" { + try teststringify("\"hello\"", "hello"); + try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r"); + try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}"); + try teststringify("\"with unicode\\u0080\"", "with unicode\u{80}"); + try teststringify("\"with unicode\\u00ff\"", "with unicode\u{FF}"); + try teststringify("\"with unicode\\u0100\"", "with unicode\u{100}"); + try teststringify("\"with unicode\\u0800\"", "with unicode\u{800}"); + try teststringify("\"with unicode\\u8000\"", "with unicode\u{8000}"); + try teststringify("\"with unicode\\ud799\"", "with unicode\u{D799}"); + try teststringify("\"with unicode\\ud800\\udc00\"", "with unicode\u{10000}"); + try teststringify("\"with unicode\\udbff\\udfff\"", "with unicode\u{10FFFF}"); +} + +test "stringify tagged unions" { + try teststringify("42", union(enum) { + Foo: u32, + Bar: bool, + }{ .Foo = 42 }); +} + +test "stringify struct" { + try teststringify("{\"foo\":42}", struct { + foo: u32, + }{ .foo = 42 }); +} + +test "stringify struct with void field" { + try teststringify("{\"foo\":42}", struct { + foo: u32, + bar: void = {}, + }{ .foo = 42 }); +} + +test "stringify array of structs" { + const MyStruct = struct { + foo: u32, + }; + try teststringify("[{\"foo\":42},{\"foo\":100},{\"foo\":1000}]", [_]MyStruct{ + MyStruct{ .foo = 42 }, + MyStruct{ .foo = 100 }, + MyStruct{ .foo = 1000 }, + }); +} + +test "stringify struct with custom stringifier" { + try teststringify("[\"something special\",42]", struct { + foo: u32, + const Self = @This(); + pub fn jsonStringify( + value: Self, + options: StringifyOptions, + context: var, + comptime Errors: type, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, + ) !void { + try output(context, "[\"something special\","); + try stringify(42, options, context, Errors, output); + try output(context, "]"); + } + }{ .foo = 42 }); +} From d989396a3473836a9e2e269b2be9675574ead389 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Sun, 29 Dec 2019 17:46:32 +1100 Subject: [PATCH 055/109] std: add json.parse to automatically decode json into a struct --- lib/std/json.zig | 552 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) diff --git a/lib/std/json.zig b/lib/std/json.zig index 37ee20f2a2..830f492e74 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -19,6 +19,74 @@ const StringEscapes = union(enum) { }, }; +/// Checks to see if a string matches what it would be as a json-encoded string +/// Assumes that `encoded` is a well-formed json string +fn encodesTo(decoded: []const u8, encoded: []const u8) bool { + var i: usize = 0; + var j: usize = 0; + while (i < decoded.len) { + if (j >= encoded.len) return false; + if (encoded[j] != '\\') { + if (decoded[i] != encoded[j]) return false; + j += 1; + i += 1; + } else { + const escape_type = encoded[j + 1]; + if (escape_type != 'u') { + const t: u8 = switch (escape_type) { + '\\' => '\\', + '/' => '/', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + 'f' => 12, + 'b' => 8, + '"' => '"', + else => unreachable, + }; + if (decoded[i] != t) return false; + j += 2; + i += 1; + } else { + var codepoint = std.fmt.parseInt(u21, encoded[j + 2 .. j + 6], 16) catch unreachable; + j += 6; + if (codepoint >= 0xD800 and codepoint < 0xDC00) { + // surrogate pair + assert(encoded[j] == '\\'); + assert(encoded[j + 1] == 'u'); + const low_surrogate = std.fmt.parseInt(u21, encoded[j + 2 .. j + 6], 16) catch unreachable; + codepoint = 0x10000 + (((codepoint & 0x03ff) << 10) | (low_surrogate & 0x03ff)); + j += 6; + } + var buf: [4]u8 = undefined; + const len = std.unicode.utf8Encode(codepoint, &buf) catch unreachable; + if (i + len > decoded.len) return false; + if (!mem.eql(u8, decoded[i .. i + len], buf[0..len])) return false; + i += len; + } + } + } + assert(i == decoded.len); + assert(j == encoded.len); + return true; +} + +test "encodesTo" { + // same + testing.expectEqual(true, encodesTo("false", "false")); + // totally different + testing.expectEqual(false, encodesTo("false", "true")); + // differnt lengths + testing.expectEqual(false, encodesTo("false", "other")); + // with escape + testing.expectEqual(true, encodesTo("\\", "\\\\")); + testing.expectEqual(true, encodesTo("with\nescape", "with\\nescape")); + // with unicode + testing.expectEqual(true, encodesTo("ą", "\\u0105")); + testing.expectEqual(true, encodesTo("😂", "\\ud83d\\ude02")); + testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02")); +} + /// A single token slice into the parent string. /// /// Use `token.slice()` on the input at the current position to get the current slice. @@ -1201,6 +1269,490 @@ pub const Value = union(enum) { } }; +pub const ParseOptions = struct { + allocator: ?*Allocator = null, + + /// Behaviour when a duplicate field is encountered. + duplicate_field_behavior: enum { + UseFirst, + Error, + UseLast, + } = .Error, +}; + +fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: ParseOptions) !T { + switch (@typeInfo(T)) { + .Bool => { + return switch (token) { + .True => true, + .False => false, + else => error.UnexpectedToken, + }; + }, + .Float, .ComptimeFloat => { + const numberToken = switch (token) { + .Number => |n| n, + else => return error.UnexpectedToken, + }; + return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1)); + }, + .Int, .ComptimeInt => { + const numberToken = switch (token) { + .Number => |n| n, + else => return error.UnexpectedToken, + }; + if (!numberToken.is_integer) return error.UnexpectedToken; + return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10); + }, + .Optional => |optionalInfo| { + if (token == .Null) { + return null; + } else { + return try parseInternal(optionalInfo.child, token, tokens, options); + } + }, + .Enum => |enumInfo| { + switch (token) { + .Number => |numberToken| { + if (!numberToken.is_integer) return error.UnexpectedToken; + const n = try std.fmt.parseInt(enumInfo.tag_type, numberToken.slice(tokens.slice, tokens.i - 1), 10); + return try std.meta.intToEnum(T, n); + }, + .String => |stringToken| { + const source_slice = stringToken.slice(tokens.slice, tokens.i - 1); + switch (stringToken.escapes) { + .None => return std.meta.stringToEnum(T, source_slice) orelse return error.InvalidEnumTag, + .Some => { + inline for (enumInfo.fields) |field| { + if (field.name.len == stringToken.decodedLength() and encodesTo(field.name, source_slice)) { + return @field(T, field.name); + } + } + return error.InvalidEnumTag; + }, + } + }, + else => return error.UnexpectedToken, + } + }, + .Union => |unionInfo| { + if (unionInfo.tag_type) |_| { + // try each of the union fields until we find one that matches + inline for (unionInfo.fields) |u_field| { + if (parseInternal(u_field.field_type, token, tokens, options)) |value| { + return @unionInit(T, u_field.name, value); + } else |err| { + // Bubble up error.OutOfMemory + // Parsing some types won't have OutOfMemory in their + // error-sets, for the condition to be valid, merge it in. + if (@as(@TypeOf(err) || error{OutOfMemory}, err) == error.OutOfMemory) return err; + // otherwise continue through the `inline for` + } + } + return error.NoUnionMembersMatched; + } else { + @compileError("Unable to parse into untagged union '" ++ @typeName(T) ++ "'"); + } + }, + .Struct => |structInfo| { + switch (token) { + .ObjectBegin => {}, + else => return error.UnexpectedToken, + } + var r: T = undefined; + var fields_seen = [_]bool{false} ** structInfo.fields.len; + errdefer { + inline for (structInfo.fields) |field, i| { + if (fields_seen[i]) { + parseFree(field.field_type, @field(r, field.name), options); + } + } + } + + while (true) { + switch ((try tokens.next()) orelse return error.UnexpectedEndOfJson) { + .ObjectEnd => break, + .String => |stringToken| { + const key_source_slice = stringToken.slice(tokens.slice, tokens.i - 1); + var found = false; + inline for (structInfo.fields) |field, i| { + // TODO: using switches here segfault the compiler (#2727?) + if ((stringToken.escapes == .None and mem.eql(u8, field.name, key_source_slice)) or (stringToken.escapes == .Some and (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)))) { + // if (switch (stringToken.escapes) { + // .None => mem.eql(u8, field.name, key_source_slice), + // .Some => (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)), + // }) { + if (fields_seen[i]) { + // switch (options.duplicate_field_behavior) { + // .UseFirst => {}, + // .Error => {}, + // .UseLast => {}, + // } + if (options.duplicate_field_behavior == .UseFirst) { + break; + } else if (options.duplicate_field_behavior == .Error) { + return error.DuplicateJSONField; + } else if (options.duplicate_field_behavior == .UseLast) { + parseFree(field.field_type, @field(r, field.name), options); + } + } + @field(r, field.name) = try parse(field.field_type, tokens, options); + fields_seen[i] = true; + found = true; + break; + } + } + if (!found) return error.UnknownField; + }, + else => return error.UnexpectedToken, + } + } + inline for (structInfo.fields) |field, i| { + if (!fields_seen[i]) { + if (field.default_value) |default| { + @field(r, field.name) = default; + } else { + return error.MissingField; + } + } + } + return r; + }, + .Array => |arrayInfo| { + switch (token) { + .ArrayBegin => { + var r: T = undefined; + var i: usize = 0; + errdefer { + while (true) : (i -= 1) { + parseFree(arrayInfo.child, r[i], options); + if (i == 0) break; + } + } + while (i < r.len) : (i += 1) { + r[i] = try parse(arrayInfo.child, tokens, options); + } + const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson; + switch (tok) { + .ArrayEnd => {}, + else => return error.UnexpectedToken, + } + return r; + }, + .String => |stringToken| { + if (arrayInfo.child != u8) return error.UnexpectedToken; + var r: T = undefined; + const source_slice = stringToken.slice(tokens.slice, tokens.i - 1); + switch (stringToken.escapes) { + .None => mem.copy(u8, &r, source_slice), + .Some => try unescapeString(&r, source_slice), + } + return r; + }, + else => return error.UnexpectedToken, + } + }, + .Pointer => |ptrInfo| { + const allocator = options.allocator orelse return error.AllocatorRequired; + switch (ptrInfo.size) { + .One => { + const r: T = allocator.create(ptrInfo.child); + r.* = try parseInternal(ptrInfo.child, token, tokens, options); + return r; + }, + .Slice => { + switch (token) { + .ArrayBegin => { + var arraylist = std.ArrayList(ptrInfo.child).init(allocator); + errdefer { + while (arraylist.popOrNull()) |v| { + parseFree(ptrInfo.child, v, options); + } + arraylist.deinit(); + } + + while (true) { + const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson; + switch (tok) { + .ArrayEnd => break, + else => {}, + } + + try arraylist.ensureCapacity(arraylist.len + 1); + const v = try parseInternal(ptrInfo.child, tok, tokens, options); + arraylist.appendAssumeCapacity(v); + } + return arraylist.toOwnedSlice(); + }, + .String => |stringToken| { + if (ptrInfo.child != u8) return error.UnexpectedToken; + const source_slice = stringToken.slice(tokens.slice, tokens.i - 1); + switch (stringToken.escapes) { + .None => return mem.dupe(allocator, u8, source_slice), + .Some => |some_escapes| { + const output = try allocator.alloc(u8, stringToken.decodedLength()); + errdefer allocator.free(output); + try unescapeString(output, source_slice); + return output; + }, + } + }, + else => return error.UnexpectedToken, + } + }, + else => @compileError("Unable to parse into type '" ++ @typeName(T) ++ "'"), + } + }, + else => @compileError("Unable to parse into type '" ++ @typeName(T) ++ "'"), + } + unreachable; +} + +pub fn parse(comptime T: type, tokens: *TokenStream, options: ParseOptions) !T { + const token = (try tokens.next()) orelse return error.UnexpectedEndOfJson; + return parseInternal(T, token, tokens, options); +} + +/// Releases resources created by `parse`. +/// Should be called with the same type and `ParseOptions` that were passed to `parse` +pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void { + switch (@typeInfo(T)) { + .Bool, .Float, .ComptimeFloat, .Int, .ComptimeInt, .Enum => {}, + .Optional => { + if (value) |v| { + return parseFree(@TypeOf(v), v, options); + } + }, + .Union => |unionInfo| { + if (unionInfo.tag_type) |UnionTagType| { + inline for (unionInfo.fields) |u_field| { + if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { + parseFree(u_field.field_type, @field(value, u_field.name), options); + break; + } + } + } else { + unreachable; + } + }, + .Struct => |structInfo| { + inline for (structInfo.fields) |field| { + parseFree(field.field_type, @field(value, field.name), options); + } + }, + .Array => |arrayInfo| { + for (value) |v| { + parseFree(arrayInfo.child, v, options); + } + }, + .Pointer => |ptrInfo| { + const allocator = options.allocator orelse unreachable; + switch (ptrInfo.size) { + .One => { + parseFree(ptrInfo.child, value.*, options); + allocator.destroy(v); + }, + .Slice => { + for (value) |v| { + parseFree(ptrInfo.child, v, options); + } + allocator.free(value); + }, + else => unreachable, + } + }, + else => unreachable, + } +} + +test "parse" { + testing.expectEqual(false, try parse(bool, &TokenStream.init("false"), ParseOptions{})); + testing.expectEqual(true, try parse(bool, &TokenStream.init("true"), ParseOptions{})); + testing.expectEqual(@as(u1, 1), try parse(u1, &TokenStream.init("1"), ParseOptions{})); + testing.expectError(error.Overflow, parse(u1, &TokenStream.init("50"), ParseOptions{})); + testing.expectEqual(@as(u64, 42), try parse(u64, &TokenStream.init("42"), ParseOptions{})); + testing.expectEqual(@as(f64, 42), try parse(f64, &TokenStream.init("42.0"), ParseOptions{})); + testing.expectEqual(@as(?bool, null), try parse(?bool, &TokenStream.init("null"), ParseOptions{})); + testing.expectEqual(@as(?bool, true), try parse(?bool, &TokenStream.init("true"), ParseOptions{})); + + testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("\"foo\""), ParseOptions{})); + testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("[102, 111, 111]"), ParseOptions{})); +} + +test "parse into enum" { + const T = extern enum { + Foo = 42, + Bar, + @"with\\escape", + }; + testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("\"Foo\""), ParseOptions{})); + testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("42"), ParseOptions{})); + testing.expectEqual(@as(T, .@"with\\escape"), try parse(T, &TokenStream.init("\"with\\\\escape\""), ParseOptions{})); + testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("5"), ParseOptions{})); + testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("\"Qux\""), ParseOptions{})); +} + +test "parse into that allocates a slice" { + testing.expectError(error.AllocatorRequired, parse([]u8, &TokenStream.init("\"foo\""), ParseOptions{})); + + const options = ParseOptions{ .allocator = testing.allocator }; + { + const r = try parse([]u8, &TokenStream.init("\"foo\""), options); + defer parseFree([]u8, r, options); + testing.expectEqualSlices(u8, "foo", r); + } + { + const r = try parse([]u8, &TokenStream.init("[102, 111, 111]"), options); + defer parseFree([]u8, r, options); + testing.expectEqualSlices(u8, "foo", r); + } + { + const r = try parse([]u8, &TokenStream.init("\"with\\\\escape\""), options); + defer parseFree([]u8, r, options); + testing.expectEqualSlices(u8, "with\\escape", r); + } +} + +test "parse into tagged union" { + { + const T = union(enum) { + int: i32, + float: f64, + string: []const u8, + }; + testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{})); + } + + { // if union matches string member, fails with NoUnionMembersMatched rather than AllocatorRequired + // Note that this behaviour wasn't necessarily by design, but was + // what fell out of the implementation and may result in interesting + // API breakage if changed + const T = union(enum) { + int: i32, + float: f64, + string: []const u8, + }; + testing.expectError(error.NoUnionMembersMatched, parse(T, &TokenStream.init("\"foo\""), ParseOptions{})); + } + + { // failing allocations should be bubbled up instantly without trying next member + var fail_alloc = testing.FailingAllocator.init(testing.allocator, 0); + const options = ParseOptions{ .allocator = &fail_alloc.allocator }; + const T = union(enum) { + // both fields here match the input + string: []const u8, + array: [3]u8, + }; + testing.expectError(error.OutOfMemory, parse(T, &TokenStream.init("[1,2,3]"), options)); + } + + { + // if multiple matches possible, takes first option + const T = union(enum) { + x: u8, + y: u8, + }; + testing.expectEqual(T{ .x = 42 }, try parse(T, &TokenStream.init("42"), ParseOptions{})); + } +} + +test "parseFree descends into tagged union" { + var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1); + const options = ParseOptions{ .allocator = &fail_alloc.allocator }; + const T = union(enum) { + int: i32, + float: f64, + string: []const u8, + }; + // use a string with unicode escape so we know result can't be a reference to global constant + const r = try parse(T, &TokenStream.init("\"with\\u0105unicode\""), options); + testing.expectEqual(@TagType(T).string, @as(@TagType(T), r)); + testing.expectEqualSlices(u8, "withąunicode", r.string); + testing.expectEqual(@as(usize, 0), fail_alloc.deallocations); + parseFree(T, r, options); + testing.expectEqual(@as(usize, 1), fail_alloc.deallocations); +} + +test "parse into struct with no fields" { + const T = struct {}; + testing.expectEqual(T{}, try parse(T, &TokenStream.init("{}"), ParseOptions{})); +} + +test "parse into struct with misc fields" { + @setEvalBranchQuota(10000); + const options = ParseOptions{ .allocator = testing.allocator }; + const T = struct { + int: i64, + float: f64, + @"with\\escape": bool, + @"withąunicode😂": bool, + language: []const u8, + optional: ?bool, + default_field: i32 = 42, + static_array: [3]f64, + dynamic_array: []f64, + + const Bar = struct { + nested: []const u8, + }; + complex: Bar, + + const Baz = struct { + foo: []const u8, + }; + veryComplex: []Baz, + + const Union = union(enum) { + x: u8, + float: f64, + string: []const u8, + }; + a_union: Union, + }; + const r = try parse(T, &TokenStream.init( + \\{ + \\ "int": 420, + \\ "float": 3.14, + \\ "with\\escape": true, + \\ "with\u0105unicode\ud83d\ude02": false, + \\ "language": "zig", + \\ "optional": null, + \\ "static_array": [66.6, 420.420, 69.69], + \\ "dynamic_array": [66.6, 420.420, 69.69], + \\ "complex": { + \\ "nested": "zig" + \\ }, + \\ "veryComplex": [ + \\ { + \\ "foo": "zig" + \\ }, { + \\ "foo": "rocks" + \\ } + \\ ], + \\ "a_union": 100000 + \\} + ), options); + defer parseFree(T, r, options); + testing.expectEqual(@as(i64, 420), r.int); + testing.expectEqual(@as(f64, 3.14), r.float); + testing.expectEqual(true, r.@"with\\escape"); + testing.expectEqual(false, r.@"withąunicode😂"); + testing.expectEqualSlices(u8, "zig", r.language); + testing.expectEqual(@as(?bool, null), r.optional); + testing.expectEqual(@as(i32, 42), r.default_field); + testing.expectEqual(@as(f64, 66.6), r.static_array[0]); + testing.expectEqual(@as(f64, 420.420), r.static_array[1]); + testing.expectEqual(@as(f64, 69.69), r.static_array[2]); + testing.expectEqual(@as(usize, 3), r.dynamic_array.len); + testing.expectEqual(@as(f64, 66.6), r.dynamic_array[0]); + testing.expectEqual(@as(f64, 420.420), r.dynamic_array[1]); + testing.expectEqual(@as(f64, 69.69), r.dynamic_array[2]); + testing.expectEqualSlices(u8, r.complex.nested, "zig"); + testing.expectEqualSlices(u8, "zig", r.veryComplex[0].foo); + testing.expectEqualSlices(u8, "rocks", r.veryComplex[1].foo); + testing.expectEqual(T.Union{ .float = 100000 }, r.a_union); +} + /// A non-stream JSON parser which constructs a tree of Value's. pub const Parser = struct { allocator: *Allocator, From e270db956c6dc45f415e0b02b69db408d4a990b1 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 18 Feb 2020 10:31:02 +1100 Subject: [PATCH 056/109] std: tagged unions are broken on arm64 --- lib/std/json.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/json.zig b/lib/std/json.zig index 830f492e74..bb59b4e0f3 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1657,6 +1657,9 @@ test "parse into tagged union" { } test "parseFree descends into tagged union" { + // tagged unions are broken on arm64: https://github.com/ziglang/zig/issues/4492 + if (std.builtin.arch == .aarch64) return error.SkipZigTest; + var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1); const options = ParseOptions{ .allocator = &fail_alloc.allocator }; const T = union(enum) { From 1483ae37f2dae6a5b9db1f7851cf5dc9a86e57f3 Mon Sep 17 00:00:00 2001 From: Bas Date: Wed, 19 Feb 2020 17:33:35 +0100 Subject: [PATCH 057/109] Add an appendValues method to ArrayList to append a value n times. (#4460) --- lib/std/array_list.zig | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index f212ae8659..d1946be02a 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -188,6 +188,14 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { self.len += items.len; } + /// Append a value to the list `n` times. Allocates more memory + /// as necessary. + pub fn appendNTimes(self: *Self, value: T, n: usize) !void { + const old_len = self.len; + try self.resize(self.len + n); + mem.set(T, self.items[old_len..self.len], value); + } + /// Adjust the list's length to `new_len`. Doesn't initialize /// added items if any. pub fn resize(self: *Self, new_len: usize) !void { @@ -311,6 +319,23 @@ test "std.ArrayList.basic" { testing.expect(list.pop() == 33); } +test "std.ArrayList.appendNTimes" { + var list = ArrayList(i32).init(testing.allocator); + defer list.deinit(); + + try list.appendNTimes(2, 10); + testing.expectEqual(@as(usize, 10), list.len); + for (list.toSlice()) |element| { + testing.expectEqual(@as(i32, 2), element); + } +} + +test "std.ArrayList.appendNTimes with failing allocator" { + var list = ArrayList(i32).init(testing.failing_allocator); + defer list.deinit(); + testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10)); +} + test "std.ArrayList.orderedRemove" { var list = ArrayList(i32).init(testing.allocator); defer list.deinit(); From 4c6f207aff482cf973218bbda1d28e6d2a619df5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 18:12:06 -0500 Subject: [PATCH 058/109] clean up arm CPU features * remove "cpu features" that are actually just processors * rename `v8` to `v8a`. this matches the corresponding change to target/aarch64.zig * rename types in preparation for removing sub-architecture from `std.Target`. I have other files changed in my dirty working tree, but about to make some changes to arm.zig that I don't want batched with this commit. --- lib/std/target/arm.zig | 333 +++++++++++++---------------------------- 1 file changed, 102 insertions(+), 231 deletions(-) diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index 62a4e1e835..16695b0006 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -1,25 +1,11 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { @"32bit", @"8msecext", - a12, - a15, - a17, - a32, - a35, - a5, - a53, - a55, - a57, - a7, - a72, - a73, - a75, a76, - a8, - a9, aclass, acquire_release, aes, @@ -89,8 +75,6 @@ pub const Feature = enum { hwdiv_arm, iwmmxt, iwmmxt2, - krait, - kryo, lob, long_calls, loop_align, @@ -114,9 +98,6 @@ pub const Feature = enum { prefer_vmovsr, prof_unpr, r4, - r5, - r52, - r7, ras, rclass, read_tp_hard, @@ -148,7 +129,7 @@ pub const Feature = enum { v6t2, v7, v7clrex, - v8, + v8a, v8_1a, v8_1m_main, v8_2a, @@ -178,13 +159,13 @@ pub const Feature = enum { zcz, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { @setEvalBranchQuota(10000); const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.@"32bit")] = .{ .llvm_name = "32bit", .description = "Prefer 32-bit Thumb instrs", @@ -195,86 +176,11 @@ pub const all_features = blk: { .description = "Enable support for ARMv8-M Security Extensions", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.a12)] = .{ - .llvm_name = "a12", - .description = "Cortex-A12 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a15)] = .{ - .llvm_name = "a15", - .description = "Cortex-A15 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a17)] = .{ - .llvm_name = "a17", - .description = "Cortex-A17 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a32)] = .{ - .llvm_name = "a32", - .description = "Cortex-A32 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a35)] = .{ - .llvm_name = "a35", - .description = "Cortex-A35 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a5)] = .{ - .llvm_name = "a5", - .description = "Cortex-A5 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a53)] = .{ - .llvm_name = "a53", - .description = "Cortex-A53 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a55)] = .{ - .llvm_name = "a55", - .description = "Cortex-A55 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a57)] = .{ - .llvm_name = "a57", - .description = "Cortex-A57 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a7)] = .{ - .llvm_name = "a7", - .description = "Cortex-A7 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a72)] = .{ - .llvm_name = "a72", - .description = "Cortex-A72 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a73)] = .{ - .llvm_name = "a73", - .description = "Cortex-A73 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a75)] = .{ - .llvm_name = "a75", - .description = "Cortex-A75 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.a76)] = .{ .llvm_name = "a76", .description = "Cortex-A76 ARM processors", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.a8)] = .{ - .llvm_name = "a8", - .description = "Cortex-A8 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.a9)] = .{ - .llvm_name = "a9", - .description = "Cortex-A9 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.aclass)] = .{ .llvm_name = "aclass", .description = "Is application profile ('A' series)", @@ -497,7 +403,7 @@ pub const all_features = blk: { .mp, .neon, .trustzone, - .v8, + .v8a, .virtualization, }), }; @@ -543,7 +449,7 @@ pub const all_features = blk: { .mp, .neon, .rclass, - .v8, + .v8a, .virtualization, }), }; @@ -872,16 +778,6 @@ pub const all_features = blk: { .armv5te, }), }; - result[@enumToInt(Feature.krait)] = .{ - .llvm_name = "krait", - .description = "Qualcomm Krait processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.kryo)] = .{ - .llvm_name = "kryo", - .description = "Qualcomm Kryo processors", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.lob)] = .{ .llvm_name = "lob", .description = "Enable Low Overhead Branch extensions", @@ -1008,21 +904,6 @@ pub const all_features = blk: { .description = "Cortex-R4 ARM processors", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.r5)] = .{ - .llvm_name = "r5", - .description = "Cortex-R5 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.r52)] = .{ - .llvm_name = "r52", - .description = "Cortex-R52 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.r7)] = .{ - .llvm_name = "r7", - .description = "Cortex-R7 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.ras)] = .{ .llvm_name = "ras", .description = "Enable Reliability, Availability and Serviceability extensions", @@ -1200,9 +1081,9 @@ pub const all_features = blk: { .description = "Has v7 clrex instruction", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v8)] = .{ - .llvm_name = "v8", - .description = "Support ARM v8 instructions", + result[@enumToInt(Feature.v8a)] = .{ + .llvm_name = "v8a", + .description = "Support ARM v8a instructions", .dependencies = featureSet(&[_]Feature{ .acquire_release, .v7, @@ -1212,7 +1093,7 @@ pub const all_features = blk: { .llvm_name = "v8.1a", .description = "Support ARM v8.1a instructions", .dependencies = featureSet(&[_]Feature{ - .v8, + .v8a, }), }; result[@enumToInt(Feature.v8_1m_main)] = .{ @@ -1415,49 +1296,49 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const arm1020e = Cpu{ + pub const arm1020e = CpuModel{ .name = "arm1020e", .llvm_name = "arm1020e", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm1020t = Cpu{ + pub const arm1020t = CpuModel{ .name = "arm1020t", .llvm_name = "arm1020t", .features = featureSet(&[_]Feature{ .armv5t, }), }; - pub const arm1022e = Cpu{ + pub const arm1022e = CpuModel{ .name = "arm1022e", .llvm_name = "arm1022e", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm10e = Cpu{ + pub const arm10e = CpuModel{ .name = "arm10e", .llvm_name = "arm10e", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm10tdmi = Cpu{ + pub const arm10tdmi = CpuModel{ .name = "arm10tdmi", .llvm_name = "arm10tdmi", .features = featureSet(&[_]Feature{ .armv5t, }), }; - pub const arm1136j_s = Cpu{ + pub const arm1136j_s = CpuModel{ .name = "arm1136j_s", .llvm_name = "arm1136j-s", .features = featureSet(&[_]Feature{ .armv6, }), }; - pub const arm1136jf_s = Cpu{ + pub const arm1136jf_s = CpuModel{ .name = "arm1136jf_s", .llvm_name = "arm1136jf-s", .features = featureSet(&[_]Feature{ @@ -1466,14 +1347,14 @@ pub const cpu = struct { .vfp2, }), }; - pub const arm1156t2_s = Cpu{ + pub const arm1156t2_s = CpuModel{ .name = "arm1156t2_s", .llvm_name = "arm1156t2-s", .features = featureSet(&[_]Feature{ .armv6t2, }), }; - pub const arm1156t2f_s = Cpu{ + pub const arm1156t2f_s = CpuModel{ .name = "arm1156t2f_s", .llvm_name = "arm1156t2f-s", .features = featureSet(&[_]Feature{ @@ -1482,21 +1363,21 @@ pub const cpu = struct { .vfp2, }), }; - pub const arm1176j_s = Cpu{ + pub const arm1176j_s = CpuModel{ .name = "arm1176j_s", .llvm_name = "arm1176j-s", .features = featureSet(&[_]Feature{ .armv6kz, }), }; - pub const arm1176jz_s = Cpu{ + pub const arm1176jz_s = CpuModel{ .name = "arm1176jz_s", .llvm_name = "arm1176jz-s", .features = featureSet(&[_]Feature{ .armv6kz, }), }; - pub const arm1176jzf_s = Cpu{ + pub const arm1176jzf_s = CpuModel{ .name = "arm1176jzf_s", .llvm_name = "arm1176jzf-s", .features = featureSet(&[_]Feature{ @@ -1505,126 +1386,133 @@ pub const cpu = struct { .vfp2, }), }; - pub const arm710t = Cpu{ + pub const arm710t = CpuModel{ .name = "arm710t", .llvm_name = "arm710t", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm720t = Cpu{ + pub const arm720t = CpuModel{ .name = "arm720t", .llvm_name = "arm720t", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm7tdmi = Cpu{ + pub const arm7tdmi = CpuModel{ .name = "arm7tdmi", .llvm_name = "arm7tdmi", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm7tdmi_s = Cpu{ + pub const arm7tdmi_s = CpuModel{ .name = "arm7tdmi_s", .llvm_name = "arm7tdmi-s", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm8 = Cpu{ + pub const arm8 = CpuModel{ .name = "arm8", .llvm_name = "arm8", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const arm810 = Cpu{ + pub const arm810 = CpuModel{ .name = "arm810", .llvm_name = "arm810", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const arm9 = Cpu{ + pub const arm9 = CpuModel{ .name = "arm9", .llvm_name = "arm9", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm920 = Cpu{ + pub const arm920 = CpuModel{ .name = "arm920", .llvm_name = "arm920", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm920t = Cpu{ + pub const arm920t = CpuModel{ .name = "arm920t", .llvm_name = "arm920t", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm922t = Cpu{ + pub const arm922t = CpuModel{ .name = "arm922t", .llvm_name = "arm922t", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm926ej_s = Cpu{ + pub const arm926ej_s = CpuModel{ .name = "arm926ej_s", .llvm_name = "arm926ej-s", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm940t = Cpu{ + pub const arm940t = CpuModel{ .name = "arm940t", .llvm_name = "arm940t", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const arm946e_s = Cpu{ + pub const arm946e_s = CpuModel{ .name = "arm946e_s", .llvm_name = "arm946e-s", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm966e_s = Cpu{ + pub const arm966e_s = CpuModel{ .name = "arm966e_s", .llvm_name = "arm966e-s", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm968e_s = Cpu{ + pub const arm968e_s = CpuModel{ .name = "arm968e_s", .llvm_name = "arm968e-s", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm9e = Cpu{ + pub const arm9e = CpuModel{ .name = "arm9e", .llvm_name = "arm9e", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const arm9tdmi = Cpu{ + pub const arm9tdmi = CpuModel{ .name = "arm9tdmi", .llvm_name = "arm9tdmi", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const cortex_a12 = Cpu{ + pub const baseline = CpuModel{ + .name = "baseline", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .armv6_m, + }), + }; + pub const cortex_a12 = CpuModel{ .name = "cortex_a12", .llvm_name = "cortex-a12", .features = featureSet(&[_]Feature{ @@ -1639,11 +1527,10 @@ pub const cpu = struct { .vmlx_forwarding, }), }; - pub const cortex_a15 = Cpu{ + pub const cortex_a15 = CpuModel{ .name = "cortex_a15", .llvm_name = "cortex-a15", .features = featureSet(&[_]Feature{ - .a15, .armv7_a, .avoid_partial_cpsr, .dont_widen_vmovs, @@ -1657,11 +1544,10 @@ pub const cpu = struct { .vldn_align, }), }; - pub const cortex_a17 = Cpu{ + pub const cortex_a17 = CpuModel{ .name = "cortex_a17", .llvm_name = "cortex-a17", .features = featureSet(&[_]Feature{ - .a17, .armv7_a, .avoid_partial_cpsr, .mp, @@ -1672,7 +1558,7 @@ pub const cpu = struct { .vmlx_forwarding, }), }; - pub const cortex_a32 = Cpu{ + pub const cortex_a32 = CpuModel{ .name = "cortex_a32", .llvm_name = "cortex-a32", .features = featureSet(&[_]Feature{ @@ -1683,11 +1569,10 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a35 = Cpu{ + pub const cortex_a35 = CpuModel{ .name = "cortex_a35", .llvm_name = "cortex-a35", .features = featureSet(&[_]Feature{ - .a35, .armv8_a, .crc, .crypto, @@ -1695,11 +1580,10 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a5 = Cpu{ + pub const cortex_a5 = CpuModel{ .name = "cortex_a5", .llvm_name = "cortex-a5", .features = featureSet(&[_]Feature{ - .a5, .armv7_a, .mp, .ret_addr_stack, @@ -1710,11 +1594,10 @@ pub const cpu = struct { .vmlx_forwarding, }), }; - pub const cortex_a53 = Cpu{ + pub const cortex_a53 = CpuModel{ .name = "cortex_a53", .llvm_name = "cortex-a53", .features = featureSet(&[_]Feature{ - .a53, .armv8_a, .crc, .crypto, @@ -1723,22 +1606,20 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a55 = Cpu{ + pub const cortex_a55 = CpuModel{ .name = "cortex_a55", .llvm_name = "cortex-a55", .features = featureSet(&[_]Feature{ - .a55, .armv8_2_a, .dotprod, .hwdiv, .hwdiv_arm, }), }; - pub const cortex_a57 = Cpu{ + pub const cortex_a57 = CpuModel{ .name = "cortex_a57", .llvm_name = "cortex-a57", .features = featureSet(&[_]Feature{ - .a57, .armv8_a, .avoid_partial_cpsr, .cheap_predicable_cpsr, @@ -1749,11 +1630,10 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a7 = Cpu{ + pub const cortex_a7 = CpuModel{ .name = "cortex_a7", .llvm_name = "cortex-a7", .features = featureSet(&[_]Feature{ - .a7, .armv7_a, .mp, .ret_addr_stack, @@ -1766,11 +1646,10 @@ pub const cpu = struct { .vmlx_hazards, }), }; - pub const cortex_a72 = Cpu{ + pub const cortex_a72 = CpuModel{ .name = "cortex_a72", .llvm_name = "cortex-a72", .features = featureSet(&[_]Feature{ - .a72, .armv8_a, .crc, .crypto, @@ -1778,11 +1657,10 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a73 = Cpu{ + pub const cortex_a73 = CpuModel{ .name = "cortex_a73", .llvm_name = "cortex-a73", .features = featureSet(&[_]Feature{ - .a73, .armv8_a, .crc, .crypto, @@ -1790,18 +1668,17 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a75 = Cpu{ + pub const cortex_a75 = CpuModel{ .name = "cortex_a75", .llvm_name = "cortex-a75", .features = featureSet(&[_]Feature{ - .a75, .armv8_2_a, .dotprod, .hwdiv, .hwdiv_arm, }), }; - pub const cortex_a76 = Cpu{ + pub const cortex_a76 = CpuModel{ .name = "cortex_a76", .llvm_name = "cortex-a76", .features = featureSet(&[_]Feature{ @@ -1815,7 +1692,7 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a76ae = Cpu{ + pub const cortex_a76ae = CpuModel{ .name = "cortex_a76ae", .llvm_name = "cortex-a76ae", .features = featureSet(&[_]Feature{ @@ -1829,11 +1706,10 @@ pub const cpu = struct { .hwdiv_arm, }), }; - pub const cortex_a8 = Cpu{ + pub const cortex_a8 = CpuModel{ .name = "cortex_a8", .llvm_name = "cortex-a8", .features = featureSet(&[_]Feature{ - .a8, .armv7_a, .nonpipelined_vfp, .ret_addr_stack, @@ -1844,11 +1720,10 @@ pub const cpu = struct { .vmlx_hazards, }), }; - pub const cortex_a9 = Cpu{ + pub const cortex_a9 = CpuModel{ .name = "cortex_a9", .llvm_name = "cortex-a9", .features = featureSet(&[_]Feature{ - .a9, .armv7_a, .avoid_partial_cpsr, .expand_fp_mlx, @@ -1864,28 +1739,28 @@ pub const cpu = struct { .vmlx_hazards, }), }; - pub const cortex_m0 = Cpu{ + pub const cortex_m0 = CpuModel{ .name = "cortex_m0", .llvm_name = "cortex-m0", .features = featureSet(&[_]Feature{ .armv6_m, }), }; - pub const cortex_m0plus = Cpu{ + pub const cortex_m0plus = CpuModel{ .name = "cortex_m0plus", .llvm_name = "cortex-m0plus", .features = featureSet(&[_]Feature{ .armv6_m, }), }; - pub const cortex_m1 = Cpu{ + pub const cortex_m1 = CpuModel{ .name = "cortex_m1", .llvm_name = "cortex-m1", .features = featureSet(&[_]Feature{ .armv6_m, }), }; - pub const cortex_m23 = Cpu{ + pub const cortex_m23 = CpuModel{ .name = "cortex_m23", .llvm_name = "cortex-m23", .features = featureSet(&[_]Feature{ @@ -1893,7 +1768,7 @@ pub const cpu = struct { .no_movt, }), }; - pub const cortex_m3 = Cpu{ + pub const cortex_m3 = CpuModel{ .name = "cortex_m3", .llvm_name = "cortex-m3", .features = featureSet(&[_]Feature{ @@ -1905,7 +1780,7 @@ pub const cpu = struct { .use_misched, }), }; - pub const cortex_m33 = Cpu{ + pub const cortex_m33 = CpuModel{ .name = "cortex_m33", .llvm_name = "cortex-m33", .features = featureSet(&[_]Feature{ @@ -1919,7 +1794,7 @@ pub const cpu = struct { .use_misched, }), }; - pub const cortex_m35p = Cpu{ + pub const cortex_m35p = CpuModel{ .name = "cortex_m35p", .llvm_name = "cortex-m35p", .features = featureSet(&[_]Feature{ @@ -1933,7 +1808,7 @@ pub const cpu = struct { .use_misched, }), }; - pub const cortex_m4 = Cpu{ + pub const cortex_m4 = CpuModel{ .name = "cortex_m4", .llvm_name = "cortex-m4", .features = featureSet(&[_]Feature{ @@ -1946,7 +1821,7 @@ pub const cpu = struct { .vfp4d16sp, }), }; - pub const cortex_m7 = Cpu{ + pub const cortex_m7 = CpuModel{ .name = "cortex_m7", .llvm_name = "cortex-m7", .features = featureSet(&[_]Feature{ @@ -1954,7 +1829,7 @@ pub const cpu = struct { .fp_armv8d16, }), }; - pub const cortex_r4 = Cpu{ + pub const cortex_r4 = CpuModel{ .name = "cortex_r4", .llvm_name = "cortex-r4", .features = featureSet(&[_]Feature{ @@ -1964,7 +1839,7 @@ pub const cpu = struct { .ret_addr_stack, }), }; - pub const cortex_r4f = Cpu{ + pub const cortex_r4f = CpuModel{ .name = "cortex_r4f", .llvm_name = "cortex-r4f", .features = featureSet(&[_]Feature{ @@ -1977,32 +1852,30 @@ pub const cpu = struct { .vfp3d16, }), }; - pub const cortex_r5 = Cpu{ + pub const cortex_r5 = CpuModel{ .name = "cortex_r5", .llvm_name = "cortex-r5", .features = featureSet(&[_]Feature{ .armv7_r, .avoid_partial_cpsr, .hwdiv_arm, - .r5, .ret_addr_stack, .slow_fp_brcc, .slowfpvmlx, .vfp3d16, }), }; - pub const cortex_r52 = Cpu{ + pub const cortex_r52 = CpuModel{ .name = "cortex_r52", .llvm_name = "cortex-r52", .features = featureSet(&[_]Feature{ .armv8_r, .fpao, - .r52, .use_aa, .use_misched, }), }; - pub const cortex_r7 = Cpu{ + pub const cortex_r7 = CpuModel{ .name = "cortex_r7", .llvm_name = "cortex-r7", .features = featureSet(&[_]Feature{ @@ -2011,14 +1884,13 @@ pub const cpu = struct { .fp16, .hwdiv_arm, .mp, - .r7, .ret_addr_stack, .slow_fp_brcc, .slowfpvmlx, .vfp3d16, }), }; - pub const cortex_r8 = Cpu{ + pub const cortex_r8 = CpuModel{ .name = "cortex_r8", .llvm_name = "cortex-r8", .features = featureSet(&[_]Feature{ @@ -2033,7 +1905,7 @@ pub const cpu = struct { .vfp3d16, }), }; - pub const cyclone = Cpu{ + pub const cyclone = CpuModel{ .name = "cyclone", .llvm_name = "cyclone", .features = featureSet(&[_]Feature{ @@ -2054,14 +1926,14 @@ pub const cpu = struct { .zcz, }), }; - pub const ep9312 = Cpu{ + pub const ep9312 = CpuModel{ .name = "ep9312", .llvm_name = "ep9312", .features = featureSet(&[_]Feature{ .armv4t, }), }; - pub const exynos_m1 = Cpu{ + pub const exynos_m1 = CpuModel{ .name = "exynos_m1", .llvm_name = "exynos-m1", .features = featureSet(&[_]Feature{ @@ -2069,7 +1941,7 @@ pub const cpu = struct { .exynos, }), }; - pub const exynos_m2 = Cpu{ + pub const exynos_m2 = CpuModel{ .name = "exynos_m2", .llvm_name = "exynos-m2", .features = featureSet(&[_]Feature{ @@ -2077,7 +1949,7 @@ pub const cpu = struct { .exynos, }), }; - pub const exynos_m3 = Cpu{ + pub const exynos_m3 = CpuModel{ .name = "exynos_m3", .llvm_name = "exynos-m3", .features = featureSet(&[_]Feature{ @@ -2085,7 +1957,7 @@ pub const cpu = struct { .exynos, }), }; - pub const exynos_m4 = Cpu{ + pub const exynos_m4 = CpuModel{ .name = "exynos_m4", .llvm_name = "exynos-m4", .features = featureSet(&[_]Feature{ @@ -2095,7 +1967,7 @@ pub const cpu = struct { .fullfp16, }), }; - pub const exynos_m5 = Cpu{ + pub const exynos_m5 = CpuModel{ .name = "exynos_m5", .llvm_name = "exynos-m5", .features = featureSet(&[_]Feature{ @@ -2105,19 +1977,19 @@ pub const cpu = struct { .fullfp16, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const iwmmxt = Cpu{ + pub const iwmmxt = CpuModel{ .name = "iwmmxt", .llvm_name = "iwmmxt", .features = featureSet(&[_]Feature{ .armv5te, }), }; - pub const krait = Cpu{ + pub const krait = CpuModel{ .name = "krait", .llvm_name = "krait", .features = featureSet(&[_]Feature{ @@ -2126,7 +1998,6 @@ pub const cpu = struct { .fp16, .hwdiv, .hwdiv_arm, - .krait, .muxed_units, .ret_addr_stack, .vfp4, @@ -2134,7 +2005,7 @@ pub const cpu = struct { .vmlx_forwarding, }), }; - pub const kryo = Cpu{ + pub const kryo = CpuModel{ .name = "kryo", .llvm_name = "kryo", .features = featureSet(&[_]Feature{ @@ -2146,7 +2017,7 @@ pub const cpu = struct { .kryo, }), }; - pub const mpcore = Cpu{ + pub const mpcore = CpuModel{ .name = "mpcore", .llvm_name = "mpcore", .features = featureSet(&[_]Feature{ @@ -2155,21 +2026,21 @@ pub const cpu = struct { .vfp2, }), }; - pub const mpcorenovfp = Cpu{ + pub const mpcorenovfp = CpuModel{ .name = "mpcorenovfp", .llvm_name = "mpcorenovfp", .features = featureSet(&[_]Feature{ .armv6k, }), }; - pub const sc000 = Cpu{ + pub const sc000 = CpuModel{ .name = "sc000", .llvm_name = "sc000", .features = featureSet(&[_]Feature{ .armv6_m, }), }; - pub const sc300 = Cpu{ + pub const sc300 = CpuModel{ .name = "sc300", .llvm_name = "sc300", .features = featureSet(&[_]Feature{ @@ -2180,35 +2051,35 @@ pub const cpu = struct { .use_misched, }), }; - pub const strongarm = Cpu{ + pub const strongarm = CpuModel{ .name = "strongarm", .llvm_name = "strongarm", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const strongarm110 = Cpu{ + pub const strongarm110 = CpuModel{ .name = "strongarm110", .llvm_name = "strongarm110", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const strongarm1100 = Cpu{ + pub const strongarm1100 = CpuModel{ .name = "strongarm1100", .llvm_name = "strongarm1100", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const strongarm1110 = Cpu{ + pub const strongarm1110 = CpuModel{ .name = "strongarm1110", .llvm_name = "strongarm1110", .features = featureSet(&[_]Feature{ .armv4, }), }; - pub const swift = Cpu{ + pub const swift = CpuModel{ .name = "swift", .llvm_name = "swift", .features = featureSet(&[_]Feature{ @@ -2235,7 +2106,7 @@ pub const cpu = struct { .wide_stride_vfp, }), }; - pub const xscale = Cpu{ + pub const xscale = CpuModel{ .name = "xscale", .llvm_name = "xscale", .features = featureSet(&[_]Feature{ @@ -2247,7 +2118,7 @@ pub const cpu = struct { /// All arm CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.arm1020e, &cpu.arm1020t, &cpu.arm1022e, From 96f45c27b65307fe4abd5d1fb1cf314b1f493d8e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 19:11:20 -0500 Subject: [PATCH 059/109] arm: clean up the messy sub-architecture & CPU features --- lib/std/target/arm.zig | 754 +++++++++++++++-------------------------- 1 file changed, 282 insertions(+), 472 deletions(-) diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index 16695b0006..48e9576004 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -9,39 +9,6 @@ pub const Feature = enum { aclass, acquire_release, aes, - armv2, - armv2a, - armv3, - armv3m, - armv4, - armv4t, - armv5t, - armv5te, - armv5tej, - armv6, - armv6_m, - armv6j, - armv6k, - armv6kz, - armv6s_m, - armv6t2, - armv7_a, - armv7_m, - armv7_r, - armv7e_m, - armv7k, - armv7s, - armv7ve, - armv8_a, - armv8_m_base, - armv8_m_main, - armv8_r, - armv8_1_a, - armv8_1_m_main, - armv8_2_a, - armv8_3_a, - armv8_4_a, - armv8_5_a, avoid_movs_shop, avoid_partial_cpsr, cheap_predicable_cpsr, @@ -57,13 +24,13 @@ pub const Feature = enum { execute_only, expand_fp_mlx, exynos, + fp16, + fp16fml, + fp64, fp_armv8, fp_armv8d16, fp_armv8d16sp, fp_armv8sp, - fp16, - fp16fml, - fp64, fpao, fpregs, fpregs16, @@ -115,29 +82,46 @@ pub const Feature = enum { splat_vfp_neon, strict_align, swift, - thumb_mode, thumb2, + thumb_mode, trustzone, use_aa, use_misched, + v2, + v2a, + v3, + v3m, + v4, v4t, v5t, v5te, + v5tej, v6, + v6j, v6k, + v6kz, v6m, + v6sm, v6t2, v7, + v7a, + v7m, + v7r, v7clrex, + v7em, + v7k, + v7s, + v7ve, v8a, + v8m, + v8m_main, + v8r, v8_1a, v8_1m_main, v8_2a, v8_3a, v8_4a, v8_5a, - v8m, - v8m_main, vfp2, vfp2d16, vfp2d16sp, @@ -198,368 +182,6 @@ pub const all_features = blk: { .neon, }), }; - result[@enumToInt(Feature.armv2)] = .{ - .llvm_name = "armv2", - .description = "ARMv2 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv2a)] = .{ - .llvm_name = "armv2a", - .description = "ARMv2a architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv3)] = .{ - .llvm_name = "armv3", - .description = "ARMv3 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv3m)] = .{ - .llvm_name = "armv3m", - .description = "ARMv3m architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv4)] = .{ - .llvm_name = "armv4", - .description = "ARMv4 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv4t)] = .{ - .llvm_name = "armv4t", - .description = "ARMv4t architecture", - .dependencies = featureSet(&[_]Feature{ - .v4t, - }), - }; - result[@enumToInt(Feature.armv5t)] = .{ - .llvm_name = "armv5t", - .description = "ARMv5t architecture", - .dependencies = featureSet(&[_]Feature{ - .v5t, - }), - }; - result[@enumToInt(Feature.armv5te)] = .{ - .llvm_name = "armv5te", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@enumToInt(Feature.armv5tej)] = .{ - .llvm_name = "armv5tej", - .description = "ARMv5tej architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@enumToInt(Feature.armv6)] = .{ - .llvm_name = "armv6", - .description = "ARMv6 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .v6, - }), - }; - result[@enumToInt(Feature.armv6_m)] = .{ - .llvm_name = "armv6-m", - .description = "ARMv6m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6m, - }), - }; - result[@enumToInt(Feature.armv6j)] = .{ - .llvm_name = "armv6j", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv6, - }), - }; - result[@enumToInt(Feature.armv6k)] = .{ - .llvm_name = "armv6k", - .description = "ARMv6k architecture", - .dependencies = featureSet(&[_]Feature{ - .v6k, - }), - }; - result[@enumToInt(Feature.armv6kz)] = .{ - .llvm_name = "armv6kz", - .description = "ARMv6kz architecture", - .dependencies = featureSet(&[_]Feature{ - .trustzone, - .v6k, - }), - }; - result[@enumToInt(Feature.armv6s_m)] = .{ - .llvm_name = "armv6s-m", - .description = "ARMv6sm architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6m, - }), - }; - result[@enumToInt(Feature.armv6t2)] = .{ - .llvm_name = "armv6t2", - .description = "ARMv6t2 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .v6t2, - }), - }; - result[@enumToInt(Feature.armv7_a)] = .{ - .llvm_name = "armv7-a", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .neon, - .v7, - }), - }; - result[@enumToInt(Feature.armv7_m)] = .{ - .llvm_name = "armv7-m", - .description = "ARMv7m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.armv7_r)] = .{ - .llvm_name = "armv7-r", - .description = "ARMv7r architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .rclass, - .v7, - }), - }; - result[@enumToInt(Feature.armv7e_m)] = .{ - .llvm_name = "armv7e-m", - .description = "ARMv7em architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.armv7k)] = .{ - .llvm_name = "armv7k", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv7_a, - }), - }; - result[@enumToInt(Feature.armv7s)] = .{ - .llvm_name = "armv7s", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv7_a, - }), - }; - result[@enumToInt(Feature.armv7ve)] = .{ - .llvm_name = "armv7ve", - .description = "ARMv7ve architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .mp, - .neon, - .trustzone, - .v7, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_a)] = .{ - .llvm_name = "armv8-a", - .description = "ARMv8a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .trustzone, - .v8a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_m_base)] = .{ - .llvm_name = "armv8-m.base", - .description = "ARMv8mBaseline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v7clrex, - .v8m, - }), - }; - result[@enumToInt(Feature.armv8_m_main)] = .{ - .llvm_name = "armv8-m.main", - .description = "ARMv8mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .v8m_main, - }), - }; - result[@enumToInt(Feature.armv8_r)] = .{ - .llvm_name = "armv8-r", - .description = "ARMv8r architecture", - .dependencies = featureSet(&[_]Feature{ - .crc, - .db, - .dfb, - .dsp, - .fp_armv8, - .mp, - .neon, - .rclass, - .v8a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_1_a)] = .{ - .llvm_name = "armv8.1-a", - .description = "ARMv81a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .trustzone, - .v8_1a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_1_m_main)] = .{ - .llvm_name = "armv8.1-m.main", - .description = "ARMv81mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .lob, - .mclass, - .noarm, - .ras, - .thumb_mode, - .v8_1m_main, - }), - }; - result[@enumToInt(Feature.armv8_2_a)] = .{ - .llvm_name = "armv8.2-a", - .description = "ARMv82a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_2a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_3_a)] = .{ - .llvm_name = "armv8.3-a", - .description = "ARMv83a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_3a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_4_a)] = .{ - .llvm_name = "armv8.4-a", - .description = "ARMv84a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dotprod, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_4a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_5_a)] = .{ - .llvm_name = "armv8.5-a", - .description = "ARMv85a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dotprod, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_5a, - .virtualization, - }), - }; result[@enumToInt(Feature.avoid_movs_shop)] = .{ .llvm_name = "avoid-movs-shop", .description = "Avoid movs instructions with shifter operand", @@ -659,6 +281,25 @@ pub const all_features = blk: { .zcz, }), }; + result[@enumToInt(Feature.fp16)] = .{ + .llvm_name = "fp16", + .description = "Enable half-precision floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable full half-precision floating point fml instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Floating point unit supports double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs64, + }), + }; result[@enumToInt(Feature.fp_armv8)] = .{ .llvm_name = "fp-armv8", .description = "Enable ARMv8 FP", @@ -693,25 +334,6 @@ pub const all_features = blk: { .vfp4sp, }), }; - result[@enumToInt(Feature.fp16)] = .{ - .llvm_name = "fp16", - .description = "Enable half-precision floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.fp16fml)] = .{ - .llvm_name = "fp16fml", - .description = "Enable full half-precision floating point fml instructions", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@enumToInt(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Floating point unit supports double precision", - .dependencies = featureSet(&[_]Feature{ - .fpregs64, - }), - }; result[@enumToInt(Feature.fpao)] = .{ .llvm_name = "fpao", .description = "Enable fast computation of positive address offsets", @@ -993,16 +615,16 @@ pub const all_features = blk: { .description = "Swift ARM processors", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.thumb_mode)] = .{ - .llvm_name = "thumb-mode", - .description = "Thumb mode", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.thumb2)] = .{ .llvm_name = "thumb2", .description = "Enable Thumb2 instructions", .dependencies = featureSet(&[_]Feature{}), }; + result[@enumToInt(Feature.thumb_mode)] = .{ + .llvm_name = "thumb-mode", + .description = "Thumb mode", + .dependencies = featureSet(&[_]Feature{}), + }; result[@enumToInt(Feature.trustzone)] = .{ .llvm_name = "trustzone", .description = "Enable support for TrustZone security extensions", @@ -1018,50 +640,116 @@ pub const all_features = blk: { .description = "Use the MachineScheduler", .dependencies = featureSet(&[_]Feature{}), }; + result[@enumToInt(Feature.v2)] = .{ + .llvm_name = "armv2", + .description = "ARMv2 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v2a)] = .{ + .llvm_name = "armv2a", + .description = "ARMv2a architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v3)] = .{ + .llvm_name = "armv3", + .description = "ARMv3 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v3m)] = .{ + .llvm_name = "armv3m", + .description = "ARMv3m architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v4)] = .{ + .llvm_name = "armv4", + .description = "ARMv4 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; result[@enumToInt(Feature.v4t)] = .{ - .llvm_name = "v4t", - .description = "Support ARM v4T instructions", + .llvm_name = "armv4t", + .description = "ARMv4t architecture", .dependencies = featureSet(&[_]Feature{}), }; result[@enumToInt(Feature.v5t)] = .{ - .llvm_name = "v5t", - .description = "Support ARM v5T instructions", + .llvm_name = "armv5t", + .description = "ARMv5t architecture", .dependencies = featureSet(&[_]Feature{ .v4t, }), }; result[@enumToInt(Feature.v5te)] = .{ - .llvm_name = "v5te", - .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", + .llvm_name = "armv5te", + .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ .v5t, }), }; - result[@enumToInt(Feature.v6)] = .{ - .llvm_name = "v6", - .description = "Support ARM v6 instructions", + result[@enumToInt(Feature.v5tej)] = .{ + .llvm_name = "armv5tej", + .description = "ARMv5tej architecture", .dependencies = featureSet(&[_]Feature{ .v5te, }), }; - result[@enumToInt(Feature.v6k)] = .{ - .llvm_name = "v6k", - .description = "Support ARM v6k instructions", + result[@enumToInt(Feature.v6)] = .{ + .llvm_name = "armv6", + .description = "ARMv6 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .v5te, + }), + }; + result[@enumToInt(Feature.v6j)] = .{ + .llvm_name = "armv6j", + .description = "ARMv7a architecture", .dependencies = featureSet(&[_]Feature{ .v6, }), }; - result[@enumToInt(Feature.v6m)] = .{ - .llvm_name = "v6m", - .description = "Support ARM v6M instructions", + result[@enumToInt(Feature.v6k)] = .{ + .llvm_name = "armv6k", + .description = "ARMv6k architecture", .dependencies = featureSet(&[_]Feature{ .v6, }), }; + result[@enumToInt(Feature.v6kz)] = .{ + .llvm_name = "armv6kz", + .description = "ARMv6kz architecture", + .dependencies = featureSet(&[_]Feature{ + .trustzone, + .v6k, + }), + }; + result[@enumToInt(Feature.v6m)] = .{ + .llvm_name = "armv6-m", + .description = "ARMv6m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6, + }), + }; + result[@enumToInt(Feature.v6sm)] = .{ + .llvm_name = "armv6s-m", + .description = "ARMv6sm architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6, + }), + }; result[@enumToInt(Feature.v6t2)] = .{ - .llvm_name = "v6t2", - .description = "Support ARM v6t2 instructions", + .llvm_name = "armv6t2", + .description = "ARMv6t2 architecture", .dependencies = featureSet(&[_]Feature{ + .dsp, .thumb2, .v6k, .v8m, @@ -1076,77 +764,199 @@ pub const all_features = blk: { .v7clrex, }), }; + result[@enumToInt(Feature.v7a)] = .{ + .llvm_name = "armv7-a", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .neon, + .v7, + }), + }; + result[@enumToInt(Feature.v7m)] = .{ + .llvm_name = "armv7-m", + .description = "ARMv7m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .v7, + }), + }; + result[@enumToInt(Feature.v7r)] = .{ + .llvm_name = "armv7-r", + .description = "ARMv7r architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .rclass, + .v7, + }), + }; result[@enumToInt(Feature.v7clrex)] = .{ .llvm_name = "v7clrex", .description = "Has v7 clrex instruction", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v8a)] = .{ - .llvm_name = "v8a", - .description = "Support ARM v8a instructions", + result[@enumToInt(Feature.v7em)] = .{ + .llvm_name = "armv7e-m", + .description = "ARMv7em architecture", .dependencies = featureSet(&[_]Feature{ - .acquire_release, + .db, + .dsp, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, .v7, }), }; + result[@enumToInt(Feature.v7k)] = .{ + .llvm_name = "armv7k", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@enumToInt(Feature.v7s)] = .{ + .llvm_name = "armv7s", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@enumToInt(Feature.v7ve)] = .{ + .llvm_name = "armv7ve", + .description = "ARMv7ve architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .mp, + .neon, + .trustzone, + .v7, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8a)] = .{ + .llvm_name = "armv8-a", + .description = "ARMv8a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .acquire_release, + .crc, + .crypto, + .db, + .fp_armv8, + .mp, + .neon, + .trustzone, + .v7, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8m)] = .{ + .llvm_name = "armv8-m.base", + .description = "ARMv8mBaseline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6m, + .v7clrex, + }), + }; + result[@enumToInt(Feature.v8m_main)] = .{ + .llvm_name = "armv8-m.main", + .description = "ARMv8mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .v7, + }), + }; + result[@enumToInt(Feature.v8r)] = .{ + .llvm_name = "armv8-r", + .description = "ARMv8r architecture", + .dependencies = featureSet(&[_]Feature{ + .dfb, + .rclass, + .v8a, + }), + }; result[@enumToInt(Feature.v8_1a)] = .{ - .llvm_name = "v8.1a", - .description = "Support ARM v8.1a instructions", + .llvm_name = "armv8.1-a", + .description = "ARMv81a architecture", .dependencies = featureSet(&[_]Feature{ .v8a, }), }; result[@enumToInt(Feature.v8_1m_main)] = .{ - .llvm_name = "v8.1m.main", - .description = "Support ARM v8-1M Mainline instructions", + .llvm_name = "armv8.1-m.main", + .description = "ARMv81mMainline architecture", .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .lob, + .mclass, + .noarm, + .ras, + .thumb_mode, .v8m_main, }), }; result[@enumToInt(Feature.v8_2a)] = .{ - .llvm_name = "v8.2a", - .description = "Support ARM v8.2a instructions", + .llvm_name = "armv8.2-a", + .description = "ARMv82a architecture", .dependencies = featureSet(&[_]Feature{ + .ras, .v8_1a, }), }; result[@enumToInt(Feature.v8_3a)] = .{ - .llvm_name = "v8.3a", - .description = "Support ARM v8.3a instructions", + .llvm_name = "armv8.3-a", + .description = "ARMv83a architecture", .dependencies = featureSet(&[_]Feature{ .v8_2a, }), }; result[@enumToInt(Feature.v8_4a)] = .{ - .llvm_name = "v8.4a", - .description = "Support ARM v8.4a instructions", + .llvm_name = "armv8.4-a", + .description = "ARMv84a architecture", .dependencies = featureSet(&[_]Feature{ .dotprod, .v8_3a, }), }; result[@enumToInt(Feature.v8_5a)] = .{ - .llvm_name = "v8.5a", - .description = "Support ARM v8.5a instructions", + .llvm_name = "armv8.5-a", + .description = "ARMv85a architecture", .dependencies = featureSet(&[_]Feature{ + .dotprod, .sb, .v8_4a, }), }; - result[@enumToInt(Feature.v8m)] = .{ - .llvm_name = "v8m", - .description = "Support ARM v8M Baseline instructions", - .dependencies = featureSet(&[_]Feature{ - .v6m, - }), - }; - result[@enumToInt(Feature.v8m_main)] = .{ - .llvm_name = "v8m.main", - .description = "Support ARM v8M Mainline instructions", - .dependencies = featureSet(&[_]Feature{ - .v7, - }), - }; result[@enumToInt(Feature.vfp2)] = .{ .llvm_name = "vfp2", .description = "Enable VFP2 instructions", From 84f1893c18c4ef12dbe268ed6d11a11966a9d447 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 21:30:36 -0500 Subject: [PATCH 060/109] remove the concept of "sub-architecture" in favor of CPU features. Also rearrange the `std.Target` data structure. * note: `@import("builtin")` was already deprecated in favor of `@import("std").builtin`. * `std.builtin.arch` is now deprecated in favor of `std.builtin.cpu.arch`. * `std.Target.CpuFeatures.Cpu` is now `std.Target.Cpu.Model`. * `std.Target.CpuFeatures` is now `std.Target.Cpu`. * `std.Target` no longer has an `arch` field. Instead it has a `cpu` field, which has `arch`, `model`, and `features`. * `std.Target` no longer has a `cpu_features` field. * `std.Target.Arch` is moved to `std.Target.Cpu.Arch` and it is an enum instead of a tagged union. * `std.Target.parseOs` is moved to `std.Target.Os.parse`. * `std.Target.parseAbi` is moved to `std.Target.Abi.parse`. * `std.Target.parseArchSub` is only for arch now and moved to `std.Target.Cpu.Arch.parse`. * `std.Target.parse` is improved to accept CPU name and features. * `std.Target.Arch.getBaselineCpuFeatures` is moved to `std.Target.Cpu.baseline`. * `std.Target.allCpus` is renamed to `std.Target.allCpuModels`. * `std.Target.defaultAbi` is moved to `std.Target.Abi.default`. * Significant cleanup of aarch64 and arm CPU features, resulting in the needed bit count for cpu feature set going from 174 to 138. * Add `std.Target.Cpu.Feature.Set.addFeatureSet` for merging feature sets together. `-target-feature` and `-target-cpu` are removed in favor of `-mcpu`, to conform to established conventions, and it gains additional power to support cpu features. The syntax is: -mcpu=name+on1+on2-off1-off2 closes #4261 --- lib/std/builtin.zig | 7 +- lib/std/target.zig | 1198 ++++++++++++------------- lib/std/target/aarch64.zig | 551 ++++-------- lib/std/target/amdgpu.zig | 89 +- lib/std/target/arm.zig | 172 ++-- lib/std/target/avr.zig | 525 +++++------ lib/std/target/bpf.zig | 21 +- lib/std/target/hexagon.zig | 25 +- lib/std/target/mips.zig | 45 +- lib/std/target/msp430.zig | 17 +- lib/std/target/nvptx.zig | 41 +- lib/std/target/powerpc.zig | 85 +- lib/std/target/riscv.zig | 19 +- lib/std/target/sparc.zig | 91 +- lib/std/target/systemz.zig | 35 +- lib/std/target/wasm.zig | 17 +- lib/std/target/x86.zig | 167 ++-- src-self-hosted/libc_installation.zig | 3 +- src-self-hosted/print_targets.zig | 84 +- src-self-hosted/stage2.zig | 395 +++----- src/codegen.cpp | 43 +- src/error.cpp | 1 - src/main.cpp | 86 +- src/stage2.cpp | 93 +- src/stage2.h | 39 +- src/target.cpp | 38 +- src/target.hpp | 2 +- test/tests.zig | 81 +- 28 files changed, 1742 insertions(+), 2228 deletions(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 58a3f1a5bf..5440de4d3b 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -6,8 +6,8 @@ pub const Target = std.Target; /// Deprecated: use `std.Target.Os`. pub const Os = std.Target.Os; -/// Deprecated: use `std.Target.Arch`. -pub const Arch = std.Target.Arch; +/// Deprecated: use `std.Target.Cpu.Arch`. +pub const Arch = std.Target.Cpu.Arch; /// Deprecated: use `std.Target.Abi`. pub const Abi = std.Target.Abi; @@ -18,9 +18,6 @@ pub const ObjectFormat = std.Target.ObjectFormat; /// Deprecated: use `std.Target.SubSystem`. pub const SubSystem = std.Target.SubSystem; -/// Deprecated: use `std.Target.CpuFeatures`. -pub const CpuFeatures = std.Target.CpuFeatures; - /// Deprecated: use `std.Target.Cpu`. pub const Cpu = std.Target.Cpu; diff --git a/lib/std/target.zig b/lib/std/target.zig index bc78b2dce5..8a3ae23337 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -47,6 +47,18 @@ pub const Target = union(enum) { emscripten, uefi, other, + + pub fn parse(text: []const u8) !Os { + if (mem.eql(u8, text, "native")) return builtin.os; + + const info = @typeInfo(Os); + inline for (info.Enum.fields) |field| { + if (mem.eql(u8, text, field.name)) { + return @field(Os, field.name); + } + } + return error.UnknownOperatingSystem; + } }; pub const aarch64 = @import("target/aarch64.zig"); @@ -65,457 +77,6 @@ pub const Target = union(enum) { pub const wasm = @import("target/wasm.zig"); pub const x86 = @import("target/x86.zig"); - pub const Arch = union(enum) { - arm: Arm32, - armeb: Arm32, - aarch64: Arm64, - aarch64_be: Arm64, - aarch64_32: Arm64, - arc, - avr, - bpfel, - bpfeb, - hexagon, - mips, - mipsel, - mips64, - mips64el, - msp430, - powerpc, - powerpc64, - powerpc64le, - r600, - amdgcn, - riscv32, - riscv64, - sparc, - sparcv9, - sparcel, - s390x, - tce, - tcele, - thumb: Arm32, - thumbeb: Arm32, - i386, - x86_64, - xcore, - nvptx, - nvptx64, - le32, - le64, - amdil, - amdil64, - hsail, - hsail64, - spir, - spir64, - kalimba: Kalimba, - shave, - lanai, - wasm32, - wasm64, - renderscript32, - renderscript64, - - pub const Arm32 = enum { - v8_5a, - v8_4a, - v8_3a, - v8_2a, - v8_1a, - v8a, - v8r, - v8m_baseline, - v8m_mainline, - v8_1m_mainline, - v7a, - v7em, - v7m, - v7s, - v7k, - v7ve, - v6, - v6m, - v6k, - v6t2, - v5, - v5te, - v4t, - - pub fn version(version: Arm32) comptime_int { - return switch (version) { - .v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8a, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8, - .v7a, .v7em, .v7m, .v7s, .v7k, .v7ve => 7, - .v6, .v6m, .v6k, .v6t2 => 6, - .v5, .v5te => 5, - .v4t => 4, - }; - } - }; - pub const Arm64 = enum { - v8_5a, - v8_4a, - v8_3a, - v8_2a, - v8_1a, - v8a, - }; - pub const Kalimba = enum { - v5, - v4, - v3, - }; - pub const Mips = enum { - r6, - }; - - pub fn subArchName(arch: Arch) ?[]const u8 { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => |arm32| @tagName(arm32), - .aarch64, .aarch64_be, .aarch64_32 => |arm64| @tagName(arm64), - .kalimba => |kalimba| @tagName(kalimba), - else => return null, - }; - } - - pub fn subArchFeature(arch: Arch) ?Cpu.Feature.Set.Index { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => |arm32| switch (arm32) { - .v8_5a => @enumToInt(arm.Feature.armv8_5_a), - .v8_4a => @enumToInt(arm.Feature.armv8_4_a), - .v8_3a => @enumToInt(arm.Feature.armv8_3_a), - .v8_2a => @enumToInt(arm.Feature.armv8_2_a), - .v8_1a => @enumToInt(arm.Feature.armv8_1_a), - .v8a => @enumToInt(arm.Feature.armv8_a), - .v8r => @enumToInt(arm.Feature.armv8_r), - .v8m_baseline => @enumToInt(arm.Feature.armv8_m_base), - .v8m_mainline => @enumToInt(arm.Feature.armv8_m_main), - .v8_1m_mainline => @enumToInt(arm.Feature.armv8_1_m_main), - .v7a => @enumToInt(arm.Feature.armv7_a), - .v7em => @enumToInt(arm.Feature.armv7e_m), - .v7m => @enumToInt(arm.Feature.armv7_m), - .v7s => @enumToInt(arm.Feature.armv7s), - .v7k => @enumToInt(arm.Feature.armv7k), - .v7ve => @enumToInt(arm.Feature.armv7ve), - .v6 => @enumToInt(arm.Feature.armv6), - .v6m => @enumToInt(arm.Feature.armv6_m), - .v6k => @enumToInt(arm.Feature.armv6k), - .v6t2 => @enumToInt(arm.Feature.armv6t2), - .v5 => @enumToInt(arm.Feature.armv5t), - .v5te => @enumToInt(arm.Feature.armv5te), - .v4t => @enumToInt(arm.Feature.armv4t), - }, - .aarch64, .aarch64_be, .aarch64_32 => |arm64| switch (arm64) { - .v8_5a => @enumToInt(aarch64.Feature.v8_5a), - .v8_4a => @enumToInt(aarch64.Feature.v8_4a), - .v8_3a => @enumToInt(aarch64.Feature.v8_3a), - .v8_2a => @enumToInt(aarch64.Feature.v8_2a), - .v8_1a => @enumToInt(aarch64.Feature.v8_1a), - .v8a => @enumToInt(aarch64.Feature.v8a), - }, - else => return null, - }; - } - - pub fn isARM(arch: Arch) bool { - return switch (arch) { - .arm, .armeb => true, - else => false, - }; - } - - pub fn isThumb(arch: Arch) bool { - return switch (arch) { - .thumb, .thumbeb => true, - else => false, - }; - } - - pub fn isWasm(arch: Arch) bool { - return switch (arch) { - .wasm32, .wasm64 => true, - else => false, - }; - } - - pub fn isRISCV(arch: Arch) bool { - return switch (arch) { - .riscv32, .riscv64 => true, - else => false, - }; - } - - pub fn isMIPS(arch: Arch) bool { - return switch (arch) { - .mips, .mipsel, .mips64, .mips64el => true, - else => false, - }; - } - - pub fn parseCpu(arch: Arch, cpu_name: []const u8) !*const Cpu { - for (arch.allCpus()) |cpu| { - if (mem.eql(u8, cpu_name, cpu.name)) { - return cpu; - } - } - return error.UnknownCpu; - } - - /// Comma-separated list of features, with + or - in front of each feature. This - /// form represents a deviation from baseline CPU, which is provided as a parameter. - /// Extra commas are ignored. - pub fn parseCpuFeatureSet(arch: Arch, cpu: *const Cpu, features_text: []const u8) !Cpu.Feature.Set { - const all_features = arch.allFeaturesList(); - var set = cpu.features; - var it = mem.tokenize(features_text, ","); - while (it.next()) |item_text| { - var feature_name: []const u8 = undefined; - var op: enum { - add, - sub, - } = undefined; - if (mem.startsWith(u8, item_text, "+")) { - op = .add; - feature_name = item_text[1..]; - } else if (mem.startsWith(u8, item_text, "-")) { - op = .sub; - feature_name = item_text[1..]; - } else { - return error.InvalidCpuFeatures; - } - for (all_features) |feature, index_usize| { - const index = @intCast(Cpu.Feature.Set.Index, index_usize); - if (mem.eql(u8, feature_name, feature.name)) { - switch (op) { - .add => set.addFeature(index), - .sub => set.removeFeature(index), - } - break; - } - } else { - return error.UnknownCpuFeature; - } - } - return set; - } - - pub fn toElfMachine(arch: Arch) std.elf.EM { - return switch (arch) { - .avr => ._AVR, - .msp430 => ._MSP430, - .arc => ._ARC, - .arm => ._ARM, - .armeb => ._ARM, - .hexagon => ._HEXAGON, - .le32 => ._NONE, - .mips => ._MIPS, - .mipsel => ._MIPS_RS3_LE, - .powerpc => ._PPC, - .r600 => ._NONE, - .riscv32 => ._RISCV, - .sparc => ._SPARC, - .sparcel => ._SPARC, - .tce => ._NONE, - .tcele => ._NONE, - .thumb => ._ARM, - .thumbeb => ._ARM, - .i386 => ._386, - .xcore => ._XCORE, - .nvptx => ._NONE, - .amdil => ._NONE, - .hsail => ._NONE, - .spir => ._NONE, - .kalimba => ._CSR_KALIMBA, - .shave => ._NONE, - .lanai => ._LANAI, - .wasm32 => ._NONE, - .renderscript32 => ._NONE, - .aarch64_32 => ._AARCH64, - .aarch64 => ._AARCH64, - .aarch64_be => ._AARCH64, - .mips64 => ._MIPS, - .mips64el => ._MIPS_RS3_LE, - .powerpc64 => ._PPC64, - .powerpc64le => ._PPC64, - .riscv64 => ._RISCV, - .x86_64 => ._X86_64, - .nvptx64 => ._NONE, - .le64 => ._NONE, - .amdil64 => ._NONE, - .hsail64 => ._NONE, - .spir64 => ._NONE, - .wasm64 => ._NONE, - .renderscript64 => ._NONE, - .amdgcn => ._NONE, - .bpfel => ._BPF, - .bpfeb => ._BPF, - .sparcv9 => ._SPARCV9, - .s390x => ._S390, - }; - } - - pub fn endian(arch: Arch) builtin.Endian { - return switch (arch) { - .avr, - .arm, - .aarch64_32, - .aarch64, - .amdgcn, - .amdil, - .amdil64, - .bpfel, - .hexagon, - .hsail, - .hsail64, - .kalimba, - .le32, - .le64, - .mipsel, - .mips64el, - .msp430, - .nvptx, - .nvptx64, - .sparcel, - .tcele, - .powerpc64le, - .r600, - .riscv32, - .riscv64, - .i386, - .x86_64, - .wasm32, - .wasm64, - .xcore, - .thumb, - .spir, - .spir64, - .renderscript32, - .renderscript64, - .shave, - => .Little, - - .arc, - .armeb, - .aarch64_be, - .bpfeb, - .mips, - .mips64, - .powerpc, - .powerpc64, - .thumbeb, - .sparc, - .sparcv9, - .tce, - .lanai, - .s390x, - => .Big, - }; - } - - /// Returns a name that matches the lib/std/target/* directory name. - pub fn genericName(arch: Arch) []const u8 { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => "arm", - .aarch64, .aarch64_be, .aarch64_32 => "aarch64", - .avr => "avr", - .bpfel, .bpfeb => "bpf", - .hexagon => "hexagon", - .mips, .mipsel, .mips64, .mips64el => "mips", - .msp430 => "msp430", - .powerpc, .powerpc64, .powerpc64le => "powerpc", - .amdgcn => "amdgpu", - .riscv32, .riscv64 => "riscv", - .sparc, .sparcv9, .sparcel => "sparc", - .s390x => "systemz", - .i386, .x86_64 => "x86", - .nvptx, .nvptx64 => "nvptx", - .wasm32, .wasm64 => "wasm", - else => @tagName(arch), - }; - } - - /// All CPU features Zig is aware of, sorted lexicographically by name. - pub fn allFeaturesList(arch: Arch) []const Cpu.Feature { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => &arm.all_features, - .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features, - .avr => &avr.all_features, - .bpfel, .bpfeb => &bpf.all_features, - .hexagon => &hexagon.all_features, - .mips, .mipsel, .mips64, .mips64el => &mips.all_features, - .msp430 => &msp430.all_features, - .powerpc, .powerpc64, .powerpc64le => &powerpc.all_features, - .amdgcn => &amdgpu.all_features, - .riscv32, .riscv64 => &riscv.all_features, - .sparc, .sparcv9, .sparcel => &sparc.all_features, - .s390x => &systemz.all_features, - .i386, .x86_64 => &x86.all_features, - .nvptx, .nvptx64 => &nvptx.all_features, - .wasm32, .wasm64 => &wasm.all_features, - - else => &[0]Cpu.Feature{}, - }; - } - - /// The "default" set of CPU features for cross-compiling. A conservative set - /// of features that is expected to be supported on most available hardware. - pub fn getBaselineCpuFeatures(arch: Arch) CpuFeatures { - const S = struct { - const generic_cpu = Cpu{ - .name = "generic", - .llvm_name = null, - .features = Cpu.Feature.Set.empty, - }; - }; - const cpu = switch (arch) { - .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic, - .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, - .avr => &avr.cpu.avr1, - .bpfel, .bpfeb => &bpf.cpu.generic, - .hexagon => &hexagon.cpu.generic, - .mips, .mipsel => &mips.cpu.mips32, - .mips64, .mips64el => &mips.cpu.mips64, - .msp430 => &msp430.cpu.generic, - .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, - .amdgcn => &amdgpu.cpu.generic, - .riscv32 => &riscv.cpu.baseline_rv32, - .riscv64 => &riscv.cpu.baseline_rv64, - .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, - .s390x => &systemz.cpu.generic, - .i386 => &x86.cpu.pentium4, - .x86_64 => &x86.cpu.x86_64, - .nvptx, .nvptx64 => &nvptx.cpu.sm_20, - .wasm32, .wasm64 => &wasm.cpu.generic, - - else => &S.generic_cpu, - }; - return CpuFeatures.initFromCpu(arch, cpu); - } - - /// All CPUs Zig is aware of, sorted lexicographically by name. - pub fn allCpus(arch: Arch) []const *const Cpu { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => arm.all_cpus, - .aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus, - .avr => avr.all_cpus, - .bpfel, .bpfeb => bpf.all_cpus, - .hexagon => hexagon.all_cpus, - .mips, .mipsel, .mips64, .mips64el => mips.all_cpus, - .msp430 => msp430.all_cpus, - .powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus, - .amdgcn => amdgpu.all_cpus, - .riscv32, .riscv64 => riscv.all_cpus, - .sparc, .sparcv9, .sparcel => sparc.all_cpus, - .s390x => systemz.all_cpus, - .i386, .x86_64 => x86.all_cpus, - .nvptx, .nvptx64 => nvptx.all_cpus, - .wasm32, .wasm64 => wasm.all_cpus, - - else => &[0]*const Cpu{}, - }; - } - }; - pub const Abi = enum { none, gnu, @@ -539,11 +100,104 @@ pub const Target = union(enum) { coreclr, simulator, macabi, + + pub fn default(arch: Cpu.Arch, target_os: Os) Abi { + switch (arch) { + .wasm32, .wasm64 => return .musl, + else => {}, + } + switch (target_os) { + .freestanding, + .ananas, + .cloudabi, + .dragonfly, + .lv2, + .solaris, + .haiku, + .minix, + .rtems, + .nacl, + .cnk, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .other, + => return .eabi, + .openbsd, + .macosx, + .freebsd, + .ios, + .tvos, + .watchos, + .fuchsia, + .kfreebsd, + .netbsd, + .hurd, + => return .gnu, + .windows, + .uefi, + => return .msvc, + .linux, + .wasi, + .emscripten, + => return .musl, + } + } + + pub fn parse(text: []const u8) !Abi { + if (mem.eql(u8, text, "native")) return builtin.abi; + + const info = @typeInfo(Abi); + inline for (info.Enum.fields) |field| { + if (mem.eql(u8, text, field.name)) { + return @field(Abi, field.name); + } + } + return error.UnknownApplicationBinaryInterface; + } + }; + + pub const ObjectFormat = enum { + unknown, + coff, + elf, + macho, + wasm, + }; + + pub const SubSystem = enum { + Console, + Windows, + Posix, + Native, + EfiApplication, + EfiBootServiceDriver, + EfiRom, + EfiRuntimeDriver, + }; + + pub const Cross = struct { + cpu: Cpu, + os: Os, + abi: Abi, }; pub const Cpu = struct { - name: []const u8, - llvm_name: ?[:0]const u8, + /// Architecture + arch: Arch, + + /// The CPU model to target. It has a set of features + /// which are overridden with the `features` field. + model: *const Model, + + /// An explicit list of the entire CPU feature set. It may differ from the specific CPU model's features. features: Feature.Set, pub const Feature = struct { @@ -569,7 +223,7 @@ pub const Target = union(enum) { pub const Set = struct { ints: [usize_count]usize, - pub const needed_bit_count = 174; + pub const needed_bit_count = 138; pub const byte_count = (needed_bit_count + 7) / 8; pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize))); @@ -593,6 +247,12 @@ pub const Target = union(enum) { set.ints[usize_index] |= @as(usize, 1) << bit_index; } + /// Adds the specified feature set but not its dependencies. + pub fn addFeatureSet(set: *Set, other_set: Set) void { + set.ints = @as(@Vector(usize_count, usize), set.ints) | + @as(@Vector(usize_count, usize), other_set.ints); + } + /// Removes the specified feature but not its dependents. pub fn removeFeature(set: *Set, arch_feature_index: Index) void { const usize_index = arch_feature_index / @bitSizeOf(usize); @@ -608,8 +268,7 @@ pub const Target = union(enum) { for (all_features_list) |feature, index_usize| { const index = @intCast(Index, index_usize); if (set.isEnabled(index)) { - set.ints = @as(@Vector(usize_count, usize), set.ints) | - @as(@Vector(usize_count, usize), feature.dependencies.ints); + set.addFeatureSet(feature.dependencies); } } const nothing_changed = mem.eql(usize, &old, &set.ints); @@ -644,77 +303,362 @@ pub const Target = union(enum) { }; } }; - }; - pub const ObjectFormat = enum { - unknown, - coff, - elf, - macho, - wasm, - }; + pub const Arch = enum { + arm, + armeb, + aarch64, + aarch64_be, + aarch64_32, + arc, + avr, + bpfel, + bpfeb, + hexagon, + mips, + mipsel, + mips64, + mips64el, + msp430, + powerpc, + powerpc64, + powerpc64le, + r600, + amdgcn, + riscv32, + riscv64, + sparc, + sparcv9, + sparcel, + s390x, + tce, + tcele, + thumb, + thumbeb, + i386, + x86_64, + xcore, + nvptx, + nvptx64, + le32, + le64, + amdil, + amdil64, + hsail, + hsail64, + spir, + spir64, + kalimba, + shave, + lanai, + wasm32, + wasm64, + renderscript32, + renderscript64, - pub const SubSystem = enum { - Console, - Windows, - Posix, - Native, - EfiApplication, - EfiBootServiceDriver, - EfiRom, - EfiRuntimeDriver, - }; - - pub const Cross = struct { - arch: Arch, - os: Os, - abi: Abi, - cpu_features: CpuFeatures, - }; - - pub const CpuFeatures = struct { - /// The CPU to target. It has a set of features - /// which are overridden with the `features` field. - cpu: *const Cpu, - - /// Explicitly provide the entire CPU feature set. - features: Cpu.Feature.Set, - - pub fn initFromCpu(arch: Arch, cpu: *const Cpu) CpuFeatures { - var features = cpu.features; - if (arch.subArchFeature()) |sub_arch_index| { - features.addFeature(sub_arch_index); + pub fn isARM(arch: Arch) bool { + return switch (arch) { + .arm, .armeb => true, + else => false, + }; } - features.populateDependencies(arch.allFeaturesList()); - return CpuFeatures{ - .cpu = cpu, - .features = features, + + pub fn isThumb(arch: Arch) bool { + return switch (arch) { + .thumb, .thumbeb => true, + else => false, + }; + } + + pub fn isWasm(arch: Arch) bool { + return switch (arch) { + .wasm32, .wasm64 => true, + else => false, + }; + } + + pub fn isRISCV(arch: Arch) bool { + return switch (arch) { + .riscv32, .riscv64 => true, + else => false, + }; + } + + pub fn isMIPS(arch: Arch) bool { + return switch (arch) { + .mips, .mipsel, .mips64, .mips64el => true, + else => false, + }; + } + + pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { + for (arch.allCpuModels()) |cpu| { + if (mem.eql(u8, cpu_name, cpu.name)) { + return cpu; + } + } + return error.UnknownCpu; + } + + pub fn toElfMachine(arch: Arch) std.elf.EM { + return switch (arch) { + .avr => ._AVR, + .msp430 => ._MSP430, + .arc => ._ARC, + .arm => ._ARM, + .armeb => ._ARM, + .hexagon => ._HEXAGON, + .le32 => ._NONE, + .mips => ._MIPS, + .mipsel => ._MIPS_RS3_LE, + .powerpc => ._PPC, + .r600 => ._NONE, + .riscv32 => ._RISCV, + .sparc => ._SPARC, + .sparcel => ._SPARC, + .tce => ._NONE, + .tcele => ._NONE, + .thumb => ._ARM, + .thumbeb => ._ARM, + .i386 => ._386, + .xcore => ._XCORE, + .nvptx => ._NONE, + .amdil => ._NONE, + .hsail => ._NONE, + .spir => ._NONE, + .kalimba => ._CSR_KALIMBA, + .shave => ._NONE, + .lanai => ._LANAI, + .wasm32 => ._NONE, + .renderscript32 => ._NONE, + .aarch64_32 => ._AARCH64, + .aarch64 => ._AARCH64, + .aarch64_be => ._AARCH64, + .mips64 => ._MIPS, + .mips64el => ._MIPS_RS3_LE, + .powerpc64 => ._PPC64, + .powerpc64le => ._PPC64, + .riscv64 => ._RISCV, + .x86_64 => ._X86_64, + .nvptx64 => ._NONE, + .le64 => ._NONE, + .amdil64 => ._NONE, + .hsail64 => ._NONE, + .spir64 => ._NONE, + .wasm64 => ._NONE, + .renderscript64 => ._NONE, + .amdgcn => ._NONE, + .bpfel => ._BPF, + .bpfeb => ._BPF, + .sparcv9 => ._SPARCV9, + .s390x => ._S390, + }; + } + + pub fn endian(arch: Arch) builtin.Endian { + return switch (arch) { + .avr, + .arm, + .aarch64_32, + .aarch64, + .amdgcn, + .amdil, + .amdil64, + .bpfel, + .hexagon, + .hsail, + .hsail64, + .kalimba, + .le32, + .le64, + .mipsel, + .mips64el, + .msp430, + .nvptx, + .nvptx64, + .sparcel, + .tcele, + .powerpc64le, + .r600, + .riscv32, + .riscv64, + .i386, + .x86_64, + .wasm32, + .wasm64, + .xcore, + .thumb, + .spir, + .spir64, + .renderscript32, + .renderscript64, + .shave, + => .Little, + + .arc, + .armeb, + .aarch64_be, + .bpfeb, + .mips, + .mips64, + .powerpc, + .powerpc64, + .thumbeb, + .sparc, + .sparcv9, + .tce, + .lanai, + .s390x, + => .Big, + }; + } + + /// Returns a name that matches the lib/std/target/* directory name. + pub fn genericName(arch: Arch) []const u8 { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => "arm", + .aarch64, .aarch64_be, .aarch64_32 => "aarch64", + .avr => "avr", + .bpfel, .bpfeb => "bpf", + .hexagon => "hexagon", + .mips, .mipsel, .mips64, .mips64el => "mips", + .msp430 => "msp430", + .powerpc, .powerpc64, .powerpc64le => "powerpc", + .amdgcn => "amdgpu", + .riscv32, .riscv64 => "riscv", + .sparc, .sparcv9, .sparcel => "sparc", + .s390x => "systemz", + .i386, .x86_64 => "x86", + .nvptx, .nvptx64 => "nvptx", + .wasm32, .wasm64 => "wasm", + else => @tagName(arch), + }; + } + + /// All CPU features Zig is aware of, sorted lexicographically by name. + pub fn allFeaturesList(arch: Arch) []const Cpu.Feature { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.all_features, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features, + .avr => &avr.all_features, + .bpfel, .bpfeb => &bpf.all_features, + .hexagon => &hexagon.all_features, + .mips, .mipsel, .mips64, .mips64el => &mips.all_features, + .msp430 => &msp430.all_features, + .powerpc, .powerpc64, .powerpc64le => &powerpc.all_features, + .amdgcn => &amdgpu.all_features, + .riscv32, .riscv64 => &riscv.all_features, + .sparc, .sparcv9, .sparcel => &sparc.all_features, + .s390x => &systemz.all_features, + .i386, .x86_64 => &x86.all_features, + .nvptx, .nvptx64 => &nvptx.all_features, + .wasm32, .wasm64 => &wasm.all_features, + + else => &[0]Cpu.Feature{}, + }; + } + + /// All processors Zig is aware of, sorted lexicographically by name. + pub fn allCpuModels(arch: Arch) []const *const Cpu.Model { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => arm.all_cpus, + .aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus, + .avr => avr.all_cpus, + .bpfel, .bpfeb => bpf.all_cpus, + .hexagon => hexagon.all_cpus, + .mips, .mipsel, .mips64, .mips64el => mips.all_cpus, + .msp430 => msp430.all_cpus, + .powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus, + .amdgcn => amdgpu.all_cpus, + .riscv32, .riscv64 => riscv.all_cpus, + .sparc, .sparcv9, .sparcel => sparc.all_cpus, + .s390x => systemz.all_cpus, + .i386, .x86_64 => x86.all_cpus, + .nvptx, .nvptx64 => nvptx.all_cpus, + .wasm32, .wasm64 => wasm.all_cpus, + + else => &[0]*const Model{}, + }; + } + + pub fn parse(text: []const u8) !Arch { + if (mem.eql(u8, text, "native")) return builtin.arch; + + const info = @typeInfo(Arch); + inline for (info.Enum.fields) |field| { + if (mem.eql(u8, text, field.name)) { + return @as(Arch, @field(Arch, field.name)); + } + } + return error.UnknownArchitecture; + } + }; + + pub const Model = struct { + name: []const u8, + llvm_name: ?[:0]const u8, + features: Feature.Set, + + pub fn toCpu(model: *const Model, arch: Arch) Cpu { + var features = model.features; + features.populateDependencies(arch.allFeaturesList()); + return .{ + .arch = arch, + .model = model, + .features = features, + }; + } + }; + + /// The "default" set of CPU features for cross-compiling. A conservative set + /// of features that is expected to be supported on most available hardware. + pub fn baseline(arch: Arch) Cpu { + const S = struct { + const generic_model = Model{ + .name = "generic", + .llvm_name = null, + .features = Cpu.Feature.Set.empty, + }; }; + const model = switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, + .avr => &avr.cpu.avr1, + .bpfel, .bpfeb => &bpf.cpu.generic, + .hexagon => &hexagon.cpu.generic, + .mips, .mipsel => &mips.cpu.mips32, + .mips64, .mips64el => &mips.cpu.mips64, + .msp430 => &msp430.cpu.generic, + .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, + .amdgcn => &amdgpu.cpu.generic, + .riscv32 => &riscv.cpu.baseline_rv32, + .riscv64 => &riscv.cpu.baseline_rv64, + .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, + .s390x => &systemz.cpu.generic, + .i386 => &x86.cpu.pentium4, + .x86_64 => &x86.cpu.x86_64, + .nvptx, .nvptx64 => &nvptx.cpu.sm_20, + .wasm32, .wasm64 => &wasm.cpu.generic, + + else => &S.generic_model, + }; + return model.toCpu(arch); } }; pub const current = Target{ .Cross = Cross{ - .arch = builtin.arch, + .cpu = builtin.cpu, .os = builtin.os, .abi = builtin.abi, - .cpu_features = builtin.cpu_features, }, }; pub const stack_align = 16; - pub fn getCpuFeatures(self: Target) CpuFeatures { - return switch (self) { - .Native => builtin.cpu_features, - .Cross => |cross| cross.cpu_features, - }; - } - pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { - return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{ + return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ @tagName(self.getArch()), - Target.archSubArchName(self.getArch()), @tagName(self.getOs()), @tagName(self.getAbi()), }); @@ -776,139 +720,81 @@ pub const Target = union(enum) { }); } - /// TODO: Support CPU features here? - /// https://github.com/ziglang/zig/issues/4261 - pub fn parse(text: []const u8) !Target { - var it = mem.separate(text, "-"); + pub const ParseOptions = struct { + /// This is sometimes called a "triple". It looks roughly like this: + /// riscv64-linux-gnu + /// The fields are, respectively: + /// * CPU Architecture + /// * Operating System + /// * C ABI (optional) + /// "native" can be used for any of the fields. + arch_os_abi: []const u8, + + /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" + /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features + /// to remove from the set. + /// The default value of `null` means to use the "baseline" feature set. + /// "native" can be used to perform CPU introspection. + cpu: ?[]const u8 = null, + }; + + pub fn parse(args: ParseOptions) !Target { + var it = mem.separate(args.arch_os_abi, "-"); const arch_name = it.next() orelse return error.MissingArchitecture; const os_name = it.next() orelse return error.MissingOperatingSystem; const abi_name = it.next(); - const arch = try parseArchSub(arch_name); + if (it.next() != null) return error.UnexpectedExtraField; - var cross = Cross{ - .arch = arch, - .cpu_features = arch.getBaselineCpuFeatures(), - .os = try parseOs(os_name), - .abi = undefined, - }; - cross.abi = if (abi_name) |n| try parseAbi(n) else defaultAbi(cross.arch, cross.os); - return Target{ .Cross = cross }; - } + const arch = try Cpu.Arch.parse(arch_name); + const os = try Os.parse(os_name); + const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os); - pub fn defaultAbi(arch: Arch, target_os: Os) Abi { - switch (arch) { - .wasm32, .wasm64 => return .musl, - else => {}, - } - switch (target_os) { - .freestanding, - .ananas, - .cloudabi, - .dragonfly, - .lv2, - .solaris, - .haiku, - .minix, - .rtems, - .nacl, - .cnk, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .other, - => return .eabi, - .openbsd, - .macosx, - .freebsd, - .ios, - .tvos, - .watchos, - .fuchsia, - .kfreebsd, - .netbsd, - .hurd, - => return .gnu, - .windows, - .uefi, - => return .msvc, - .linux, - .wasi, - .emscripten, - => return .musl, - } - } + const all_features = arch.allFeaturesList(); + const cpu: Cpu = if (args.cpu) |cpu_text| blk: { + var index: usize = 0; + while (index < cpu_text.len and cpu_text[index] != '+' and cpu_text[index] != '-') { + index += 1; + } + const cpu_name = cpu_text[0..index]; + const cpu_model = try arch.parseCpuModel(cpu_name); - pub const ParseArchSubError = error{ - UnknownArchitecture, - UnknownSubArchitecture, - }; - - pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch { - const info = @typeInfo(Arch); - inline for (info.Union.fields) |field| { - if (mem.startsWith(u8, text, field.name)) { - if (field.field_type == void) { - return @as(Arch, @field(Arch, field.name)); - } else { - const sub_info = @typeInfo(field.field_type); - inline for (sub_info.Enum.fields) |sub_field| { - const combined = field.name ++ sub_field.name; - if (mem.eql(u8, text, combined)) { - return @unionInit(Arch, field.name, @field(field.field_type, sub_field.name)); + var set = cpu_model.features; + while (index < cpu_text.len) { + const op = cpu_text[index]; + index += 1; + const start = index; + while (index < cpu_text.len and cpu_text[index] != '+' and cpu_text[index] != '-') { + index += 1; + } + const feature_name = cpu_text[start..index]; + for (all_features) |feature, feat_index_usize| { + const feat_index = @intCast(Cpu.Feature.Set.Index, feat_index_usize); + if (mem.eql(u8, feature_name, feature.name)) { + switch (op) { + '+' => set.addFeature(feat_index), + '-' => set.removeFeature(feat_index), + else => unreachable, } + break; } - return error.UnknownSubArchitecture; + } else { + return error.UnknownCpuFeature; } } - } - return error.UnknownArchitecture; - } + set.populateDependencies(all_features); + break :blk .{ + .arch = arch, + .model = cpu_model, + .features = set, + }; + } else Cpu.baseline(arch); - pub fn parseOs(text: []const u8) !Os { - const info = @typeInfo(Os); - inline for (info.Enum.fields) |field| { - if (mem.eql(u8, text, field.name)) { - return @field(Os, field.name); - } - } - return error.UnknownOperatingSystem; - } - - pub fn parseAbi(text: []const u8) !Abi { - const info = @typeInfo(Abi); - inline for (info.Enum.fields) |field| { - if (mem.eql(u8, text, field.name)) { - return @field(Abi, field.name); - } - } - return error.UnknownApplicationBinaryInterface; - } - - fn archSubArchName(arch: Arch) []const u8 { - return switch (arch) { - .arm => |sub| @tagName(sub), - .armeb => |sub| @tagName(sub), - .thumb => |sub| @tagName(sub), - .thumbeb => |sub| @tagName(sub), - .aarch64 => |sub| @tagName(sub), - .aarch64_be => |sub| @tagName(sub), - .kalimba => |sub| @tagName(sub), - else => "", + var cross = Cross{ + .cpu = cpu, + .os = os, + .abi = abi, }; - } - - pub fn subArchName(self: Target) []const u8 { - switch (self) { - .Native => return archSubArchName(builtin.arch), - .Cross => |cross| return archSubArchName(cross.arch), - } + return Target{ .Cross = cross }; } pub fn oFileExt(self: Target) []const u8 { @@ -967,11 +853,15 @@ pub const Target = union(enum) { }; } - pub fn getArch(self: Target) Arch { - switch (self) { - .Native => return builtin.arch, - .Cross => |t| return t.arch, - } + pub fn getCpu(self: Target) Cpu { + return switch (self) { + .Native => builtin.cpu, + .Cross => |cross| cross.cpu, + }; + } + + pub fn getArch(self: Target) Cpu.Arch { + return self.getCpu().arch; } pub fn getAbi(self: Target) Abi { @@ -1372,14 +1262,32 @@ pub const Target = union(enum) { } }; -test "parseCpuFeatureSet" { - const arch: Target.Arch = .x86_64; - const baseline = arch.getBaselineCpuFeatures(); - const set = try arch.parseCpuFeatureSet(baseline.cpu, "-sse,-avx,-cx8"); - std.testing.expect(!Target.x86.featureSetHas(set, .sse)); - std.testing.expect(!Target.x86.featureSetHas(set, .avx)); - std.testing.expect(!Target.x86.featureSetHas(set, .cx8)); - // These are expected because they are part of the baseline - std.testing.expect(Target.x86.featureSetHas(set, .cmov)); - std.testing.expect(Target.x86.featureSetHas(set, .fxsr)); +test "Target.parse" { + { + const target = (try Target.parse(.{ + .arch_os_abi = "x86_64-linux-gnu", + .cpu = "x86_64-sse-avx-cx8", + })).Cross; + + std.testing.expect(target.os == .linux); + std.testing.expect(target.abi == .gnu); + std.testing.expect(target.cpu.arch == .x86_64); + std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); + std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); + std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); + std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); + std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); + } + { + const target = (try Target.parse(.{ + .arch_os_abi = "arm-linux-musleabihf", + .cpu = "generic+v8a", + })).Cross; + + std.testing.expect(target.os == .linux); + std.testing.expect(target.abi == .musleabihf); + std.testing.expect(target.cpu.arch == .arm); + std.testing.expect(target.cpu.model == &Target.arm.cpu.generic); + std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a)); + } } diff --git a/lib/std/target/aarch64.zig b/lib/std/target/aarch64.zig index d2878e2423..40d3ea96ba 100644 --- a/lib/std/target/aarch64.zig +++ b/lib/std/target/aarch64.zig @@ -1,14 +1,8 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { - a35, - a53, - a55, - a57, - a72, - a73, - a75, a76, aes, aggressive_fma, @@ -40,11 +34,7 @@ pub const Feature = enum { dit, dotprod, exynos_cheap_as_move, - exynosm1, - exynosm2, - exynosm3, exynosm4, - falkor, fmi, force_32bit_jump_tables, fp_armv8, @@ -58,7 +48,6 @@ pub const Feature = enum { fuse_csel, fuse_literals, jsconv, - kryo, lor, lse, lsl_fast, @@ -103,7 +92,6 @@ pub const Feature = enum { reserve_x6, reserve_x7, reserve_x9, - saphira, sb, sel2, sha2, @@ -122,17 +110,11 @@ pub const Feature = enum { sve2_bitperm, sve2_sha3, sve2_sm4, - thunderx, - thunderx2t99, - thunderxt81, - thunderxt83, - thunderxt88, tlb_rmi, tpidr_el1, tpidr_el2, tpidr_el3, tracev8_4, - tsv110, uaops, use_aa, use_postra_scheduler, @@ -151,120 +133,20 @@ pub const Feature = enum { zcz_gp, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { @setEvalBranchQuota(2000); const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; - result[@enumToInt(Feature.a35)] = .{ - .llvm_name = "a35", - .description = "Cortex-A35 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .neon, - .perfmon, - }), - }; - result[@enumToInt(Feature.a53)] = .{ - .llvm_name = "a53", - .description = "Cortex-A53 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .balance_fp_ops, - .crc, - .crypto, - .custom_cheap_as_move, - .fp_armv8, - .fuse_aes, - .neon, - .perfmon, - .use_aa, - .use_postra_scheduler, - }), - }; - result[@enumToInt(Feature.a55)] = .{ - .llvm_name = "a55", - .description = "Cortex-A55 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .fp_armv8, - .fullfp16, - .fuse_aes, - .neon, - .perfmon, - .rcpc, - .v8_2a, - }), - }; - result[@enumToInt(Feature.a57)] = .{ - .llvm_name = "a57", - .description = "Cortex-A57 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .balance_fp_ops, - .crc, - .crypto, - .custom_cheap_as_move, - .fp_armv8, - .fuse_aes, - .fuse_literals, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@enumToInt(Feature.a72)] = .{ - .llvm_name = "a72", - .description = "Cortex-A72 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .fuse_aes, - .neon, - .perfmon, - }), - }; - result[@enumToInt(Feature.a73)] = .{ - .llvm_name = "a73", - .description = "Cortex-A73 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .fuse_aes, - .neon, - .perfmon, - }), - }; - result[@enumToInt(Feature.a75)] = .{ - .llvm_name = "a75", - .description = "Cortex-A75 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .fp_armv8, - .fullfp16, - .fuse_aes, - .neon, - .perfmon, - .rcpc, - .v8_2a, - }), - }; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.a76)] = .{ .llvm_name = "a76", .description = "Cortex-A76 ARM processors", .dependencies = featureSet(&[_]Feature{ .crypto, .dotprod, - .fp_armv8, .fullfp16, - .neon, .rcpc, .ssbs, .v8_2a, @@ -412,11 +294,10 @@ pub const all_features = blk: { .arith_cbz_fusion, .crypto, .disable_latency_sched_heuristic, - .fp_armv8, .fuse_aes, .fuse_crypto_eor, - .neon, .perfmon, + .v8a, .zcm, .zcz, .zcz_fp_workaround, @@ -444,58 +325,6 @@ pub const all_features = blk: { .custom_cheap_as_move, }), }; - result[@enumToInt(Feature.exynosm1)] = .{ - .llvm_name = "exynosm1", - .description = "Samsung Exynos-M1 processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_aes, - .perfmon, - .slow_misaligned_128store, - .slow_paired_128, - .use_postra_scheduler, - .use_reciprocal_square_root, - .zcz_fp, - }), - }; - result[@enumToInt(Feature.exynosm2)] = .{ - .llvm_name = "exynosm2", - .description = "Samsung Exynos-M2 processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_aes, - .perfmon, - .slow_misaligned_128store, - .slow_paired_128, - .use_postra_scheduler, - .zcz_fp, - }), - }; - result[@enumToInt(Feature.exynosm3)] = .{ - .llvm_name = "exynosm3", - .description = "Samsung Exynos-M3 processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_address, - .fuse_aes, - .fuse_csel, - .fuse_literals, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .zcz_fp, - }), - }; result[@enumToInt(Feature.exynosm4)] = .{ .llvm_name = "exynosm4", .description = "Samsung Exynos-M4 processors", @@ -519,24 +348,6 @@ pub const all_features = blk: { .zcz, }), }; - result[@enumToInt(Feature.falkor)] = .{ - .llvm_name = "falkor", - .description = "Qualcomm Falkor processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .custom_cheap_as_move, - .fp_armv8, - .lsl_fast, - .neon, - .perfmon, - .predictable_select_expensive, - .rdm, - .slow_strqro_store, - .use_postra_scheduler, - .zcz, - }), - }; result[@enumToInt(Feature.fmi)] = .{ .llvm_name = "fmi", .description = "Enable v8.4-A Flag Manipulation Instructions", @@ -608,22 +419,6 @@ pub const all_features = blk: { .fp_armv8, }), }; - result[@enumToInt(Feature.kryo)] = .{ - .llvm_name = "kryo", - .description = "Qualcomm Kryo processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .custom_cheap_as_move, - .fp_armv8, - .lsl_fast, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .zcz, - }), - }; result[@enumToInt(Feature.lor)] = .{ .llvm_name = "lor", .description = "Enables ARM v8.1 Limited Ordering Regions extension", @@ -852,23 +647,6 @@ pub const all_features = blk: { .description = "Reserve X9, making it unavailable as a GPR", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.saphira)] = .{ - .llvm_name = "saphira", - .description = "Qualcomm Saphira processors", - .dependencies = featureSet(&[_]Feature{ - .crypto, - .custom_cheap_as_move, - .fp_armv8, - .lsl_fast, - .neon, - .perfmon, - .predictable_select_expensive, - .spe, - .use_postra_scheduler, - .v8_4a, - .zcz, - }), - }; result[@enumToInt(Feature.sb)] = .{ .llvm_name = "sb", .description = "Enable v8.5 Speculation Barrier", @@ -979,74 +757,6 @@ pub const all_features = blk: { .sve2, }), }; - result[@enumToInt(Feature.thunderx)] = .{ - .llvm_name = "thunderx", - .description = "Cavium ThunderX processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@enumToInt(Feature.thunderx2t99)] = .{ - .llvm_name = "thunderx2t99", - .description = "Cavium ThunderX2 processors", - .dependencies = featureSet(&[_]Feature{ - .aggressive_fma, - .arith_bcc_fusion, - .crc, - .crypto, - .fp_armv8, - .lse, - .neon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8_1a, - }), - }; - result[@enumToInt(Feature.thunderxt81)] = .{ - .llvm_name = "thunderxt81", - .description = "Cavium ThunderX processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@enumToInt(Feature.thunderxt83)] = .{ - .llvm_name = "thunderxt83", - .description = "Cavium ThunderX processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@enumToInt(Feature.thunderxt88)] = .{ - .llvm_name = "thunderxt88", - .description = "Cavium ThunderX processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .fp_armv8, - .neon, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; result[@enumToInt(Feature.tlb_rmi)] = .{ .llvm_name = "tlb-rmi", .description = "Enable v8.4-A TLB Range and Maintenance Instructions", @@ -1072,24 +782,6 @@ pub const all_features = blk: { .description = "Enable v8.4-A Trace extension", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.tsv110)] = .{ - .llvm_name = "tsv110", - .description = "HiSilicon TS-V110 processors", - .dependencies = featureSet(&[_]Feature{ - .crypto, - .custom_cheap_as_move, - .dotprod, - .fp_armv8, - .fp16fml, - .fullfp16, - .fuse_aes, - .neon, - .perfmon, - .spe, - .use_postra_scheduler, - .v8_2a, - }), - }; result[@enumToInt(Feature.uaops)] = .{ .llvm_name = "uaops", .description = "Enable v8.2 UAO PState", @@ -1229,190 +921,325 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const apple_latest = Cpu{ + pub const apple_latest = CpuModel{ .name = "apple_latest", .llvm_name = "apple-latest", .features = featureSet(&[_]Feature{ .cyclone, }), }; - pub const cortex_a35 = Cpu{ + pub const cortex_a35 = CpuModel{ .name = "cortex_a35", .llvm_name = "cortex-a35", .features = featureSet(&[_]Feature{ - .a35, + .crc, + .crypto, + .perfmon, + .v8a, }), }; - pub const cortex_a53 = Cpu{ + pub const cortex_a53 = CpuModel{ .name = "cortex_a53", .llvm_name = "cortex-a53", .features = featureSet(&[_]Feature{ - .a53, + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .fuse_aes, + .perfmon, + .use_aa, + .use_postra_scheduler, + .v8a, }), }; - pub const cortex_a55 = Cpu{ + pub const cortex_a55 = CpuModel{ .name = "cortex_a55", .llvm_name = "cortex-a55", .features = featureSet(&[_]Feature{ - .a55, + .crypto, + .dotprod, + .fullfp16, + .fuse_aes, + .perfmon, + .rcpc, + .v8_2a, }), }; - pub const cortex_a57 = Cpu{ + pub const cortex_a57 = CpuModel{ .name = "cortex_a57", .llvm_name = "cortex-a57", .features = featureSet(&[_]Feature{ - .a57, + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .fuse_aes, + .fuse_literals, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, }), }; - pub const cortex_a72 = Cpu{ + pub const cortex_a72 = CpuModel{ .name = "cortex_a72", .llvm_name = "cortex-a72", .features = featureSet(&[_]Feature{ - .a72, + .crc, + .crypto, + .fuse_aes, + .perfmon, + .v8a, }), }; - pub const cortex_a73 = Cpu{ + pub const cortex_a73 = CpuModel{ .name = "cortex_a73", .llvm_name = "cortex-a73", .features = featureSet(&[_]Feature{ - .a73, + .crc, + .crypto, + .fuse_aes, + .perfmon, + .v8a, }), }; - pub const cortex_a75 = Cpu{ + pub const cortex_a75 = CpuModel{ .name = "cortex_a75", .llvm_name = "cortex-a75", .features = featureSet(&[_]Feature{ - .a75, + .crypto, + .dotprod, + .fullfp16, + .fuse_aes, + .perfmon, + .rcpc, + .v8_2a, }), }; - pub const cortex_a76 = Cpu{ + pub const cortex_a76 = CpuModel{ .name = "cortex_a76", .llvm_name = "cortex-a76", .features = featureSet(&[_]Feature{ .a76, }), }; - pub const cortex_a76ae = Cpu{ + pub const cortex_a76ae = CpuModel{ .name = "cortex_a76ae", .llvm_name = "cortex-a76ae", .features = featureSet(&[_]Feature{ .a76, }), }; - pub const cyclone = Cpu{ + pub const cyclone = CpuModel{ .name = "cyclone", .llvm_name = "cyclone", .features = featureSet(&[_]Feature{ .cyclone, }), }; - pub const exynos_m1 = Cpu{ + pub const exynos_m1 = CpuModel{ .name = "exynos_m1", .llvm_name = "exynos-m1", .features = featureSet(&[_]Feature{ - .exynosm1, + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .use_reciprocal_square_root, + .v8a, + .zcz_fp, }), }; - pub const exynos_m2 = Cpu{ + pub const exynos_m2 = CpuModel{ .name = "exynos_m2", .llvm_name = "exynos-m2", .features = featureSet(&[_]Feature{ - .exynosm2, + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .v8a, + .zcz_fp, }), }; - pub const exynos_m3 = Cpu{ + pub const exynos_m3 = CpuModel{ .name = "exynos_m3", .llvm_name = "exynos-m3", .features = featureSet(&[_]Feature{ - .exynosm3, + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_address, + .fuse_aes, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + .zcz_fp, }), }; - pub const exynos_m4 = Cpu{ + pub const exynos_m4 = CpuModel{ .name = "exynos_m4", .llvm_name = "exynos-m4", .features = featureSet(&[_]Feature{ .exynosm4, }), }; - pub const exynos_m5 = Cpu{ + pub const exynos_m5 = CpuModel{ .name = "exynos_m5", .llvm_name = "exynos-m5", .features = featureSet(&[_]Feature{ .exynosm4, }), }; - pub const falkor = Cpu{ + pub const falkor = CpuModel{ .name = "falkor", .llvm_name = "falkor", .features = featureSet(&[_]Feature{ - .falkor, + .crc, + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rdm, + .slow_strqro_store, + .use_postra_scheduler, + .v8a, + .zcz, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{ - .fp_armv8, .fuse_aes, - .neon, .perfmon, .use_postra_scheduler, + .v8a, }), }; - pub const kryo = Cpu{ + pub const kryo = CpuModel{ .name = "kryo", .llvm_name = "kryo", .features = featureSet(&[_]Feature{ - .kryo, + .crc, + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .zcz, + .v8a, }), }; - pub const saphira = Cpu{ + pub const saphira = CpuModel{ .name = "saphira", .llvm_name = "saphira", .features = featureSet(&[_]Feature{ - .saphira, + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .spe, + .use_postra_scheduler, + .v8_4a, + .zcz, }), }; - pub const thunderx = Cpu{ + pub const thunderx = CpuModel{ .name = "thunderx", .llvm_name = "thunderx", .features = featureSet(&[_]Feature{ - .thunderx, + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, }), }; - pub const thunderx2t99 = Cpu{ + pub const thunderx2t99 = CpuModel{ .name = "thunderx2t99", .llvm_name = "thunderx2t99", .features = featureSet(&[_]Feature{ - .thunderx2t99, + .aggressive_fma, + .arith_bcc_fusion, + .crc, + .crypto, + .lse, + .predictable_select_expensive, + .use_postra_scheduler, + .v8_1a, }), }; - pub const thunderxt81 = Cpu{ + pub const thunderxt81 = CpuModel{ .name = "thunderxt81", .llvm_name = "thunderxt81", .features = featureSet(&[_]Feature{ - .thunderxt81, + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, }), }; - pub const thunderxt83 = Cpu{ + pub const thunderxt83 = CpuModel{ .name = "thunderxt83", .llvm_name = "thunderxt83", .features = featureSet(&[_]Feature{ - .thunderxt83, + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, }), }; - pub const thunderxt88 = Cpu{ + pub const thunderxt88 = CpuModel{ .name = "thunderxt88", .llvm_name = "thunderxt88", .features = featureSet(&[_]Feature{ - .thunderxt88, + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, }), }; - pub const tsv110 = Cpu{ + pub const tsv110 = CpuModel{ .name = "tsv110", .llvm_name = "tsv110", .features = featureSet(&[_]Feature{ - .tsv110, + .crypto, + .custom_cheap_as_move, + .dotprod, + .fp16fml, + .fullfp16, + .fuse_aes, + .perfmon, + .spe, + .use_postra_scheduler, + .v8_2a, }), }; }; @@ -1420,7 +1247,7 @@ pub const cpu = struct { /// All aarch64 CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.apple_latest, &cpu.cortex_a35, &cpu.cortex_a53, diff --git a/lib/std/target/amdgpu.zig b/lib/std/target/amdgpu.zig index 182b9fa453..e524dc12a2 100644 --- a/lib/std/target/amdgpu.zig +++ b/lib/std/target/amdgpu.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { @"16_bit_insts", @@ -111,12 +112,12 @@ pub const Feature = enum { xnack, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.@"16_bit_insts")] = .{ .llvm_name = "16-bit-insts", .description = "Has i16/f16 instructions", @@ -778,7 +779,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const bonaire = Cpu{ + pub const bonaire = CpuModel{ .name = "bonaire", .llvm_name = "bonaire", .features = featureSet(&[_]Feature{ @@ -788,7 +789,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const carrizo = Cpu{ + pub const carrizo = CpuModel{ .name = "carrizo", .llvm_name = "carrizo", .features = featureSet(&[_]Feature{ @@ -801,7 +802,7 @@ pub const cpu = struct { .xnack, }), }; - pub const fiji = Cpu{ + pub const fiji = CpuModel{ .name = "fiji", .llvm_name = "fiji", .features = featureSet(&[_]Feature{ @@ -812,14 +813,14 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{ .wavefrontsize64, }), }; - pub const generic_hsa = Cpu{ + pub const generic_hsa = CpuModel{ .name = "generic_hsa", .llvm_name = "generic-hsa", .features = featureSet(&[_]Feature{ @@ -827,7 +828,7 @@ pub const cpu = struct { .wavefrontsize64, }), }; - pub const gfx1010 = Cpu{ + pub const gfx1010 = CpuModel{ .name = "gfx1010", .llvm_name = "gfx1010", .features = featureSet(&[_]Feature{ @@ -853,7 +854,7 @@ pub const cpu = struct { .wavefrontsize32, }), }; - pub const gfx1011 = Cpu{ + pub const gfx1011 = CpuModel{ .name = "gfx1011", .llvm_name = "gfx1011", .features = featureSet(&[_]Feature{ @@ -882,7 +883,7 @@ pub const cpu = struct { .wavefrontsize32, }), }; - pub const gfx1012 = Cpu{ + pub const gfx1012 = CpuModel{ .name = "gfx1012", .llvm_name = "gfx1012", .features = featureSet(&[_]Feature{ @@ -912,7 +913,7 @@ pub const cpu = struct { .wavefrontsize32, }), }; - pub const gfx600 = Cpu{ + pub const gfx600 = CpuModel{ .name = "gfx600", .llvm_name = "gfx600", .features = featureSet(&[_]Feature{ @@ -924,7 +925,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const gfx601 = Cpu{ + pub const gfx601 = CpuModel{ .name = "gfx601", .llvm_name = "gfx601", .features = featureSet(&[_]Feature{ @@ -934,7 +935,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const gfx700 = Cpu{ + pub const gfx700 = CpuModel{ .name = "gfx700", .llvm_name = "gfx700", .features = featureSet(&[_]Feature{ @@ -944,7 +945,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const gfx701 = Cpu{ + pub const gfx701 = CpuModel{ .name = "gfx701", .llvm_name = "gfx701", .features = featureSet(&[_]Feature{ @@ -956,7 +957,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const gfx702 = Cpu{ + pub const gfx702 = CpuModel{ .name = "gfx702", .llvm_name = "gfx702", .features = featureSet(&[_]Feature{ @@ -967,7 +968,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const gfx703 = Cpu{ + pub const gfx703 = CpuModel{ .name = "gfx703", .llvm_name = "gfx703", .features = featureSet(&[_]Feature{ @@ -977,7 +978,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const gfx704 = Cpu{ + pub const gfx704 = CpuModel{ .name = "gfx704", .llvm_name = "gfx704", .features = featureSet(&[_]Feature{ @@ -987,7 +988,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const gfx801 = Cpu{ + pub const gfx801 = CpuModel{ .name = "gfx801", .llvm_name = "gfx801", .features = featureSet(&[_]Feature{ @@ -1000,7 +1001,7 @@ pub const cpu = struct { .xnack, }), }; - pub const gfx802 = Cpu{ + pub const gfx802 = CpuModel{ .name = "gfx802", .llvm_name = "gfx802", .features = featureSet(&[_]Feature{ @@ -1012,7 +1013,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const gfx803 = Cpu{ + pub const gfx803 = CpuModel{ .name = "gfx803", .llvm_name = "gfx803", .features = featureSet(&[_]Feature{ @@ -1023,7 +1024,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const gfx810 = Cpu{ + pub const gfx810 = CpuModel{ .name = "gfx810", .llvm_name = "gfx810", .features = featureSet(&[_]Feature{ @@ -1033,7 +1034,7 @@ pub const cpu = struct { .xnack, }), }; - pub const gfx900 = Cpu{ + pub const gfx900 = CpuModel{ .name = "gfx900", .llvm_name = "gfx900", .features = featureSet(&[_]Feature{ @@ -1045,7 +1046,7 @@ pub const cpu = struct { .no_xnack_support, }), }; - pub const gfx902 = Cpu{ + pub const gfx902 = CpuModel{ .name = "gfx902", .llvm_name = "gfx902", .features = featureSet(&[_]Feature{ @@ -1057,7 +1058,7 @@ pub const cpu = struct { .xnack, }), }; - pub const gfx904 = Cpu{ + pub const gfx904 = CpuModel{ .name = "gfx904", .llvm_name = "gfx904", .features = featureSet(&[_]Feature{ @@ -1069,7 +1070,7 @@ pub const cpu = struct { .no_xnack_support, }), }; - pub const gfx906 = Cpu{ + pub const gfx906 = CpuModel{ .name = "gfx906", .llvm_name = "gfx906", .features = featureSet(&[_]Feature{ @@ -1084,7 +1085,7 @@ pub const cpu = struct { .no_xnack_support, }), }; - pub const gfx908 = Cpu{ + pub const gfx908 = CpuModel{ .name = "gfx908", .llvm_name = "gfx908", .features = featureSet(&[_]Feature{ @@ -1106,7 +1107,7 @@ pub const cpu = struct { .sram_ecc, }), }; - pub const gfx909 = Cpu{ + pub const gfx909 = CpuModel{ .name = "gfx909", .llvm_name = "gfx909", .features = featureSet(&[_]Feature{ @@ -1117,7 +1118,7 @@ pub const cpu = struct { .xnack, }), }; - pub const hainan = Cpu{ + pub const hainan = CpuModel{ .name = "hainan", .llvm_name = "hainan", .features = featureSet(&[_]Feature{ @@ -1127,7 +1128,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const hawaii = Cpu{ + pub const hawaii = CpuModel{ .name = "hawaii", .llvm_name = "hawaii", .features = featureSet(&[_]Feature{ @@ -1139,7 +1140,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const iceland = Cpu{ + pub const iceland = CpuModel{ .name = "iceland", .llvm_name = "iceland", .features = featureSet(&[_]Feature{ @@ -1151,7 +1152,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const kabini = Cpu{ + pub const kabini = CpuModel{ .name = "kabini", .llvm_name = "kabini", .features = featureSet(&[_]Feature{ @@ -1161,7 +1162,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const kaveri = Cpu{ + pub const kaveri = CpuModel{ .name = "kaveri", .llvm_name = "kaveri", .features = featureSet(&[_]Feature{ @@ -1171,7 +1172,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const mullins = Cpu{ + pub const mullins = CpuModel{ .name = "mullins", .llvm_name = "mullins", .features = featureSet(&[_]Feature{ @@ -1181,7 +1182,7 @@ pub const cpu = struct { .sea_islands, }), }; - pub const oland = Cpu{ + pub const oland = CpuModel{ .name = "oland", .llvm_name = "oland", .features = featureSet(&[_]Feature{ @@ -1191,7 +1192,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const pitcairn = Cpu{ + pub const pitcairn = CpuModel{ .name = "pitcairn", .llvm_name = "pitcairn", .features = featureSet(&[_]Feature{ @@ -1201,7 +1202,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const polaris10 = Cpu{ + pub const polaris10 = CpuModel{ .name = "polaris10", .llvm_name = "polaris10", .features = featureSet(&[_]Feature{ @@ -1212,7 +1213,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const polaris11 = Cpu{ + pub const polaris11 = CpuModel{ .name = "polaris11", .llvm_name = "polaris11", .features = featureSet(&[_]Feature{ @@ -1223,7 +1224,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const stoney = Cpu{ + pub const stoney = CpuModel{ .name = "stoney", .llvm_name = "stoney", .features = featureSet(&[_]Feature{ @@ -1233,7 +1234,7 @@ pub const cpu = struct { .xnack, }), }; - pub const tahiti = Cpu{ + pub const tahiti = CpuModel{ .name = "tahiti", .llvm_name = "tahiti", .features = featureSet(&[_]Feature{ @@ -1245,7 +1246,7 @@ pub const cpu = struct { .southern_islands, }), }; - pub const tonga = Cpu{ + pub const tonga = CpuModel{ .name = "tonga", .llvm_name = "tonga", .features = featureSet(&[_]Feature{ @@ -1257,7 +1258,7 @@ pub const cpu = struct { .volcanic_islands, }), }; - pub const verde = Cpu{ + pub const verde = CpuModel{ .name = "verde", .llvm_name = "verde", .features = featureSet(&[_]Feature{ @@ -1272,7 +1273,7 @@ pub const cpu = struct { /// All amdgpu CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.bonaire, &cpu.carrizo, &cpu.fiji, diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index 48e9576004..e9b95ee4d3 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -390,14 +390,14 @@ pub const all_features = blk: { .llvm_name = "iwmmxt", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; result[@enumToInt(Feature.iwmmxt2)] = .{ .llvm_name = "iwmmxt2", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; result[@enumToInt(Feature.lob)] = .{ @@ -1089,7 +1089,7 @@ pub const all_features = blk: { .llvm_name = "xscale", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; result[@enumToInt(Feature.zcz)] = .{ @@ -1110,49 +1110,49 @@ pub const cpu = struct { .name = "arm1020e", .llvm_name = "arm1020e", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm1020t = CpuModel{ .name = "arm1020t", .llvm_name = "arm1020t", .features = featureSet(&[_]Feature{ - .armv5t, + .v5t, }), }; pub const arm1022e = CpuModel{ .name = "arm1022e", .llvm_name = "arm1022e", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm10e = CpuModel{ .name = "arm10e", .llvm_name = "arm10e", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm10tdmi = CpuModel{ .name = "arm10tdmi", .llvm_name = "arm10tdmi", .features = featureSet(&[_]Feature{ - .armv5t, + .v5t, }), }; pub const arm1136j_s = CpuModel{ .name = "arm1136j_s", .llvm_name = "arm1136j-s", .features = featureSet(&[_]Feature{ - .armv6, + .v6, }), }; pub const arm1136jf_s = CpuModel{ .name = "arm1136jf_s", .llvm_name = "arm1136jf-s", .features = featureSet(&[_]Feature{ - .armv6, + .v6, .slowfpvmlx, .vfp2, }), @@ -1161,14 +1161,14 @@ pub const cpu = struct { .name = "arm1156t2_s", .llvm_name = "arm1156t2-s", .features = featureSet(&[_]Feature{ - .armv6t2, + .v6t2, }), }; pub const arm1156t2f_s = CpuModel{ .name = "arm1156t2f_s", .llvm_name = "arm1156t2f-s", .features = featureSet(&[_]Feature{ - .armv6t2, + .v6t2, .slowfpvmlx, .vfp2, }), @@ -1177,21 +1177,21 @@ pub const cpu = struct { .name = "arm1176j_s", .llvm_name = "arm1176j-s", .features = featureSet(&[_]Feature{ - .armv6kz, + .v6kz, }), }; pub const arm1176jz_s = CpuModel{ .name = "arm1176jz_s", .llvm_name = "arm1176jz-s", .features = featureSet(&[_]Feature{ - .armv6kz, + .v6kz, }), }; pub const arm1176jzf_s = CpuModel{ .name = "arm1176jzf_s", .llvm_name = "arm1176jzf-s", .features = featureSet(&[_]Feature{ - .armv6kz, + .v6kz, .slowfpvmlx, .vfp2, }), @@ -1200,134 +1200,133 @@ pub const cpu = struct { .name = "arm710t", .llvm_name = "arm710t", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm720t = CpuModel{ .name = "arm720t", .llvm_name = "arm720t", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm7tdmi = CpuModel{ .name = "arm7tdmi", .llvm_name = "arm7tdmi", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm7tdmi_s = CpuModel{ .name = "arm7tdmi_s", .llvm_name = "arm7tdmi-s", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm8 = CpuModel{ .name = "arm8", .llvm_name = "arm8", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const arm810 = CpuModel{ .name = "arm810", .llvm_name = "arm810", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const arm9 = CpuModel{ .name = "arm9", .llvm_name = "arm9", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm920 = CpuModel{ .name = "arm920", .llvm_name = "arm920", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm920t = CpuModel{ .name = "arm920t", .llvm_name = "arm920t", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm922t = CpuModel{ .name = "arm922t", .llvm_name = "arm922t", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm926ej_s = CpuModel{ .name = "arm926ej_s", .llvm_name = "arm926ej-s", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm940t = CpuModel{ .name = "arm940t", .llvm_name = "arm940t", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const arm946e_s = CpuModel{ .name = "arm946e_s", .llvm_name = "arm946e-s", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm966e_s = CpuModel{ .name = "arm966e_s", .llvm_name = "arm966e-s", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm968e_s = CpuModel{ .name = "arm968e_s", .llvm_name = "arm968e-s", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm9e = CpuModel{ .name = "arm9e", .llvm_name = "arm9e", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const arm9tdmi = CpuModel{ .name = "arm9tdmi", .llvm_name = "arm9tdmi", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const baseline = CpuModel{ .name = "baseline", .llvm_name = "generic", .features = featureSet(&[_]Feature{ - .armv6_m, + .v6m, }), }; pub const cortex_a12 = CpuModel{ .name = "cortex_a12", .llvm_name = "cortex-a12", .features = featureSet(&[_]Feature{ - .a12, - .armv7_a, + .v7a, .avoid_partial_cpsr, .mp, .ret_addr_stack, @@ -1341,7 +1340,7 @@ pub const cpu = struct { .name = "cortex_a15", .llvm_name = "cortex-a15", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .avoid_partial_cpsr, .dont_widen_vmovs, .mp, @@ -1358,7 +1357,7 @@ pub const cpu = struct { .name = "cortex_a17", .llvm_name = "cortex-a17", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .avoid_partial_cpsr, .mp, .ret_addr_stack, @@ -1372,7 +1371,7 @@ pub const cpu = struct { .name = "cortex_a32", .llvm_name = "cortex-a32", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .crc, .crypto, .hwdiv, @@ -1383,7 +1382,7 @@ pub const cpu = struct { .name = "cortex_a35", .llvm_name = "cortex-a35", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .crc, .crypto, .hwdiv, @@ -1394,7 +1393,7 @@ pub const cpu = struct { .name = "cortex_a5", .llvm_name = "cortex-a5", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .mp, .ret_addr_stack, .slow_fp_brcc, @@ -1408,7 +1407,7 @@ pub const cpu = struct { .name = "cortex_a53", .llvm_name = "cortex-a53", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .crc, .crypto, .fpao, @@ -1420,7 +1419,7 @@ pub const cpu = struct { .name = "cortex_a55", .llvm_name = "cortex-a55", .features = featureSet(&[_]Feature{ - .armv8_2_a, + .v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1430,7 +1429,7 @@ pub const cpu = struct { .name = "cortex_a57", .llvm_name = "cortex-a57", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .avoid_partial_cpsr, .cheap_predicable_cpsr, .crc, @@ -1444,7 +1443,7 @@ pub const cpu = struct { .name = "cortex_a7", .llvm_name = "cortex-a7", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .mp, .ret_addr_stack, .slow_fp_brcc, @@ -1460,7 +1459,7 @@ pub const cpu = struct { .name = "cortex_a72", .llvm_name = "cortex-a72", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .crc, .crypto, .hwdiv, @@ -1471,7 +1470,7 @@ pub const cpu = struct { .name = "cortex_a73", .llvm_name = "cortex-a73", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .crc, .crypto, .hwdiv, @@ -1482,7 +1481,7 @@ pub const cpu = struct { .name = "cortex_a75", .llvm_name = "cortex-a75", .features = featureSet(&[_]Feature{ - .armv8_2_a, + .v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1493,7 +1492,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76", .features = featureSet(&[_]Feature{ .a76, - .armv8_2_a, + .v8_2a, .crc, .crypto, .dotprod, @@ -1507,7 +1506,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76ae", .features = featureSet(&[_]Feature{ .a76, - .armv8_2_a, + .v8_2a, .crc, .crypto, .dotprod, @@ -1520,7 +1519,7 @@ pub const cpu = struct { .name = "cortex_a8", .llvm_name = "cortex-a8", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .nonpipelined_vfp, .ret_addr_stack, .slow_fp_brcc, @@ -1534,7 +1533,7 @@ pub const cpu = struct { .name = "cortex_a9", .llvm_name = "cortex-a9", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .avoid_partial_cpsr, .expand_fp_mlx, .fp16, @@ -1553,28 +1552,28 @@ pub const cpu = struct { .name = "cortex_m0", .llvm_name = "cortex-m0", .features = featureSet(&[_]Feature{ - .armv6_m, + .v6m, }), }; pub const cortex_m0plus = CpuModel{ .name = "cortex_m0plus", .llvm_name = "cortex-m0plus", .features = featureSet(&[_]Feature{ - .armv6_m, + .v6m, }), }; pub const cortex_m1 = CpuModel{ .name = "cortex_m1", .llvm_name = "cortex-m1", .features = featureSet(&[_]Feature{ - .armv6_m, + .v6m, }), }; pub const cortex_m23 = CpuModel{ .name = "cortex_m23", .llvm_name = "cortex-m23", .features = featureSet(&[_]Feature{ - .armv8_m_base, + .v8m, .no_movt, }), }; @@ -1582,7 +1581,7 @@ pub const cpu = struct { .name = "cortex_m3", .llvm_name = "cortex-m3", .features = featureSet(&[_]Feature{ - .armv7_m, + .v7m, .loop_align, .m3, .no_branch_predictor, @@ -1594,7 +1593,7 @@ pub const cpu = struct { .name = "cortex_m33", .llvm_name = "cortex-m33", .features = featureSet(&[_]Feature{ - .armv8_m_main, + .v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1608,7 +1607,7 @@ pub const cpu = struct { .name = "cortex_m35p", .llvm_name = "cortex-m35p", .features = featureSet(&[_]Feature{ - .armv8_m_main, + .v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1622,7 +1621,7 @@ pub const cpu = struct { .name = "cortex_m4", .llvm_name = "cortex-m4", .features = featureSet(&[_]Feature{ - .armv7e_m, + .v7em, .loop_align, .no_branch_predictor, .slowfpvmlx, @@ -1635,7 +1634,7 @@ pub const cpu = struct { .name = "cortex_m7", .llvm_name = "cortex-m7", .features = featureSet(&[_]Feature{ - .armv7e_m, + .v7em, .fp_armv8d16, }), }; @@ -1643,7 +1642,7 @@ pub const cpu = struct { .name = "cortex_r4", .llvm_name = "cortex-r4", .features = featureSet(&[_]Feature{ - .armv7_r, + .v7r, .avoid_partial_cpsr, .r4, .ret_addr_stack, @@ -1653,7 +1652,7 @@ pub const cpu = struct { .name = "cortex_r4f", .llvm_name = "cortex-r4f", .features = featureSet(&[_]Feature{ - .armv7_r, + .v7r, .avoid_partial_cpsr, .r4, .ret_addr_stack, @@ -1666,7 +1665,7 @@ pub const cpu = struct { .name = "cortex_r5", .llvm_name = "cortex-r5", .features = featureSet(&[_]Feature{ - .armv7_r, + .v7r, .avoid_partial_cpsr, .hwdiv_arm, .ret_addr_stack, @@ -1679,7 +1678,7 @@ pub const cpu = struct { .name = "cortex_r52", .llvm_name = "cortex-r52", .features = featureSet(&[_]Feature{ - .armv8_r, + .v8r, .fpao, .use_aa, .use_misched, @@ -1689,7 +1688,7 @@ pub const cpu = struct { .name = "cortex_r7", .llvm_name = "cortex-r7", .features = featureSet(&[_]Feature{ - .armv7_r, + .v7r, .avoid_partial_cpsr, .fp16, .hwdiv_arm, @@ -1704,7 +1703,7 @@ pub const cpu = struct { .name = "cortex_r8", .llvm_name = "cortex-r8", .features = featureSet(&[_]Feature{ - .armv7_r, + .v7r, .avoid_partial_cpsr, .fp16, .hwdiv_arm, @@ -1719,7 +1718,7 @@ pub const cpu = struct { .name = "cyclone", .llvm_name = "cyclone", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .avoid_movs_shop, .avoid_partial_cpsr, .crypto, @@ -1740,14 +1739,14 @@ pub const cpu = struct { .name = "ep9312", .llvm_name = "ep9312", .features = featureSet(&[_]Feature{ - .armv4t, + .v4t, }), }; pub const exynos_m1 = CpuModel{ .name = "exynos_m1", .llvm_name = "exynos-m1", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .exynos, }), }; @@ -1755,7 +1754,7 @@ pub const cpu = struct { .name = "exynos_m2", .llvm_name = "exynos-m2", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .exynos, }), }; @@ -1763,7 +1762,7 @@ pub const cpu = struct { .name = "exynos_m3", .llvm_name = "exynos-m3", .features = featureSet(&[_]Feature{ - .armv8_a, + .v8a, .exynos, }), }; @@ -1771,7 +1770,7 @@ pub const cpu = struct { .name = "exynos_m4", .llvm_name = "exynos-m4", .features = featureSet(&[_]Feature{ - .armv8_2_a, + .v8_2a, .dotprod, .exynos, .fullfp16, @@ -1781,10 +1780,10 @@ pub const cpu = struct { .name = "exynos_m5", .llvm_name = "exynos-m5", .features = featureSet(&[_]Feature{ - .armv8_2_a, .dotprod, .exynos, .fullfp16, + .v8_2a, }), }; pub const generic = CpuModel{ @@ -1796,20 +1795,20 @@ pub const cpu = struct { .name = "iwmmxt", .llvm_name = "iwmmxt", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; pub const krait = CpuModel{ .name = "krait", .llvm_name = "krait", .features = featureSet(&[_]Feature{ - .armv7_a, .avoid_partial_cpsr, .fp16, .hwdiv, .hwdiv_arm, .muxed_units, .ret_addr_stack, + .v7a, .vfp4, .vldn_align, .vmlx_forwarding, @@ -1819,19 +1818,18 @@ pub const cpu = struct { .name = "kryo", .llvm_name = "kryo", .features = featureSet(&[_]Feature{ - .armv8_a, .crc, .crypto, .hwdiv, .hwdiv_arm, - .kryo, + .v8a, }), }; pub const mpcore = CpuModel{ .name = "mpcore", .llvm_name = "mpcore", .features = featureSet(&[_]Feature{ - .armv6k, + .v6k, .slowfpvmlx, .vfp2, }), @@ -1840,21 +1838,21 @@ pub const cpu = struct { .name = "mpcorenovfp", .llvm_name = "mpcorenovfp", .features = featureSet(&[_]Feature{ - .armv6k, + .v6k, }), }; pub const sc000 = CpuModel{ .name = "sc000", .llvm_name = "sc000", .features = featureSet(&[_]Feature{ - .armv6_m, + .v6m, }), }; pub const sc300 = CpuModel{ .name = "sc300", .llvm_name = "sc300", .features = featureSet(&[_]Feature{ - .armv7_m, + .v7m, .m3, .no_branch_predictor, .use_aa, @@ -1865,35 +1863,35 @@ pub const cpu = struct { .name = "strongarm", .llvm_name = "strongarm", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const strongarm110 = CpuModel{ .name = "strongarm110", .llvm_name = "strongarm110", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const strongarm1100 = CpuModel{ .name = "strongarm1100", .llvm_name = "strongarm1100", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const strongarm1110 = CpuModel{ .name = "strongarm1110", .llvm_name = "strongarm1110", .features = featureSet(&[_]Feature{ - .armv4, + .v4, }), }; pub const swift = CpuModel{ .name = "swift", .llvm_name = "swift", .features = featureSet(&[_]Feature{ - .armv7_a, + .v7a, .avoid_movs_shop, .avoid_partial_cpsr, .disable_postra_scheduler, @@ -1920,7 +1918,7 @@ pub const cpu = struct { .name = "xscale", .llvm_name = "xscale", .features = featureSet(&[_]Feature{ - .armv5te, + .v5te, }), }; }; diff --git a/lib/std/target/avr.zig b/lib/std/target/avr.zig index 3902a3860f..4d0da9b2c3 100644 --- a/lib/std/target/avr.zig +++ b/lib/std/target/avr.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { addsubiw, @@ -37,12 +38,12 @@ pub const Feature = enum { xmegau, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.addsubiw)] = .{ .llvm_name = "addsubiw", .description = "Enable 16-bit register-immediate addition and subtraction instructions", @@ -293,28 +294,28 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const at43usb320 = Cpu{ + pub const at43usb320 = CpuModel{ .name = "at43usb320", .llvm_name = "at43usb320", .features = featureSet(&[_]Feature{ .avr31, }), }; - pub const at43usb355 = Cpu{ + pub const at43usb355 = CpuModel{ .name = "at43usb355", .llvm_name = "at43usb355", .features = featureSet(&[_]Feature{ .avr3, }), }; - pub const at76c711 = Cpu{ + pub const at76c711 = CpuModel{ .name = "at76c711", .llvm_name = "at76c711", .features = featureSet(&[_]Feature{ .avr3, }), }; - pub const at86rf401 = Cpu{ + pub const at86rf401 = CpuModel{ .name = "at86rf401", .llvm_name = "at86rf401", .features = featureSet(&[_]Feature{ @@ -323,217 +324,217 @@ pub const cpu = struct { .movw, }), }; - pub const at90c8534 = Cpu{ + pub const at90c8534 = CpuModel{ .name = "at90c8534", .llvm_name = "at90c8534", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90can128 = Cpu{ + pub const at90can128 = CpuModel{ .name = "at90can128", .llvm_name = "at90can128", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const at90can32 = Cpu{ + pub const at90can32 = CpuModel{ .name = "at90can32", .llvm_name = "at90can32", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90can64 = Cpu{ + pub const at90can64 = CpuModel{ .name = "at90can64", .llvm_name = "at90can64", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90pwm1 = Cpu{ + pub const at90pwm1 = CpuModel{ .name = "at90pwm1", .llvm_name = "at90pwm1", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90pwm161 = Cpu{ + pub const at90pwm161 = CpuModel{ .name = "at90pwm161", .llvm_name = "at90pwm161", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90pwm2 = Cpu{ + pub const at90pwm2 = CpuModel{ .name = "at90pwm2", .llvm_name = "at90pwm2", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90pwm216 = Cpu{ + pub const at90pwm216 = CpuModel{ .name = "at90pwm216", .llvm_name = "at90pwm216", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90pwm2b = Cpu{ + pub const at90pwm2b = CpuModel{ .name = "at90pwm2b", .llvm_name = "at90pwm2b", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90pwm3 = Cpu{ + pub const at90pwm3 = CpuModel{ .name = "at90pwm3", .llvm_name = "at90pwm3", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90pwm316 = Cpu{ + pub const at90pwm316 = CpuModel{ .name = "at90pwm316", .llvm_name = "at90pwm316", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90pwm3b = Cpu{ + pub const at90pwm3b = CpuModel{ .name = "at90pwm3b", .llvm_name = "at90pwm3b", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90pwm81 = Cpu{ + pub const at90pwm81 = CpuModel{ .name = "at90pwm81", .llvm_name = "at90pwm81", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const at90s1200 = Cpu{ + pub const at90s1200 = CpuModel{ .name = "at90s1200", .llvm_name = "at90s1200", .features = featureSet(&[_]Feature{ .avr0, }), }; - pub const at90s2313 = Cpu{ + pub const at90s2313 = CpuModel{ .name = "at90s2313", .llvm_name = "at90s2313", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s2323 = Cpu{ + pub const at90s2323 = CpuModel{ .name = "at90s2323", .llvm_name = "at90s2323", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s2333 = Cpu{ + pub const at90s2333 = CpuModel{ .name = "at90s2333", .llvm_name = "at90s2333", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s2343 = Cpu{ + pub const at90s2343 = CpuModel{ .name = "at90s2343", .llvm_name = "at90s2343", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s4414 = Cpu{ + pub const at90s4414 = CpuModel{ .name = "at90s4414", .llvm_name = "at90s4414", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s4433 = Cpu{ + pub const at90s4433 = CpuModel{ .name = "at90s4433", .llvm_name = "at90s4433", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s4434 = Cpu{ + pub const at90s4434 = CpuModel{ .name = "at90s4434", .llvm_name = "at90s4434", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s8515 = Cpu{ + pub const at90s8515 = CpuModel{ .name = "at90s8515", .llvm_name = "at90s8515", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90s8535 = Cpu{ + pub const at90s8535 = CpuModel{ .name = "at90s8535", .llvm_name = "at90s8535", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const at90scr100 = Cpu{ + pub const at90scr100 = CpuModel{ .name = "at90scr100", .llvm_name = "at90scr100", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90usb1286 = Cpu{ + pub const at90usb1286 = CpuModel{ .name = "at90usb1286", .llvm_name = "at90usb1286", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const at90usb1287 = Cpu{ + pub const at90usb1287 = CpuModel{ .name = "at90usb1287", .llvm_name = "at90usb1287", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const at90usb162 = Cpu{ + pub const at90usb162 = CpuModel{ .name = "at90usb162", .llvm_name = "at90usb162", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const at90usb646 = Cpu{ + pub const at90usb646 = CpuModel{ .name = "at90usb646", .llvm_name = "at90usb646", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90usb647 = Cpu{ + pub const at90usb647 = CpuModel{ .name = "at90usb647", .llvm_name = "at90usb647", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const at90usb82 = Cpu{ + pub const at90usb82 = CpuModel{ .name = "at90usb82", .llvm_name = "at90usb82", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const at94k = Cpu{ + pub const at94k = CpuModel{ .name = "at94k", .llvm_name = "at94k", .features = featureSet(&[_]Feature{ @@ -543,133 +544,133 @@ pub const cpu = struct { .mul, }), }; - pub const ata5272 = Cpu{ + pub const ata5272 = CpuModel{ .name = "ata5272", .llvm_name = "ata5272", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const ata5505 = Cpu{ + pub const ata5505 = CpuModel{ .name = "ata5505", .llvm_name = "ata5505", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const ata5790 = Cpu{ + pub const ata5790 = CpuModel{ .name = "ata5790", .llvm_name = "ata5790", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const ata5795 = Cpu{ + pub const ata5795 = CpuModel{ .name = "ata5795", .llvm_name = "ata5795", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const ata6285 = Cpu{ + pub const ata6285 = CpuModel{ .name = "ata6285", .llvm_name = "ata6285", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const ata6286 = Cpu{ + pub const ata6286 = CpuModel{ .name = "ata6286", .llvm_name = "ata6286", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const ata6289 = Cpu{ + pub const ata6289 = CpuModel{ .name = "ata6289", .llvm_name = "ata6289", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega103 = Cpu{ + pub const atmega103 = CpuModel{ .name = "atmega103", .llvm_name = "atmega103", .features = featureSet(&[_]Feature{ .avr31, }), }; - pub const atmega128 = Cpu{ + pub const atmega128 = CpuModel{ .name = "atmega128", .llvm_name = "atmega128", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega1280 = Cpu{ + pub const atmega1280 = CpuModel{ .name = "atmega1280", .llvm_name = "atmega1280", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega1281 = Cpu{ + pub const atmega1281 = CpuModel{ .name = "atmega1281", .llvm_name = "atmega1281", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega1284 = Cpu{ + pub const atmega1284 = CpuModel{ .name = "atmega1284", .llvm_name = "atmega1284", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega1284p = Cpu{ + pub const atmega1284p = CpuModel{ .name = "atmega1284p", .llvm_name = "atmega1284p", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega1284rfr2 = Cpu{ + pub const atmega1284rfr2 = CpuModel{ .name = "atmega1284rfr2", .llvm_name = "atmega1284rfr2", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega128a = Cpu{ + pub const atmega128a = CpuModel{ .name = "atmega128a", .llvm_name = "atmega128a", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega128rfa1 = Cpu{ + pub const atmega128rfa1 = CpuModel{ .name = "atmega128rfa1", .llvm_name = "atmega128rfa1", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega128rfr2 = Cpu{ + pub const atmega128rfr2 = CpuModel{ .name = "atmega128rfr2", .llvm_name = "atmega128rfr2", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const atmega16 = Cpu{ + pub const atmega16 = CpuModel{ .name = "atmega16", .llvm_name = "atmega16", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega161 = Cpu{ + pub const atmega161 = CpuModel{ .name = "atmega161", .llvm_name = "atmega161", .features = featureSet(&[_]Feature{ @@ -680,14 +681,14 @@ pub const cpu = struct { .spm, }), }; - pub const atmega162 = Cpu{ + pub const atmega162 = CpuModel{ .name = "atmega162", .llvm_name = "atmega162", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega163 = Cpu{ + pub const atmega163 = CpuModel{ .name = "atmega163", .llvm_name = "atmega163", .features = featureSet(&[_]Feature{ @@ -698,623 +699,623 @@ pub const cpu = struct { .spm, }), }; - pub const atmega164a = Cpu{ + pub const atmega164a = CpuModel{ .name = "atmega164a", .llvm_name = "atmega164a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega164p = Cpu{ + pub const atmega164p = CpuModel{ .name = "atmega164p", .llvm_name = "atmega164p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega164pa = Cpu{ + pub const atmega164pa = CpuModel{ .name = "atmega164pa", .llvm_name = "atmega164pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega165 = Cpu{ + pub const atmega165 = CpuModel{ .name = "atmega165", .llvm_name = "atmega165", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega165a = Cpu{ + pub const atmega165a = CpuModel{ .name = "atmega165a", .llvm_name = "atmega165a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega165p = Cpu{ + pub const atmega165p = CpuModel{ .name = "atmega165p", .llvm_name = "atmega165p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega165pa = Cpu{ + pub const atmega165pa = CpuModel{ .name = "atmega165pa", .llvm_name = "atmega165pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega168 = Cpu{ + pub const atmega168 = CpuModel{ .name = "atmega168", .llvm_name = "atmega168", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega168a = Cpu{ + pub const atmega168a = CpuModel{ .name = "atmega168a", .llvm_name = "atmega168a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega168p = Cpu{ + pub const atmega168p = CpuModel{ .name = "atmega168p", .llvm_name = "atmega168p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega168pa = Cpu{ + pub const atmega168pa = CpuModel{ .name = "atmega168pa", .llvm_name = "atmega168pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega169 = Cpu{ + pub const atmega169 = CpuModel{ .name = "atmega169", .llvm_name = "atmega169", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega169a = Cpu{ + pub const atmega169a = CpuModel{ .name = "atmega169a", .llvm_name = "atmega169a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega169p = Cpu{ + pub const atmega169p = CpuModel{ .name = "atmega169p", .llvm_name = "atmega169p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega169pa = Cpu{ + pub const atmega169pa = CpuModel{ .name = "atmega169pa", .llvm_name = "atmega169pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16a = Cpu{ + pub const atmega16a = CpuModel{ .name = "atmega16a", .llvm_name = "atmega16a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16hva = Cpu{ + pub const atmega16hva = CpuModel{ .name = "atmega16hva", .llvm_name = "atmega16hva", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16hva2 = Cpu{ + pub const atmega16hva2 = CpuModel{ .name = "atmega16hva2", .llvm_name = "atmega16hva2", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16hvb = Cpu{ + pub const atmega16hvb = CpuModel{ .name = "atmega16hvb", .llvm_name = "atmega16hvb", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16hvbrevb = Cpu{ + pub const atmega16hvbrevb = CpuModel{ .name = "atmega16hvbrevb", .llvm_name = "atmega16hvbrevb", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16m1 = Cpu{ + pub const atmega16m1 = CpuModel{ .name = "atmega16m1", .llvm_name = "atmega16m1", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega16u2 = Cpu{ + pub const atmega16u2 = CpuModel{ .name = "atmega16u2", .llvm_name = "atmega16u2", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const atmega16u4 = Cpu{ + pub const atmega16u4 = CpuModel{ .name = "atmega16u4", .llvm_name = "atmega16u4", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega2560 = Cpu{ + pub const atmega2560 = CpuModel{ .name = "atmega2560", .llvm_name = "atmega2560", .features = featureSet(&[_]Feature{ .avr6, }), }; - pub const atmega2561 = Cpu{ + pub const atmega2561 = CpuModel{ .name = "atmega2561", .llvm_name = "atmega2561", .features = featureSet(&[_]Feature{ .avr6, }), }; - pub const atmega2564rfr2 = Cpu{ + pub const atmega2564rfr2 = CpuModel{ .name = "atmega2564rfr2", .llvm_name = "atmega2564rfr2", .features = featureSet(&[_]Feature{ .avr6, }), }; - pub const atmega256rfr2 = Cpu{ + pub const atmega256rfr2 = CpuModel{ .name = "atmega256rfr2", .llvm_name = "atmega256rfr2", .features = featureSet(&[_]Feature{ .avr6, }), }; - pub const atmega32 = Cpu{ + pub const atmega32 = CpuModel{ .name = "atmega32", .llvm_name = "atmega32", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega323 = Cpu{ + pub const atmega323 = CpuModel{ .name = "atmega323", .llvm_name = "atmega323", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega324a = Cpu{ + pub const atmega324a = CpuModel{ .name = "atmega324a", .llvm_name = "atmega324a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega324p = Cpu{ + pub const atmega324p = CpuModel{ .name = "atmega324p", .llvm_name = "atmega324p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega324pa = Cpu{ + pub const atmega324pa = CpuModel{ .name = "atmega324pa", .llvm_name = "atmega324pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega325 = Cpu{ + pub const atmega325 = CpuModel{ .name = "atmega325", .llvm_name = "atmega325", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3250 = Cpu{ + pub const atmega3250 = CpuModel{ .name = "atmega3250", .llvm_name = "atmega3250", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3250a = Cpu{ + pub const atmega3250a = CpuModel{ .name = "atmega3250a", .llvm_name = "atmega3250a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3250p = Cpu{ + pub const atmega3250p = CpuModel{ .name = "atmega3250p", .llvm_name = "atmega3250p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3250pa = Cpu{ + pub const atmega3250pa = CpuModel{ .name = "atmega3250pa", .llvm_name = "atmega3250pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega325a = Cpu{ + pub const atmega325a = CpuModel{ .name = "atmega325a", .llvm_name = "atmega325a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega325p = Cpu{ + pub const atmega325p = CpuModel{ .name = "atmega325p", .llvm_name = "atmega325p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega325pa = Cpu{ + pub const atmega325pa = CpuModel{ .name = "atmega325pa", .llvm_name = "atmega325pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega328 = Cpu{ + pub const atmega328 = CpuModel{ .name = "atmega328", .llvm_name = "atmega328", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega328p = Cpu{ + pub const atmega328p = CpuModel{ .name = "atmega328p", .llvm_name = "atmega328p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega329 = Cpu{ + pub const atmega329 = CpuModel{ .name = "atmega329", .llvm_name = "atmega329", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3290 = Cpu{ + pub const atmega3290 = CpuModel{ .name = "atmega3290", .llvm_name = "atmega3290", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3290a = Cpu{ + pub const atmega3290a = CpuModel{ .name = "atmega3290a", .llvm_name = "atmega3290a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3290p = Cpu{ + pub const atmega3290p = CpuModel{ .name = "atmega3290p", .llvm_name = "atmega3290p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega3290pa = Cpu{ + pub const atmega3290pa = CpuModel{ .name = "atmega3290pa", .llvm_name = "atmega3290pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega329a = Cpu{ + pub const atmega329a = CpuModel{ .name = "atmega329a", .llvm_name = "atmega329a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega329p = Cpu{ + pub const atmega329p = CpuModel{ .name = "atmega329p", .llvm_name = "atmega329p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega329pa = Cpu{ + pub const atmega329pa = CpuModel{ .name = "atmega329pa", .llvm_name = "atmega329pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32a = Cpu{ + pub const atmega32a = CpuModel{ .name = "atmega32a", .llvm_name = "atmega32a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32c1 = Cpu{ + pub const atmega32c1 = CpuModel{ .name = "atmega32c1", .llvm_name = "atmega32c1", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32hvb = Cpu{ + pub const atmega32hvb = CpuModel{ .name = "atmega32hvb", .llvm_name = "atmega32hvb", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32hvbrevb = Cpu{ + pub const atmega32hvbrevb = CpuModel{ .name = "atmega32hvbrevb", .llvm_name = "atmega32hvbrevb", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32m1 = Cpu{ + pub const atmega32m1 = CpuModel{ .name = "atmega32m1", .llvm_name = "atmega32m1", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32u2 = Cpu{ + pub const atmega32u2 = CpuModel{ .name = "atmega32u2", .llvm_name = "atmega32u2", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const atmega32u4 = Cpu{ + pub const atmega32u4 = CpuModel{ .name = "atmega32u4", .llvm_name = "atmega32u4", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega32u6 = Cpu{ + pub const atmega32u6 = CpuModel{ .name = "atmega32u6", .llvm_name = "atmega32u6", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega406 = Cpu{ + pub const atmega406 = CpuModel{ .name = "atmega406", .llvm_name = "atmega406", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega48 = Cpu{ + pub const atmega48 = CpuModel{ .name = "atmega48", .llvm_name = "atmega48", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega48a = Cpu{ + pub const atmega48a = CpuModel{ .name = "atmega48a", .llvm_name = "atmega48a", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega48p = Cpu{ + pub const atmega48p = CpuModel{ .name = "atmega48p", .llvm_name = "atmega48p", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega48pa = Cpu{ + pub const atmega48pa = CpuModel{ .name = "atmega48pa", .llvm_name = "atmega48pa", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega64 = Cpu{ + pub const atmega64 = CpuModel{ .name = "atmega64", .llvm_name = "atmega64", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega640 = Cpu{ + pub const atmega640 = CpuModel{ .name = "atmega640", .llvm_name = "atmega640", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega644 = Cpu{ + pub const atmega644 = CpuModel{ .name = "atmega644", .llvm_name = "atmega644", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega644a = Cpu{ + pub const atmega644a = CpuModel{ .name = "atmega644a", .llvm_name = "atmega644a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega644p = Cpu{ + pub const atmega644p = CpuModel{ .name = "atmega644p", .llvm_name = "atmega644p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega644pa = Cpu{ + pub const atmega644pa = CpuModel{ .name = "atmega644pa", .llvm_name = "atmega644pa", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega644rfr2 = Cpu{ + pub const atmega644rfr2 = CpuModel{ .name = "atmega644rfr2", .llvm_name = "atmega644rfr2", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega645 = Cpu{ + pub const atmega645 = CpuModel{ .name = "atmega645", .llvm_name = "atmega645", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6450 = Cpu{ + pub const atmega6450 = CpuModel{ .name = "atmega6450", .llvm_name = "atmega6450", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6450a = Cpu{ + pub const atmega6450a = CpuModel{ .name = "atmega6450a", .llvm_name = "atmega6450a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6450p = Cpu{ + pub const atmega6450p = CpuModel{ .name = "atmega6450p", .llvm_name = "atmega6450p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega645a = Cpu{ + pub const atmega645a = CpuModel{ .name = "atmega645a", .llvm_name = "atmega645a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega645p = Cpu{ + pub const atmega645p = CpuModel{ .name = "atmega645p", .llvm_name = "atmega645p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega649 = Cpu{ + pub const atmega649 = CpuModel{ .name = "atmega649", .llvm_name = "atmega649", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6490 = Cpu{ + pub const atmega6490 = CpuModel{ .name = "atmega6490", .llvm_name = "atmega6490", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6490a = Cpu{ + pub const atmega6490a = CpuModel{ .name = "atmega6490a", .llvm_name = "atmega6490a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega6490p = Cpu{ + pub const atmega6490p = CpuModel{ .name = "atmega6490p", .llvm_name = "atmega6490p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega649a = Cpu{ + pub const atmega649a = CpuModel{ .name = "atmega649a", .llvm_name = "atmega649a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega649p = Cpu{ + pub const atmega649p = CpuModel{ .name = "atmega649p", .llvm_name = "atmega649p", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega64a = Cpu{ + pub const atmega64a = CpuModel{ .name = "atmega64a", .llvm_name = "atmega64a", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega64c1 = Cpu{ + pub const atmega64c1 = CpuModel{ .name = "atmega64c1", .llvm_name = "atmega64c1", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega64hve = Cpu{ + pub const atmega64hve = CpuModel{ .name = "atmega64hve", .llvm_name = "atmega64hve", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega64m1 = Cpu{ + pub const atmega64m1 = CpuModel{ .name = "atmega64m1", .llvm_name = "atmega64m1", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega64rfr2 = Cpu{ + pub const atmega64rfr2 = CpuModel{ .name = "atmega64rfr2", .llvm_name = "atmega64rfr2", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const atmega8 = Cpu{ + pub const atmega8 = CpuModel{ .name = "atmega8", .llvm_name = "atmega8", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega8515 = Cpu{ + pub const atmega8515 = CpuModel{ .name = "atmega8515", .llvm_name = "atmega8515", .features = featureSet(&[_]Feature{ @@ -1325,7 +1326,7 @@ pub const cpu = struct { .spm, }), }; - pub const atmega8535 = Cpu{ + pub const atmega8535 = CpuModel{ .name = "atmega8535", .llvm_name = "atmega8535", .features = featureSet(&[_]Feature{ @@ -1336,175 +1337,175 @@ pub const cpu = struct { .spm, }), }; - pub const atmega88 = Cpu{ + pub const atmega88 = CpuModel{ .name = "atmega88", .llvm_name = "atmega88", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega88a = Cpu{ + pub const atmega88a = CpuModel{ .name = "atmega88a", .llvm_name = "atmega88a", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega88p = Cpu{ + pub const atmega88p = CpuModel{ .name = "atmega88p", .llvm_name = "atmega88p", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega88pa = Cpu{ + pub const atmega88pa = CpuModel{ .name = "atmega88pa", .llvm_name = "atmega88pa", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega8a = Cpu{ + pub const atmega8a = CpuModel{ .name = "atmega8a", .llvm_name = "atmega8a", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega8hva = Cpu{ + pub const atmega8hva = CpuModel{ .name = "atmega8hva", .llvm_name = "atmega8hva", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const atmega8u2 = Cpu{ + pub const atmega8u2 = CpuModel{ .name = "atmega8u2", .llvm_name = "atmega8u2", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const attiny10 = Cpu{ + pub const attiny10 = CpuModel{ .name = "attiny10", .llvm_name = "attiny10", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny102 = Cpu{ + pub const attiny102 = CpuModel{ .name = "attiny102", .llvm_name = "attiny102", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny104 = Cpu{ + pub const attiny104 = CpuModel{ .name = "attiny104", .llvm_name = "attiny104", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny11 = Cpu{ + pub const attiny11 = CpuModel{ .name = "attiny11", .llvm_name = "attiny11", .features = featureSet(&[_]Feature{ .avr1, }), }; - pub const attiny12 = Cpu{ + pub const attiny12 = CpuModel{ .name = "attiny12", .llvm_name = "attiny12", .features = featureSet(&[_]Feature{ .avr1, }), }; - pub const attiny13 = Cpu{ + pub const attiny13 = CpuModel{ .name = "attiny13", .llvm_name = "attiny13", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny13a = Cpu{ + pub const attiny13a = CpuModel{ .name = "attiny13a", .llvm_name = "attiny13a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny15 = Cpu{ + pub const attiny15 = CpuModel{ .name = "attiny15", .llvm_name = "attiny15", .features = featureSet(&[_]Feature{ .avr1, }), }; - pub const attiny1634 = Cpu{ + pub const attiny1634 = CpuModel{ .name = "attiny1634", .llvm_name = "attiny1634", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const attiny167 = Cpu{ + pub const attiny167 = CpuModel{ .name = "attiny167", .llvm_name = "attiny167", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const attiny20 = Cpu{ + pub const attiny20 = CpuModel{ .name = "attiny20", .llvm_name = "attiny20", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny22 = Cpu{ + pub const attiny22 = CpuModel{ .name = "attiny22", .llvm_name = "attiny22", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const attiny2313 = Cpu{ + pub const attiny2313 = CpuModel{ .name = "attiny2313", .llvm_name = "attiny2313", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny2313a = Cpu{ + pub const attiny2313a = CpuModel{ .name = "attiny2313a", .llvm_name = "attiny2313a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny24 = Cpu{ + pub const attiny24 = CpuModel{ .name = "attiny24", .llvm_name = "attiny24", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny24a = Cpu{ + pub const attiny24a = CpuModel{ .name = "attiny24a", .llvm_name = "attiny24a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny25 = Cpu{ + pub const attiny25 = CpuModel{ .name = "attiny25", .llvm_name = "attiny25", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny26 = Cpu{ + pub const attiny26 = CpuModel{ .name = "attiny26", .llvm_name = "attiny26", .features = featureSet(&[_]Feature{ @@ -1512,602 +1513,602 @@ pub const cpu = struct { .lpmx, }), }; - pub const attiny261 = Cpu{ + pub const attiny261 = CpuModel{ .name = "attiny261", .llvm_name = "attiny261", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny261a = Cpu{ + pub const attiny261a = CpuModel{ .name = "attiny261a", .llvm_name = "attiny261a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny28 = Cpu{ + pub const attiny28 = CpuModel{ .name = "attiny28", .llvm_name = "attiny28", .features = featureSet(&[_]Feature{ .avr1, }), }; - pub const attiny4 = Cpu{ + pub const attiny4 = CpuModel{ .name = "attiny4", .llvm_name = "attiny4", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny40 = Cpu{ + pub const attiny40 = CpuModel{ .name = "attiny40", .llvm_name = "attiny40", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny4313 = Cpu{ + pub const attiny4313 = CpuModel{ .name = "attiny4313", .llvm_name = "attiny4313", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny43u = Cpu{ + pub const attiny43u = CpuModel{ .name = "attiny43u", .llvm_name = "attiny43u", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny44 = Cpu{ + pub const attiny44 = CpuModel{ .name = "attiny44", .llvm_name = "attiny44", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny44a = Cpu{ + pub const attiny44a = CpuModel{ .name = "attiny44a", .llvm_name = "attiny44a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny45 = Cpu{ + pub const attiny45 = CpuModel{ .name = "attiny45", .llvm_name = "attiny45", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny461 = Cpu{ + pub const attiny461 = CpuModel{ .name = "attiny461", .llvm_name = "attiny461", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny461a = Cpu{ + pub const attiny461a = CpuModel{ .name = "attiny461a", .llvm_name = "attiny461a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny48 = Cpu{ + pub const attiny48 = CpuModel{ .name = "attiny48", .llvm_name = "attiny48", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny5 = Cpu{ + pub const attiny5 = CpuModel{ .name = "attiny5", .llvm_name = "attiny5", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const attiny828 = Cpu{ + pub const attiny828 = CpuModel{ .name = "attiny828", .llvm_name = "attiny828", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny84 = Cpu{ + pub const attiny84 = CpuModel{ .name = "attiny84", .llvm_name = "attiny84", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny84a = Cpu{ + pub const attiny84a = CpuModel{ .name = "attiny84a", .llvm_name = "attiny84a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny85 = Cpu{ + pub const attiny85 = CpuModel{ .name = "attiny85", .llvm_name = "attiny85", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny861 = Cpu{ + pub const attiny861 = CpuModel{ .name = "attiny861", .llvm_name = "attiny861", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny861a = Cpu{ + pub const attiny861a = CpuModel{ .name = "attiny861a", .llvm_name = "attiny861a", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny87 = Cpu{ + pub const attiny87 = CpuModel{ .name = "attiny87", .llvm_name = "attiny87", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny88 = Cpu{ + pub const attiny88 = CpuModel{ .name = "attiny88", .llvm_name = "attiny88", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const attiny9 = Cpu{ + pub const attiny9 = CpuModel{ .name = "attiny9", .llvm_name = "attiny9", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const atxmega128a1 = Cpu{ + pub const atxmega128a1 = CpuModel{ .name = "atxmega128a1", .llvm_name = "atxmega128a1", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega128a1u = Cpu{ + pub const atxmega128a1u = CpuModel{ .name = "atxmega128a1u", .llvm_name = "atxmega128a1u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128a3 = Cpu{ + pub const atxmega128a3 = CpuModel{ .name = "atxmega128a3", .llvm_name = "atxmega128a3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega128a3u = Cpu{ + pub const atxmega128a3u = CpuModel{ .name = "atxmega128a3u", .llvm_name = "atxmega128a3u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128a4u = Cpu{ + pub const atxmega128a4u = CpuModel{ .name = "atxmega128a4u", .llvm_name = "atxmega128a4u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128b1 = Cpu{ + pub const atxmega128b1 = CpuModel{ .name = "atxmega128b1", .llvm_name = "atxmega128b1", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128b3 = Cpu{ + pub const atxmega128b3 = CpuModel{ .name = "atxmega128b3", .llvm_name = "atxmega128b3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128c3 = Cpu{ + pub const atxmega128c3 = CpuModel{ .name = "atxmega128c3", .llvm_name = "atxmega128c3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega128d3 = Cpu{ + pub const atxmega128d3 = CpuModel{ .name = "atxmega128d3", .llvm_name = "atxmega128d3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega128d4 = Cpu{ + pub const atxmega128d4 = CpuModel{ .name = "atxmega128d4", .llvm_name = "atxmega128d4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega16a4 = Cpu{ + pub const atxmega16a4 = CpuModel{ .name = "atxmega16a4", .llvm_name = "atxmega16a4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega16a4u = Cpu{ + pub const atxmega16a4u = CpuModel{ .name = "atxmega16a4u", .llvm_name = "atxmega16a4u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega16c4 = Cpu{ + pub const atxmega16c4 = CpuModel{ .name = "atxmega16c4", .llvm_name = "atxmega16c4", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega16d4 = Cpu{ + pub const atxmega16d4 = CpuModel{ .name = "atxmega16d4", .llvm_name = "atxmega16d4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega16e5 = Cpu{ + pub const atxmega16e5 = CpuModel{ .name = "atxmega16e5", .llvm_name = "atxmega16e5", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega192a3 = Cpu{ + pub const atxmega192a3 = CpuModel{ .name = "atxmega192a3", .llvm_name = "atxmega192a3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega192a3u = Cpu{ + pub const atxmega192a3u = CpuModel{ .name = "atxmega192a3u", .llvm_name = "atxmega192a3u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega192c3 = Cpu{ + pub const atxmega192c3 = CpuModel{ .name = "atxmega192c3", .llvm_name = "atxmega192c3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega192d3 = Cpu{ + pub const atxmega192d3 = CpuModel{ .name = "atxmega192d3", .llvm_name = "atxmega192d3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega256a3 = Cpu{ + pub const atxmega256a3 = CpuModel{ .name = "atxmega256a3", .llvm_name = "atxmega256a3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega256a3b = Cpu{ + pub const atxmega256a3b = CpuModel{ .name = "atxmega256a3b", .llvm_name = "atxmega256a3b", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega256a3bu = Cpu{ + pub const atxmega256a3bu = CpuModel{ .name = "atxmega256a3bu", .llvm_name = "atxmega256a3bu", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega256a3u = Cpu{ + pub const atxmega256a3u = CpuModel{ .name = "atxmega256a3u", .llvm_name = "atxmega256a3u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega256c3 = Cpu{ + pub const atxmega256c3 = CpuModel{ .name = "atxmega256c3", .llvm_name = "atxmega256c3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega256d3 = Cpu{ + pub const atxmega256d3 = CpuModel{ .name = "atxmega256d3", .llvm_name = "atxmega256d3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega32a4 = Cpu{ + pub const atxmega32a4 = CpuModel{ .name = "atxmega32a4", .llvm_name = "atxmega32a4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega32a4u = Cpu{ + pub const atxmega32a4u = CpuModel{ .name = "atxmega32a4u", .llvm_name = "atxmega32a4u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega32c4 = Cpu{ + pub const atxmega32c4 = CpuModel{ .name = "atxmega32c4", .llvm_name = "atxmega32c4", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega32d4 = Cpu{ + pub const atxmega32d4 = CpuModel{ .name = "atxmega32d4", .llvm_name = "atxmega32d4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega32e5 = Cpu{ + pub const atxmega32e5 = CpuModel{ .name = "atxmega32e5", .llvm_name = "atxmega32e5", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega32x1 = Cpu{ + pub const atxmega32x1 = CpuModel{ .name = "atxmega32x1", .llvm_name = "atxmega32x1", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega384c3 = Cpu{ + pub const atxmega384c3 = CpuModel{ .name = "atxmega384c3", .llvm_name = "atxmega384c3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega384d3 = Cpu{ + pub const atxmega384d3 = CpuModel{ .name = "atxmega384d3", .llvm_name = "atxmega384d3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega64a1 = Cpu{ + pub const atxmega64a1 = CpuModel{ .name = "atxmega64a1", .llvm_name = "atxmega64a1", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega64a1u = Cpu{ + pub const atxmega64a1u = CpuModel{ .name = "atxmega64a1u", .llvm_name = "atxmega64a1u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64a3 = Cpu{ + pub const atxmega64a3 = CpuModel{ .name = "atxmega64a3", .llvm_name = "atxmega64a3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega64a3u = Cpu{ + pub const atxmega64a3u = CpuModel{ .name = "atxmega64a3u", .llvm_name = "atxmega64a3u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64a4u = Cpu{ + pub const atxmega64a4u = CpuModel{ .name = "atxmega64a4u", .llvm_name = "atxmega64a4u", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64b1 = Cpu{ + pub const atxmega64b1 = CpuModel{ .name = "atxmega64b1", .llvm_name = "atxmega64b1", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64b3 = Cpu{ + pub const atxmega64b3 = CpuModel{ .name = "atxmega64b3", .llvm_name = "atxmega64b3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64c3 = Cpu{ + pub const atxmega64c3 = CpuModel{ .name = "atxmega64c3", .llvm_name = "atxmega64c3", .features = featureSet(&[_]Feature{ .xmegau, }), }; - pub const atxmega64d3 = Cpu{ + pub const atxmega64d3 = CpuModel{ .name = "atxmega64d3", .llvm_name = "atxmega64d3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega64d4 = Cpu{ + pub const atxmega64d4 = CpuModel{ .name = "atxmega64d4", .llvm_name = "atxmega64d4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const atxmega8e5 = Cpu{ + pub const atxmega8e5 = CpuModel{ .name = "atxmega8e5", .llvm_name = "atxmega8e5", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avr1 = Cpu{ + pub const avr1 = CpuModel{ .name = "avr1", .llvm_name = "avr1", .features = featureSet(&[_]Feature{ .avr1, }), }; - pub const avr2 = Cpu{ + pub const avr2 = CpuModel{ .name = "avr2", .llvm_name = "avr2", .features = featureSet(&[_]Feature{ .avr2, }), }; - pub const avr25 = Cpu{ + pub const avr25 = CpuModel{ .name = "avr25", .llvm_name = "avr25", .features = featureSet(&[_]Feature{ .avr25, }), }; - pub const avr3 = Cpu{ + pub const avr3 = CpuModel{ .name = "avr3", .llvm_name = "avr3", .features = featureSet(&[_]Feature{ .avr3, }), }; - pub const avr31 = Cpu{ + pub const avr31 = CpuModel{ .name = "avr31", .llvm_name = "avr31", .features = featureSet(&[_]Feature{ .avr31, }), }; - pub const avr35 = Cpu{ + pub const avr35 = CpuModel{ .name = "avr35", .llvm_name = "avr35", .features = featureSet(&[_]Feature{ .avr35, }), }; - pub const avr4 = Cpu{ + pub const avr4 = CpuModel{ .name = "avr4", .llvm_name = "avr4", .features = featureSet(&[_]Feature{ .avr4, }), }; - pub const avr5 = Cpu{ + pub const avr5 = CpuModel{ .name = "avr5", .llvm_name = "avr5", .features = featureSet(&[_]Feature{ .avr5, }), }; - pub const avr51 = Cpu{ + pub const avr51 = CpuModel{ .name = "avr51", .llvm_name = "avr51", .features = featureSet(&[_]Feature{ .avr51, }), }; - pub const avr6 = Cpu{ + pub const avr6 = CpuModel{ .name = "avr6", .llvm_name = "avr6", .features = featureSet(&[_]Feature{ .avr6, }), }; - pub const avrtiny = Cpu{ + pub const avrtiny = CpuModel{ .name = "avrtiny", .llvm_name = "avrtiny", .features = featureSet(&[_]Feature{ .avrtiny, }), }; - pub const avrxmega1 = Cpu{ + pub const avrxmega1 = CpuModel{ .name = "avrxmega1", .llvm_name = "avrxmega1", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega2 = Cpu{ + pub const avrxmega2 = CpuModel{ .name = "avrxmega2", .llvm_name = "avrxmega2", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega3 = Cpu{ + pub const avrxmega3 = CpuModel{ .name = "avrxmega3", .llvm_name = "avrxmega3", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega4 = Cpu{ + pub const avrxmega4 = CpuModel{ .name = "avrxmega4", .llvm_name = "avrxmega4", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega5 = Cpu{ + pub const avrxmega5 = CpuModel{ .name = "avrxmega5", .llvm_name = "avrxmega5", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega6 = Cpu{ + pub const avrxmega6 = CpuModel{ .name = "avrxmega6", .llvm_name = "avrxmega6", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const avrxmega7 = Cpu{ + pub const avrxmega7 = CpuModel{ .name = "avrxmega7", .llvm_name = "avrxmega7", .features = featureSet(&[_]Feature{ .xmega, }), }; - pub const m3000 = Cpu{ + pub const m3000 = CpuModel{ .name = "m3000", .llvm_name = "m3000", .features = featureSet(&[_]Feature{ @@ -2119,7 +2120,7 @@ pub const cpu = struct { /// All avr CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.at43usb320, &cpu.at43usb355, &cpu.at76c711, diff --git a/lib/std/target/bpf.zig b/lib/std/target/bpf.zig index b6179075cc..6b548ac031 100644 --- a/lib/std/target/bpf.zig +++ b/lib/std/target/bpf.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { alu32, @@ -7,12 +8,12 @@ pub const Feature = enum { dwarfris, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.alu32)] = .{ .llvm_name = "alu32", .description = "Enable ALU32 instructions", @@ -37,27 +38,27 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const probe = Cpu{ + pub const probe = CpuModel{ .name = "probe", .llvm_name = "probe", .features = featureSet(&[_]Feature{}), }; - pub const v1 = Cpu{ + pub const v1 = CpuModel{ .name = "v1", .llvm_name = "v1", .features = featureSet(&[_]Feature{}), }; - pub const v2 = Cpu{ + pub const v2 = CpuModel{ .name = "v2", .llvm_name = "v2", .features = featureSet(&[_]Feature{}), }; - pub const v3 = Cpu{ + pub const v3 = CpuModel{ .name = "v3", .llvm_name = "v3", .features = featureSet(&[_]Feature{}), @@ -67,7 +68,7 @@ pub const cpu = struct { /// All bpf CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.generic, &cpu.probe, &cpu.v1, diff --git a/lib/std/target/hexagon.zig b/lib/std/target/hexagon.zig index f873237493..b0558908e3 100644 --- a/lib/std/target/hexagon.zig +++ b/lib/std/target/hexagon.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { duplex, @@ -28,12 +29,12 @@ pub const Feature = enum { zreg, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.duplex)] = .{ .llvm_name = "duplex", .description = "Enable generation of duplex instruction", @@ -186,7 +187,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{ @@ -201,7 +202,7 @@ pub const cpu = struct { .v60, }), }; - pub const hexagonv5 = Cpu{ + pub const hexagonv5 = CpuModel{ .name = "hexagonv5", .llvm_name = "hexagonv5", .features = featureSet(&[_]Feature{ @@ -214,7 +215,7 @@ pub const cpu = struct { .v5, }), }; - pub const hexagonv55 = Cpu{ + pub const hexagonv55 = CpuModel{ .name = "hexagonv55", .llvm_name = "hexagonv55", .features = featureSet(&[_]Feature{ @@ -228,7 +229,7 @@ pub const cpu = struct { .v55, }), }; - pub const hexagonv60 = Cpu{ + pub const hexagonv60 = CpuModel{ .name = "hexagonv60", .llvm_name = "hexagonv60", .features = featureSet(&[_]Feature{ @@ -243,7 +244,7 @@ pub const cpu = struct { .v60, }), }; - pub const hexagonv62 = Cpu{ + pub const hexagonv62 = CpuModel{ .name = "hexagonv62", .llvm_name = "hexagonv62", .features = featureSet(&[_]Feature{ @@ -259,7 +260,7 @@ pub const cpu = struct { .v62, }), }; - pub const hexagonv65 = Cpu{ + pub const hexagonv65 = CpuModel{ .name = "hexagonv65", .llvm_name = "hexagonv65", .features = featureSet(&[_]Feature{ @@ -277,7 +278,7 @@ pub const cpu = struct { .v65, }), }; - pub const hexagonv66 = Cpu{ + pub const hexagonv66 = CpuModel{ .name = "hexagonv66", .llvm_name = "hexagonv66", .features = featureSet(&[_]Feature{ @@ -301,7 +302,7 @@ pub const cpu = struct { /// All hexagon CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.generic, &cpu.hexagonv5, &cpu.hexagonv55, diff --git a/lib/std/target/mips.zig b/lib/std/target/mips.zig index fce7c9ce36..6ea7f665f0 100644 --- a/lib/std/target/mips.zig +++ b/lib/std/target/mips.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { abs2008, @@ -53,12 +54,12 @@ pub const Feature = enum { virt, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.abs2008)] = .{ .llvm_name = "abs2008", .description = "Disable IEEE 754-2008 abs.fmt mode", @@ -372,112 +373,112 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const mips1 = Cpu{ + pub const mips1 = CpuModel{ .name = "mips1", .llvm_name = "mips1", .features = featureSet(&[_]Feature{ .mips1, }), }; - pub const mips2 = Cpu{ + pub const mips2 = CpuModel{ .name = "mips2", .llvm_name = "mips2", .features = featureSet(&[_]Feature{ .mips2, }), }; - pub const mips3 = Cpu{ + pub const mips3 = CpuModel{ .name = "mips3", .llvm_name = "mips3", .features = featureSet(&[_]Feature{ .mips3, }), }; - pub const mips32 = Cpu{ + pub const mips32 = CpuModel{ .name = "mips32", .llvm_name = "mips32", .features = featureSet(&[_]Feature{ .mips32, }), }; - pub const mips32r2 = Cpu{ + pub const mips32r2 = CpuModel{ .name = "mips32r2", .llvm_name = "mips32r2", .features = featureSet(&[_]Feature{ .mips32r2, }), }; - pub const mips32r3 = Cpu{ + pub const mips32r3 = CpuModel{ .name = "mips32r3", .llvm_name = "mips32r3", .features = featureSet(&[_]Feature{ .mips32r3, }), }; - pub const mips32r5 = Cpu{ + pub const mips32r5 = CpuModel{ .name = "mips32r5", .llvm_name = "mips32r5", .features = featureSet(&[_]Feature{ .mips32r5, }), }; - pub const mips32r6 = Cpu{ + pub const mips32r6 = CpuModel{ .name = "mips32r6", .llvm_name = "mips32r6", .features = featureSet(&[_]Feature{ .mips32r6, }), }; - pub const mips4 = Cpu{ + pub const mips4 = CpuModel{ .name = "mips4", .llvm_name = "mips4", .features = featureSet(&[_]Feature{ .mips4, }), }; - pub const mips5 = Cpu{ + pub const mips5 = CpuModel{ .name = "mips5", .llvm_name = "mips5", .features = featureSet(&[_]Feature{ .mips5, }), }; - pub const mips64 = Cpu{ + pub const mips64 = CpuModel{ .name = "mips64", .llvm_name = "mips64", .features = featureSet(&[_]Feature{ .mips64, }), }; - pub const mips64r2 = Cpu{ + pub const mips64r2 = CpuModel{ .name = "mips64r2", .llvm_name = "mips64r2", .features = featureSet(&[_]Feature{ .mips64r2, }), }; - pub const mips64r3 = Cpu{ + pub const mips64r3 = CpuModel{ .name = "mips64r3", .llvm_name = "mips64r3", .features = featureSet(&[_]Feature{ .mips64r3, }), }; - pub const mips64r5 = Cpu{ + pub const mips64r5 = CpuModel{ .name = "mips64r5", .llvm_name = "mips64r5", .features = featureSet(&[_]Feature{ .mips64r5, }), }; - pub const mips64r6 = Cpu{ + pub const mips64r6 = CpuModel{ .name = "mips64r6", .llvm_name = "mips64r6", .features = featureSet(&[_]Feature{ .mips64r6, }), }; - pub const octeon = Cpu{ + pub const octeon = CpuModel{ .name = "octeon", .llvm_name = "octeon", .features = featureSet(&[_]Feature{ @@ -485,7 +486,7 @@ pub const cpu = struct { .mips64r2, }), }; - pub const p5600 = Cpu{ + pub const p5600 = CpuModel{ .name = "p5600", .llvm_name = "p5600", .features = featureSet(&[_]Feature{ @@ -497,7 +498,7 @@ pub const cpu = struct { /// All mips CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.mips1, &cpu.mips2, &cpu.mips3, diff --git a/lib/std/target/msp430.zig b/lib/std/target/msp430.zig index bc932f2295..e1b858341f 100644 --- a/lib/std/target/msp430.zig +++ b/lib/std/target/msp430.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { ext, @@ -8,12 +9,12 @@ pub const Feature = enum { hwmultf5, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.ext)] = .{ .llvm_name = "ext", .description = "Enable MSP430-X extensions", @@ -43,17 +44,17 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const msp430 = Cpu{ + pub const msp430 = CpuModel{ .name = "msp430", .llvm_name = "msp430", .features = featureSet(&[_]Feature{}), }; - pub const msp430x = Cpu{ + pub const msp430x = CpuModel{ .name = "msp430x", .llvm_name = "msp430x", .features = featureSet(&[_]Feature{ @@ -65,7 +66,7 @@ pub const cpu = struct { /// All msp430 CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.generic, &cpu.msp430, &cpu.msp430x, diff --git a/lib/std/target/nvptx.zig b/lib/std/target/nvptx.zig index 1800e320b4..6a79aea1da 100644 --- a/lib/std/target/nvptx.zig +++ b/lib/std/target/nvptx.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { ptx32, @@ -29,12 +30,12 @@ pub const Feature = enum { sm_75, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.ptx32)] = .{ .llvm_name = "ptx32", .description = "Use PTX version 3.2", @@ -169,28 +170,28 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const sm_20 = Cpu{ + pub const sm_20 = CpuModel{ .name = "sm_20", .llvm_name = "sm_20", .features = featureSet(&[_]Feature{ .sm_20, }), }; - pub const sm_21 = Cpu{ + pub const sm_21 = CpuModel{ .name = "sm_21", .llvm_name = "sm_21", .features = featureSet(&[_]Feature{ .sm_21, }), }; - pub const sm_30 = Cpu{ + pub const sm_30 = CpuModel{ .name = "sm_30", .llvm_name = "sm_30", .features = featureSet(&[_]Feature{ .sm_30, }), }; - pub const sm_32 = Cpu{ + pub const sm_32 = CpuModel{ .name = "sm_32", .llvm_name = "sm_32", .features = featureSet(&[_]Feature{ @@ -198,14 +199,14 @@ pub const cpu = struct { .sm_32, }), }; - pub const sm_35 = Cpu{ + pub const sm_35 = CpuModel{ .name = "sm_35", .llvm_name = "sm_35", .features = featureSet(&[_]Feature{ .sm_35, }), }; - pub const sm_37 = Cpu{ + pub const sm_37 = CpuModel{ .name = "sm_37", .llvm_name = "sm_37", .features = featureSet(&[_]Feature{ @@ -213,7 +214,7 @@ pub const cpu = struct { .sm_37, }), }; - pub const sm_50 = Cpu{ + pub const sm_50 = CpuModel{ .name = "sm_50", .llvm_name = "sm_50", .features = featureSet(&[_]Feature{ @@ -221,7 +222,7 @@ pub const cpu = struct { .sm_50, }), }; - pub const sm_52 = Cpu{ + pub const sm_52 = CpuModel{ .name = "sm_52", .llvm_name = "sm_52", .features = featureSet(&[_]Feature{ @@ -229,7 +230,7 @@ pub const cpu = struct { .sm_52, }), }; - pub const sm_53 = Cpu{ + pub const sm_53 = CpuModel{ .name = "sm_53", .llvm_name = "sm_53", .features = featureSet(&[_]Feature{ @@ -237,7 +238,7 @@ pub const cpu = struct { .sm_53, }), }; - pub const sm_60 = Cpu{ + pub const sm_60 = CpuModel{ .name = "sm_60", .llvm_name = "sm_60", .features = featureSet(&[_]Feature{ @@ -245,7 +246,7 @@ pub const cpu = struct { .sm_60, }), }; - pub const sm_61 = Cpu{ + pub const sm_61 = CpuModel{ .name = "sm_61", .llvm_name = "sm_61", .features = featureSet(&[_]Feature{ @@ -253,7 +254,7 @@ pub const cpu = struct { .sm_61, }), }; - pub const sm_62 = Cpu{ + pub const sm_62 = CpuModel{ .name = "sm_62", .llvm_name = "sm_62", .features = featureSet(&[_]Feature{ @@ -261,7 +262,7 @@ pub const cpu = struct { .sm_62, }), }; - pub const sm_70 = Cpu{ + pub const sm_70 = CpuModel{ .name = "sm_70", .llvm_name = "sm_70", .features = featureSet(&[_]Feature{ @@ -269,7 +270,7 @@ pub const cpu = struct { .sm_70, }), }; - pub const sm_72 = Cpu{ + pub const sm_72 = CpuModel{ .name = "sm_72", .llvm_name = "sm_72", .features = featureSet(&[_]Feature{ @@ -277,7 +278,7 @@ pub const cpu = struct { .sm_72, }), }; - pub const sm_75 = Cpu{ + pub const sm_75 = CpuModel{ .name = "sm_75", .llvm_name = "sm_75", .features = featureSet(&[_]Feature{ @@ -290,7 +291,7 @@ pub const cpu = struct { /// All nvptx CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.sm_20, &cpu.sm_21, &cpu.sm_30, diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig index 41321f7b04..ae3371e066 100644 --- a/lib/std/target/powerpc.zig +++ b/lib/std/target/powerpc.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { @"64bit", @@ -55,12 +56,12 @@ pub const Feature = enum { vsx, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.@"64bit")] = .{ .llvm_name = "64bit", .description = "Enable 64-bit instructions", @@ -377,7 +378,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const @"440" = Cpu{ + pub const @"440" = CpuModel{ .name = "440", .llvm_name = "440", .features = featureSet(&[_]Feature{ @@ -389,7 +390,7 @@ pub const cpu = struct { .msync, }), }; - pub const @"450" = Cpu{ + pub const @"450" = CpuModel{ .name = "450", .llvm_name = "450", .features = featureSet(&[_]Feature{ @@ -401,21 +402,21 @@ pub const cpu = struct { .msync, }), }; - pub const @"601" = Cpu{ + pub const @"601" = CpuModel{ .name = "601", .llvm_name = "601", .features = featureSet(&[_]Feature{ .fpu, }), }; - pub const @"602" = Cpu{ + pub const @"602" = CpuModel{ .name = "602", .llvm_name = "602", .features = featureSet(&[_]Feature{ .fpu, }), }; - pub const @"603" = Cpu{ + pub const @"603" = CpuModel{ .name = "603", .llvm_name = "603", .features = featureSet(&[_]Feature{ @@ -423,7 +424,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"603e" = Cpu{ + pub const @"603e" = CpuModel{ .name = "603e", .llvm_name = "603e", .features = featureSet(&[_]Feature{ @@ -431,7 +432,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"603ev" = Cpu{ + pub const @"603ev" = CpuModel{ .name = "603ev", .llvm_name = "603ev", .features = featureSet(&[_]Feature{ @@ -439,7 +440,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"604" = Cpu{ + pub const @"604" = CpuModel{ .name = "604", .llvm_name = "604", .features = featureSet(&[_]Feature{ @@ -447,7 +448,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"604e" = Cpu{ + pub const @"604e" = CpuModel{ .name = "604e", .llvm_name = "604e", .features = featureSet(&[_]Feature{ @@ -455,7 +456,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"620" = Cpu{ + pub const @"620" = CpuModel{ .name = "620", .llvm_name = "620", .features = featureSet(&[_]Feature{ @@ -463,7 +464,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"7400" = Cpu{ + pub const @"7400" = CpuModel{ .name = "7400", .llvm_name = "7400", .features = featureSet(&[_]Feature{ @@ -472,7 +473,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"7450" = Cpu{ + pub const @"7450" = CpuModel{ .name = "7450", .llvm_name = "7450", .features = featureSet(&[_]Feature{ @@ -481,7 +482,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"750" = Cpu{ + pub const @"750" = CpuModel{ .name = "750", .llvm_name = "750", .features = featureSet(&[_]Feature{ @@ -489,7 +490,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"970" = Cpu{ + pub const @"970" = CpuModel{ .name = "970", .llvm_name = "970", .features = featureSet(&[_]Feature{ @@ -502,7 +503,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const a2 = Cpu{ + pub const a2 = CpuModel{ .name = "a2", .llvm_name = "a2", .features = featureSet(&[_]Feature{ @@ -527,7 +528,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const a2q = Cpu{ + pub const a2q = CpuModel{ .name = "a2q", .llvm_name = "a2q", .features = featureSet(&[_]Feature{ @@ -553,7 +554,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const e500 = Cpu{ + pub const e500 = CpuModel{ .name = "e500", .llvm_name = "e500", .features = featureSet(&[_]Feature{ @@ -562,7 +563,7 @@ pub const cpu = struct { .isel, }), }; - pub const e500mc = Cpu{ + pub const e500mc = CpuModel{ .name = "e500mc", .llvm_name = "e500mc", .features = featureSet(&[_]Feature{ @@ -572,7 +573,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const e5500 = Cpu{ + pub const e5500 = CpuModel{ .name = "e5500", .llvm_name = "e5500", .features = featureSet(&[_]Feature{ @@ -584,7 +585,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const g3 = Cpu{ + pub const g3 = CpuModel{ .name = "g3", .llvm_name = "g3", .features = featureSet(&[_]Feature{ @@ -592,7 +593,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const g4 = Cpu{ + pub const g4 = CpuModel{ .name = "g4", .llvm_name = "g4", .features = featureSet(&[_]Feature{ @@ -601,7 +602,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const @"g4+" = Cpu{ + pub const @"g4+" = CpuModel{ .name = "g4+", .llvm_name = "g4+", .features = featureSet(&[_]Feature{ @@ -610,7 +611,7 @@ pub const cpu = struct { .frsqrte, }), }; - pub const g5 = Cpu{ + pub const g5 = CpuModel{ .name = "g5", .llvm_name = "g5", .features = featureSet(&[_]Feature{ @@ -623,28 +624,28 @@ pub const cpu = struct { .stfiwx, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{ .hard_float, }), }; - pub const ppc = Cpu{ + pub const ppc = CpuModel{ .name = "ppc", .llvm_name = "ppc", .features = featureSet(&[_]Feature{ .hard_float, }), }; - pub const ppc32 = Cpu{ + pub const ppc32 = CpuModel{ .name = "ppc32", .llvm_name = "ppc32", .features = featureSet(&[_]Feature{ .hard_float, }), }; - pub const ppc64 = Cpu{ + pub const ppc64 = CpuModel{ .name = "ppc64", .llvm_name = "ppc64", .features = featureSet(&[_]Feature{ @@ -657,7 +658,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const ppc64le = Cpu{ + pub const ppc64le = CpuModel{ .name = "ppc64le", .llvm_name = "ppc64le", .features = featureSet(&[_]Feature{ @@ -692,7 +693,7 @@ pub const cpu = struct { .vsx, }), }; - pub const pwr3 = Cpu{ + pub const pwr3 = CpuModel{ .name = "pwr3", .llvm_name = "pwr3", .features = featureSet(&[_]Feature{ @@ -704,7 +705,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr4 = Cpu{ + pub const pwr4 = CpuModel{ .name = "pwr4", .llvm_name = "pwr4", .features = featureSet(&[_]Feature{ @@ -717,7 +718,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr5 = Cpu{ + pub const pwr5 = CpuModel{ .name = "pwr5", .llvm_name = "pwr5", .features = featureSet(&[_]Feature{ @@ -732,7 +733,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr5x = Cpu{ + pub const pwr5x = CpuModel{ .name = "pwr5x", .llvm_name = "pwr5x", .features = featureSet(&[_]Feature{ @@ -748,7 +749,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr6 = Cpu{ + pub const pwr6 = CpuModel{ .name = "pwr6", .llvm_name = "pwr6", .features = featureSet(&[_]Feature{ @@ -768,7 +769,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr6x = Cpu{ + pub const pwr6x = CpuModel{ .name = "pwr6x", .llvm_name = "pwr6x", .features = featureSet(&[_]Feature{ @@ -788,7 +789,7 @@ pub const cpu = struct { .stfiwx, }), }; - pub const pwr7 = Cpu{ + pub const pwr7 = CpuModel{ .name = "pwr7", .llvm_name = "pwr7", .features = featureSet(&[_]Feature{ @@ -816,7 +817,7 @@ pub const cpu = struct { .vsx, }), }; - pub const pwr8 = Cpu{ + pub const pwr8 = CpuModel{ .name = "pwr8", .llvm_name = "pwr8", .features = featureSet(&[_]Feature{ @@ -851,7 +852,7 @@ pub const cpu = struct { .vsx, }), }; - pub const pwr9 = Cpu{ + pub const pwr9 = CpuModel{ .name = "pwr9", .llvm_name = "pwr9", .features = featureSet(&[_]Feature{ @@ -897,7 +898,7 @@ pub const cpu = struct { /// All powerpc CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.@"440", &cpu.@"450", &cpu.@"601", diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig index ddf1049a20..a799c29df6 100644 --- a/lib/std/target/riscv.zig +++ b/lib/std/target/riscv.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { @"64bit", @@ -12,12 +13,12 @@ pub const Feature = enum { relax, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.@"64bit")] = .{ .llvm_name = "64bit", .description = "Implements RV64", @@ -69,7 +70,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const baseline_rv32 = Cpu{ + pub const baseline_rv32 = CpuModel{ .name = "baseline_rv32", .llvm_name = "generic-rv32", .features = featureSet(&[_]Feature{ @@ -81,7 +82,7 @@ pub const cpu = struct { }), }; - pub const baseline_rv64 = Cpu{ + pub const baseline_rv64 = CpuModel{ .name = "baseline_rv64", .llvm_name = "generic-rv64", .features = featureSet(&[_]Feature{ @@ -94,13 +95,13 @@ pub const cpu = struct { }), }; - pub const generic_rv32 = Cpu{ + pub const generic_rv32 = CpuModel{ .name = "generic_rv32", .llvm_name = "generic-rv32", .features = featureSet(&[_]Feature{}), }; - pub const generic_rv64 = Cpu{ + pub const generic_rv64 = CpuModel{ .name = "generic_rv64", .llvm_name = "generic-rv64", .features = featureSet(&[_]Feature{ @@ -112,7 +113,7 @@ pub const cpu = struct { /// All riscv CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.baseline_rv32, &cpu.baseline_rv64, &cpu.generic_rv32, diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig index 923cc0732c..3ec6cc7c20 100644 --- a/lib/std/target/sparc.zig +++ b/lib/std/target/sparc.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { deprecated_v8, @@ -23,12 +24,12 @@ pub const Feature = enum { vis3, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.deprecated_v8)] = .{ .llvm_name = "deprecated-v8", .description = "Enable deprecated V8 instructions in V9 mode", @@ -133,7 +134,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const at697e = Cpu{ + pub const at697e = CpuModel{ .name = "at697e", .llvm_name = "at697e", .features = featureSet(&[_]Feature{ @@ -141,7 +142,7 @@ pub const cpu = struct { .leon, }), }; - pub const at697f = Cpu{ + pub const at697f = CpuModel{ .name = "at697f", .llvm_name = "at697f", .features = featureSet(&[_]Feature{ @@ -149,17 +150,17 @@ pub const cpu = struct { .leon, }), }; - pub const f934 = Cpu{ + pub const f934 = CpuModel{ .name = "f934", .llvm_name = "f934", .features = featureSet(&[_]Feature{}), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const gr712rc = Cpu{ + pub const gr712rc = CpuModel{ .name = "gr712rc", .llvm_name = "gr712rc", .features = featureSet(&[_]Feature{ @@ -167,7 +168,7 @@ pub const cpu = struct { .leon, }), }; - pub const gr740 = Cpu{ + pub const gr740 = CpuModel{ .name = "gr740", .llvm_name = "gr740", .features = featureSet(&[_]Feature{ @@ -178,19 +179,19 @@ pub const cpu = struct { .leonpwrpsr, }), }; - pub const hypersparc = Cpu{ + pub const hypersparc = CpuModel{ .name = "hypersparc", .llvm_name = "hypersparc", .features = featureSet(&[_]Feature{}), }; - pub const leon2 = Cpu{ + pub const leon2 = CpuModel{ .name = "leon2", .llvm_name = "leon2", .features = featureSet(&[_]Feature{ .leon, }), }; - pub const leon3 = Cpu{ + pub const leon3 = CpuModel{ .name = "leon3", .llvm_name = "leon3", .features = featureSet(&[_]Feature{ @@ -198,7 +199,7 @@ pub const cpu = struct { .leon, }), }; - pub const leon4 = Cpu{ + pub const leon4 = CpuModel{ .name = "leon4", .llvm_name = "leon4", .features = featureSet(&[_]Feature{ @@ -207,7 +208,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2080 = Cpu{ + pub const ma2080 = CpuModel{ .name = "ma2080", .llvm_name = "ma2080", .features = featureSet(&[_]Feature{ @@ -215,7 +216,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2085 = Cpu{ + pub const ma2085 = CpuModel{ .name = "ma2085", .llvm_name = "ma2085", .features = featureSet(&[_]Feature{ @@ -223,7 +224,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2100 = Cpu{ + pub const ma2100 = CpuModel{ .name = "ma2100", .llvm_name = "ma2100", .features = featureSet(&[_]Feature{ @@ -231,7 +232,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2150 = Cpu{ + pub const ma2150 = CpuModel{ .name = "ma2150", .llvm_name = "ma2150", .features = featureSet(&[_]Feature{ @@ -239,7 +240,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2155 = Cpu{ + pub const ma2155 = CpuModel{ .name = "ma2155", .llvm_name = "ma2155", .features = featureSet(&[_]Feature{ @@ -247,7 +248,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2450 = Cpu{ + pub const ma2450 = CpuModel{ .name = "ma2450", .llvm_name = "ma2450", .features = featureSet(&[_]Feature{ @@ -255,7 +256,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2455 = Cpu{ + pub const ma2455 = CpuModel{ .name = "ma2455", .llvm_name = "ma2455", .features = featureSet(&[_]Feature{ @@ -263,7 +264,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2480 = Cpu{ + pub const ma2480 = CpuModel{ .name = "ma2480", .llvm_name = "ma2480", .features = featureSet(&[_]Feature{ @@ -271,7 +272,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2485 = Cpu{ + pub const ma2485 = CpuModel{ .name = "ma2485", .llvm_name = "ma2485", .features = featureSet(&[_]Feature{ @@ -279,7 +280,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2x5x = Cpu{ + pub const ma2x5x = CpuModel{ .name = "ma2x5x", .llvm_name = "ma2x5x", .features = featureSet(&[_]Feature{ @@ -287,7 +288,7 @@ pub const cpu = struct { .leon, }), }; - pub const ma2x8x = Cpu{ + pub const ma2x8x = CpuModel{ .name = "ma2x8x", .llvm_name = "ma2x8x", .features = featureSet(&[_]Feature{ @@ -295,7 +296,7 @@ pub const cpu = struct { .leon, }), }; - pub const myriad2 = Cpu{ + pub const myriad2 = CpuModel{ .name = "myriad2", .llvm_name = "myriad2", .features = featureSet(&[_]Feature{ @@ -303,7 +304,7 @@ pub const cpu = struct { .leon, }), }; - pub const myriad2_1 = Cpu{ + pub const myriad2_1 = CpuModel{ .name = "myriad2_1", .llvm_name = "myriad2.1", .features = featureSet(&[_]Feature{ @@ -311,7 +312,7 @@ pub const cpu = struct { .leon, }), }; - pub const myriad2_2 = Cpu{ + pub const myriad2_2 = CpuModel{ .name = "myriad2_2", .llvm_name = "myriad2.2", .features = featureSet(&[_]Feature{ @@ -319,7 +320,7 @@ pub const cpu = struct { .leon, }), }; - pub const myriad2_3 = Cpu{ + pub const myriad2_3 = CpuModel{ .name = "myriad2_3", .llvm_name = "myriad2.3", .features = featureSet(&[_]Feature{ @@ -327,7 +328,7 @@ pub const cpu = struct { .leon, }), }; - pub const niagara = Cpu{ + pub const niagara = CpuModel{ .name = "niagara", .llvm_name = "niagara", .features = featureSet(&[_]Feature{ @@ -337,7 +338,7 @@ pub const cpu = struct { .vis2, }), }; - pub const niagara2 = Cpu{ + pub const niagara2 = CpuModel{ .name = "niagara2", .llvm_name = "niagara2", .features = featureSet(&[_]Feature{ @@ -348,7 +349,7 @@ pub const cpu = struct { .vis2, }), }; - pub const niagara3 = Cpu{ + pub const niagara3 = CpuModel{ .name = "niagara3", .llvm_name = "niagara3", .features = featureSet(&[_]Feature{ @@ -359,7 +360,7 @@ pub const cpu = struct { .vis2, }), }; - pub const niagara4 = Cpu{ + pub const niagara4 = CpuModel{ .name = "niagara4", .llvm_name = "niagara4", .features = featureSet(&[_]Feature{ @@ -371,32 +372,32 @@ pub const cpu = struct { .vis3, }), }; - pub const sparclet = Cpu{ + pub const sparclet = CpuModel{ .name = "sparclet", .llvm_name = "sparclet", .features = featureSet(&[_]Feature{}), }; - pub const sparclite = Cpu{ + pub const sparclite = CpuModel{ .name = "sparclite", .llvm_name = "sparclite", .features = featureSet(&[_]Feature{}), }; - pub const sparclite86x = Cpu{ + pub const sparclite86x = CpuModel{ .name = "sparclite86x", .llvm_name = "sparclite86x", .features = featureSet(&[_]Feature{}), }; - pub const supersparc = Cpu{ + pub const supersparc = CpuModel{ .name = "supersparc", .llvm_name = "supersparc", .features = featureSet(&[_]Feature{}), }; - pub const tsc701 = Cpu{ + pub const tsc701 = CpuModel{ .name = "tsc701", .llvm_name = "tsc701", .features = featureSet(&[_]Feature{}), }; - pub const ultrasparc = Cpu{ + pub const ultrasparc = CpuModel{ .name = "ultrasparc", .llvm_name = "ultrasparc", .features = featureSet(&[_]Feature{ @@ -405,7 +406,7 @@ pub const cpu = struct { .vis, }), }; - pub const ultrasparc3 = Cpu{ + pub const ultrasparc3 = CpuModel{ .name = "ultrasparc3", .llvm_name = "ultrasparc3", .features = featureSet(&[_]Feature{ @@ -415,7 +416,7 @@ pub const cpu = struct { .vis2, }), }; - pub const ut699 = Cpu{ + pub const ut699 = CpuModel{ .name = "ut699", .llvm_name = "ut699", .features = featureSet(&[_]Feature{ @@ -426,7 +427,7 @@ pub const cpu = struct { .no_fsmuld, }), }; - pub const v7 = Cpu{ + pub const v7 = CpuModel{ .name = "v7", .llvm_name = "v7", .features = featureSet(&[_]Feature{ @@ -434,12 +435,12 @@ pub const cpu = struct { .soft_mul_div, }), }; - pub const v8 = Cpu{ + pub const v8 = CpuModel{ .name = "v8", .llvm_name = "v8", .features = featureSet(&[_]Feature{}), }; - pub const v9 = Cpu{ + pub const v9 = CpuModel{ .name = "v9", .llvm_name = "v9", .features = featureSet(&[_]Feature{ @@ -451,7 +452,7 @@ pub const cpu = struct { /// All sparc CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.at697e, &cpu.at697f, &cpu.f934, diff --git a/lib/std/target/systemz.zig b/lib/std/target/systemz.zig index c924af6e70..798ecf5630 100644 --- a/lib/std/target/systemz.zig +++ b/lib/std/target/systemz.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { deflate_conversion, @@ -39,12 +40,12 @@ pub const Feature = enum { vector_packed_decimal_enhancement, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.deflate_conversion)] = .{ .llvm_name = "deflate-conversion", .description = "Assume that the deflate-conversion facility is installed", @@ -229,7 +230,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const arch10 = Cpu{ + pub const arch10 = CpuModel{ .name = "arch10", .llvm_name = "arch10", .features = featureSet(&[_]Feature{ @@ -252,7 +253,7 @@ pub const cpu = struct { .transactional_execution, }), }; - pub const arch11 = Cpu{ + pub const arch11 = CpuModel{ .name = "arch11", .llvm_name = "arch11", .features = featureSet(&[_]Feature{ @@ -280,7 +281,7 @@ pub const cpu = struct { .vector, }), }; - pub const arch12 = Cpu{ + pub const arch12 = CpuModel{ .name = "arch12", .llvm_name = "arch12", .features = featureSet(&[_]Feature{ @@ -315,7 +316,7 @@ pub const cpu = struct { .vector_packed_decimal, }), }; - pub const arch13 = Cpu{ + pub const arch13 = CpuModel{ .name = "arch13", .llvm_name = "arch13", .features = featureSet(&[_]Feature{ @@ -356,12 +357,12 @@ pub const cpu = struct { .vector_packed_decimal_enhancement, }), }; - pub const arch8 = Cpu{ + pub const arch8 = CpuModel{ .name = "arch8", .llvm_name = "arch8", .features = featureSet(&[_]Feature{}), }; - pub const arch9 = Cpu{ + pub const arch9 = CpuModel{ .name = "arch9", .llvm_name = "arch9", .features = featureSet(&[_]Feature{ @@ -377,17 +378,17 @@ pub const cpu = struct { .reset_reference_bits_multiple, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const z10 = Cpu{ + pub const z10 = CpuModel{ .name = "z10", .llvm_name = "z10", .features = featureSet(&[_]Feature{}), }; - pub const z13 = Cpu{ + pub const z13 = CpuModel{ .name = "z13", .llvm_name = "z13", .features = featureSet(&[_]Feature{ @@ -415,7 +416,7 @@ pub const cpu = struct { .vector, }), }; - pub const z14 = Cpu{ + pub const z14 = CpuModel{ .name = "z14", .llvm_name = "z14", .features = featureSet(&[_]Feature{ @@ -450,7 +451,7 @@ pub const cpu = struct { .vector_packed_decimal, }), }; - pub const z196 = Cpu{ + pub const z196 = CpuModel{ .name = "z196", .llvm_name = "z196", .features = featureSet(&[_]Feature{ @@ -466,7 +467,7 @@ pub const cpu = struct { .reset_reference_bits_multiple, }), }; - pub const zEC12 = Cpu{ + pub const zEC12 = CpuModel{ .name = "zEC12", .llvm_name = "zEC12", .features = featureSet(&[_]Feature{ @@ -494,7 +495,7 @@ pub const cpu = struct { /// All systemz CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.arch10, &cpu.arch11, &cpu.arch12, diff --git a/lib/std/target/wasm.zig b/lib/std/target/wasm.zig index 6d79bbb282..066282f3c6 100644 --- a/lib/std/target/wasm.zig +++ b/lib/std/target/wasm.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { atomics, @@ -14,12 +15,12 @@ pub const Feature = enum { unimplemented_simd128, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.atomics)] = .{ .llvm_name = "atomics", .description = "Enable Atomics", @@ -81,7 +82,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const bleeding_edge = Cpu{ + pub const bleeding_edge = CpuModel{ .name = "bleeding_edge", .llvm_name = "bleeding-edge", .features = featureSet(&[_]Feature{ @@ -92,12 +93,12 @@ pub const cpu = struct { .simd128, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{}), }; - pub const mvp = Cpu{ + pub const mvp = CpuModel{ .name = "mvp", .llvm_name = "mvp", .features = featureSet(&[_]Feature{}), @@ -107,7 +108,7 @@ pub const cpu = struct { /// All wasm CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.bleeding_edge, &cpu.generic, &cpu.mvp, diff --git a/lib/std/target/x86.zig b/lib/std/target/x86.zig index 3c2e306e79..1e2ac409bd 100644 --- a/lib/std/target/x86.zig +++ b/lib/std/target/x86.zig @@ -1,5 +1,6 @@ const std = @import("../std.zig"); -const Cpu = std.Target.Cpu; +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; pub const Feature = enum { @"3dnow", @@ -125,12 +126,12 @@ pub const Feature = enum { xsaves, }; -pub usingnamespace Cpu.Feature.feature_set_fns(Feature); +pub usingnamespace CpuFeature.feature_set_fns(Feature); pub const all_features = blk: { const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); - var result: [len]Cpu.Feature = undefined; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; result[@enumToInt(Feature.@"3dnow")] = .{ .llvm_name = "3dnow", .description = "Enable 3DNow! instructions", @@ -829,7 +830,7 @@ pub const all_features = blk: { }; pub const cpu = struct { - pub const amdfam10 = Cpu{ + pub const amdfam10 = CpuModel{ .name = "amdfam10", .llvm_name = "amdfam10", .features = featureSet(&[_]Feature{ @@ -849,7 +850,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon = Cpu{ + pub const athlon = CpuModel{ .name = "athlon", .llvm_name = "athlon", .features = featureSet(&[_]Feature{ @@ -862,7 +863,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon_4 = Cpu{ + pub const athlon_4 = CpuModel{ .name = "athlon_4", .llvm_name = "athlon-4", .features = featureSet(&[_]Feature{ @@ -877,7 +878,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon_fx = Cpu{ + pub const athlon_fx = CpuModel{ .name = "athlon_fx", .llvm_name = "athlon-fx", .features = featureSet(&[_]Feature{ @@ -894,7 +895,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon_mp = Cpu{ + pub const athlon_mp = CpuModel{ .name = "athlon_mp", .llvm_name = "athlon-mp", .features = featureSet(&[_]Feature{ @@ -909,7 +910,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon_tbird = Cpu{ + pub const athlon_tbird = CpuModel{ .name = "athlon_tbird", .llvm_name = "athlon-tbird", .features = featureSet(&[_]Feature{ @@ -922,7 +923,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon_xp = Cpu{ + pub const athlon_xp = CpuModel{ .name = "athlon_xp", .llvm_name = "athlon-xp", .features = featureSet(&[_]Feature{ @@ -937,7 +938,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon64 = Cpu{ + pub const athlon64 = CpuModel{ .name = "athlon64", .llvm_name = "athlon64", .features = featureSet(&[_]Feature{ @@ -954,7 +955,7 @@ pub const cpu = struct { .x87, }), }; - pub const athlon64_sse3 = Cpu{ + pub const athlon64_sse3 = CpuModel{ .name = "athlon64_sse3", .llvm_name = "athlon64-sse3", .features = featureSet(&[_]Feature{ @@ -972,7 +973,7 @@ pub const cpu = struct { .x87, }), }; - pub const atom = Cpu{ + pub const atom = CpuModel{ .name = "atom", .llvm_name = "atom", .features = featureSet(&[_]Feature{ @@ -996,7 +997,7 @@ pub const cpu = struct { .x87, }), }; - pub const barcelona = Cpu{ + pub const barcelona = CpuModel{ .name = "barcelona", .llvm_name = "barcelona", .features = featureSet(&[_]Feature{ @@ -1016,7 +1017,7 @@ pub const cpu = struct { .x87, }), }; - pub const bdver1 = Cpu{ + pub const bdver1 = CpuModel{ .name = "bdver1", .llvm_name = "bdver1", .features = featureSet(&[_]Feature{ @@ -1043,7 +1044,7 @@ pub const cpu = struct { .xsave, }), }; - pub const bdver2 = Cpu{ + pub const bdver2 = CpuModel{ .name = "bdver2", .llvm_name = "bdver2", .features = featureSet(&[_]Feature{ @@ -1075,7 +1076,7 @@ pub const cpu = struct { .xsave, }), }; - pub const bdver3 = Cpu{ + pub const bdver3 = CpuModel{ .name = "bdver3", .llvm_name = "bdver3", .features = featureSet(&[_]Feature{ @@ -1109,7 +1110,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const bdver4 = Cpu{ + pub const bdver4 = CpuModel{ .name = "bdver4", .llvm_name = "bdver4", .features = featureSet(&[_]Feature{ @@ -1146,7 +1147,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const bonnell = Cpu{ + pub const bonnell = CpuModel{ .name = "bonnell", .llvm_name = "bonnell", .features = featureSet(&[_]Feature{ @@ -1170,7 +1171,7 @@ pub const cpu = struct { .x87, }), }; - pub const broadwell = Cpu{ + pub const broadwell = CpuModel{ .name = "broadwell", .llvm_name = "broadwell", .features = featureSet(&[_]Feature{ @@ -1214,7 +1215,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const btver1 = Cpu{ + pub const btver1 = CpuModel{ .name = "btver1", .llvm_name = "btver1", .features = featureSet(&[_]Feature{ @@ -1238,7 +1239,7 @@ pub const cpu = struct { .x87, }), }; - pub const btver2 = Cpu{ + pub const btver2 = CpuModel{ .name = "btver2", .llvm_name = "btver2", .features = featureSet(&[_]Feature{ @@ -1274,7 +1275,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const c3 = Cpu{ + pub const c3 = CpuModel{ .name = "c3", .llvm_name = "c3", .features = featureSet(&[_]Feature{ @@ -1283,7 +1284,7 @@ pub const cpu = struct { .x87, }), }; - pub const c3_2 = Cpu{ + pub const c3_2 = CpuModel{ .name = "c3_2", .llvm_name = "c3-2", .features = featureSet(&[_]Feature{ @@ -1296,7 +1297,7 @@ pub const cpu = struct { .x87, }), }; - pub const cannonlake = Cpu{ + pub const cannonlake = CpuModel{ .name = "cannonlake", .llvm_name = "cannonlake", .features = featureSet(&[_]Feature{ @@ -1355,7 +1356,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const cascadelake = Cpu{ + pub const cascadelake = CpuModel{ .name = "cascadelake", .llvm_name = "cascadelake", .features = featureSet(&[_]Feature{ @@ -1413,7 +1414,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const cooperlake = Cpu{ + pub const cooperlake = CpuModel{ .name = "cooperlake", .llvm_name = "cooperlake", .features = featureSet(&[_]Feature{ @@ -1472,7 +1473,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const core_avx_i = Cpu{ + pub const core_avx_i = CpuModel{ .name = "core_avx_i", .llvm_name = "core-avx-i", .features = featureSet(&[_]Feature{ @@ -1504,7 +1505,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const core_avx2 = Cpu{ + pub const core_avx2 = CpuModel{ .name = "core_avx2", .llvm_name = "core-avx2", .features = featureSet(&[_]Feature{ @@ -1545,7 +1546,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const core2 = Cpu{ + pub const core2 = CpuModel{ .name = "core2", .llvm_name = "core2", .features = featureSet(&[_]Feature{ @@ -1563,7 +1564,7 @@ pub const cpu = struct { .x87, }), }; - pub const corei7 = Cpu{ + pub const corei7 = CpuModel{ .name = "corei7", .llvm_name = "corei7", .features = featureSet(&[_]Feature{ @@ -1581,7 +1582,7 @@ pub const cpu = struct { .x87, }), }; - pub const corei7_avx = Cpu{ + pub const corei7_avx = CpuModel{ .name = "corei7_avx", .llvm_name = "corei7-avx", .features = featureSet(&[_]Feature{ @@ -1610,7 +1611,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const generic = Cpu{ + pub const generic = CpuModel{ .name = "generic", .llvm_name = "generic", .features = featureSet(&[_]Feature{ @@ -1619,7 +1620,7 @@ pub const cpu = struct { .x87, }), }; - pub const geode = Cpu{ + pub const geode = CpuModel{ .name = "geode", .llvm_name = "geode", .features = featureSet(&[_]Feature{ @@ -1629,7 +1630,7 @@ pub const cpu = struct { .x87, }), }; - pub const goldmont = Cpu{ + pub const goldmont = CpuModel{ .name = "goldmont", .llvm_name = "goldmont", .features = featureSet(&[_]Feature{ @@ -1665,7 +1666,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const goldmont_plus = Cpu{ + pub const goldmont_plus = CpuModel{ .name = "goldmont_plus", .llvm_name = "goldmont-plus", .features = featureSet(&[_]Feature{ @@ -1703,7 +1704,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const haswell = Cpu{ + pub const haswell = CpuModel{ .name = "haswell", .llvm_name = "haswell", .features = featureSet(&[_]Feature{ @@ -1744,7 +1745,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const _i386 = Cpu{ + pub const _i386 = CpuModel{ .name = "_i386", .llvm_name = "i386", .features = featureSet(&[_]Feature{ @@ -1752,7 +1753,7 @@ pub const cpu = struct { .x87, }), }; - pub const _i486 = Cpu{ + pub const _i486 = CpuModel{ .name = "_i486", .llvm_name = "i486", .features = featureSet(&[_]Feature{ @@ -1760,7 +1761,7 @@ pub const cpu = struct { .x87, }), }; - pub const _i586 = Cpu{ + pub const _i586 = CpuModel{ .name = "_i586", .llvm_name = "i586", .features = featureSet(&[_]Feature{ @@ -1769,7 +1770,7 @@ pub const cpu = struct { .x87, }), }; - pub const _i686 = Cpu{ + pub const _i686 = CpuModel{ .name = "_i686", .llvm_name = "i686", .features = featureSet(&[_]Feature{ @@ -1779,7 +1780,7 @@ pub const cpu = struct { .x87, }), }; - pub const icelake_client = Cpu{ + pub const icelake_client = CpuModel{ .name = "icelake_client", .llvm_name = "icelake-client", .features = featureSet(&[_]Feature{ @@ -1847,7 +1848,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const icelake_server = Cpu{ + pub const icelake_server = CpuModel{ .name = "icelake_server", .llvm_name = "icelake-server", .features = featureSet(&[_]Feature{ @@ -1917,7 +1918,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const ivybridge = Cpu{ + pub const ivybridge = CpuModel{ .name = "ivybridge", .llvm_name = "ivybridge", .features = featureSet(&[_]Feature{ @@ -1949,7 +1950,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const k6 = Cpu{ + pub const k6 = CpuModel{ .name = "k6", .llvm_name = "k6", .features = featureSet(&[_]Feature{ @@ -1959,7 +1960,7 @@ pub const cpu = struct { .x87, }), }; - pub const k6_2 = Cpu{ + pub const k6_2 = CpuModel{ .name = "k6_2", .llvm_name = "k6-2", .features = featureSet(&[_]Feature{ @@ -1969,7 +1970,7 @@ pub const cpu = struct { .x87, }), }; - pub const k6_3 = Cpu{ + pub const k6_3 = CpuModel{ .name = "k6_3", .llvm_name = "k6-3", .features = featureSet(&[_]Feature{ @@ -1979,7 +1980,7 @@ pub const cpu = struct { .x87, }), }; - pub const k8 = Cpu{ + pub const k8 = CpuModel{ .name = "k8", .llvm_name = "k8", .features = featureSet(&[_]Feature{ @@ -1996,7 +1997,7 @@ pub const cpu = struct { .x87, }), }; - pub const k8_sse3 = Cpu{ + pub const k8_sse3 = CpuModel{ .name = "k8_sse3", .llvm_name = "k8-sse3", .features = featureSet(&[_]Feature{ @@ -2014,7 +2015,7 @@ pub const cpu = struct { .x87, }), }; - pub const knl = Cpu{ + pub const knl = CpuModel{ .name = "knl", .llvm_name = "knl", .features = featureSet(&[_]Feature{ @@ -2057,7 +2058,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const knm = Cpu{ + pub const knm = CpuModel{ .name = "knm", .llvm_name = "knm", .features = featureSet(&[_]Feature{ @@ -2101,12 +2102,12 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const lakemont = Cpu{ + pub const lakemont = CpuModel{ .name = "lakemont", .llvm_name = "lakemont", .features = featureSet(&[_]Feature{}), }; - pub const nehalem = Cpu{ + pub const nehalem = CpuModel{ .name = "nehalem", .llvm_name = "nehalem", .features = featureSet(&[_]Feature{ @@ -2124,7 +2125,7 @@ pub const cpu = struct { .x87, }), }; - pub const nocona = Cpu{ + pub const nocona = CpuModel{ .name = "nocona", .llvm_name = "nocona", .features = featureSet(&[_]Feature{ @@ -2140,7 +2141,7 @@ pub const cpu = struct { .x87, }), }; - pub const opteron = Cpu{ + pub const opteron = CpuModel{ .name = "opteron", .llvm_name = "opteron", .features = featureSet(&[_]Feature{ @@ -2157,7 +2158,7 @@ pub const cpu = struct { .x87, }), }; - pub const opteron_sse3 = Cpu{ + pub const opteron_sse3 = CpuModel{ .name = "opteron_sse3", .llvm_name = "opteron-sse3", .features = featureSet(&[_]Feature{ @@ -2175,7 +2176,7 @@ pub const cpu = struct { .x87, }), }; - pub const penryn = Cpu{ + pub const penryn = CpuModel{ .name = "penryn", .llvm_name = "penryn", .features = featureSet(&[_]Feature{ @@ -2193,7 +2194,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium = Cpu{ + pub const pentium = CpuModel{ .name = "pentium", .llvm_name = "pentium", .features = featureSet(&[_]Feature{ @@ -2202,7 +2203,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium_m = Cpu{ + pub const pentium_m = CpuModel{ .name = "pentium_m", .llvm_name = "pentium-m", .features = featureSet(&[_]Feature{ @@ -2216,7 +2217,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium_mmx = Cpu{ + pub const pentium_mmx = CpuModel{ .name = "pentium_mmx", .llvm_name = "pentium-mmx", .features = featureSet(&[_]Feature{ @@ -2226,7 +2227,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium2 = Cpu{ + pub const pentium2 = CpuModel{ .name = "pentium2", .llvm_name = "pentium2", .features = featureSet(&[_]Feature{ @@ -2239,7 +2240,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium3 = Cpu{ + pub const pentium3 = CpuModel{ .name = "pentium3", .llvm_name = "pentium3", .features = featureSet(&[_]Feature{ @@ -2253,7 +2254,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium3m = Cpu{ + pub const pentium3m = CpuModel{ .name = "pentium3m", .llvm_name = "pentium3m", .features = featureSet(&[_]Feature{ @@ -2267,7 +2268,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium4 = Cpu{ + pub const pentium4 = CpuModel{ .name = "pentium4", .llvm_name = "pentium4", .features = featureSet(&[_]Feature{ @@ -2281,7 +2282,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentium4m = Cpu{ + pub const pentium4m = CpuModel{ .name = "pentium4m", .llvm_name = "pentium4m", .features = featureSet(&[_]Feature{ @@ -2295,7 +2296,7 @@ pub const cpu = struct { .x87, }), }; - pub const pentiumpro = Cpu{ + pub const pentiumpro = CpuModel{ .name = "pentiumpro", .llvm_name = "pentiumpro", .features = featureSet(&[_]Feature{ @@ -2306,7 +2307,7 @@ pub const cpu = struct { .x87, }), }; - pub const prescott = Cpu{ + pub const prescott = CpuModel{ .name = "prescott", .llvm_name = "prescott", .features = featureSet(&[_]Feature{ @@ -2320,7 +2321,7 @@ pub const cpu = struct { .x87, }), }; - pub const sandybridge = Cpu{ + pub const sandybridge = CpuModel{ .name = "sandybridge", .llvm_name = "sandybridge", .features = featureSet(&[_]Feature{ @@ -2349,7 +2350,7 @@ pub const cpu = struct { .xsaveopt, }), }; - pub const silvermont = Cpu{ + pub const silvermont = CpuModel{ .name = "silvermont", .llvm_name = "silvermont", .features = featureSet(&[_]Feature{ @@ -2377,7 +2378,7 @@ pub const cpu = struct { .x87, }), }; - pub const skx = Cpu{ + pub const skx = CpuModel{ .name = "skx", .llvm_name = "skx", .features = featureSet(&[_]Feature{ @@ -2434,7 +2435,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const skylake = Cpu{ + pub const skylake = CpuModel{ .name = "skylake", .llvm_name = "skylake", .features = featureSet(&[_]Feature{ @@ -2485,7 +2486,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const skylake_avx512 = Cpu{ + pub const skylake_avx512 = CpuModel{ .name = "skylake_avx512", .llvm_name = "skylake-avx512", .features = featureSet(&[_]Feature{ @@ -2542,7 +2543,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const slm = Cpu{ + pub const slm = CpuModel{ .name = "slm", .llvm_name = "slm", .features = featureSet(&[_]Feature{ @@ -2570,7 +2571,7 @@ pub const cpu = struct { .x87, }), }; - pub const tremont = Cpu{ + pub const tremont = CpuModel{ .name = "tremont", .llvm_name = "tremont", .features = featureSet(&[_]Feature{ @@ -2613,7 +2614,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const westmere = Cpu{ + pub const westmere = CpuModel{ .name = "westmere", .llvm_name = "westmere", .features = featureSet(&[_]Feature{ @@ -2632,7 +2633,7 @@ pub const cpu = struct { .x87, }), }; - pub const winchip_c6 = Cpu{ + pub const winchip_c6 = CpuModel{ .name = "winchip_c6", .llvm_name = "winchip-c6", .features = featureSet(&[_]Feature{ @@ -2641,7 +2642,7 @@ pub const cpu = struct { .x87, }), }; - pub const winchip2 = Cpu{ + pub const winchip2 = CpuModel{ .name = "winchip2", .llvm_name = "winchip2", .features = featureSet(&[_]Feature{ @@ -2650,7 +2651,7 @@ pub const cpu = struct { .x87, }), }; - pub const x86_64 = Cpu{ + pub const x86_64 = CpuModel{ .name = "x86_64", .llvm_name = "x86-64", .features = featureSet(&[_]Feature{ @@ -2667,7 +2668,7 @@ pub const cpu = struct { .x87, }), }; - pub const yonah = Cpu{ + pub const yonah = CpuModel{ .name = "yonah", .llvm_name = "yonah", .features = featureSet(&[_]Feature{ @@ -2681,7 +2682,7 @@ pub const cpu = struct { .x87, }), }; - pub const znver1 = Cpu{ + pub const znver1 = CpuModel{ .name = "znver1", .llvm_name = "znver1", .features = featureSet(&[_]Feature{ @@ -2725,7 +2726,7 @@ pub const cpu = struct { .xsaves, }), }; - pub const znver2 = Cpu{ + pub const znver2 = CpuModel{ .name = "znver2", .llvm_name = "znver2", .features = featureSet(&[_]Feature{ @@ -2777,7 +2778,7 @@ pub const cpu = struct { /// All x86 CPUs, sorted alphabetically by name. /// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 /// compiler has inefficient memory and CPU usage, affecting build times. -pub const all_cpus = &[_]*const Cpu{ +pub const all_cpus = &[_]*const CpuModel{ &cpu.amdfam10, &cpu.athlon, &cpu.athlon_4, diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index fd920ad291..8d7bd1fd4d 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -577,10 +577,9 @@ pub fn detectNativeDynamicLinker(allocator: *Allocator) error{ // skip adding it to `ld_info_list`. const target: Target = .{ .Cross = .{ - .arch = Target.current.getArch(), + .cpu = Target.Cpu.baseline(Target.current.getArch()), .os = Target.current.getOs(), .abi = abi, - .cpu_features = Target.current.getArch().getBaselineCpuFeatures(), }, }; const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) { diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig index 79041da431..16f1891164 100644 --- a/src-self-hosted/print_targets.zig +++ b/src-self-hosted/print_targets.zig @@ -113,37 +113,14 @@ pub fn cmdTargets( try jws.beginObject(); try jws.objectField("arch"); - try jws.beginObject(); + try jws.beginArray(); { - inline for (@typeInfo(Target.Arch).Union.fields) |field| { - try jws.objectField(field.name); - if (field.field_type == void) { - try jws.emitNull(); - } else { - try jws.emitString(@typeName(field.field_type)); - } - } - } - try jws.endObject(); - - try jws.objectField("subArch"); - try jws.beginObject(); - const sub_arch_list = [_]type{ - Target.Arch.Arm32, - Target.Arch.Arm64, - Target.Arch.Kalimba, - Target.Arch.Mips, - }; - inline for (sub_arch_list) |SubArch| { - try jws.objectField(@typeName(SubArch)); - try jws.beginArray(); - inline for (@typeInfo(SubArch).Enum.fields) |field| { + inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| { try jws.arrayElem(); try jws.emitString(field.name); } - try jws.endArray(); } - try jws.endObject(); + try jws.endArray(); try jws.objectField("os"); try jws.beginArray(); @@ -179,15 +156,15 @@ pub fn cmdTargets( try jws.objectField("cpus"); try jws.beginObject(); - inline for (@typeInfo(Target.Arch).Union.fields) |field| { + inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| { try jws.objectField(field.name); try jws.beginObject(); - const arch = @unionInit(Target.Arch, field.name, undefined); - for (arch.allCpus()) |cpu| { - try jws.objectField(cpu.name); + const arch = @field(Target.Cpu.Arch, field.name); + for (arch.allCpuModels()) |model| { + try jws.objectField(model.name); try jws.beginArray(); for (arch.allFeaturesList()) |feature, i| { - if (cpu.features.isEnabled(@intCast(u8, i))) { + if (model.features.isEnabled(@intCast(u8, i))) { try jws.arrayElem(); try jws.emitString(feature.name); } @@ -200,10 +177,10 @@ pub fn cmdTargets( try jws.objectField("cpuFeatures"); try jws.beginObject(); - inline for (@typeInfo(Target.Arch).Union.fields) |field| { + inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| { try jws.objectField(field.name); try jws.beginArray(); - const arch = @unionInit(Target.Arch, field.name, undefined); + const arch = @field(Target.Cpu.Arch, field.name); for (arch.allFeaturesList()) |feature| { try jws.arrayElem(); try jws.emitString(feature.name); @@ -220,27 +197,34 @@ pub fn cmdTargets( try jws.objectField("triple"); try jws.emitString(triple); } - try jws.objectField("arch"); - try jws.emitString(@tagName(native_target.getArch())); + { + try jws.objectField("cpu"); + try jws.beginObject(); + try jws.objectField("arch"); + try jws.emitString(@tagName(native_target.getArch())); + + try jws.objectField("name"); + const cpu = native_target.getCpu(); + try jws.emitString(cpu.model.name); + + { + try jws.objectField("features"); + try jws.beginArray(); + for (native_target.getArch().allFeaturesList()) |feature, i_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize); + if (cpu.features.isEnabled(index)) { + try jws.arrayElem(); + try jws.emitString(feature.name); + } + } + try jws.endArray(); + } + try jws.endObject(); + } try jws.objectField("os"); try jws.emitString(@tagName(native_target.getOs())); try jws.objectField("abi"); try jws.emitString(@tagName(native_target.getAbi())); - try jws.objectField("cpuName"); - const cpu_features = native_target.getCpuFeatures(); - try jws.emitString(cpu_features.cpu.name); - { - try jws.objectField("cpuFeatures"); - try jws.beginArray(); - for (native_target.getArch().allFeaturesList()) |feature, i_usize| { - const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize); - if (cpu_features.features.isEnabled(index)) { - try jws.arrayElem(); - try jws.emitString(feature.name); - } - } - try jws.endArray(); - } // TODO implement native glibc version detection in self-hosted try jws.endObject(); diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index b278bb9f75..048686190d 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -88,7 +88,6 @@ const Error = extern enum { IsAsync, ImportOutsidePkgPath, UnknownCpu, - UnknownSubArchitecture, UnknownCpuFeature, InvalidCpuFeatures, InvalidLlvmCpuFeaturesFormat, @@ -560,25 +559,26 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz node.context.maybeRefresh(); } -fn cpuFeaturesFromLLVM( - arch: Target.Arch, +fn detectNativeCpuWithLLVM( + arch: Target.Cpu.Arch, llvm_cpu_name_z: ?[*:0]const u8, llvm_cpu_features_opt: ?[*:0]const u8, -) !Target.CpuFeatures { - var result = arch.getBaselineCpuFeatures(); +) !Target.Cpu { + var result = Target.Cpu.baseline(arch); if (llvm_cpu_name_z) |cpu_name_z| { const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); - for (arch.allCpus()) |cpu| { - const this_llvm_name = cpu.llvm_name orelse continue; + for (arch.allCpuModels()) |model| { + const this_llvm_name = model.llvm_name orelse continue; if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { // Here we use the non-dependencies-populated set, // so that subtracting features later in this function // affect the prepopulated set. - result = Target.CpuFeatures{ - .cpu = cpu, - .features = cpu.features, + result = Target.Cpu{ + .arch = arch, + .model = model, + .features = model.features, }; break; } @@ -632,12 +632,12 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { } fn cmdTargets(zig_triple: [*:0]const u8) !void { - var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); - target.Cross.cpu_features = blk: { + var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) }); + target.Cross.cpu = blk: { const llvm = @import("llvm.zig"); const llvm_cpu_name = llvm.GetHostCPUName(); const llvm_cpu_features = llvm.GetNativeFeatures(); - break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); + break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features); }; return @import("print_targets.zig").cmdTargets( std.heap.c_allocator, @@ -647,208 +647,101 @@ fn cmdTargets(zig_triple: [*:0]const u8) !void { ); } -const Stage2CpuFeatures = struct { - allocator: *mem.Allocator, - cpu_features: Target.CpuFeatures, - - llvm_features_str: ?[*:0]const u8, - - builtin_str: [:0]const u8, - cache_hash: [:0]const u8, - - const Self = @This(); - - fn createFromNative(allocator: *mem.Allocator) !*Self { - const arch = Target.current.getArch(); - const llvm = @import("llvm.zig"); - const llvm_cpu_name = llvm.GetHostCPUName(); - const llvm_cpu_features = llvm.GetNativeFeatures(); - const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); - return createFromCpuFeatures(allocator, arch, cpu_features); - } - - fn createFromCpuFeatures( - allocator: *mem.Allocator, - arch: Target.Arch, - cpu_features: Target.CpuFeatures, - ) !*Self { - const self = try allocator.create(Self); - errdefer allocator.destroy(self); - - const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ - cpu_features.cpu.name, - cpu_features.features.asBytes(), - }); - errdefer allocator.free(cache_hash); - - const generic_arch_name = arch.genericName(); - var builtin_str_buffer = try std.Buffer.allocPrint(allocator, - \\CpuFeatures{{ - \\ .cpu = &Target.{}.cpu.{}, - \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ - \\ - , .{ - generic_arch_name, - cpu_features.cpu.name, - generic_arch_name, - generic_arch_name, - }); - defer builtin_str_buffer.deinit(); - - var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); - defer llvm_features_buffer.deinit(); - - for (arch.allFeaturesList()) |feature, index_usize| { - const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); - const is_enabled = cpu_features.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - const plus_or_minus = "-+"[@boolToInt(is_enabled)]; - try llvm_features_buffer.appendByte(plus_or_minus); - try llvm_features_buffer.append(llvm_name); - try llvm_features_buffer.append(","); - } - - if (is_enabled) { - // TODO some kind of "zig identifier escape" function rather than - // unconditionally using @"" syntax - try builtin_str_buffer.append(" .@\""); - try builtin_str_buffer.append(feature.name); - try builtin_str_buffer.append("\",\n"); - } - } - - try builtin_str_buffer.append( - \\ }), - \\}; - \\ - ); - - assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); - llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); - - self.* = Self{ - .allocator = allocator, - .cpu_features = cpu_features, - .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, - .builtin_str = builtin_str_buffer.toOwnedSlice(), - .cache_hash = cache_hash, - }; - return self; - } - - fn destroy(self: *Self) void { - self.allocator.free(self.cache_hash); - self.allocator.free(self.builtin_str); - // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); - self.allocator.destroy(self); - } -}; - // ABI warning -export fn stage2_cpu_features_parse( - result: **Stage2CpuFeatures, +export fn stage2_target_parse( + target: *Stage2Target, zig_triple: ?[*:0]const u8, - cpu_name: ?[*:0]const u8, - cpu_features: ?[*:0]const u8, + mcpu: ?[*:0]const u8, ) Error { - result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { + stage2TargetParse(target, zig_triple, mcpu) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, error.UnknownArchitecture => return .UnknownArchitecture, - error.UnknownSubArchitecture => return .UnknownSubArchitecture, error.UnknownOperatingSystem => return .UnknownOperatingSystem, error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, error.MissingOperatingSystem => return .MissingOperatingSystem, error.MissingArchitecture => return .MissingArchitecture, error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, - error.InvalidCpuFeatures => return .InvalidCpuFeatures, + error.UnknownCpu => return .UnknownCpu, + error.UnexpectedExtraField => return .SemanticAnalyzeFail, + error.UnknownCpuFeature => return .UnknownCpuFeature, }; return .None; } -fn stage2ParseCpuFeatures( +fn stage2TargetParse( + stage1_target: *Stage2Target, zig_triple_oz: ?[*:0]const u8, - cpu_name_oz: ?[*:0]const u8, - cpu_features_oz: ?[*:0]const u8, -) !*Stage2CpuFeatures { - const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); - const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); - const arch = target.Cross.arch; + mcpu_oz: ?[*:0]const u8, +) !void { + const target: Target = if (zig_triple_oz) |zig_triple_z| blk: { + const zig_triple = mem.toSliceConst(u8, zig_triple_z); + const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null; + break :blk try Target.parse(.{ .arch_os_abi = zig_triple, .cpu = mcpu }); + } else Target.Native; - const cpu = if (cpu_name_oz) |cpu_name_z| blk: { - const cpu_name = mem.toSliceConst(u8, cpu_name_z); - break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { - error.UnknownCpu => { - std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ - cpu_name, - @tagName(arch), - }); - for (arch.allCpus()) |cpu| { - std.debug.warn(" {}\n", .{cpu.name}); - } - process.exit(1); - }, - else => |e| return e, - }; - } else target.Cross.cpu_features.cpu; + try stage1_target.fromTarget(target); +} - var set = if (cpu_features_oz) |cpu_features_z| blk: { - const cpu_features = mem.toSliceConst(u8, cpu_features_z); - break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { - error.UnknownCpuFeature => { - std.debug.warn( - \\Unknown CPU features specified. - \\Available CPU features for architecture '{}': - \\ - , .{@tagName(arch)}); - for (arch.allFeaturesList()) |feature| { - std.debug.warn(" {}\n", .{feature.name}); - } - process.exit(1); - }, - else => |e| return e, - }; - } else cpu.features; - - if (arch.subArchFeature()) |index| { - set.addFeature(index); - } - set.populateDependencies(arch.allFeaturesList()); - - return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ - .cpu = cpu, - .features = set, +fn initStage1TargetCpuFeatures(stage1_target: *Stage2Target, cpu: Target.Cpu) !void { + const allocator = std.heap.c_allocator; + const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ + cpu.model.name, + cpu.features.asBytes(), }); -} + errdefer allocator.free(cache_hash); -// ABI warning -export fn stage2_cpu_features_get_cache_hash( - cpu_features: *const Stage2CpuFeatures, - ptr: *[*:0]const u8, - len: *usize, -) void { - ptr.* = cpu_features.cache_hash.ptr; - len.* = cpu_features.cache_hash.len; -} + const generic_arch_name = cpu.arch.genericName(); + var builtin_str_buffer = try std.Buffer.allocPrint(allocator, + \\Cpu{{ + \\ .arch = .{}, + \\ .model = &Target.{}.cpu.{}, + \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ + \\ + , .{ + @tagName(cpu.arch), + generic_arch_name, + cpu.model.name, + generic_arch_name, + generic_arch_name, + }); + defer builtin_str_buffer.deinit(); -// ABI warning -export fn stage2_cpu_features_get_builtin_str( - cpu_features: *const Stage2CpuFeatures, - ptr: *[*:0]const u8, - len: *usize, -) void { - ptr.* = cpu_features.builtin_str.ptr; - len.* = cpu_features.builtin_str.len; -} + var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); + defer llvm_features_buffer.deinit(); -// ABI warning -export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { - return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; -} + for (cpu.arch.allFeaturesList()) |feature, index_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + const is_enabled = cpu.features.isEnabled(index); -// ABI warning -export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { - return cpu_features.llvm_features_str; + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@boolToInt(is_enabled)]; + try llvm_features_buffer.appendByte(plus_or_minus); + try llvm_features_buffer.append(llvm_name); + try llvm_features_buffer.append(","); + } + + if (is_enabled) { + // TODO some kind of "zig identifier escape" function rather than + // unconditionally using @"" syntax + try builtin_str_buffer.append(" .@\""); + try builtin_str_buffer.append(feature.name); + try builtin_str_buffer.append("\",\n"); + } + } + + try builtin_str_buffer.append( + \\ }), + \\}; + \\ + ); + + assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); + llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); + + stage1_target.llvm_cpu_name = if (cpu.model.llvm_name) |s| s.ptr else null; + stage1_target.llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr; + stage1_target.builtin_str = builtin_str_buffer.toOwnedSlice().ptr; + stage1_target.cache_hash = cache_hash.ptr; } // ABI warning @@ -1017,12 +910,55 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: const Stage2Target = extern struct { arch: c_int, sub_arch: c_int, + vendor: c_int, - os: c_int, abi: c_int, - glibc_version: ?*Stage2GLibCVersion, // null means default - cpu_features: *Stage2CpuFeatures, + + os: c_int, is_native: bool, + + glibc_version: ?*Stage2GLibCVersion, // null means default + + llvm_cpu_name: ?[*:0]const u8, + llvm_cpu_features: ?[*:0]const u8, + builtin_str: ?[*:0]const u8, + cache_hash: ?[*:0]const u8, + + fn toTarget(in_target: Stage2Target) Target { + if (in_target.is_native) return .Native; + + const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch + const in_sub_arch = in_target.sub_arch - 1; // skip over ZigLLVM_NoSubArch + const in_os = in_target.os; + const in_abi = in_target.abi - 1; // skip over ZigLLVM_UnknownEnvironment + + return .{ + .Cross = .{ + .cpu = Target.Cpu.baseline(enumInt(Target.Cpu.Arch, in_arch)), + .os = enumInt(Target.Os, in_os), + .abi = enumInt(Target.Abi, in_abi), + }, + }; + } + + fn fromTarget(self: *Stage2Target, target: Target) !void { + const cpu = switch (target) { + .Native => blk: { + // TODO self-host CPU model and feature detection instead of relying on LLVM + const llvm = @import("llvm.zig"); + const llvm_cpu_name = llvm.GetHostCPUName(); + const llvm_cpu_features = llvm.GetNativeFeatures(); + break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features); + }, + .Cross => target.getCpu(), + }; + self.arch = @enumToInt(target.getArch()) + 1; // skip over ZigLLVM_UnknownArch + self.sub_arch = 0; + self.vendor = 0; + self.os = @enumToInt(target.getOs()); + self.abi = @enumToInt(target.getAbi()) + 1; // skip over ZigLLVM_UnknownEnvironment + try initStage1TargetCpuFeatures(self, cpu); + } }; // ABI warning @@ -1034,72 +970,7 @@ const Stage2GLibCVersion = extern struct { // ABI warning export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error { - const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch - const in_sub_arch = in_target.sub_arch - 1; // skip over ZigLLVM_NoSubArch - const in_os = in_target.os; - const in_abi = in_target.abi - 1; // skip over ZigLLVM_UnknownEnvironment - const target: Target = if (in_target.is_native) .Native else .{ - .Cross = .{ - .arch = switch (enumInt(@TagType(Target.Arch), in_arch)) { - .arm => .{ .arm = enumInt(Target.Arch.Arm32, in_sub_arch) }, - .armeb => .{ .armeb = enumInt(Target.Arch.Arm32, in_sub_arch) }, - .thumb => .{ .thumb = enumInt(Target.Arch.Arm32, in_sub_arch) }, - .thumbeb => .{ .thumbeb = enumInt(Target.Arch.Arm32, in_sub_arch) }, - - .aarch64 => .{ .aarch64 = enumInt(Target.Arch.Arm64, in_sub_arch) }, - .aarch64_be => .{ .aarch64_be = enumInt(Target.Arch.Arm64, in_sub_arch) }, - .aarch64_32 => .{ .aarch64_32 = enumInt(Target.Arch.Arm64, in_sub_arch) }, - - .kalimba => .{ .kalimba = enumInt(Target.Arch.Kalimba, in_sub_arch) }, - - .arc => .arc, - .avr => .avr, - .bpfel => .bpfel, - .bpfeb => .bpfeb, - .hexagon => .hexagon, - .mips => .mips, - .mipsel => .mipsel, - .mips64 => .mips64, - .mips64el => .mips64el, - .msp430 => .msp430, - .powerpc => .powerpc, - .powerpc64 => .powerpc64, - .powerpc64le => .powerpc64le, - .r600 => .r600, - .amdgcn => .amdgcn, - .riscv32 => .riscv32, - .riscv64 => .riscv64, - .sparc => .sparc, - .sparcv9 => .sparcv9, - .sparcel => .sparcel, - .s390x => .s390x, - .tce => .tce, - .tcele => .tcele, - .i386 => .i386, - .x86_64 => .x86_64, - .xcore => .xcore, - .nvptx => .nvptx, - .nvptx64 => .nvptx64, - .le32 => .le32, - .le64 => .le64, - .amdil => .amdil, - .amdil64 => .amdil64, - .hsail => .hsail, - .hsail64 => .hsail64, - .spir => .spir, - .spir64 => .spir64, - .shave => .shave, - .lanai => .lanai, - .wasm32 => .wasm32, - .wasm64 => .wasm64, - .renderscript32 => .renderscript32, - .renderscript64 => .renderscript64, - }, - .os = enumInt(Target.Os, in_os), - .abi = enumInt(Target.Abi, in_abi), - .cpu_features = in_target.cpu_features.cpu_features, - }, - }; + const target = in_target.toTarget(); const result = @import("introspect.zig").detectDynamicLinker( std.heap.c_allocator, target, diff --git a/src/codegen.cpp b/src/codegen.cpp index a28d2d469d..0c35bcd1ed 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8624,14 +8624,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, "pub const arch = %s;\n", cur_arch); buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); { - buf_append_str(contents, "pub const cpu_features: CpuFeatures = "); - if (g->zig_target->cpu_features != nullptr) { - const char *ptr; - size_t len; - stage2_cpu_features_get_builtin_str(g->zig_target->cpu_features, &ptr, &len); - buf_append_mem(contents, ptr, len); + buf_append_str(contents, "pub const cpu: Cpu = "); + if (g->zig_target->builtin_str != nullptr) { + buf_append_str(contents, g->zig_target->builtin_str); } else { - buf_append_str(contents, "arch.getBaselineCpuFeatures();\n"); + buf_append_str(contents, "Target.Cpu.baseline(arch);\n"); } } if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) { @@ -8734,11 +8731,8 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->zig_target->vendor); cache_int(&cache_hash, g->zig_target->os); cache_int(&cache_hash, g->zig_target->abi); - if (g->zig_target->cpu_features != nullptr) { - const char *ptr; - size_t len; - stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len); - cache_str(&cache_hash, ptr); + if (g->zig_target->cache_hash != nullptr) { + cache_str(&cache_hash, g->zig_target->cache_hash); } if (g->zig_target->glibc_version != nullptr) { cache_int(&cache_hash, g->zig_target->glibc_version->major); @@ -8873,9 +8867,11 @@ static void init(CodeGen *g) { } // Override CPU and features if defined by user. - if (g->zig_target->cpu_features != nullptr) { - target_specific_cpu_args = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features); - target_specific_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features); + if (g->zig_target->llvm_cpu_name != nullptr) { + target_specific_cpu_args = g->zig_target->llvm_cpu_name; + } + if (g->zig_target->llvm_cpu_features != nullptr) { + target_specific_features = g->zig_target->llvm_cpu_features; } if (g->verbose_llvm_cpu_features) { fprintf(stderr, "name=%s triple=%s\n", buf_ptr(g->root_out_name), buf_ptr(&g->llvm_triple_str)); @@ -9190,19 +9186,17 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-target"); args.append(buf_ptr(&g->llvm_triple_str)); - const char *llvm_cpu = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features); - if (llvm_cpu != nullptr) { + if (g->zig_target->llvm_cpu_name != nullptr) { args.append("-Xclang"); args.append("-target-cpu"); args.append("-Xclang"); - args.append(llvm_cpu); + args.append(g->zig_target->llvm_cpu_name); } - const char *llvm_target_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features); - if (llvm_target_features != nullptr) { + if (g->zig_target->llvm_cpu_features != nullptr) { args.append("-Xclang"); args.append("-target-feature"); args.append("-Xclang"); - args.append(llvm_target_features); + args.append(g->zig_target->llvm_cpu_features); } } @@ -10406,11 +10400,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_int(ch, g->zig_target->vendor); cache_int(ch, g->zig_target->os); cache_int(ch, g->zig_target->abi); - if (g->zig_target->cpu_features != nullptr) { - const char *ptr; - size_t len; - stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len); - cache_str(ch, ptr); + if (g->zig_target->cache_hash != nullptr) { + cache_str(ch, g->zig_target->cache_hash); } if (g->zig_target->glibc_version != nullptr) { cache_int(ch, g->zig_target->glibc_version->major); diff --git a/src/error.cpp b/src/error.cpp index c633e2fe67..730c6e7193 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -59,7 +59,6 @@ const char *err_str(Error err) { case ErrorIsAsync: return "is async"; case ErrorImportOutsidePkgPath: return "import of file outside package path"; case ErrorUnknownCpu: return "unknown CPU"; - case ErrorUnknownSubArchitecture: return "unknown sub-architecture"; case ErrorUnknownCpuFeature: return "unknown CPU feature"; case ErrorInvalidCpuFeatures: return "invalid CPU features"; case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; diff --git a/src/main.cpp b/src/main.cpp index d7f5e5b7b0..c9076d0002 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,8 +106,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --override-lib-dir [arg] override path to Zig lib directory\n" " -ffunction-sections places each function in a separate section\n" " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" - " -target-cpu [cpu] target one specific CPU by name\n" - " -target-feature [features] specify the set of CPU features to target\n" + " -mcpu [cpu] specify target CPU and feature set\n" " -code-model [default|tiny| set target code model\n" " small|kernel|\n" " medium|large]\n" @@ -238,6 +237,14 @@ static int zig_error_no_build_file(void) { return EXIT_FAILURE; } +static bool str_starts_with(const char *s1, const char *s2) { + size_t s2_len = strlen(s2); + if (strlen(s1) < s2_len) { + return false; + } + return memcmp(s1, s2, s2_len) == 0; +} + extern "C" int ZigClang_main(int argc, char **argv); #ifdef ZIG_ENABLE_MEM_PROFILE @@ -447,8 +454,7 @@ static int main0(int argc, char **argv) { WantStackCheck want_stack_check = WantStackCheckAuto; WantCSanitize want_sanitize_c = WantCSanitizeAuto; bool function_sections = false; - const char *cpu = nullptr; - const char *features = nullptr; + const char *mcpu = nullptr; CodeModel code_model = CodeModelDefault; ZigList llvm_argv = {0}; @@ -716,6 +722,8 @@ static int main0(int argc, char **argv) { emit_llvm_ir = true; } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) { emit_llvm_ir = false; + } else if (str_starts_with(arg, "-mcpu=")) { + mcpu = arg + strlen("-mcpu="); } else if (i + 1 >= argc) { fprintf(stderr, "Expected another argument after %s\n", arg); return print_error_usage(arg0); @@ -892,10 +900,8 @@ static int main0(int argc, char **argv) { , argv[i]); return EXIT_FAILURE; } - } else if (strcmp(arg, "-target-cpu") == 0) { - cpu = argv[i]; - } else if (strcmp(arg, "-target-feature") == 0) { - features = argv[i]; + } else if (strcmp(arg, "-mcpu") == 0) { + mcpu = argv[i]; } else { fprintf(stderr, "Invalid argument: %s\n", arg); return print_error_usage(arg0); @@ -971,55 +977,41 @@ static int main0(int argc, char **argv) { init_all_targets(); ZigTarget target; - if (target_string == nullptr) { - get_native_target(&target); - if (target_glibc != nullptr) { - fprintf(stderr, "-target-glibc provided but no -target parameter\n"); + if ((err = target_parse_triple(&target, target_string, mcpu))) { + if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) { + fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n", + target_arch_name(target.arch)); + SubArchList sub_arch_list = target_subarch_list(target.arch); + size_t subarch_count = target_subarch_count(sub_arch_list); + for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { + ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); + fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub)); + } + return print_error_usage(arg0); + } else { + fprintf(stderr, "invalid target: %s\n", err_str(err)); return print_error_usage(arg0); } - } else { - if ((err = target_parse_triple(&target, target_string))) { - if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) { - fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n", - target_arch_name(target.arch)); - SubArchList sub_arch_list = target_subarch_list(target.arch); - size_t subarch_count = target_subarch_count(sub_arch_list); - for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { - ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); - fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub)); - } - return print_error_usage(arg0); - } else { - fprintf(stderr, "invalid target: %s\n", err_str(err)); - return print_error_usage(arg0); - } - } - if (target_is_glibc(&target)) { - target.glibc_version = heap::c_allocator.create(); + } + if (target_is_glibc(&target)) { + target.glibc_version = heap::c_allocator.create(); - if (target_glibc != nullptr) { - if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) { - fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err)); - return print_error_usage(arg0); - } - } else { - target_init_default_glibc_version(&target); + if (target_glibc != nullptr) { + if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) { + fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err)); + return print_error_usage(arg0); } - } else if (target_glibc != nullptr) { - fprintf(stderr, "'%s' is not a glibc-compatible target", target_string); - return print_error_usage(arg0); + } else { + target_init_default_glibc_version(&target); } + } else if (target_glibc != nullptr) { + fprintf(stderr, "'%s' is not a glibc-compatible target", target_string); + return print_error_usage(arg0); } Buf zig_triple_buf = BUF_INIT; target_triple_zig(&zig_triple_buf, &target); - const char *stage2_triple_arg = target.is_native ? nullptr : buf_ptr(&zig_triple_buf); - if ((err = stage2_cpu_features_parse(&target.cpu_features, stage2_triple_arg, cpu, features))) { - fprintf(stderr, "unable to initialize CPU features: %s\n", err_str(err)); - return main_exit(root_progress_node, EXIT_FAILURE); - } - // If both output_dir and enable_cache are provided, and doing build-lib, we // will just do a file copy at the end. This helps when bootstrapping zig from zig0 // because we want to pass something like this: diff --git a/src/stage2.cpp b/src/stage2.cpp index c3abe54d77..f3ae03242e 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -4,6 +4,7 @@ #include "stage2.h" #include "util.hpp" #include "zig_llvm.h" +#include "target.hpp" #include #include #include @@ -90,54 +91,60 @@ void stage2_progress_complete_one(Stage2ProgressNode *node) {} void stage2_progress_disable_tty(Stage2Progress *progress) {} void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} -struct Stage2CpuFeatures { - const char *llvm_cpu_name; - const char *llvm_cpu_features; - const char *builtin_str; - const char *cache_hash; -}; +Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu) { + Error err; -Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, - const char *cpu_name, const char *cpu_features) -{ if (zig_triple == nullptr) { - Stage2CpuFeatures *result = heap::c_allocator.create(); - result->llvm_cpu_name = ZigLLVMGetHostCPUName(); - result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); - result->builtin_str = "arch.getBaselineCpuFeatures();\n"; - result->cache_hash = "native\n\n"; - *out = result; - return ErrorNone; - } - if (cpu_name == nullptr && cpu_features == nullptr) { - Stage2CpuFeatures *result = heap::c_allocator.create(); - result->builtin_str = "arch.getBaselineCpuFeatures();\n"; - result->cache_hash = "\n\n"; - *out = result; - return ErrorNone; + get_native_target(target); + + target->llvm_cpu_name = ZigLLVMGetHostCPUName(); + target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); + target->builtin_str = "Target.Cpu.baseline(arch);\n"; + target->cache_hash = "native\n\n"; + } else { + // first initialize all to zero + *target = {}; + + SplitIterator it = memSplit(str(zig_triple), str("-")); + + Optional> opt_archsub = SplitIterator_next(&it); + Optional> opt_os = SplitIterator_next(&it); + Optional> opt_abi = SplitIterator_next(&it); + + if (!opt_archsub.is_some) + return ErrorMissingArchitecture; + + if ((err = target_parse_archsub(&target->arch, &target->sub_arch, + (char*)opt_archsub.value.ptr, opt_archsub.value.len))) + { + return err; + } + + if (!opt_os.is_some) + return ErrorMissingOperatingSystem; + + if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { + return err; + } + + if (opt_abi.is_some) { + if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { + return err; + } + } else { + target->abi = target_default_abi(target->arch, target->os); + } + + target->builtin_str = "Target.Cpu.baseline(arch);\n"; + target->cache_hash = "\n\n"; } - const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; - stage2_panic(msg, strlen(msg)); -} + if (mcpu != nullptr) { + const char *msg = "stage0 can't handle CPU/features in the target"; + stage2_panic(msg, strlen(msg)); + } -void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len) -{ - *ptr = cpu_features->cache_hash; - *len = strlen(cpu_features->cache_hash); -} -const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { - return cpu_features->llvm_cpu_name; -} -const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { - return cpu_features->llvm_cpu_features; -} -void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len) -{ - *ptr = cpu_features->builtin_str; - *len = strlen(cpu_features->builtin_str); + return ErrorNone; } int stage2_cmd_targets(const char *zig_triple) { diff --git a/src/stage2.h b/src/stage2.h index 302cffafc6..fe49c943a0 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -81,7 +81,6 @@ enum Error { ErrorIsAsync, ErrorImportOutsidePkgPath, ErrorUnknownCpu, - ErrorUnknownSubArchitecture, ErrorUnknownCpuFeature, ErrorInvalidCpuFeatures, ErrorInvalidLlvmCpuFeaturesFormat, @@ -200,27 +199,6 @@ ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items); -// ABI warning -struct Stage2CpuFeatures; - -// ABI warning -ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, - const char *zig_triple, const char *cpu_name, const char *cpu_features); - -// ABI warning -ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); - -// ABI warning -ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); - -// ABI warning -ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len); - -// ABI warning -ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len); - // ABI warning ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); @@ -296,22 +274,33 @@ struct ZigGLibCVersion { uint32_t patch; }; +struct Stage2TargetData; + // ABI warning struct ZigTarget { enum ZigLLVM_ArchType arch; enum ZigLLVM_SubArchType sub_arch; + enum ZigLLVM_VendorType vendor; - Os os; enum ZigLLVM_EnvironmentType abi; - struct ZigGLibCVersion *glibc_version; // null means default - struct Stage2CpuFeatures *cpu_features; + + Os os; bool is_native; + + struct ZigGLibCVersion *glibc_version; // null means default + + const char *llvm_cpu_name; + const char *llvm_cpu_features; + const char *builtin_str; + const char *cache_hash; }; // ABI warning ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len); +// ABI warning +ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu); // ABI warning diff --git a/src/target.cpp b/src/target.cpp index 209b42f3c9..fb064c4849 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -776,42 +776,8 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si return ErrorUnknownABI; } -Error target_parse_triple(ZigTarget *target, const char *triple) { - Error err; - - // first initialize all to zero - *target = {}; - - SplitIterator it = memSplit(str(triple), str("-")); - - Optional> opt_archsub = SplitIterator_next(&it); - Optional> opt_os = SplitIterator_next(&it); - Optional> opt_abi = SplitIterator_next(&it); - - if (!opt_archsub.is_some) - return ErrorMissingArchitecture; - - if ((err = target_parse_archsub(&target->arch, &target->sub_arch, - (char*)opt_archsub.value.ptr, opt_archsub.value.len))) - { - return err; - } - - if (!opt_os.is_some) - return ErrorMissingOperatingSystem; - - if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { - return err; - } - - if (opt_abi.is_some) { - if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { - return err; - } - } else { - target->abi = target_default_abi(target->arch, target->os); - } - return ErrorNone; +Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu) { + return stage2_target_parse(target, triple, mcpu); } const char *target_arch_name(ZigLLVM_ArchType arch) { diff --git a/src/target.hpp b/src/target.hpp index 4344749719..95acbe259e 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -50,7 +50,7 @@ enum CIntType { CIntTypeCount, }; -Error target_parse_triple(ZigTarget *target, const char *triple); +Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu); Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub, const char *archsub_ptr, size_t archsub_len); Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); diff --git a/test/tests.zig b/test/tests.zig index f079b4664c..3190126208 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -55,20 +55,18 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .linux, - .arch = .x86_64, .abi = .none, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), }, }, }, TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .linux, - .arch = .x86_64, .abi = .gnu, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), }, }, .link_libc = true, @@ -76,9 +74,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .linux, - .arch = .x86_64, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), .abi = .musl, }, }, @@ -88,9 +85,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.i386), .os = .linux, - .arch = .i386, - .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), .abi = .none, }, }, @@ -98,9 +94,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.i386), .os = .linux, - .arch = .i386, - .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), .abi = .musl, }, }, @@ -110,9 +105,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.aarch64), .os = .linux, - .arch = Target.Arch{ .aarch64 = .v8a }, - .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), .abi = .none, }, }, @@ -120,9 +114,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.aarch64), .os = .linux, - .arch = Target.Arch{ .aarch64 = .v8a }, - .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), .abi = .musl, }, }, @@ -131,9 +124,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.aarch64), .os = .linux, - .arch = Target.Arch{ .aarch64 = .v8a }, - .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), .abi = .gnu, }, }, @@ -141,45 +133,32 @@ const test_targets = blk: { }, TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = Target.Arch{ .arm = .v8a }, - .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), - .abi = .none, - }, - }, + .target = Target.parse(.{ + .arch_os_abi = "arm-linux-none", + .cpu = "generic+v8a", + }) catch unreachable, }, TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = Target.Arch{ .arm = .v8a }, - .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), - .abi = .musleabihf, - }, - }, + .target = Target.parse(.{ + .arch_os_abi = "arm-linux-musleabihf", + .cpu = "generic+v8a", + }) catch unreachable, .link_libc = true, }, // TODO https://github.com/ziglang/zig/issues/3287 //TestTarget{ - // .target = Target{ - // .Cross = CrossTarget{ - // .os = .linux, - // .arch = Target.Arch{ .arm = .v8a }, - // .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), - // .abi = .gnueabihf, - // }, - // }, + // .target = Target.parse(.{ + // .arch_os_abi = "arm-linux-gnueabihf", + // .cpu = "generic+v8a", + // }) catch unreachable, // .link_libc = true, //}, TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.mipsel), .os = .linux, - .arch = .mipsel, - .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(), .abi = .none, }, }, @@ -187,9 +166,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.mipsel), .os = .linux, - .arch = .mipsel, - .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(), .abi = .musl, }, }, @@ -199,9 +177,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .macosx, - .arch = .x86_64, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), .abi = .gnu, }, }, @@ -212,9 +189,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.i386), .os = .windows, - .arch = .i386, - .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), .abi = .msvc, }, }, @@ -223,9 +199,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .windows, - .arch = .x86_64, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), .abi = .msvc, }, }, @@ -234,9 +209,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.i386), .os = .windows, - .arch = .i386, - .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), .abi = .gnu, }, }, @@ -246,9 +220,8 @@ const test_targets = blk: { TestTarget{ .target = Target{ .Cross = CrossTarget{ + .cpu = Target.Cpu.baseline(.x86_64), .os = .windows, - .arch = .x86_64, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), .abi = .gnu, }, }, From ef2d237f2fbcca0f16b307dda01287e78363627a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 21:51:24 -0500 Subject: [PATCH 061/109] this is not the proper way to support this feature --- lib/std/target.zig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 8a3ae23337..9d2f3c29eb 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -49,8 +49,6 @@ pub const Target = union(enum) { other, pub fn parse(text: []const u8) !Os { - if (mem.eql(u8, text, "native")) return builtin.os; - const info = @typeInfo(Os); inline for (info.Enum.fields) |field| { if (mem.eql(u8, text, field.name)) { @@ -152,8 +150,6 @@ pub const Target = union(enum) { } pub fn parse(text: []const u8) !Abi { - if (mem.eql(u8, text, "native")) return builtin.abi; - const info = @typeInfo(Abi); inline for (info.Enum.fields) |field| { if (mem.eql(u8, text, field.name)) { @@ -582,8 +578,6 @@ pub const Target = union(enum) { } pub fn parse(text: []const u8) !Arch { - if (mem.eql(u8, text, "native")) return builtin.arch; - const info = @typeInfo(Arch); inline for (info.Enum.fields) |field| { if (mem.eql(u8, text, field.name)) { @@ -727,14 +721,12 @@ pub const Target = union(enum) { /// * CPU Architecture /// * Operating System /// * C ABI (optional) - /// "native" can be used for any of the fields. arch_os_abi: []const u8, /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features /// to remove from the set. /// The default value of `null` means to use the "baseline" feature set. - /// "native" can be used to perform CPU introspection. cpu: ?[]const u8 = null, }; From c33cd370fc2a9cbb2b417530d8a2205bb94491d3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 21:55:25 -0500 Subject: [PATCH 062/109] fix unit test for Target.parse I think this is working correctly. Without also removing sse2 from the feature set, sse gets added back into the set because sse2 is part of the x86_64 baseline (which is the cpu provided) and sse2 depends on sse. --- lib/std/target.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 9d2f3c29eb..951c02d55a 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1258,7 +1258,7 @@ test "Target.parse" { { const target = (try Target.parse(.{ .arch_os_abi = "x86_64-linux-gnu", - .cpu = "x86_64-sse-avx-cx8", + .cpu = "x86_64-sse-sse2-avx-cx8", })).Cross; std.testing.expect(target.os == .linux); From 884d1504082dcef1ce8edd18f7be0242b11e29e3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 22:09:05 -0500 Subject: [PATCH 063/109] stage1 main: fix cli parsing of architecture --- src/main.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c9076d0002..d6148d4587 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -978,20 +978,9 @@ static int main0(int argc, char **argv) { ZigTarget target; if ((err = target_parse_triple(&target, target_string, mcpu))) { - if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) { - fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n", - target_arch_name(target.arch)); - SubArchList sub_arch_list = target_subarch_list(target.arch); - size_t subarch_count = target_subarch_count(sub_arch_list); - for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { - ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); - fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub)); - } - return print_error_usage(arg0); - } else { - fprintf(stderr, "invalid target: %s\n", err_str(err)); - return print_error_usage(arg0); - } + fprintf(stderr, "invalid target: %s\n" + "See `%s targets` to display valid targets.\n", err_str(err), arg0); + return print_error_usage(arg0); } if (target_is_glibc(&target)) { target.glibc_version = heap::c_allocator.create(); From 7c298c8c172c00a2f8c138434c66a8d192031a95 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 22:09:25 -0500 Subject: [PATCH 064/109] fix generation of builtin import --- src/codegen.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 0c35bcd1ed..b5d621dd7c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8504,25 +8504,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) { ZigLLVM_ArchType arch = target_arch_enum(arch_i); const char *arch_name = target_arch_name(arch); - SubArchList sub_arch_list = target_subarch_list(arch); - if (sub_arch_list == SubArchListNone) { - if (arch == g->zig_target->arch) { - g->target_arch_index = arch_i; - cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name)); - } - } else { - const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list); - if (arch == g->zig_target->arch) { - size_t sub_count = target_subarch_count(sub_arch_list); - for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { - ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); - if (sub == g->zig_target->sub_arch) { - g->target_sub_arch_index = sub_i; - cur_arch = buf_ptr(buf_sprintf("Arch{ .%s = Arch.%s.%s }", - arch_name, sub_arch_list_name, target_subarch_name(sub))); - } - } - } + if (arch == g->zig_target->arch) { + g->target_arch_index = arch_i; + cur_arch = arch_name; } } } @@ -8621,7 +8605,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); - buf_appendf(contents, "pub const arch = %s;\n", cur_arch); + buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); { buf_append_str(contents, "pub const cpu: Cpu = "); From 3c76e5e33dd1abcbf02eaea32168e1368ade8025 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Feb 2020 22:09:35 -0500 Subject: [PATCH 065/109] update tls in std lib for lack of sub-arch --- lib/std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 5dbdafb60a..20c51abdfa 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -152,7 +152,7 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr) ); }, - .arm => |arm| { + .arm => { const rc = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr); assert(rc == 0); }, From 81cc52d4af1f1ecd05d8b75c3cfdc0105a3c53c3 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Thu, 20 Feb 2020 00:38:35 -0500 Subject: [PATCH 066/109] stage1/ir_print: show GenConst in trailing fahsion --- src/ir_print.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 47c984f2ef..c0a127dd16 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -590,11 +590,6 @@ static void ir_print_const_value(CodeGen *g, FILE *f, ZigValue *const_val) { static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) { if (inst == nullptr) { fprintf(irp->f, "(null)"); - return; - } - - if (inst->value->special != ConstValSpecialRuntime) { - ir_print_const_value(irp->codegen, irp->f, inst->value); } else { ir_print_var_gen(irp, inst); } From a3855477866bbe59b0583ca07170a981e7ca5839 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 20 Feb 2020 13:14:19 +0100 Subject: [PATCH 067/109] ir: Compile error on result_loc type mismatch w/ slicing Closes #4508 --- src/ir.cpp | 14 ++++++++++++-- test/compile_errors.zig | 12 ++++++++++++ test/tests.zig | 6 ++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3044d54d17..5f50586f72 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -26677,9 +26677,19 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, return_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { - return result_loc; + + if (result_loc != nullptr) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { + return result_loc; + } + IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type); + dummy_value->value->special = ConstValSpecialRuntime; + IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base, + dummy_value, result_loc->value->type->data.pointer.child_type); + if (type_is_invalid(dummy_result->value->type)) + return ira->codegen->invalid_inst_gen; } + return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 9f2b3716b0..1b32786e40 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,6 +3,18 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("slice to pointer conversion mismatch", + \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 { + \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1]; + \\} + \\test "bytesAsSlice" { + \\ const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF }; + \\ const slice = bytesAsSlice(bytes[0..]); + \\} + , &[_][]const u8{ + "tmp.zig:2:54: error: expected type '[*]align(1) const u16', found '[]align(1) const u16'", + }); + cases.addTest("access invalid @typeInfo decl", \\const A = B; \\test "Crash" { diff --git a/test/tests.zig b/test/tests.zig index f079b4664c..64a46abbc2 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -677,8 +677,10 @@ pub const StackTracesContext = struct { const got: []const u8 = got_result: { var buf = try Buffer.initSize(b.allocator, 0); defer buf.deinit(); - var bytes = stderr.toSliceConst(); - if (bytes.len != 0 and bytes[bytes.len - 1] == '\n') bytes = bytes[0 .. bytes.len - 1]; + const bytes = if (stderr.endsWith("\n")) + stderr.toSliceConst()[0 .. stderr.len() - 1] + else + stderr.toSliceConst()[0..stderr.len()]; var it = mem.separate(bytes, "\n"); process_lines: while (it.next()) |line| { if (line.len == 0) continue; From ae16a6773fd7853a3589b5650a33b4b8d37b9ef8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 20 Feb 2020 13:25:45 +0100 Subject: [PATCH 068/109] std: Handle NO_MEDIA_IN_DEVICE error in openFileWindows Closes #4507 --- lib/std/fs.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index a00ba6a63f..3bb89f5d7e 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -864,6 +864,7 @@ pub const Dir = struct { .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .NO_MEDIA_IN_DEVICE => return error.FileNotFound, .INVALID_PARAMETER => unreachable, .SHARING_VIOLATION => return error.SharingViolation, .ACCESS_DENIED => return error.AccessDenied, From 9c3eff91937dfc2f075342916d1fce659e18672f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 12:18:32 -0500 Subject: [PATCH 069/109] Revert "arm: clean up the messy sub-architecture & CPU features" This reverts commit 96f45c27b65307fe4abd5d1fb1cf314b1f493d8e. --- lib/std/target/arm.zig | 744 ++++++++++++++++++++++++++--------------- 1 file changed, 467 insertions(+), 277 deletions(-) diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index e9b95ee4d3..86593049cf 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -9,6 +9,39 @@ pub const Feature = enum { aclass, acquire_release, aes, + armv2, + armv2a, + armv3, + armv3m, + armv4, + armv4t, + armv5t, + armv5te, + armv5tej, + armv6, + armv6_m, + armv6j, + armv6k, + armv6kz, + armv6s_m, + armv6t2, + armv7_a, + armv7_m, + armv7_r, + armv7e_m, + armv7k, + armv7s, + armv7ve, + armv8_a, + armv8_m_base, + armv8_m_main, + armv8_r, + armv8_1_a, + armv8_1_m_main, + armv8_2_a, + armv8_3_a, + armv8_4_a, + armv8_5_a, avoid_movs_shop, avoid_partial_cpsr, cheap_predicable_cpsr, @@ -24,13 +57,13 @@ pub const Feature = enum { execute_only, expand_fp_mlx, exynos, - fp16, - fp16fml, - fp64, fp_armv8, fp_armv8d16, fp_armv8d16sp, fp_armv8sp, + fp16, + fp16fml, + fp64, fpao, fpregs, fpregs16, @@ -82,46 +115,29 @@ pub const Feature = enum { splat_vfp_neon, strict_align, swift, - thumb2, thumb_mode, + thumb2, trustzone, use_aa, use_misched, - v2, - v2a, - v3, - v3m, - v4, v4t, v5t, v5te, - v5tej, v6, - v6j, v6k, - v6kz, v6m, - v6sm, v6t2, v7, - v7a, - v7m, - v7r, v7clrex, - v7em, - v7k, - v7s, - v7ve, v8a, - v8m, - v8m_main, - v8r, v8_1a, v8_1m_main, v8_2a, v8_3a, v8_4a, v8_5a, + v8m, + v8m_main, vfp2, vfp2d16, vfp2d16sp, @@ -182,6 +198,368 @@ pub const all_features = blk: { .neon, }), }; + result[@enumToInt(Feature.armv2)] = .{ + .llvm_name = "armv2", + .description = "ARMv2 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv2a)] = .{ + .llvm_name = "armv2a", + .description = "ARMv2a architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv3)] = .{ + .llvm_name = "armv3", + .description = "ARMv3 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv3m)] = .{ + .llvm_name = "armv3m", + .description = "ARMv3m architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv4)] = .{ + .llvm_name = "armv4", + .description = "ARMv4 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv4t)] = .{ + .llvm_name = "armv4t", + .description = "ARMv4t architecture", + .dependencies = featureSet(&[_]Feature{ + .v4t, + }), + }; + result[@enumToInt(Feature.armv5t)] = .{ + .llvm_name = "armv5t", + .description = "ARMv5t architecture", + .dependencies = featureSet(&[_]Feature{ + .v5t, + }), + }; + result[@enumToInt(Feature.armv5te)] = .{ + .llvm_name = "armv5te", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@enumToInt(Feature.armv5tej)] = .{ + .llvm_name = "armv5tej", + .description = "ARMv5tej architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@enumToInt(Feature.armv6)] = .{ + .llvm_name = "armv6", + .description = "ARMv6 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .v6, + }), + }; + result[@enumToInt(Feature.armv6_m)] = .{ + .llvm_name = "armv6-m", + .description = "ARMv6m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6m, + }), + }; + result[@enumToInt(Feature.armv6j)] = .{ + .llvm_name = "armv6j", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv6, + }), + }; + result[@enumToInt(Feature.armv6k)] = .{ + .llvm_name = "armv6k", + .description = "ARMv6k architecture", + .dependencies = featureSet(&[_]Feature{ + .v6k, + }), + }; + result[@enumToInt(Feature.armv6kz)] = .{ + .llvm_name = "armv6kz", + .description = "ARMv6kz architecture", + .dependencies = featureSet(&[_]Feature{ + .trustzone, + .v6k, + }), + }; + result[@enumToInt(Feature.armv6s_m)] = .{ + .llvm_name = "armv6s-m", + .description = "ARMv6sm architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6m, + }), + }; + result[@enumToInt(Feature.armv6t2)] = .{ + .llvm_name = "armv6t2", + .description = "ARMv6t2 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .v6t2, + }), + }; + result[@enumToInt(Feature.armv7_a)] = .{ + .llvm_name = "armv7-a", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .neon, + .v7, + }), + }; + result[@enumToInt(Feature.armv7_m)] = .{ + .llvm_name = "armv7-m", + .description = "ARMv7m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .v7, + }), + }; + result[@enumToInt(Feature.armv7_r)] = .{ + .llvm_name = "armv7-r", + .description = "ARMv7r architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .rclass, + .v7, + }), + }; + result[@enumToInt(Feature.armv7e_m)] = .{ + .llvm_name = "armv7e-m", + .description = "ARMv7em architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .v7, + }), + }; + result[@enumToInt(Feature.armv7k)] = .{ + .llvm_name = "armv7k", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv7_a, + }), + }; + result[@enumToInt(Feature.armv7s)] = .{ + .llvm_name = "armv7s", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv7_a, + }), + }; + result[@enumToInt(Feature.armv7ve)] = .{ + .llvm_name = "armv7ve", + .description = "ARMv7ve architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .mp, + .neon, + .trustzone, + .v7, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_a)] = .{ + .llvm_name = "armv8-a", + .description = "ARMv8a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .v8a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_m_base)] = .{ + .llvm_name = "armv8-m.base", + .description = "ARMv8mBaseline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v7clrex, + .v8m, + }), + }; + result[@enumToInt(Feature.armv8_m_main)] = .{ + .llvm_name = "armv8-m.main", + .description = "ARMv8mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .v8m_main, + }), + }; + result[@enumToInt(Feature.armv8_r)] = .{ + .llvm_name = "armv8-r", + .description = "ARMv8r architecture", + .dependencies = featureSet(&[_]Feature{ + .crc, + .db, + .dfb, + .dsp, + .fp_armv8, + .mp, + .neon, + .rclass, + .v8a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_1_a)] = .{ + .llvm_name = "armv8.1-a", + .description = "ARMv81a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .v8_1a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_1_m_main)] = .{ + .llvm_name = "armv8.1-m.main", + .description = "ARMv81mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .lob, + .mclass, + .noarm, + .ras, + .thumb_mode, + .v8_1m_main, + }), + }; + result[@enumToInt(Feature.armv8_2_a)] = .{ + .llvm_name = "armv8.2-a", + .description = "ARMv82a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_2a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_3_a)] = .{ + .llvm_name = "armv8.3-a", + .description = "ARMv83a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_3a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_4_a)] = .{ + .llvm_name = "armv8.4-a", + .description = "ARMv84a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_4a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_5_a)] = .{ + .llvm_name = "armv8.5-a", + .description = "ARMv85a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_5a, + .virtualization, + }), + }; result[@enumToInt(Feature.avoid_movs_shop)] = .{ .llvm_name = "avoid-movs-shop", .description = "Avoid movs instructions with shifter operand", @@ -281,25 +659,6 @@ pub const all_features = blk: { .zcz, }), }; - result[@enumToInt(Feature.fp16)] = .{ - .llvm_name = "fp16", - .description = "Enable half-precision floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.fp16fml)] = .{ - .llvm_name = "fp16fml", - .description = "Enable full half-precision floating point fml instructions", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@enumToInt(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Floating point unit supports double precision", - .dependencies = featureSet(&[_]Feature{ - .fpregs64, - }), - }; result[@enumToInt(Feature.fp_armv8)] = .{ .llvm_name = "fp-armv8", .description = "Enable ARMv8 FP", @@ -334,6 +693,25 @@ pub const all_features = blk: { .vfp4sp, }), }; + result[@enumToInt(Feature.fp16)] = .{ + .llvm_name = "fp16", + .description = "Enable half-precision floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable full half-precision floating point fml instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Floating point unit supports double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs64, + }), + }; result[@enumToInt(Feature.fpao)] = .{ .llvm_name = "fpao", .description = "Enable fast computation of positive address offsets", @@ -615,16 +993,16 @@ pub const all_features = blk: { .description = "Swift ARM processors", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.thumb2)] = .{ - .llvm_name = "thumb2", - .description = "Enable Thumb2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.thumb_mode)] = .{ .llvm_name = "thumb-mode", .description = "Thumb mode", .dependencies = featureSet(&[_]Feature{}), }; + result[@enumToInt(Feature.thumb2)] = .{ + .llvm_name = "thumb2", + .description = "Enable Thumb2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; result[@enumToInt(Feature.trustzone)] = .{ .llvm_name = "trustzone", .description = "Enable support for TrustZone security extensions", @@ -640,116 +1018,50 @@ pub const all_features = blk: { .description = "Use the MachineScheduler", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v2)] = .{ - .llvm_name = "armv2", - .description = "ARMv2 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.v2a)] = .{ - .llvm_name = "armv2a", - .description = "ARMv2a architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.v3)] = .{ - .llvm_name = "armv3", - .description = "ARMv3 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.v3m)] = .{ - .llvm_name = "armv3m", - .description = "ARMv3m architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.v4)] = .{ - .llvm_name = "armv4", - .description = "ARMv4 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.v4t)] = .{ - .llvm_name = "armv4t", - .description = "ARMv4t architecture", + .llvm_name = "v4t", + .description = "Support ARM v4T instructions", .dependencies = featureSet(&[_]Feature{}), }; result[@enumToInt(Feature.v5t)] = .{ - .llvm_name = "armv5t", - .description = "ARMv5t architecture", + .llvm_name = "v5t", + .description = "Support ARM v5T instructions", .dependencies = featureSet(&[_]Feature{ .v4t, }), }; result[@enumToInt(Feature.v5te)] = .{ - .llvm_name = "armv5te", - .description = "ARMv5te architecture", + .llvm_name = "v5te", + .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", .dependencies = featureSet(&[_]Feature{ .v5t, }), }; - result[@enumToInt(Feature.v5tej)] = .{ - .llvm_name = "armv5tej", - .description = "ARMv5tej architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; result[@enumToInt(Feature.v6)] = .{ - .llvm_name = "armv6", - .description = "ARMv6 architecture", + .llvm_name = "v6", + .description = "Support ARM v6 instructions", .dependencies = featureSet(&[_]Feature{ - .dsp, .v5te, }), }; - result[@enumToInt(Feature.v6j)] = .{ - .llvm_name = "armv6j", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v6, - }), - }; result[@enumToInt(Feature.v6k)] = .{ - .llvm_name = "armv6k", - .description = "ARMv6k architecture", + .llvm_name = "v6k", + .description = "Support ARM v6k instructions", .dependencies = featureSet(&[_]Feature{ .v6, }), }; - result[@enumToInt(Feature.v6kz)] = .{ - .llvm_name = "armv6kz", - .description = "ARMv6kz architecture", - .dependencies = featureSet(&[_]Feature{ - .trustzone, - .v6k, - }), - }; result[@enumToInt(Feature.v6m)] = .{ - .llvm_name = "armv6-m", - .description = "ARMv6m architecture", + .llvm_name = "v6m", + .description = "Support ARM v6M instructions", .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6, - }), - }; - result[@enumToInt(Feature.v6sm)] = .{ - .llvm_name = "armv6s-m", - .description = "ARMv6sm architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, .v6, }), }; result[@enumToInt(Feature.v6t2)] = .{ - .llvm_name = "armv6t2", - .description = "ARMv6t2 architecture", + .llvm_name = "v6t2", + .description = "Support ARM v6t2 instructions", .dependencies = featureSet(&[_]Feature{ - .dsp, .thumb2, .v6k, .v8m, @@ -764,199 +1076,77 @@ pub const all_features = blk: { .v7clrex, }), }; - result[@enumToInt(Feature.v7a)] = .{ - .llvm_name = "armv7-a", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .neon, - .v7, - }), - }; - result[@enumToInt(Feature.v7m)] = .{ - .llvm_name = "armv7-m", - .description = "ARMv7m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.v7r)] = .{ - .llvm_name = "armv7-r", - .description = "ARMv7r architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .rclass, - .v7, - }), - }; result[@enumToInt(Feature.v7clrex)] = .{ .llvm_name = "v7clrex", .description = "Has v7 clrex instruction", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v7em)] = .{ - .llvm_name = "armv7e-m", - .description = "ARMv7em architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.v7k)] = .{ - .llvm_name = "armv7k", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v7a, - }), - }; - result[@enumToInt(Feature.v7s)] = .{ - .llvm_name = "armv7s", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v7a, - }), - }; - result[@enumToInt(Feature.v7ve)] = .{ - .llvm_name = "armv7ve", - .description = "ARMv7ve architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .mp, - .neon, - .trustzone, - .v7, - .virtualization, - }), - }; result[@enumToInt(Feature.v8a)] = .{ - .llvm_name = "armv8-a", - .description = "ARMv8a architecture", + .llvm_name = "v8a", + .description = "Support ARM v8a instructions", .dependencies = featureSet(&[_]Feature{ - .aclass, .acquire_release, - .crc, - .crypto, - .db, - .fp_armv8, - .mp, - .neon, - .trustzone, .v7, - .virtualization, - }), - }; - result[@enumToInt(Feature.v8m)] = .{ - .llvm_name = "armv8-m.base", - .description = "ARMv8mBaseline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6m, - .v7clrex, - }), - }; - result[@enumToInt(Feature.v8m_main)] = .{ - .llvm_name = "armv8-m.main", - .description = "ARMv8mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .v7, - }), - }; - result[@enumToInt(Feature.v8r)] = .{ - .llvm_name = "armv8-r", - .description = "ARMv8r architecture", - .dependencies = featureSet(&[_]Feature{ - .dfb, - .rclass, - .v8a, }), }; result[@enumToInt(Feature.v8_1a)] = .{ - .llvm_name = "armv8.1-a", - .description = "ARMv81a architecture", + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", .dependencies = featureSet(&[_]Feature{ .v8a, }), }; result[@enumToInt(Feature.v8_1m_main)] = .{ - .llvm_name = "armv8.1-m.main", - .description = "ARMv81mMainline architecture", + .llvm_name = "v8.1m.main", + .description = "Support ARM v8-1M Mainline instructions", .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .lob, - .mclass, - .noarm, - .ras, - .thumb_mode, .v8m_main, }), }; result[@enumToInt(Feature.v8_2a)] = .{ - .llvm_name = "armv8.2-a", - .description = "ARMv82a architecture", + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", .dependencies = featureSet(&[_]Feature{ - .ras, .v8_1a, }), }; result[@enumToInt(Feature.v8_3a)] = .{ - .llvm_name = "armv8.3-a", - .description = "ARMv83a architecture", + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", .dependencies = featureSet(&[_]Feature{ .v8_2a, }), }; result[@enumToInt(Feature.v8_4a)] = .{ - .llvm_name = "armv8.4-a", - .description = "ARMv84a architecture", + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", .dependencies = featureSet(&[_]Feature{ .dotprod, .v8_3a, }), }; result[@enumToInt(Feature.v8_5a)] = .{ - .llvm_name = "armv8.5-a", - .description = "ARMv85a architecture", + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", .dependencies = featureSet(&[_]Feature{ - .dotprod, .sb, .v8_4a, }), }; + result[@enumToInt(Feature.v8m)] = .{ + .llvm_name = "v8m", + .description = "Support ARM v8M Baseline instructions", + .dependencies = featureSet(&[_]Feature{ + .v6m, + }), + }; + result[@enumToInt(Feature.v8m_main)] = .{ + .llvm_name = "v8m.main", + .description = "Support ARM v8M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .v7, + }), + }; result[@enumToInt(Feature.vfp2)] = .{ .llvm_name = "vfp2", .description = "Enable VFP2 instructions", From ec889d5888c57d0337a1e00398d71241a9716ebe Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 12:39:46 -0500 Subject: [PATCH 070/109] NO_MEDIA_IN_DEVICE => return error.NoDevice --- lib/std/fs.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 3bb89f5d7e..c3d418eb8c 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -864,7 +864,7 @@ pub const Dir = struct { .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .NO_MEDIA_IN_DEVICE => return error.FileNotFound, + .NO_MEDIA_IN_DEVICE => return error.NoDevice, .INVALID_PARAMETER => unreachable, .SHARING_VIOLATION => return error.SharingViolation, .ACCESS_DENIED => return error.AccessDenied, From 33c69d5cb6fd555e164dd92e5b9dcfac37d82672 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 15:27:42 -0500 Subject: [PATCH 071/109] arm: clarify which CPU features are sub-architectures versus which ones are instruction sets. --- lib/std/target.zig | 2 +- lib/std/target/arm.zig | 1150 ++++++++++++++++++++-------------------- 2 files changed, 576 insertions(+), 576 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 951c02d55a..3d04e3424e 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -219,7 +219,7 @@ pub const Target = union(enum) { pub const Set = struct { ints: [usize_count]usize, - pub const needed_bit_count = 138; + pub const needed_bit_count = 154; pub const byte_count = (needed_bit_count + 7) / 8; pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize))); diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index 86593049cf..7195e2803e 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -9,39 +9,6 @@ pub const Feature = enum { aclass, acquire_release, aes, - armv2, - armv2a, - armv3, - armv3m, - armv4, - armv4t, - armv5t, - armv5te, - armv5tej, - armv6, - armv6_m, - armv6j, - armv6k, - armv6kz, - armv6s_m, - armv6t2, - armv7_a, - armv7_m, - armv7_r, - armv7e_m, - armv7k, - armv7s, - armv7ve, - armv8_a, - armv8_m_base, - armv8_m_main, - armv8_r, - armv8_1_a, - armv8_1_m_main, - armv8_2_a, - armv8_3_a, - armv8_4_a, - armv8_5_a, avoid_movs_shop, avoid_partial_cpsr, cheap_predicable_cpsr, @@ -57,13 +24,13 @@ pub const Feature = enum { execute_only, expand_fp_mlx, exynos, + fp16, + fp16fml, + fp64, fp_armv8, fp_armv8d16, fp_armv8d16sp, fp_armv8sp, - fp16, - fp16fml, - fp64, fpao, fpregs, fpregs16, @@ -71,6 +38,24 @@ pub const Feature = enum { fullfp16, fuse_aes, fuse_literals, + has_v4t, + has_v5t, + has_v5te, + has_v6, + has_v6k, + has_v6m, + has_v6t2, + has_v7, + has_v7clrex, + has_v8_1a, + has_v8_1m_main, + has_v8_2a, + has_v8_3a, + has_v8_4a, + has_v8_5a, + has_v8, + has_v8m, + has_v8m_main, hwdiv, hwdiv_arm, iwmmxt, @@ -115,29 +100,44 @@ pub const Feature = enum { splat_vfp_neon, strict_align, swift, - thumb_mode, thumb2, + thumb_mode, trustzone, use_aa, use_misched, + v2, + v2a, + v3, + v3m, + v4, v4t, v5t, v5te, + v5tej, v6, + v6j, v6k, + v6kz, v6m, + v6sm, v6t2, - v7, - v7clrex, + v7a, + v7em, + v7k, + v7m, + v7r, + v7s, + v7ve, v8a, + v8m, + v8m_main, + v8r, v8_1a, v8_1m_main, v8_2a, v8_3a, v8_4a, v8_5a, - v8m, - v8m_main, vfp2, vfp2d16, vfp2d16sp, @@ -198,368 +198,6 @@ pub const all_features = blk: { .neon, }), }; - result[@enumToInt(Feature.armv2)] = .{ - .llvm_name = "armv2", - .description = "ARMv2 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv2a)] = .{ - .llvm_name = "armv2a", - .description = "ARMv2a architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv3)] = .{ - .llvm_name = "armv3", - .description = "ARMv3 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv3m)] = .{ - .llvm_name = "armv3m", - .description = "ARMv3m architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv4)] = .{ - .llvm_name = "armv4", - .description = "ARMv4 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.armv4t)] = .{ - .llvm_name = "armv4t", - .description = "ARMv4t architecture", - .dependencies = featureSet(&[_]Feature{ - .v4t, - }), - }; - result[@enumToInt(Feature.armv5t)] = .{ - .llvm_name = "armv5t", - .description = "ARMv5t architecture", - .dependencies = featureSet(&[_]Feature{ - .v5t, - }), - }; - result[@enumToInt(Feature.armv5te)] = .{ - .llvm_name = "armv5te", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@enumToInt(Feature.armv5tej)] = .{ - .llvm_name = "armv5tej", - .description = "ARMv5tej architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@enumToInt(Feature.armv6)] = .{ - .llvm_name = "armv6", - .description = "ARMv6 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .v6, - }), - }; - result[@enumToInt(Feature.armv6_m)] = .{ - .llvm_name = "armv6-m", - .description = "ARMv6m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6m, - }), - }; - result[@enumToInt(Feature.armv6j)] = .{ - .llvm_name = "armv6j", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv6, - }), - }; - result[@enumToInt(Feature.armv6k)] = .{ - .llvm_name = "armv6k", - .description = "ARMv6k architecture", - .dependencies = featureSet(&[_]Feature{ - .v6k, - }), - }; - result[@enumToInt(Feature.armv6kz)] = .{ - .llvm_name = "armv6kz", - .description = "ARMv6kz architecture", - .dependencies = featureSet(&[_]Feature{ - .trustzone, - .v6k, - }), - }; - result[@enumToInt(Feature.armv6s_m)] = .{ - .llvm_name = "armv6s-m", - .description = "ARMv6sm architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v6m, - }), - }; - result[@enumToInt(Feature.armv6t2)] = .{ - .llvm_name = "armv6t2", - .description = "ARMv6t2 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .v6t2, - }), - }; - result[@enumToInt(Feature.armv7_a)] = .{ - .llvm_name = "armv7-a", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .neon, - .v7, - }), - }; - result[@enumToInt(Feature.armv7_m)] = .{ - .llvm_name = "armv7-m", - .description = "ARMv7m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.armv7_r)] = .{ - .llvm_name = "armv7-r", - .description = "ARMv7r architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .rclass, - .v7, - }), - }; - result[@enumToInt(Feature.armv7e_m)] = .{ - .llvm_name = "armv7e-m", - .description = "ARMv7em architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .thumb2, - .v7, - }), - }; - result[@enumToInt(Feature.armv7k)] = .{ - .llvm_name = "armv7k", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv7_a, - }), - }; - result[@enumToInt(Feature.armv7s)] = .{ - .llvm_name = "armv7s", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .armv7_a, - }), - }; - result[@enumToInt(Feature.armv7ve)] = .{ - .llvm_name = "armv7ve", - .description = "ARMv7ve architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .mp, - .neon, - .trustzone, - .v7, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_a)] = .{ - .llvm_name = "armv8-a", - .description = "ARMv8a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .trustzone, - .v8a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_m_base)] = .{ - .llvm_name = "armv8-m.base", - .description = "ARMv8mBaseline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - .v7clrex, - .v8m, - }), - }; - result[@enumToInt(Feature.armv8_m_main)] = .{ - .llvm_name = "armv8-m.main", - .description = "ARMv8mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - .v8m_main, - }), - }; - result[@enumToInt(Feature.armv8_r)] = .{ - .llvm_name = "armv8-r", - .description = "ARMv8r architecture", - .dependencies = featureSet(&[_]Feature{ - .crc, - .db, - .dfb, - .dsp, - .fp_armv8, - .mp, - .neon, - .rclass, - .v8a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_1_a)] = .{ - .llvm_name = "armv8.1-a", - .description = "ARMv81a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .trustzone, - .v8_1a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_1_m_main)] = .{ - .llvm_name = "armv8.1-m.main", - .description = "ARMv81mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .hwdiv, - .lob, - .mclass, - .noarm, - .ras, - .thumb_mode, - .v8_1m_main, - }), - }; - result[@enumToInt(Feature.armv8_2_a)] = .{ - .llvm_name = "armv8.2-a", - .description = "ARMv82a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_2a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_3_a)] = .{ - .llvm_name = "armv8.3-a", - .description = "ARMv83a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_3a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_4_a)] = .{ - .llvm_name = "armv8.4-a", - .description = "ARMv84a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dotprod, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_4a, - .virtualization, - }), - }; - result[@enumToInt(Feature.armv8_5_a)] = .{ - .llvm_name = "armv8.5-a", - .description = "ARMv85a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dotprod, - .dsp, - .fp_armv8, - .mp, - .neon, - .ras, - .trustzone, - .v8_5a, - .virtualization, - }), - }; result[@enumToInt(Feature.avoid_movs_shop)] = .{ .llvm_name = "avoid-movs-shop", .description = "Avoid movs instructions with shifter operand", @@ -659,6 +297,25 @@ pub const all_features = blk: { .zcz, }), }; + result[@enumToInt(Feature.fp16)] = .{ + .llvm_name = "fp16", + .description = "Enable half-precision floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable full half-precision floating point fml instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Floating point unit supports double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs64, + }), + }; result[@enumToInt(Feature.fp_armv8)] = .{ .llvm_name = "fp-armv8", .description = "Enable ARMv8 FP", @@ -693,25 +350,6 @@ pub const all_features = blk: { .vfp4sp, }), }; - result[@enumToInt(Feature.fp16)] = .{ - .llvm_name = "fp16", - .description = "Enable half-precision floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@enumToInt(Feature.fp16fml)] = .{ - .llvm_name = "fp16fml", - .description = "Enable full half-precision floating point fml instructions", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@enumToInt(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Floating point unit supports double precision", - .dependencies = featureSet(&[_]Feature{ - .fpregs64, - }), - }; result[@enumToInt(Feature.fpao)] = .{ .llvm_name = "fpao", .description = "Enable fast computation of positive address offsets", @@ -754,6 +392,135 @@ pub const all_features = blk: { .description = "CPU fuses literal generation operations", .dependencies = featureSet(&[_]Feature{}), }; + result[@enumToInt(Feature.has_v4t)] = .{ + .llvm_name = "v4t", + .description = "Support ARM v4T instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.has_v5t)] = .{ + .llvm_name = "v5t", + .description = "Support ARM v5T instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v4t, + }), + }; + result[@enumToInt(Feature.has_v5te)] = .{ + .llvm_name = "v5te", + .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v5t, + }), + }; + result[@enumToInt(Feature.has_v6)] = .{ + .llvm_name = "v6", + .description = "Support ARM v6 instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v5te, + }), + }; + result[@enumToInt(Feature.has_v6k)] = .{ + .llvm_name = "v6k", + .description = "Support ARM v6k instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6, + }), + }; + result[@enumToInt(Feature.has_v6m)] = .{ + .llvm_name = "v6m", + .description = "Support ARM v6M instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6, + }), + }; + result[@enumToInt(Feature.has_v6t2)] = .{ + .llvm_name = "v6t2", + .description = "Support ARM v6t2 instructions", + .dependencies = featureSet(&[_]Feature{ + .thumb2, + .has_v6k, + .has_v8m, + }), + }; + result[@enumToInt(Feature.has_v7)] = .{ + .llvm_name = "v7", + .description = "Support ARM v7 instructions", + .dependencies = featureSet(&[_]Feature{ + .perfmon, + .has_v6t2, + .has_v7clrex, + }), + }; + result[@enumToInt(Feature.has_v7clrex)] = .{ + .llvm_name = "v7clrex", + .description = "Has v7 clrex instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.has_v8)] = .{ + .llvm_name = "v8", + .description = "Support ARM v8 instructions", + .dependencies = featureSet(&[_]Feature{ + .acquire_release, + .has_v7, + }), + }; + result[@enumToInt(Feature.has_v8_1a)] = .{ + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8, + }), + }; + result[@enumToInt(Feature.has_v8_1m_main)] = .{ + .llvm_name = "v8.1m.main", + .description = "Support ARM v8-1M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8m_main, + }), + }; + result[@enumToInt(Feature.has_v8_2a)] = .{ + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_1a, + }), + }; + result[@enumToInt(Feature.has_v8_3a)] = .{ + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_2a, + }), + }; + result[@enumToInt(Feature.has_v8_4a)] = .{ + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .dotprod, + .has_v8_3a, + }), + }; + result[@enumToInt(Feature.has_v8_5a)] = .{ + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", + .dependencies = featureSet(&[_]Feature{ + .sb, + .has_v8_4a, + }), + }; + result[@enumToInt(Feature.has_v8m)] = .{ + .llvm_name = "v8m", + .description = "Support ARM v8M Baseline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6m, + }), + }; + result[@enumToInt(Feature.has_v8m_main)] = .{ + .llvm_name = "v8m.main", + .description = "Support ARM v8M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v7, + }), + }; result[@enumToInt(Feature.hwdiv)] = .{ .llvm_name = "hwdiv", .description = "Enable divide instructions in Thumb", @@ -768,14 +535,14 @@ pub const all_features = blk: { .llvm_name = "iwmmxt", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; result[@enumToInt(Feature.iwmmxt2)] = .{ .llvm_name = "iwmmxt2", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; result[@enumToInt(Feature.lob)] = .{ @@ -820,7 +587,7 @@ pub const all_features = blk: { .dsp, .fpregs16, .fpregs64, - .v8_1m_main, + .has_v8_1m_main, }), }; result[@enumToInt(Feature.mve_fp)] = .{ @@ -993,16 +760,16 @@ pub const all_features = blk: { .description = "Swift ARM processors", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.thumb_mode)] = .{ - .llvm_name = "thumb-mode", - .description = "Thumb mode", - .dependencies = featureSet(&[_]Feature{}), - }; result[@enumToInt(Feature.thumb2)] = .{ .llvm_name = "thumb2", .description = "Enable Thumb2 instructions", .dependencies = featureSet(&[_]Feature{}), }; + result[@enumToInt(Feature.thumb_mode)] = .{ + .llvm_name = "thumb-mode", + .description = "Thumb mode", + .dependencies = featureSet(&[_]Feature{}), + }; result[@enumToInt(Feature.trustzone)] = .{ .llvm_name = "trustzone", .description = "Enable support for TrustZone security extensions", @@ -1018,133 +785,366 @@ pub const all_features = blk: { .description = "Use the MachineScheduler", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v4t)] = .{ - .llvm_name = "v4t", - .description = "Support ARM v4T instructions", + result[@enumToInt(Feature.v2)] = .{ + .llvm_name = "armv2", + .description = "ARMv2 architecture", .dependencies = featureSet(&[_]Feature{}), }; - result[@enumToInt(Feature.v5t)] = .{ - .llvm_name = "v5t", - .description = "Support ARM v5T instructions", + result[@enumToInt(Feature.v2a)] = .{ + .llvm_name = "armv2a", + .description = "ARMv2a architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v3)] = .{ + .llvm_name = "armv3", + .description = "ARMv3 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v3m)] = .{ + .llvm_name = "armv3m", + .description = "ARMv3m architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v4)] = .{ + .llvm_name = "armv4", + .description = "ARMv4 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v4t)] = .{ + .llvm_name = "armv4t", + .description = "ARMv4t architecture", .dependencies = featureSet(&[_]Feature{ - .v4t, + .has_v4t, + }), + }; + result[@enumToInt(Feature.v5t)] = .{ + .llvm_name = "armv5t", + .description = "ARMv5t architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v5t, }), }; result[@enumToInt(Feature.v5te)] = .{ - .llvm_name = "v5te", - .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", + .llvm_name = "armv5te", + .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .v5t, + .has_v5te, + }), + }; + result[@enumToInt(Feature.v5tej)] = .{ + .llvm_name = "armv5tej", + .description = "ARMv5tej architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v5te, }), }; result[@enumToInt(Feature.v6)] = .{ - .llvm_name = "v6", - .description = "Support ARM v6 instructions", + .llvm_name = "armv6", + .description = "ARMv6 architecture", .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@enumToInt(Feature.v6k)] = .{ - .llvm_name = "v6k", - .description = "Support ARM v6k instructions", - .dependencies = featureSet(&[_]Feature{ - .v6, + .dsp, + .has_v6, }), }; result[@enumToInt(Feature.v6m)] = .{ - .llvm_name = "v6m", - .description = "Support ARM v6M instructions", + .llvm_name = "armv6-m", + .description = "ARMv6m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .has_v6m, + }), + }; + result[@enumToInt(Feature.v6j)] = .{ + .llvm_name = "armv6j", + .description = "ARMv7a architecture", .dependencies = featureSet(&[_]Feature{ .v6, }), }; + result[@enumToInt(Feature.v6k)] = .{ + .llvm_name = "armv6k", + .description = "ARMv6k architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v6k, + }), + }; + result[@enumToInt(Feature.v6kz)] = .{ + .llvm_name = "armv6kz", + .description = "ARMv6kz architecture", + .dependencies = featureSet(&[_]Feature{ + .trustzone, + .has_v6k, + }), + }; + result[@enumToInt(Feature.v6sm)] = .{ + .llvm_name = "armv6s-m", + .description = "ARMv6sm architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .has_v6m, + }), + }; result[@enumToInt(Feature.v6t2)] = .{ - .llvm_name = "v6t2", - .description = "Support ARM v6t2 instructions", + .llvm_name = "armv6t2", + .description = "ARMv6t2 architecture", .dependencies = featureSet(&[_]Feature{ + .dsp, + .has_v6t2, + }), + }; + result[@enumToInt(Feature.v7a)] = .{ + .llvm_name = "armv7-a", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .neon, + .has_v7, + }), + }; + result[@enumToInt(Feature.v7m)] = .{ + .llvm_name = "armv7-m", + .description = "ARMv7m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, .thumb2, - .v6k, - .v8m, + .has_v7, }), }; - result[@enumToInt(Feature.v7)] = .{ - .llvm_name = "v7", - .description = "Support ARM v7 instructions", + result[@enumToInt(Feature.v7r)] = .{ + .llvm_name = "armv7-r", + .description = "ARMv7r architecture", .dependencies = featureSet(&[_]Feature{ - .perfmon, - .v6t2, - .v7clrex, + .db, + .dsp, + .hwdiv, + .rclass, + .has_v7, }), }; - result[@enumToInt(Feature.v7clrex)] = .{ - .llvm_name = "v7clrex", - .description = "Has v7 clrex instruction", - .dependencies = featureSet(&[_]Feature{}), + result[@enumToInt(Feature.v7em)] = .{ + .llvm_name = "armv7e-m", + .description = "ARMv7em architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .has_v7, + }), + }; + result[@enumToInt(Feature.v7k)] = .{ + .llvm_name = "armv7k", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@enumToInt(Feature.v7s)] = .{ + .llvm_name = "armv7s", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@enumToInt(Feature.v7ve)] = .{ + .llvm_name = "armv7ve", + .description = "ARMv7ve architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .mp, + .neon, + .trustzone, + .has_v7, + .virtualization, + }), }; result[@enumToInt(Feature.v8a)] = .{ - .llvm_name = "v8a", - .description = "Support ARM v8a instructions", + .llvm_name = "armv8-a", + .description = "ARMv8a architecture", .dependencies = featureSet(&[_]Feature{ - .acquire_release, - .v7, - }), - }; - result[@enumToInt(Feature.v8_1a)] = .{ - .llvm_name = "v8.1a", - .description = "Support ARM v8.1a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8a, - }), - }; - result[@enumToInt(Feature.v8_1m_main)] = .{ - .llvm_name = "v8.1m.main", - .description = "Support ARM v8-1M Mainline instructions", - .dependencies = featureSet(&[_]Feature{ - .v8m_main, - }), - }; - result[@enumToInt(Feature.v8_2a)] = .{ - .llvm_name = "v8.2a", - .description = "Support ARM v8.2a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_1a, - }), - }; - result[@enumToInt(Feature.v8_3a)] = .{ - .llvm_name = "v8.3a", - .description = "Support ARM v8.3a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_2a, - }), - }; - result[@enumToInt(Feature.v8_4a)] = .{ - .llvm_name = "v8.4a", - .description = "Support ARM v8.4a instructions", - .dependencies = featureSet(&[_]Feature{ - .dotprod, - .v8_3a, - }), - }; - result[@enumToInt(Feature.v8_5a)] = .{ - .llvm_name = "v8.5a", - .description = "Support ARM v8.5a instructions", - .dependencies = featureSet(&[_]Feature{ - .sb, - .v8_4a, + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .has_v8, + .virtualization, }), }; result[@enumToInt(Feature.v8m)] = .{ - .llvm_name = "v8m", - .description = "Support ARM v8M Baseline instructions", + .llvm_name = "armv8-m.base", + .description = "ARMv8mBaseline architecture", .dependencies = featureSet(&[_]Feature{ - .v6m, + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .has_v7clrex, + .has_v8m, }), }; result[@enumToInt(Feature.v8m_main)] = .{ - .llvm_name = "v8m.main", - .description = "Support ARM v8M Mainline instructions", + .llvm_name = "armv8-m.main", + .description = "ARMv8mMainline architecture", .dependencies = featureSet(&[_]Feature{ - .v7, + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .has_v8m_main, + }), + }; + result[@enumToInt(Feature.v8r)] = .{ + .llvm_name = "armv8-r", + .description = "ARMv8r architecture", + .dependencies = featureSet(&[_]Feature{ + .crc, + .db, + .dfb, + .dsp, + .fp_armv8, + .mp, + .neon, + .rclass, + .has_v8, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8_1a)] = .{ + .llvm_name = "armv8.1-a", + .description = "ARMv81a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .has_v8_1a, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8_1m_main)] = .{ + .llvm_name = "armv8.1-m.main", + .description = "ARMv81mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .lob, + .mclass, + .noarm, + .ras, + .thumb_mode, + .has_v8_1m_main, + }), + }; + result[@enumToInt(Feature.v8_2a)] = .{ + .llvm_name = "armv8.2-a", + .description = "ARMv82a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .has_v8_2a, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8_3a)] = .{ + .llvm_name = "armv8.3-a", + .description = "ARMv83a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .has_v8_3a, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8_4a)] = .{ + .llvm_name = "armv8.4-a", + .description = "ARMv84a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .has_v8_4a, + .virtualization, + }), + }; + result[@enumToInt(Feature.v8_5a)] = .{ + .llvm_name = "armv8.5-a", + .description = "ARMv85a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .has_v8_5a, + .virtualization, }), }; result[@enumToInt(Feature.vfp2)] = .{ @@ -1279,7 +1279,7 @@ pub const all_features = blk: { .llvm_name = "xscale", .description = "ARMv5te architecture", .dependencies = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; result[@enumToInt(Feature.zcz)] = .{ @@ -1300,49 +1300,49 @@ pub const cpu = struct { .name = "arm1020e", .llvm_name = "arm1020e", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm1020t = CpuModel{ .name = "arm1020t", .llvm_name = "arm1020t", .features = featureSet(&[_]Feature{ - .v5t, + .has_v5t, }), }; pub const arm1022e = CpuModel{ .name = "arm1022e", .llvm_name = "arm1022e", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm10e = CpuModel{ .name = "arm10e", .llvm_name = "arm10e", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm10tdmi = CpuModel{ .name = "arm10tdmi", .llvm_name = "arm10tdmi", .features = featureSet(&[_]Feature{ - .v5t, + .has_v5t, }), }; pub const arm1136j_s = CpuModel{ .name = "arm1136j_s", .llvm_name = "arm1136j-s", .features = featureSet(&[_]Feature{ - .v6, + .has_v6, }), }; pub const arm1136jf_s = CpuModel{ .name = "arm1136jf_s", .llvm_name = "arm1136jf-s", .features = featureSet(&[_]Feature{ - .v6, + .has_v6, .slowfpvmlx, .vfp2, }), @@ -1351,14 +1351,14 @@ pub const cpu = struct { .name = "arm1156t2_s", .llvm_name = "arm1156t2-s", .features = featureSet(&[_]Feature{ - .v6t2, + .has_v6t2, }), }; pub const arm1156t2f_s = CpuModel{ .name = "arm1156t2f_s", .llvm_name = "arm1156t2f-s", .features = featureSet(&[_]Feature{ - .v6t2, + .has_v6t2, .slowfpvmlx, .vfp2, }), @@ -1390,28 +1390,28 @@ pub const cpu = struct { .name = "arm710t", .llvm_name = "arm710t", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm720t = CpuModel{ .name = "arm720t", .llvm_name = "arm720t", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm7tdmi = CpuModel{ .name = "arm7tdmi", .llvm_name = "arm7tdmi", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm7tdmi_s = CpuModel{ .name = "arm7tdmi_s", .llvm_name = "arm7tdmi-s", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm8 = CpuModel{ @@ -1432,84 +1432,84 @@ pub const cpu = struct { .name = "arm9", .llvm_name = "arm9", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm920 = CpuModel{ .name = "arm920", .llvm_name = "arm920", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm920t = CpuModel{ .name = "arm920t", .llvm_name = "arm920t", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm922t = CpuModel{ .name = "arm922t", .llvm_name = "arm922t", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm926ej_s = CpuModel{ .name = "arm926ej_s", .llvm_name = "arm926ej-s", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm940t = CpuModel{ .name = "arm940t", .llvm_name = "arm940t", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const arm946e_s = CpuModel{ .name = "arm946e_s", .llvm_name = "arm946e-s", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm966e_s = CpuModel{ .name = "arm966e_s", .llvm_name = "arm966e-s", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm968e_s = CpuModel{ .name = "arm968e_s", .llvm_name = "arm968e-s", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm9e = CpuModel{ .name = "arm9e", .llvm_name = "arm9e", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const arm9tdmi = CpuModel{ .name = "arm9tdmi", .llvm_name = "arm9tdmi", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const baseline = CpuModel{ .name = "baseline", .llvm_name = "generic", .features = featureSet(&[_]Feature{ - .v6m, + .has_v6m, }), }; pub const cortex_a12 = CpuModel{ @@ -1561,7 +1561,7 @@ pub const cpu = struct { .name = "cortex_a32", .llvm_name = "cortex-a32", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .crc, .crypto, .hwdiv, @@ -1572,7 +1572,7 @@ pub const cpu = struct { .name = "cortex_a35", .llvm_name = "cortex-a35", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .crc, .crypto, .hwdiv, @@ -1597,7 +1597,7 @@ pub const cpu = struct { .name = "cortex_a53", .llvm_name = "cortex-a53", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .crc, .crypto, .fpao, @@ -1609,7 +1609,7 @@ pub const cpu = struct { .name = "cortex_a55", .llvm_name = "cortex-a55", .features = featureSet(&[_]Feature{ - .v8_2a, + .has_v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1619,7 +1619,7 @@ pub const cpu = struct { .name = "cortex_a57", .llvm_name = "cortex-a57", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .avoid_partial_cpsr, .cheap_predicable_cpsr, .crc, @@ -1649,7 +1649,7 @@ pub const cpu = struct { .name = "cortex_a72", .llvm_name = "cortex-a72", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .crc, .crypto, .hwdiv, @@ -1660,7 +1660,7 @@ pub const cpu = struct { .name = "cortex_a73", .llvm_name = "cortex-a73", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .crc, .crypto, .hwdiv, @@ -1671,7 +1671,7 @@ pub const cpu = struct { .name = "cortex_a75", .llvm_name = "cortex-a75", .features = featureSet(&[_]Feature{ - .v8_2a, + .has_v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1682,7 +1682,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76", .features = featureSet(&[_]Feature{ .a76, - .v8_2a, + .has_v8_2a, .crc, .crypto, .dotprod, @@ -1696,7 +1696,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76ae", .features = featureSet(&[_]Feature{ .a76, - .v8_2a, + .has_v8_2a, .crc, .crypto, .dotprod, @@ -1742,28 +1742,28 @@ pub const cpu = struct { .name = "cortex_m0", .llvm_name = "cortex-m0", .features = featureSet(&[_]Feature{ - .v6m, + .has_v6m, }), }; pub const cortex_m0plus = CpuModel{ .name = "cortex_m0plus", .llvm_name = "cortex-m0plus", .features = featureSet(&[_]Feature{ - .v6m, + .has_v6m, }), }; pub const cortex_m1 = CpuModel{ .name = "cortex_m1", .llvm_name = "cortex-m1", .features = featureSet(&[_]Feature{ - .v6m, + .has_v6m, }), }; pub const cortex_m23 = CpuModel{ .name = "cortex_m23", .llvm_name = "cortex-m23", .features = featureSet(&[_]Feature{ - .v8m, + .has_v8m, .no_movt, }), }; @@ -1783,7 +1783,7 @@ pub const cpu = struct { .name = "cortex_m33", .llvm_name = "cortex-m33", .features = featureSet(&[_]Feature{ - .v8m_main, + .has_v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1797,7 +1797,7 @@ pub const cpu = struct { .name = "cortex_m35p", .llvm_name = "cortex-m35p", .features = featureSet(&[_]Feature{ - .v8m_main, + .has_v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1908,7 +1908,7 @@ pub const cpu = struct { .name = "cyclone", .llvm_name = "cyclone", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .avoid_movs_shop, .avoid_partial_cpsr, .crypto, @@ -1929,14 +1929,14 @@ pub const cpu = struct { .name = "ep9312", .llvm_name = "ep9312", .features = featureSet(&[_]Feature{ - .v4t, + .has_v4t, }), }; pub const exynos_m1 = CpuModel{ .name = "exynos_m1", .llvm_name = "exynos-m1", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .exynos, }), }; @@ -1944,7 +1944,7 @@ pub const cpu = struct { .name = "exynos_m2", .llvm_name = "exynos-m2", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .exynos, }), }; @@ -1952,7 +1952,7 @@ pub const cpu = struct { .name = "exynos_m3", .llvm_name = "exynos-m3", .features = featureSet(&[_]Feature{ - .v8a, + .has_v8, .exynos, }), }; @@ -1960,7 +1960,7 @@ pub const cpu = struct { .name = "exynos_m4", .llvm_name = "exynos-m4", .features = featureSet(&[_]Feature{ - .v8_2a, + .has_v8_2a, .dotprod, .exynos, .fullfp16, @@ -1973,7 +1973,7 @@ pub const cpu = struct { .dotprod, .exynos, .fullfp16, - .v8_2a, + .has_v8_2a, }), }; pub const generic = CpuModel{ @@ -1985,7 +1985,7 @@ pub const cpu = struct { .name = "iwmmxt", .llvm_name = "iwmmxt", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; pub const krait = CpuModel{ @@ -2012,14 +2012,14 @@ pub const cpu = struct { .crypto, .hwdiv, .hwdiv_arm, - .v8a, + .has_v8, }), }; pub const mpcore = CpuModel{ .name = "mpcore", .llvm_name = "mpcore", .features = featureSet(&[_]Feature{ - .v6k, + .has_v6k, .slowfpvmlx, .vfp2, }), @@ -2028,14 +2028,14 @@ pub const cpu = struct { .name = "mpcorenovfp", .llvm_name = "mpcorenovfp", .features = featureSet(&[_]Feature{ - .v6k, + .has_v6k, }), }; pub const sc000 = CpuModel{ .name = "sc000", .llvm_name = "sc000", .features = featureSet(&[_]Feature{ - .v6m, + .has_v6m, }), }; pub const sc300 = CpuModel{ @@ -2108,7 +2108,7 @@ pub const cpu = struct { .name = "xscale", .llvm_name = "xscale", .features = featureSet(&[_]Feature{ - .v5te, + .has_v5te, }), }; }; From b0d2ebe529593566f209d34d5bbbfd72cde2a6b9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 13:43:05 -0500 Subject: [PATCH 072/109] remove std.io.readLine This was deceptive. It was always meant to be sort of a "GNU readline" sort of thing where it provides a Command Line Interface to input text. However that functionality did not exist and it was basically a red herring for people trying to read line-delimited input from a stream. In this commit the API is deleted, so that people can find the proper API more easily. A CLI text input abstraction would be useful but may not even need to be in the standard library. As you can see in this commit, the guess_number CLI game gets by just fine by using `std.fs.File.read`. --- lib/std/io.zig | 67 --------------------------- test/standalone/guess_number/main.zig | 14 +++--- 2 files changed, 7 insertions(+), 74 deletions(-) diff --git a/lib/std/io.zig b/lib/std/io.zig index 22ba0b9bf4..b6e1b12534 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -790,73 +790,6 @@ pub const BufferedAtomicFile = struct { } }; -pub fn readLine(buf: *std.Buffer) ![]u8 { - var stdin_stream = getStdIn().inStream(); - return readLineFrom(&stdin_stream.stream, buf); -} - -/// Reads all characters until the next newline into buf, and returns -/// a slice of the characters read (excluding the newline character(s)). -pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 { - const start = buf.len(); - while (true) { - const byte = try stream.readByte(); - switch (byte) { - '\r' => { - // trash the following \n - _ = try stream.readByte(); - return buf.toSlice()[start..]; - }, - '\n' => return buf.toSlice()[start..], - else => try buf.appendByte(byte), - } - } -} - -test "io.readLineFrom" { - var buf = try std.Buffer.initSize(testing.allocator, 0); - defer buf.deinit(); - var mem_stream = SliceInStream.init( - \\Line 1 - \\Line 22 - \\Line 333 - ); - const stream = &mem_stream.stream; - - testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf)); - testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf)); - testing.expectError(error.EndOfStream, readLineFrom(stream, &buf)); - testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice()); -} - -pub fn readLineSlice(slice: []u8) ![]u8 { - var stdin_stream = getStdIn().inStream(); - return readLineSliceFrom(&stdin_stream.stream, slice); -} - -/// Reads all characters until the next newline into slice, and returns -/// a slice of the characters read (excluding the newline character(s)). -pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 { - // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte - // after taking ownership, which would always require an allocation. - var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(testing.failing_allocator, slice) }; - try buf.resize(0); - return try readLineFrom(stream, &buf); -} - -test "io.readLineSliceFrom" { - var buf: [7]u8 = undefined; - var mem_stream = SliceInStream.init( - \\Line 1 - \\Line 22 - \\Line 333 - ); - const stream = &mem_stream.stream; - - testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])); - testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..])); -} - pub const Packing = enum { /// Pack data to byte alignment Byte, diff --git a/test/standalone/guess_number/main.zig b/test/standalone/guess_number/main.zig index ce7d58ac17..f5b3b36993 100644 --- a/test/standalone/guess_number/main.zig +++ b/test/standalone/guess_number/main.zig @@ -5,6 +5,7 @@ const fmt = std.fmt; pub fn main() !void { const stdout = &io.getStdOut().outStream().stream; + const stdin = io.getStdIn(); try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{}); @@ -22,13 +23,12 @@ pub fn main() !void { try stdout.print("\nGuess a number between 1 and 100: ", .{}); var line_buf: [20]u8 = undefined; - const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) { - error.OutOfMemory => { - try stdout.print("Input too long.\n", .{}); - continue; - }, - else => return err, - }; + const amt = try stdin.read(&line_buf); + if (amt == line_buf.len) { + try stdout.print("Input too long.\n", .{}); + continue; + } + const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n"); const guess = fmt.parseUnsigned(u8, line, 10) catch { try stdout.print("Invalid number.\n", .{}); From e381a42de9c0f0c5439a926b0ac99026a0373f49 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 17:02:29 -0500 Subject: [PATCH 073/109] quick fix: add -mcpu=baseline support to zig0 When the build.zig logic to build libzigstage2 was converted to a cmake command, it neglected to use baseline CPU features rather than compiling with native features. This adds a hard coded flag `-mcpu=baseline` which can be used to detect the native target, but mark it as non-native so that it does not get the CPU features specific to the host used to compile libzigstage2. Full `-mcpu` support is happening in the upcoming pull request #4509, and so this "quick fix" will be cleaned up in that branch, before it is merged to master. closes #4506 --- CMakeLists.txt | 1 + src/main.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab4607d230..a3d6a7fb68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -616,6 +616,7 @@ endif() set(BUILD_LIBSTAGE2_ARGS "build-lib" "src-self-hosted/stage2.zig" + -mcpu=baseline --name zigstage2 --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" --cache on diff --git a/src/main.cpp b/src/main.cpp index d7f5e5b7b0..5046c92ddd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -450,6 +450,7 @@ static int main0(int argc, char **argv) { const char *cpu = nullptr; const char *features = nullptr; CodeModel code_model = CodeModelDefault; + bool baseline_cpu = false; ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); @@ -716,6 +717,8 @@ static int main0(int argc, char **argv) { emit_llvm_ir = true; } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) { emit_llvm_ir = false; + } else if (strcmp(arg, "-mcpu=baseline") == 0) { + baseline_cpu = true; } else if (i + 1 >= argc) { fprintf(stderr, "Expected another argument after %s\n", arg); return print_error_usage(arg0); @@ -977,6 +980,9 @@ static int main0(int argc, char **argv) { fprintf(stderr, "-target-glibc provided but no -target parameter\n"); return print_error_usage(arg0); } + if (baseline_cpu) { + target.is_native = false; + } } else { if ((err = target_parse_triple(&target, target_string))) { if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) { From 0f016b368de2ac93a298ab771646931329062fb5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 18:31:17 -0500 Subject: [PATCH 074/109] support -mcpu=baseline, both in stage1 and stage2 See e381a42de9c0f0c5439a926b0ac99026a0373f49 for more details. This is set up so that if we wish to make "baseline" depend on the OS in the future, it is possible to do that. --- lib/std/target.zig | 32 ++++++++++++++++++-------------- src-self-hosted/stage2.zig | 4 ++-- src/stage2.cpp | 27 ++++++++++++++++++--------- test/compile_errors.zig | 3 +-- test/tests.zig | 8 ++++---- test/translate_c.zig | 3 +-- 6 files changed, 44 insertions(+), 33 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 3d04e3424e..875ccda57f 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -726,8 +726,7 @@ pub const Target = union(enum) { /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features /// to remove from the set. - /// The default value of `null` means to use the "baseline" feature set. - cpu: ?[]const u8 = null, + cpu_features: []const u8 = "baseline", }; pub fn parse(args: ParseOptions) !Target { @@ -742,23 +741,29 @@ pub const Target = union(enum) { const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os); const all_features = arch.allFeaturesList(); - const cpu: Cpu = if (args.cpu) |cpu_text| blk: { - var index: usize = 0; - while (index < cpu_text.len and cpu_text[index] != '+' and cpu_text[index] != '-') { - index += 1; - } - const cpu_name = cpu_text[0..index]; + var index: usize = 0; + while (index < args.cpu_features.len and + args.cpu_features[index] != '+' and + args.cpu_features[index] != '-') + { + index += 1; + } + const cpu_name = args.cpu_features[0..index]; + const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: { const cpu_model = try arch.parseCpuModel(cpu_name); var set = cpu_model.features; - while (index < cpu_text.len) { - const op = cpu_text[index]; + while (index < args.cpu_features.len) { + const op = args.cpu_features[index]; index += 1; const start = index; - while (index < cpu_text.len and cpu_text[index] != '+' and cpu_text[index] != '-') { + while (index < args.cpu_features.len and + args.cpu_features[index] != '+' and + args.cpu_features[index] != '-') + { index += 1; } - const feature_name = cpu_text[start..index]; + const feature_name = args.cpu_features[start..index]; for (all_features) |feature, feat_index_usize| { const feat_index = @intCast(Cpu.Feature.Set.Index, feat_index_usize); if (mem.eql(u8, feature_name, feature.name)) { @@ -779,8 +784,7 @@ pub const Target = union(enum) { .model = cpu_model, .features = set, }; - } else Cpu.baseline(arch); - + }; var cross = Cross{ .cpu = cpu, .os = os, diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 048686190d..f7c4306cd5 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -675,8 +675,8 @@ fn stage2TargetParse( ) !void { const target: Target = if (zig_triple_oz) |zig_triple_z| blk: { const zig_triple = mem.toSliceConst(u8, zig_triple_z); - const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else null; - break :blk try Target.parse(.{ .arch_os_abi = zig_triple, .cpu = mcpu }); + const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline"; + break :blk try Target.parse(.{ .arch_os_abi = zig_triple, .cpu_features = mcpu }); } else Target.Native; try stage1_target.fromTarget(target); diff --git a/src/stage2.cpp b/src/stage2.cpp index f3ae03242e..035ce5a008 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -97,10 +97,20 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons if (zig_triple == nullptr) { get_native_target(target); - target->llvm_cpu_name = ZigLLVMGetHostCPUName(); - target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); - target->builtin_str = "Target.Cpu.baseline(arch);\n"; - target->cache_hash = "native\n\n"; + if (mcpu == nullptr) { + target->llvm_cpu_name = ZigLLVMGetHostCPUName(); + target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); + target->builtin_str = "Target.Cpu.baseline(arch);\n"; + target->cache_hash = "native\n\n"; + } else if (strcmp(mcpu, "baseline") == 0) { + target->llvm_cpu_name = ""; + target->llvm_cpu_features = ""; + target->builtin_str = "Target.Cpu.baseline(arch);\n"; + target->cache_hash = "baseline\n\n"; + } else { + const char *msg = "stage0 can't handle CPU/features in the target"; + stage2_panic(msg, strlen(msg)); + } } else { // first initialize all to zero *target = {}; @@ -135,15 +145,14 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons target->abi = target_default_abi(target->arch, target->os); } + if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) { + const char *msg = "stage0 can't handle CPU/features in the target"; + stage2_panic(msg, strlen(msg)); + } target->builtin_str = "Target.Cpu.baseline(arch);\n"; target->cache_hash = "\n\n"; } - if (mcpu != nullptr) { - const char *msg = "stage0 can't handle CPU/features in the target"; - stage2_panic(msg, strlen(msg)); - } - return ErrorNone; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 9f2b3716b0..4d133a1b5c 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -350,8 +350,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); tc.target = Target{ .Cross = .{ - .arch = .wasm32, - .cpu_features = Target.Arch.wasm32.getBaselineCpuFeatures(), + .cpu = Target.Cpu.baseline(.wasm32), .os = .wasi, .abi = .none, }, diff --git a/test/tests.zig b/test/tests.zig index 3190126208..f12f7f83d4 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -135,13 +135,13 @@ const test_targets = blk: { TestTarget{ .target = Target.parse(.{ .arch_os_abi = "arm-linux-none", - .cpu = "generic+v8a", + .cpu_features = "generic+v8a", }) catch unreachable, }, TestTarget{ .target = Target.parse(.{ .arch_os_abi = "arm-linux-musleabihf", - .cpu = "generic+v8a", + .cpu_features = "generic+v8a", }) catch unreachable, .link_libc = true, }, @@ -149,7 +149,7 @@ const test_targets = blk: { //TestTarget{ // .target = Target.parse(.{ // .arch_os_abi = "arm-linux-gnueabihf", - // .cpu = "generic+v8a", + // .cpu_features = "generic+v8a", // }) catch unreachable, // .link_libc = true, //}, @@ -449,7 +449,7 @@ pub fn addPkgTests( const ArchTag = @TagType(builtin.Arch); if (test_target.disable_native and test_target.target.getOs() == builtin.os and - @as(ArchTag, test_target.target.getArch()) == @as(ArchTag, builtin.arch)) + test_target.target.getArch() == builtin.arch) { continue; } diff --git a/test/translate_c.zig b/test/translate_c.zig index b69142e864..2351a6c94f 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1095,10 +1095,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.addWithTarget("Calling convention", tests.Target{ .Cross = .{ + .cpu = Target.Cpu.baseline(.i386), .os = .linux, - .arch = .i386, .abi = .none, - .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), }, }, \\void __attribute__((fastcall)) foo1(float *a); From 2de7d0b10c29442f556654b61d0c5c4a53047a09 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Feb 2020 18:50:20 -0500 Subject: [PATCH 075/109] fix zig build, ABI ABI, and update tests to new Target layout --- lib/std/build.zig | 36 +++++++++++++----------------------- src-self-hosted/stage2.zig | 4 ++-- test/compile_errors.zig | 3 +-- test/translate_c.zig | 24 ++++++++---------------- 4 files changed, 24 insertions(+), 43 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index f6e8474701..beb89ab7ce 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1909,43 +1909,33 @@ pub const LibExeObjStep = struct { try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable); const all_features = self.target.getArch().allFeaturesList(); - var populated_cpu_features = cross.cpu_features.cpu.features; - if (self.target.getArch().subArchFeature()) |sub_arch_index| { - populated_cpu_features.addFeature(sub_arch_index); - } + var populated_cpu_features = cross.cpu.model.features; populated_cpu_features.populateDependencies(all_features); - if (populated_cpu_features.eql(cross.cpu_features.features)) { + if (populated_cpu_features.eql(cross.cpu.features)) { // The CPU name alone is sufficient. // If it is the baseline CPU, no command line args are required. - if (cross.cpu_features.cpu != self.target.getArch().getBaselineCpuFeatures().cpu) { - try zig_args.append("-target-cpu"); - try zig_args.append(cross.cpu_features.cpu.name); + if (cross.cpu.model != Target.Cpu.baseline(self.target.getArch()).model) { + try zig_args.append("-mcpu"); + try zig_args.append(cross.cpu.model.name); } } else { - try zig_args.append("-target-cpu"); - try zig_args.append(cross.cpu_features.cpu.name); + var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu="); + try zig_args.append(cross.cpu.model.name); - try zig_args.append("-target-feature"); - var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0); for (all_features) |feature, i_usize| { const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize); const in_cpu_set = populated_cpu_features.isEnabled(i); - const in_actual_set = cross.cpu_features.features.isEnabled(i); + const in_actual_set = cross.cpu.features.isEnabled(i); if (in_cpu_set and !in_actual_set) { - try feature_str_buffer.appendByte('-'); - try feature_str_buffer.append(feature.name); - try feature_str_buffer.appendByte(','); + try mcpu_buffer.appendByte('-'); + try mcpu_buffer.append(feature.name); } else if (!in_cpu_set and in_actual_set) { - try feature_str_buffer.appendByte('+'); - try feature_str_buffer.append(feature.name); - try feature_str_buffer.appendByte(','); + try mcpu_buffer.appendByte('+'); + try mcpu_buffer.append(feature.name); } } - if (mem.endsWith(u8, feature_str_buffer.toSliceConst(), ",")) { - feature_str_buffer.shrink(feature_str_buffer.len() - 1); - } - try zig_args.append(feature_str_buffer.toSliceConst()); + try zig_args.append(mcpu_buffer.toSliceConst()); } }, } diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index f7c4306cd5..683e698010 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -930,7 +930,7 @@ const Stage2Target = extern struct { const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch const in_sub_arch = in_target.sub_arch - 1; // skip over ZigLLVM_NoSubArch const in_os = in_target.os; - const in_abi = in_target.abi - 1; // skip over ZigLLVM_UnknownEnvironment + const in_abi = in_target.abi; return .{ .Cross = .{ @@ -956,7 +956,7 @@ const Stage2Target = extern struct { self.sub_arch = 0; self.vendor = 0; self.os = @enumToInt(target.getOs()); - self.abi = @enumToInt(target.getAbi()) + 1; // skip over ZigLLVM_UnknownEnvironment + self.abi = @enumToInt(target.getAbi()); try initStage1TargetCpuFeatures(self, cpu); } }; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a204273313..56dde8dd8f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -763,8 +763,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); tc.target = Target{ .Cross = .{ - .arch = .x86_64, - .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + .cpu = Target.Cpu.baseline(.x86_64), .os = .linux, .abi = .gnu, }, diff --git a/test/translate_c.zig b/test/translate_c.zig index 2351a6c94f..e3c68a6d53 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1113,14 +1113,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void; }); - cases.addWithTarget("Calling convention", tests.Target{ - .Cross = .{ - .os = .linux, - .arch = .{ .arm = .v8_5a }, - .abi = .none, - .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(), - }, - }, + cases.addWithTarget("Calling convention", Target.parse(.{ + .arch_os_abi = "arm-linux-none", + .cpu_features = "generic+v8_5a", + }) catch unreachable, \\void __attribute__((pcs("aapcs"))) foo1(float *a); \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); , &[_][]const u8{ @@ -1128,14 +1124,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; }); - cases.addWithTarget("Calling convention", tests.Target{ - .Cross = .{ - .os = .linux, - .arch = .{ .aarch64 = .v8_5a }, - .abi = .none, - .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(), - }, - }, + cases.addWithTarget("Calling convention", Target.parse(.{ + .arch_os_abi = "aarch64-linux-none", + .cpu_features = "generic+v8_5a", + }) catch unreachable, \\void __attribute__((aarch64_vector_pcs)) foo1(float *a); , &[_][]const u8{ \\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void; From 770631cc79a655bc5e21184ca15bdb6192e905de Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Thu, 20 Feb 2020 02:45:58 -0500 Subject: [PATCH 076/109] stage1: free more heap after analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - immediately free dangling IrInstGenConst after analysis - fixup mem::List params `&Allocator` → `*Allocator` --- src/ir.cpp | 19 +++++++++++++++++++ src/mem_list.hpp | 15 +++++++++------ src/mem_profile.cpp | 4 ++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 5f50586f72..aa46b37d4f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14,6 +14,7 @@ #include "range_set.hpp" #include "softfloat.hpp" #include "util.hpp" +#include "mem_list.hpp" #include @@ -28,6 +29,9 @@ struct IrBuilderGen { CodeGen *codegen; IrExecutableGen *exec; IrBasicBlockGen *current_basic_block; + + // track for immediate post-analysis destruction + mem::List constants; }; struct IrAnalyze { @@ -741,6 +745,10 @@ static void ira_ref(IrAnalyze *ira) { static void ira_deref(IrAnalyze *ira) { if (ira->ref_count > 1) { ira->ref_count -= 1; + + // immediate destruction of dangling IrInstGenConst is not possible + // free tracking memory because it will never be used + ira->new_irb.constants.deinit(&heap::c_allocator); return; } assert(ira->ref_count != 0); @@ -758,6 +766,15 @@ static void ira_deref(IrAnalyze *ira) { heap::c_allocator.destroy(ira->old_irb.exec); ira->src_implicit_return_type_list.deinit(); ira->resume_stack.deinit(); + + // destroy dangling IrInstGenConst + for (size_t i = 0; i < ira->new_irb.constants.length; i += 1) { + auto constant = ira->new_irb.constants.items[i]; + if (constant->base.base.ref_count == 0 && !ir_inst_gen_has_side_effects(&constant->base)) + destroy_instruction_gen(&constant->base); + } + ira->new_irb.constants.deinit(&heap::c_allocator); + heap::c_allocator.destroy(ira); } @@ -12746,12 +12763,14 @@ static IrInstGen *ir_const(IrAnalyze *ira, IrInst *inst, ZigType *ty) { IrInstGen *new_instruction = &const_instruction->base; new_instruction->value->type = ty; new_instruction->value->special = ConstValSpecialStatic; + ira->new_irb.constants.append(&heap::c_allocator, const_instruction); return new_instruction; } static IrInstGen *ir_const_noval(IrAnalyze *ira, IrInst *old_instruction) { IrInstGenConst *const_instruction = ir_create_inst_noval(&ira->new_irb, old_instruction->scope, old_instruction->source_node); + ira->new_irb.constants.append(&heap::c_allocator, const_instruction); return &const_instruction->base; } diff --git a/src/mem_list.hpp b/src/mem_list.hpp index a09d4d1c8d..df82358ea9 100644 --- a/src/mem_list.hpp +++ b/src/mem_list.hpp @@ -14,11 +14,14 @@ namespace mem { template struct List { - void deinit(Allocator& allocator) { - allocator.deallocate(items, capacity); + void deinit(Allocator *allocator) { + allocator->deallocate(items, capacity); + items = nullptr; + length = 0; + capacity = 0; } - void append(Allocator& allocator, const T& item) { + void append(Allocator *allocator, const T& item) { ensure_capacity(allocator, length + 1); items[length++] = item; } @@ -57,7 +60,7 @@ struct List { return items[length - 1]; } - void resize(Allocator& allocator, size_t new_length) { + void resize(Allocator *allocator, size_t new_length) { assert(new_length != SIZE_MAX); ensure_capacity(allocator, new_length); length = new_length; @@ -67,7 +70,7 @@ struct List { length = 0; } - void ensure_capacity(Allocator& allocator, size_t new_capacity) { + void ensure_capacity(Allocator *allocator, size_t new_capacity) { if (capacity >= new_capacity) return; @@ -76,7 +79,7 @@ struct List { better_capacity = better_capacity * 5 / 2 + 8; } while (better_capacity < new_capacity); - items = allocator.reallocate_nonzero(items, capacity, better_capacity); + items = allocator->reallocate_nonzero(items, capacity, better_capacity); capacity = better_capacity; } diff --git a/src/mem_profile.cpp b/src/mem_profile.cpp index ef47c3f426..13ba57f913 100644 --- a/src/mem_profile.cpp +++ b/src/mem_profile.cpp @@ -92,7 +92,7 @@ void Profile::print_report(FILE *file) { auto entry = it.next(); if (!entry) break; - list.append(heap::bootstrap_allocator, &entry->value); + list.append(&heap::bootstrap_allocator, &entry->value); } qsort(list.items, list.length, sizeof(const Entry *), entry_compare); @@ -143,7 +143,7 @@ void Profile::print_report(FILE *file) { fprintf(file, "\n Total calls alloc: %zu, dealloc: %zu, remain: %zu\n", total_calls_alloc, total_calls_dealloc, (total_calls_alloc - total_calls_dealloc)); - list.deinit(heap::bootstrap_allocator); + list.deinit(&heap::bootstrap_allocator); } uint32_t Profile::usage_hash(UsageKey key) { From 7b8b4d200cce5030efb758eb4fc8fade9c3e8402 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 01:54:00 -0500 Subject: [PATCH 077/109] fix not initializing some ZigTarget fields --- src-self-hosted/stage2.zig | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 683e698010..6a537a486a 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -952,11 +952,19 @@ const Stage2Target = extern struct { }, .Cross => target.getCpu(), }; - self.arch = @enumToInt(target.getArch()) + 1; // skip over ZigLLVM_UnknownArch - self.sub_arch = 0; - self.vendor = 0; - self.os = @enumToInt(target.getOs()); - self.abi = @enumToInt(target.getAbi()); + self.* = .{ + .arch = @enumToInt(target.getArch()) + 1, // skip over ZigLLVM_UnknownArch + .sub_arch = 0, + .vendor = 0, + .os = @enumToInt(target.getOs()), + .abi = @enumToInt(target.getAbi()), + .llvm_cpu_name = null, + .llvm_cpu_features = null, + .builtin_str = null, + .cache_hash = null, + .is_native = target == .Native, + .glibc_version = null, + }; try initStage1TargetCpuFeatures(self, cpu); } }; From a391a82e4987728e30bf5c27be5631f9d4db530f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 01:58:40 -0500 Subject: [PATCH 078/109] fix zig build adding invalid cli args --- lib/std/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index beb89ab7ce..43cc4a2150 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1921,7 +1921,7 @@ pub const LibExeObjStep = struct { } } else { var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu="); - try zig_args.append(cross.cpu.model.name); + try mcpu_buffer.append(cross.cpu.model.name); for (all_features) |feature, i_usize| { const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize); From ab56d3e18ca7dbc430fdc2ca51fce08804cc3599 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 11:07:56 -0500 Subject: [PATCH 079/109] fix std.Target unit tests --- lib/std/target.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 875ccda57f..a341fb3977 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1262,7 +1262,7 @@ test "Target.parse" { { const target = (try Target.parse(.{ .arch_os_abi = "x86_64-linux-gnu", - .cpu = "x86_64-sse-sse2-avx-cx8", + .cpu_features = "x86_64-sse-sse2-avx-cx8", })).Cross; std.testing.expect(target.os == .linux); @@ -1277,7 +1277,7 @@ test "Target.parse" { { const target = (try Target.parse(.{ .arch_os_abi = "arm-linux-musleabihf", - .cpu = "generic+v8a", + .cpu_features = "generic+v8a", })).Cross; std.testing.expect(target.os == .linux); From 61c67a9833c312678289272e5e0547a78cbd299c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 11:47:34 -0500 Subject: [PATCH 080/109] remove sub-arch from stage1 --- src-self-hosted/stage2.zig | 7 +- src/codegen.cpp | 3 - src/glibc.cpp | 6 +- src/stage2.cpp | 4 +- src/stage2.h | 5 +- src/target.cpp | 279 +------------------------------------ src/target.hpp | 21 +-- src/zig_llvm.cpp | 94 +------------ src/zig_llvm.h | 38 +---- 9 files changed, 17 insertions(+), 440 deletions(-) diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 6a537a486a..d99f436a75 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -909,12 +909,11 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: // ABI warning const Stage2Target = extern struct { arch: c_int, - sub_arch: c_int, - vendor: c_int, - abi: c_int, + abi: c_int, os: c_int, + is_native: bool, glibc_version: ?*Stage2GLibCVersion, // null means default @@ -928,7 +927,6 @@ const Stage2Target = extern struct { if (in_target.is_native) return .Native; const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch - const in_sub_arch = in_target.sub_arch - 1; // skip over ZigLLVM_NoSubArch const in_os = in_target.os; const in_abi = in_target.abi; @@ -954,7 +952,6 @@ const Stage2Target = extern struct { }; self.* = .{ .arch = @enumToInt(target.getArch()) + 1, // skip over ZigLLVM_UnknownArch - .sub_arch = 0, .vendor = 0, .os = @enumToInt(target.getOs()), .abi = @enumToInt(target.getAbi()), diff --git a/src/codegen.cpp b/src/codegen.cpp index b5d621dd7c..6e48f9be42 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8711,7 +8711,6 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->code_model); cache_int(&cache_hash, g->zig_target->is_native); cache_int(&cache_hash, g->zig_target->arch); - cache_int(&cache_hash, g->zig_target->sub_arch); cache_int(&cache_hash, g->zig_target->vendor); cache_int(&cache_hash, g->zig_target->os); cache_int(&cache_hash, g->zig_target->abi); @@ -9616,7 +9615,6 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose cache_list_of_str(cache_hash, g->libc_include_dir_list, g->libc_include_dir_len); cache_int(cache_hash, g->zig_target->is_native); cache_int(cache_hash, g->zig_target->arch); - cache_int(cache_hash, g->zig_target->sub_arch); cache_int(cache_hash, g->zig_target->vendor); cache_int(cache_hash, g->zig_target->os); cache_int(cache_hash, g->zig_target->abi); @@ -10380,7 +10378,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_int(ch, g->out_type); cache_bool(ch, g->zig_target->is_native); cache_int(ch, g->zig_target->arch); - cache_int(ch, g->zig_target->sub_arch); cache_int(ch, g->zig_target->vendor); cache_int(ch, g->zig_target->os); cache_int(ch, g->zig_target->abi); diff --git a/src/glibc.cpp b/src/glibc.cpp index ec45b6afa7..849aac6c77 100644 --- a/src/glibc.cpp +++ b/src/glibc.cpp @@ -116,10 +116,8 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo assert(opt_abi.is_some); - err = target_parse_archsub(&target->arch, &target->sub_arch, - (char*)opt_arch.value.ptr, opt_arch.value.len); - // there's no sub arch so we might get an error, but the arch is still populated - assert(err == ErrorNone || err == ErrorUnknownArchitecture); + err = target_parse_arch(&target->arch, (char*)opt_arch.value.ptr, opt_arch.value.len); + assert(err == ErrorNone); target->os = OsLinux; diff --git a/src/stage2.cpp b/src/stage2.cpp index f5bfc1001c..736f11622e 100644 --- a/src/stage2.cpp +++ b/src/stage2.cpp @@ -125,9 +125,7 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons if (!opt_archsub.is_some) return ErrorMissingArchitecture; - if ((err = target_parse_archsub(&target->arch, &target->sub_arch, - (char*)opt_archsub.value.ptr, opt_archsub.value.len))) - { + if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { return err; } diff --git a/src/stage2.h b/src/stage2.h index fe49c943a0..e6db241e88 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -279,12 +279,11 @@ struct Stage2TargetData; // ABI warning struct ZigTarget { enum ZigLLVM_ArchType arch; - enum ZigLLVM_SubArchType sub_arch; - enum ZigLLVM_VendorType vendor; - enum ZigLLVM_EnvironmentType abi; + enum ZigLLVM_EnvironmentType abi; Os os; + bool is_native; struct ZigGLibCVersion *glibc_version; // null means default diff --git a/src/target.cpp b/src/target.cpp index fb064c4849..0a3fb3da5f 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -15,60 +15,6 @@ #include -static const SubArchList subarch_list_list[] = { - SubArchListNone, - SubArchListArm32, - SubArchListArm64, - SubArchListKalimba, - SubArchListMips, -}; - -static const ZigLLVM_SubArchType subarch_list_arm32[] = { - ZigLLVM_ARMSubArch_v8_5a, - ZigLLVM_ARMSubArch_v8_4a, - ZigLLVM_ARMSubArch_v8_3a, - ZigLLVM_ARMSubArch_v8_2a, - ZigLLVM_ARMSubArch_v8_1a, - ZigLLVM_ARMSubArch_v8, - ZigLLVM_ARMSubArch_v8r, - ZigLLVM_ARMSubArch_v8m_baseline, - ZigLLVM_ARMSubArch_v8m_mainline, - ZigLLVM_ARMSubArch_v8_1m_mainline, - ZigLLVM_ARMSubArch_v7, - ZigLLVM_ARMSubArch_v7em, - ZigLLVM_ARMSubArch_v7m, - ZigLLVM_ARMSubArch_v7s, - ZigLLVM_ARMSubArch_v7k, - ZigLLVM_ARMSubArch_v7ve, - ZigLLVM_ARMSubArch_v6, - ZigLLVM_ARMSubArch_v6m, - ZigLLVM_ARMSubArch_v6k, - ZigLLVM_ARMSubArch_v6t2, - ZigLLVM_ARMSubArch_v5, - ZigLLVM_ARMSubArch_v5te, - ZigLLVM_ARMSubArch_v4t, - -}; - -static const ZigLLVM_SubArchType subarch_list_arm64[] = { - ZigLLVM_ARMSubArch_v8_5a, - ZigLLVM_ARMSubArch_v8_4a, - ZigLLVM_ARMSubArch_v8_3a, - ZigLLVM_ARMSubArch_v8_2a, - ZigLLVM_ARMSubArch_v8_1a, - ZigLLVM_ARMSubArch_v8, -}; - -static const ZigLLVM_SubArchType subarch_list_kalimba[] = { - ZigLLVM_KalimbaSubArch_v5, - ZigLLVM_KalimbaSubArch_v4, - ZigLLVM_KalimbaSubArch_v3, -}; - -static const ZigLLVM_SubArchType subarch_list_mips[] = { - ZigLLVM_MipsSubArch_r6, -}; - static const ZigLLVM_ArchType arch_list[] = { ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale ZigLLVM_armeb, // ARM (big endian): armeb @@ -509,7 +455,6 @@ void get_native_target(ZigTarget *target) { ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os ZigLLVMGetNativeTarget( &target->arch, - &target->sub_arch, &target->vendor, &os_type, &target->abi, @@ -535,223 +480,18 @@ void target_init_default_glibc_version(ZigTarget *target) { *target->glibc_version = {2, 17, 0}; } -Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub, - const char *archsub_ptr, size_t archsub_len) -{ +Error target_parse_arch(ZigLLVM_ArchType *out_arch, const char *arch_ptr, size_t arch_len) { *out_arch = ZigLLVM_UnknownArch; - *out_sub = ZigLLVM_NoSubArch; for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) { ZigLLVM_ArchType arch = arch_list[arch_i]; - SubArchList sub_arch_list = target_subarch_list(arch); - size_t subarch_count = target_subarch_count(sub_arch_list); - if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) { + if (mem_eql_str(arch_ptr, arch_len, target_arch_name(arch))) { *out_arch = arch; - if (subarch_count == 0) { - return ErrorNone; - } - } - for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { - ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); - char arch_name[64]; - int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub)); - if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) { - *out_arch = arch; - *out_sub = sub; - return ErrorNone; - } + return ErrorNone; } } return ErrorUnknownArchitecture; } -SubArchList target_subarch_list(ZigLLVM_ArchType arch) { - switch (arch) { - case ZigLLVM_UnknownArch: - zig_unreachable(); - case ZigLLVM_arm: - case ZigLLVM_armeb: - case ZigLLVM_thumb: - case ZigLLVM_thumbeb: - return SubArchListArm32; - - case ZigLLVM_aarch64: - case ZigLLVM_aarch64_be: - case ZigLLVM_aarch64_32: - return SubArchListArm64; - - case ZigLLVM_kalimba: - return SubArchListKalimba; - - case ZigLLVM_arc: - case ZigLLVM_avr: - case ZigLLVM_bpfel: - case ZigLLVM_bpfeb: - case ZigLLVM_hexagon: - case ZigLLVM_mips: - case ZigLLVM_mipsel: - case ZigLLVM_mips64: - case ZigLLVM_mips64el: - case ZigLLVM_msp430: - case ZigLLVM_ppc: - case ZigLLVM_ppc64: - case ZigLLVM_ppc64le: - case ZigLLVM_r600: - case ZigLLVM_amdgcn: - case ZigLLVM_riscv32: - case ZigLLVM_riscv64: - case ZigLLVM_sparc: - case ZigLLVM_sparcv9: - case ZigLLVM_sparcel: - case ZigLLVM_systemz: - case ZigLLVM_tce: - case ZigLLVM_tcele: - case ZigLLVM_x86: - case ZigLLVM_x86_64: - case ZigLLVM_xcore: - case ZigLLVM_nvptx: - case ZigLLVM_nvptx64: - case ZigLLVM_le32: - case ZigLLVM_le64: - case ZigLLVM_amdil: - case ZigLLVM_amdil64: - case ZigLLVM_hsail: - case ZigLLVM_hsail64: - case ZigLLVM_spir: - case ZigLLVM_spir64: - case ZigLLVM_shave: - case ZigLLVM_lanai: - case ZigLLVM_wasm32: - case ZigLLVM_wasm64: - case ZigLLVM_renderscript32: - case ZigLLVM_renderscript64: - return SubArchListNone; - } - zig_unreachable(); -} - -size_t target_subarch_count(SubArchList sub_arch_list) { - switch (sub_arch_list) { - case SubArchListNone: - return 0; - case SubArchListArm32: - return array_length(subarch_list_arm32); - case SubArchListArm64: - return array_length(subarch_list_arm64); - case SubArchListKalimba: - return array_length(subarch_list_kalimba); - case SubArchListMips: - return array_length(subarch_list_mips); - } - zig_unreachable(); -} - -ZigLLVM_SubArchType target_subarch_enum(SubArchList sub_arch_list, size_t i) { - switch (sub_arch_list) { - case SubArchListNone: - zig_unreachable(); - case SubArchListArm32: - assert(i < array_length(subarch_list_arm32)); - return subarch_list_arm32[i]; - case SubArchListArm64: - assert(i < array_length(subarch_list_arm64)); - return subarch_list_arm64[i]; - case SubArchListKalimba: - assert(i < array_length(subarch_list_kalimba)); - return subarch_list_kalimba[i]; - case SubArchListMips: - assert(i < array_length(subarch_list_mips)); - return subarch_list_mips[i]; - } - zig_unreachable(); -} - -const char *target_subarch_name(ZigLLVM_SubArchType subarch) { - switch (subarch) { - case ZigLLVM_NoSubArch: - return ""; - case ZigLLVM_ARMSubArch_v8_5a: - return "v8_5a"; - case ZigLLVM_ARMSubArch_v8_4a: - return "v8_4a"; - case ZigLLVM_ARMSubArch_v8_3a: - return "v8_3a"; - case ZigLLVM_ARMSubArch_v8_2a: - return "v8_2a"; - case ZigLLVM_ARMSubArch_v8_1a: - return "v8_1a"; - case ZigLLVM_ARMSubArch_v8: - return "v8a"; - case ZigLLVM_ARMSubArch_v8r: - return "v8r"; - case ZigLLVM_ARMSubArch_v8m_baseline: - return "v8m_baseline"; - case ZigLLVM_ARMSubArch_v8m_mainline: - return "v8m_mainline"; - case ZigLLVM_ARMSubArch_v8_1m_mainline: - return "v8_1m_mainline"; - case ZigLLVM_ARMSubArch_v7: - return "v7a"; - case ZigLLVM_ARMSubArch_v7em: - return "v7em"; - case ZigLLVM_ARMSubArch_v7m: - return "v7m"; - case ZigLLVM_ARMSubArch_v7s: - return "v7s"; - case ZigLLVM_ARMSubArch_v7k: - return "v7k"; - case ZigLLVM_ARMSubArch_v7ve: - return "v7ve"; - case ZigLLVM_ARMSubArch_v6: - return "v6"; - case ZigLLVM_ARMSubArch_v6m: - return "v6m"; - case ZigLLVM_ARMSubArch_v6k: - return "v6k"; - case ZigLLVM_ARMSubArch_v6t2: - return "v6t2"; - case ZigLLVM_ARMSubArch_v5: - return "v5"; - case ZigLLVM_ARMSubArch_v5te: - return "v5te"; - case ZigLLVM_ARMSubArch_v4t: - return "v4t"; - case ZigLLVM_KalimbaSubArch_v3: - return "v3"; - case ZigLLVM_KalimbaSubArch_v4: - return "v4"; - case ZigLLVM_KalimbaSubArch_v5: - return "v5"; - case ZigLLVM_MipsSubArch_r6: - return "r6"; - } - zig_unreachable(); -} - -size_t target_subarch_list_count(void) { - return array_length(subarch_list_list); -} - -SubArchList target_subarch_list_enum(size_t index) { - assert(index < array_length(subarch_list_list)); - return subarch_list_list[index]; -} - -const char *target_subarch_list_name(SubArchList sub_arch_list) { - switch (sub_arch_list) { - case SubArchListNone: - return "None"; - case SubArchListArm32: - return "Arm32"; - case SubArchListArm64: - return "Arm64"; - case SubArchListKalimba: - return "Kalimba"; - case SubArchListMips: - return "Mips"; - } - zig_unreachable(); -} - Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) { for (size_t i = 0; i < array_length(os_list); i += 1) { Os os = os_list[i]; @@ -794,18 +534,16 @@ void init_all_targets(void) { void target_triple_zig(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); - buf_appendf(triple, "%s%s-%s-%s", + buf_appendf(triple, "%s-%s-%s", target_arch_name(target->arch), - target_subarch_name(target->sub_arch), target_os_name(target->os), target_abi_name(target->abi)); } void target_triple_llvm(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); - buf_appendf(triple, "%s%s-%s-%s-%s", + buf_appendf(triple, "%s-%s-%s-%s", ZigLLVMGetArchTypeName(target->arch), - ZigLLVMGetSubArchTypeName(target->sub_arch), ZigLLVMGetVendorTypeName(target->vendor), ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), ZigLLVMGetEnvironmentTypeName(target->abi)); @@ -1182,10 +920,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target return true; } - if (guest_target->os == host_target->os && guest_target->arch == host_target->arch && - guest_target->sub_arch == host_target->sub_arch) - { - // OS, arch, and sub-arch match + if (guest_target->os == host_target->os && guest_target->arch == host_target->arch) { + // OS and arch match return true; } @@ -1607,7 +1343,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) { out_target->arch = libcs_available[index].arch; out_target->os = libcs_available[index].os; out_target->abi = libcs_available[index].abi; - out_target->sub_arch = ZigLLVM_NoSubArch; out_target->vendor = ZigLLVM_UnknownVendor; out_target->is_native = false; } diff --git a/src/target.hpp b/src/target.hpp index 95acbe259e..9396eb2623 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -12,15 +12,6 @@ struct Buf; -// Synchronize with target.cpp::subarch_list_list -enum SubArchList { - SubArchListNone, - SubArchListArm32, - SubArchListArm64, - SubArchListKalimba, - SubArchListMips, -}; - enum TargetSubsystem { TargetSubsystemConsole, TargetSubsystemWindows, @@ -51,8 +42,7 @@ enum CIntType { }; Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu); -Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub, - const char *archsub_ptr, size_t archsub_len); +Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len); Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); @@ -63,15 +53,6 @@ size_t target_arch_count(void); ZigLLVM_ArchType target_arch_enum(size_t index); const char *target_arch_name(ZigLLVM_ArchType arch); -SubArchList target_subarch_list(ZigLLVM_ArchType arch); -size_t target_subarch_count(SubArchList sub_arch_list); -ZigLLVM_SubArchType target_subarch_enum(SubArchList subarch_list, size_t index); -const char *target_subarch_name(ZigLLVM_SubArchType subarch); - -size_t target_subarch_list_count(void); -SubArchList target_subarch_list_enum(size_t index); -const char *target_subarch_list_name(SubArchList sub_arch_list); - const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch); size_t target_vendor_count(void); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 64706500d5..aed2944f62 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -806,7 +806,7 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) { return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin(); } -void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, +void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, ZigLLVM_ObjectFormatType *oformat) { @@ -814,7 +814,6 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su Triple triple(Triple::normalize(native_triple)); *arch_type = (ZigLLVM_ArchType)triple.getArch(); - *sub_arch_type = (ZigLLVM_SubArchType)triple.getSubArch(); *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); *os_type = (ZigLLVM_OSType)triple.getOS(); *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); @@ -823,68 +822,6 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su free(native_triple); } -const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { - switch (sub_arch) { - case ZigLLVM_NoSubArch: - return ""; - case ZigLLVM_ARMSubArch_v8_5a: - return "v8.5a"; - case ZigLLVM_ARMSubArch_v8_4a: - return "v8.4a"; - case ZigLLVM_ARMSubArch_v8_3a: - return "v8.3a"; - case ZigLLVM_ARMSubArch_v8_2a: - return "v8.2a"; - case ZigLLVM_ARMSubArch_v8_1a: - return "v8.1a"; - case ZigLLVM_ARMSubArch_v8: - return "v8a"; - case ZigLLVM_ARMSubArch_v8r: - return "v8r"; - case ZigLLVM_ARMSubArch_v8m_baseline: - return "v8m.base"; - case ZigLLVM_ARMSubArch_v8m_mainline: - return "v8m.main"; - case ZigLLVM_ARMSubArch_v8_1m_mainline: - return "v8.1m.main"; - case ZigLLVM_ARMSubArch_v7: - return "v7a"; - case ZigLLVM_ARMSubArch_v7em: - return "v7em"; - case ZigLLVM_ARMSubArch_v7m: - return "v7m"; - case ZigLLVM_ARMSubArch_v7s: - return "v7s"; - case ZigLLVM_ARMSubArch_v7k: - return "v7k"; - case ZigLLVM_ARMSubArch_v7ve: - return "v7ve"; - case ZigLLVM_ARMSubArch_v6: - return "v6"; - case ZigLLVM_ARMSubArch_v6m: - return "v6m"; - case ZigLLVM_ARMSubArch_v6k: - return "v6k"; - case ZigLLVM_ARMSubArch_v6t2: - return "v6t2"; - case ZigLLVM_ARMSubArch_v5: - return "v5"; - case ZigLLVM_ARMSubArch_v5te: - return "v5te"; - case ZigLLVM_ARMSubArch_v4t: - return "v4t"; - case ZigLLVM_KalimbaSubArch_v3: - return "v3"; - case ZigLLVM_KalimbaSubArch_v4: - return "v4"; - case ZigLLVM_KalimbaSubArch_v5: - return "v5"; - case ZigLLVM_MipsSubArch_r6: - return "r6"; - } - abort(); -} - void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4); @@ -1218,35 +1155,6 @@ static_assert((Triple::ArchType)ZigLLVM_renderscript32 == Triple::renderscript32 static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64, ""); static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); -static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1m_mainline == Triple::ARMSubArch_v8_1m_mainline, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, ""); -static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, ""); -static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, ""); -static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, ""); -static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); -static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); -static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, ""); - static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, ""); static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, ""); static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, ""); diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 95751cd08a..95f5926ec7 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -324,41 +324,6 @@ enum ZigLLVM_ArchType { ZigLLVM_LastArchType = ZigLLVM_renderscript64 }; -// synchronize with lists in target.cpp -enum ZigLLVM_SubArchType { - ZigLLVM_NoSubArch, - - ZigLLVM_ARMSubArch_v8_5a, - ZigLLVM_ARMSubArch_v8_4a, - ZigLLVM_ARMSubArch_v8_3a, - ZigLLVM_ARMSubArch_v8_2a, - ZigLLVM_ARMSubArch_v8_1a, - ZigLLVM_ARMSubArch_v8, - ZigLLVM_ARMSubArch_v8r, - ZigLLVM_ARMSubArch_v8m_baseline, - ZigLLVM_ARMSubArch_v8m_mainline, - ZigLLVM_ARMSubArch_v8_1m_mainline, - ZigLLVM_ARMSubArch_v7, - ZigLLVM_ARMSubArch_v7em, - ZigLLVM_ARMSubArch_v7m, - ZigLLVM_ARMSubArch_v7s, - ZigLLVM_ARMSubArch_v7k, - ZigLLVM_ARMSubArch_v7ve, - ZigLLVM_ARMSubArch_v6, - ZigLLVM_ARMSubArch_v6m, - ZigLLVM_ARMSubArch_v6k, - ZigLLVM_ARMSubArch_v6t2, - ZigLLVM_ARMSubArch_v5, - ZigLLVM_ARMSubArch_v5te, - ZigLLVM_ARMSubArch_v4t, - - ZigLLVM_KalimbaSubArch_v3, - ZigLLVM_KalimbaSubArch_v4, - ZigLLVM_KalimbaSubArch_v5, - - ZigLLVM_MipsSubArch_r6, -}; - enum ZigLLVM_VendorType { ZigLLVM_UnknownVendor, @@ -518,7 +483,6 @@ LLVMValueRef ZigLLVMBuildAtomicRMW(LLVMBuilderRef B, enum ZigLLVM_AtomicRMWBinOp #define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29) ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch); -ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch); ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor); ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os); ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi); @@ -532,7 +496,7 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch, const char *output_lib_path, const bool kill_at); -ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type, +ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type, enum ZigLLVM_ObjectFormatType *oformat); From 7da7fbb9122e6e2a5f936ce9c1eaf8b5776fa8ac Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 12:29:27 -0500 Subject: [PATCH 081/109] update ARM cpu models to correctly include the sub-arch --- lib/std/target/arm.zig | 108 ++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig index 7195e2803e..50c1bfed15 100644 --- a/lib/std/target/arm.zig +++ b/lib/std/target/arm.zig @@ -1300,49 +1300,49 @@ pub const cpu = struct { .name = "arm1020e", .llvm_name = "arm1020e", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm1020t = CpuModel{ .name = "arm1020t", .llvm_name = "arm1020t", .features = featureSet(&[_]Feature{ - .has_v5t, + .v5t, }), }; pub const arm1022e = CpuModel{ .name = "arm1022e", .llvm_name = "arm1022e", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm10e = CpuModel{ .name = "arm10e", .llvm_name = "arm10e", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm10tdmi = CpuModel{ .name = "arm10tdmi", .llvm_name = "arm10tdmi", .features = featureSet(&[_]Feature{ - .has_v5t, + .v5t, }), }; pub const arm1136j_s = CpuModel{ .name = "arm1136j_s", .llvm_name = "arm1136j-s", .features = featureSet(&[_]Feature{ - .has_v6, + .v6, }), }; pub const arm1136jf_s = CpuModel{ .name = "arm1136jf_s", .llvm_name = "arm1136jf-s", .features = featureSet(&[_]Feature{ - .has_v6, + .v6, .slowfpvmlx, .vfp2, }), @@ -1351,14 +1351,14 @@ pub const cpu = struct { .name = "arm1156t2_s", .llvm_name = "arm1156t2-s", .features = featureSet(&[_]Feature{ - .has_v6t2, + .v6t2, }), }; pub const arm1156t2f_s = CpuModel{ .name = "arm1156t2f_s", .llvm_name = "arm1156t2f-s", .features = featureSet(&[_]Feature{ - .has_v6t2, + .v6t2, .slowfpvmlx, .vfp2, }), @@ -1390,28 +1390,28 @@ pub const cpu = struct { .name = "arm710t", .llvm_name = "arm710t", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm720t = CpuModel{ .name = "arm720t", .llvm_name = "arm720t", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm7tdmi = CpuModel{ .name = "arm7tdmi", .llvm_name = "arm7tdmi", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm7tdmi_s = CpuModel{ .name = "arm7tdmi_s", .llvm_name = "arm7tdmi-s", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm8 = CpuModel{ @@ -1432,84 +1432,84 @@ pub const cpu = struct { .name = "arm9", .llvm_name = "arm9", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm920 = CpuModel{ .name = "arm920", .llvm_name = "arm920", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm920t = CpuModel{ .name = "arm920t", .llvm_name = "arm920t", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm922t = CpuModel{ .name = "arm922t", .llvm_name = "arm922t", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm926ej_s = CpuModel{ .name = "arm926ej_s", .llvm_name = "arm926ej-s", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm940t = CpuModel{ .name = "arm940t", .llvm_name = "arm940t", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const arm946e_s = CpuModel{ .name = "arm946e_s", .llvm_name = "arm946e-s", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm966e_s = CpuModel{ .name = "arm966e_s", .llvm_name = "arm966e-s", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm968e_s = CpuModel{ .name = "arm968e_s", .llvm_name = "arm968e-s", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm9e = CpuModel{ .name = "arm9e", .llvm_name = "arm9e", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const arm9tdmi = CpuModel{ .name = "arm9tdmi", .llvm_name = "arm9tdmi", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const baseline = CpuModel{ .name = "baseline", .llvm_name = "generic", .features = featureSet(&[_]Feature{ - .has_v6m, + .v6m, }), }; pub const cortex_a12 = CpuModel{ @@ -1561,22 +1561,22 @@ pub const cpu = struct { .name = "cortex_a32", .llvm_name = "cortex-a32", .features = featureSet(&[_]Feature{ - .has_v8, .crc, .crypto, .hwdiv, .hwdiv_arm, + .v8a, }), }; pub const cortex_a35 = CpuModel{ .name = "cortex_a35", .llvm_name = "cortex-a35", .features = featureSet(&[_]Feature{ - .has_v8, .crc, .crypto, .hwdiv, .hwdiv_arm, + .v8a, }), }; pub const cortex_a5 = CpuModel{ @@ -1597,7 +1597,7 @@ pub const cpu = struct { .name = "cortex_a53", .llvm_name = "cortex-a53", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .crc, .crypto, .fpao, @@ -1609,7 +1609,7 @@ pub const cpu = struct { .name = "cortex_a55", .llvm_name = "cortex-a55", .features = featureSet(&[_]Feature{ - .has_v8_2a, + .v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1619,7 +1619,7 @@ pub const cpu = struct { .name = "cortex_a57", .llvm_name = "cortex-a57", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .avoid_partial_cpsr, .cheap_predicable_cpsr, .crc, @@ -1649,7 +1649,7 @@ pub const cpu = struct { .name = "cortex_a72", .llvm_name = "cortex-a72", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .crc, .crypto, .hwdiv, @@ -1660,7 +1660,7 @@ pub const cpu = struct { .name = "cortex_a73", .llvm_name = "cortex-a73", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .crc, .crypto, .hwdiv, @@ -1671,7 +1671,7 @@ pub const cpu = struct { .name = "cortex_a75", .llvm_name = "cortex-a75", .features = featureSet(&[_]Feature{ - .has_v8_2a, + .v8_2a, .dotprod, .hwdiv, .hwdiv_arm, @@ -1682,7 +1682,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76", .features = featureSet(&[_]Feature{ .a76, - .has_v8_2a, + .v8_2a, .crc, .crypto, .dotprod, @@ -1696,7 +1696,7 @@ pub const cpu = struct { .llvm_name = "cortex-a76ae", .features = featureSet(&[_]Feature{ .a76, - .has_v8_2a, + .v8_2a, .crc, .crypto, .dotprod, @@ -1742,28 +1742,28 @@ pub const cpu = struct { .name = "cortex_m0", .llvm_name = "cortex-m0", .features = featureSet(&[_]Feature{ - .has_v6m, + .v6m, }), }; pub const cortex_m0plus = CpuModel{ .name = "cortex_m0plus", .llvm_name = "cortex-m0plus", .features = featureSet(&[_]Feature{ - .has_v6m, + .v6m, }), }; pub const cortex_m1 = CpuModel{ .name = "cortex_m1", .llvm_name = "cortex-m1", .features = featureSet(&[_]Feature{ - .has_v6m, + .v6m, }), }; pub const cortex_m23 = CpuModel{ .name = "cortex_m23", .llvm_name = "cortex-m23", .features = featureSet(&[_]Feature{ - .has_v8m, + .v8m, .no_movt, }), }; @@ -1783,7 +1783,7 @@ pub const cpu = struct { .name = "cortex_m33", .llvm_name = "cortex-m33", .features = featureSet(&[_]Feature{ - .has_v8m_main, + .v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1797,7 +1797,7 @@ pub const cpu = struct { .name = "cortex_m35p", .llvm_name = "cortex-m35p", .features = featureSet(&[_]Feature{ - .has_v8m_main, + .v8m_main, .dsp, .fp_armv8d16sp, .loop_align, @@ -1908,7 +1908,7 @@ pub const cpu = struct { .name = "cyclone", .llvm_name = "cyclone", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .avoid_movs_shop, .avoid_partial_cpsr, .crypto, @@ -1929,14 +1929,14 @@ pub const cpu = struct { .name = "ep9312", .llvm_name = "ep9312", .features = featureSet(&[_]Feature{ - .has_v4t, + .v4t, }), }; pub const exynos_m1 = CpuModel{ .name = "exynos_m1", .llvm_name = "exynos-m1", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .exynos, }), }; @@ -1944,7 +1944,7 @@ pub const cpu = struct { .name = "exynos_m2", .llvm_name = "exynos-m2", .features = featureSet(&[_]Feature{ - .has_v8, + .v8a, .exynos, }), }; @@ -1952,7 +1952,7 @@ pub const cpu = struct { .name = "exynos_m3", .llvm_name = "exynos-m3", .features = featureSet(&[_]Feature{ - .has_v8, + .v8_2a, .exynos, }), }; @@ -1960,7 +1960,7 @@ pub const cpu = struct { .name = "exynos_m4", .llvm_name = "exynos-m4", .features = featureSet(&[_]Feature{ - .has_v8_2a, + .v8_2a, .dotprod, .exynos, .fullfp16, @@ -1973,7 +1973,7 @@ pub const cpu = struct { .dotprod, .exynos, .fullfp16, - .has_v8_2a, + .v8_2a, }), }; pub const generic = CpuModel{ @@ -1985,7 +1985,7 @@ pub const cpu = struct { .name = "iwmmxt", .llvm_name = "iwmmxt", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; pub const krait = CpuModel{ @@ -2012,14 +2012,14 @@ pub const cpu = struct { .crypto, .hwdiv, .hwdiv_arm, - .has_v8, + .v8a, }), }; pub const mpcore = CpuModel{ .name = "mpcore", .llvm_name = "mpcore", .features = featureSet(&[_]Feature{ - .has_v6k, + .v6k, .slowfpvmlx, .vfp2, }), @@ -2028,14 +2028,14 @@ pub const cpu = struct { .name = "mpcorenovfp", .llvm_name = "mpcorenovfp", .features = featureSet(&[_]Feature{ - .has_v6k, + .v6k, }), }; pub const sc000 = CpuModel{ .name = "sc000", .llvm_name = "sc000", .features = featureSet(&[_]Feature{ - .has_v6m, + .v6m, }), }; pub const sc300 = CpuModel{ @@ -2108,7 +2108,7 @@ pub const cpu = struct { .name = "xscale", .llvm_name = "xscale", .features = featureSet(&[_]Feature{ - .has_v5te, + .v5te, }), }; }; From 71573584cdfb1ddb176681fcb7d1544cac7a72ca Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 13:34:55 -0500 Subject: [PATCH 082/109] std.Target.parse gives parsing diagnostics --- lib/std/target.zig | 40 ++++++++++++++++++++++++++++++++++---- src-self-hosted/stage2.zig | 35 ++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index a341fb3977..83d3dafbc2 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -727,18 +727,47 @@ pub const Target = union(enum) { /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features /// to remove from the set. cpu_features: []const u8 = "baseline", + + /// If this is provided, the function will populate some information about parsing failures, + /// so that user-friendly error messages can be delivered. + diagnostics: ?*Diagnostics = null, + + pub const Diagnostics = struct { + /// If the architecture was determined, this will be populated. + arch: ?Cpu.Arch = null, + + /// If the OS was determined, this will be populated. + os: ?Os = null, + + /// If the ABI was determined, this will be populated. + abi: ?Abi = null, + + /// If the CPU name was determined, this will be populated. + cpu_name: ?[]const u8 = null, + + /// If error.UnknownCpuFeature is returned, this will be populated. + unknown_feature_name: ?[]const u8 = null, + }; }; pub fn parse(args: ParseOptions) !Target { + var dummy_diags: ParseOptions.Diagnostics = undefined; + var diags = args.diagnostics orelse &dummy_diags; + var it = mem.separate(args.arch_os_abi, "-"); const arch_name = it.next() orelse return error.MissingArchitecture; - const os_name = it.next() orelse return error.MissingOperatingSystem; - const abi_name = it.next(); - if (it.next() != null) return error.UnexpectedExtraField; - const arch = try Cpu.Arch.parse(arch_name); + diags.arch = arch; + + const os_name = it.next() orelse return error.MissingOperatingSystem; const os = try Os.parse(os_name); + diags.os = os; + + const abi_name = it.next(); const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os); + diags.abi = abi; + + if (it.next() != null) return error.UnexpectedExtraField; const all_features = arch.allFeaturesList(); var index: usize = 0; @@ -749,6 +778,8 @@ pub const Target = union(enum) { index += 1; } const cpu_name = args.cpu_features[0..index]; + diags.cpu_name = cpu_name; + const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: { const cpu_model = try arch.parseCpuModel(cpu_name); @@ -775,6 +806,7 @@ pub const Target = union(enum) { break; } } else { + diags.unknown_feature_name = feature_name; return error.UnknownCpuFeature; } } diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index d99f436a75..3aea04b919 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -661,9 +661,7 @@ export fn stage2_target_parse( error.MissingOperatingSystem => return .MissingOperatingSystem, error.MissingArchitecture => return .MissingArchitecture, error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, - error.UnknownCpu => return .UnknownCpu, error.UnexpectedExtraField => return .SemanticAnalyzeFail, - error.UnknownCpuFeature => return .UnknownCpuFeature, }; return .None; } @@ -676,7 +674,38 @@ fn stage2TargetParse( const target: Target = if (zig_triple_oz) |zig_triple_z| blk: { const zig_triple = mem.toSliceConst(u8, zig_triple_z); const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline"; - break :blk try Target.parse(.{ .arch_os_abi = zig_triple, .cpu_features = mcpu }); + var diags: std.Target.ParseOptions.Diagnostics = .{}; + break :blk Target.parse(.{ + .arch_os_abi = zig_triple, + .cpu_features = mcpu, + .diagnostics = &diags, + }) catch |err| switch (err) { + error.UnknownCpu => { + std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ + diags.cpu_name.?, + @tagName(diags.arch.?), + }); + for (diags.arch.?.allCpuModels()) |cpu| { + std.debug.warn(" {}\n", .{cpu.name}); + } + process.exit(1); + }, + error.UnknownCpuFeature => { + std.debug.warn( + \\Unknown CPU feature: '{}' + \\Available CPU features for architecture '{}': + \\ + , .{ + diags.unknown_feature_name, + @tagName(diags.arch.?), + }); + for (diags.arch.?.allFeaturesList()) |feature| { + std.debug.warn(" {}: {}\n", .{ feature.name, feature.description }); + } + process.exit(1); + }, + else => |e| return e, + }; } else Target.Native; try stage1_target.fromTarget(target); From fdae5f5a07c043d9eeefe4933bcfbd03df581fde Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Thu, 20 Feb 2020 20:01:52 +0100 Subject: [PATCH 083/109] implement bytesAsSlice, sliceAsBytes --- lib/std/mem.zig | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 71be738def..f4c117e537 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1486,6 +1486,76 @@ test "bytesToValue" { testing.expect(deadbeef == @as(u32, 0xDEADBEEF)); } +//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. +fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { + if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) { + @compileError("expected []u8, passed " ++ @typeName(bytesType)); + } + + const alignment = comptime meta.alignment(bytesType); + + return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; +} + +pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) { + // let's not give an undefined pointer to @ptrCast + // it may be equal to zero and fail a null check + if (bytes.len == 0) { + return &[0]T{}; + } + + const bytesType = @TypeOf(bytes); + const alignment = comptime meta.alignment(bytesType); + + const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T; + + return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; +} + +test "bytesAsSlice" { + const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF }; + const slice = bytesAsSlice(u16, bytes[0..]); + testing.expect(slice.len == 2); + testing.expect(bigToNative(u16, slice[0]) == 0xDEAD); + testing.expect(bigToNative(u16, slice[1]) == 0xBEEF); +} + +//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. +fn SliceAsBytesReturnType(comptime sliceType: type) type { + if (comptime !trait.isSlice(sliceType)) { + @compileError("expected []T, passed " ++ @typeName(sliceType)); + } + + const alignment = comptime meta.alignment(sliceType); + + return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; +} + +pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { + // let's not give an undefined pointer to @ptrCast + // it may be equal to zero and fail a null check + if (slice.len == 0) { + return &[0]u8{}; + } + + const sliceType = @TypeOf(slice); + const alignment = comptime meta.alignment(sliceType); + + const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8; + + return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))]; +} + +test "sliceAsBytes" { + const bytes = [_]u16{ 0xDEAD, 0xBEEF }; + const slice = sliceAsBytes(bytes[0..]); + testing.expect(slice.len == 4); + testing.expect(eql(u8, slice, switch (builtin.endian) { + .Big => "\xDE\xAD\xBE\xEF", + .Little => "\xAD\xDE\xEF\xBE", + })); +} + fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { if (trait.isConstPtr(T)) return *const [length]meta.Child(meta.Child(T)); From 783e8ad0319b950a1d42d5a93e4fbb9e9df1be10 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Fri, 21 Feb 2020 19:46:53 +0100 Subject: [PATCH 084/109] remove @bytesToSlice, @sliceToBytes from std lib --- lib/std/crypto/gimli.zig | 4 ++-- lib/std/cstr.zig | 2 +- lib/std/fifo.zig | 8 ++++---- lib/std/fs/watch.zig | 2 +- lib/std/heap.zig | 6 +++--- lib/std/io/in_stream.zig | 2 +- lib/std/mem.zig | 12 ++++++------ lib/std/net.zig | 4 ++-- lib/std/os.zig | 2 +- lib/std/process.zig | 2 +- lib/std/unicode.zig | 12 ++++++------ 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig index ed2c5e764f..30304f59cf 100644 --- a/lib/std/crypto/gimli.zig +++ b/lib/std/crypto/gimli.zig @@ -24,11 +24,11 @@ pub const State = struct { const Self = @This(); pub fn toSlice(self: *Self) []u8 { - return @sliceToBytes(self.data[0..]); + return mem.sliceAsBytes(self.data[0..]); } pub fn toSliceConst(self: *Self) []const u8 { - return @sliceToBytes(self.data[0..]); + return mem.sliceAsBytes(self.data[0..]); } pub fn permute(self: *Self) void { diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig index 5d16e9387b..765e0a45cf 100644 --- a/lib/std/cstr.zig +++ b/lib/std/cstr.zig @@ -72,7 +72,7 @@ pub const NullTerminated2DArray = struct { errdefer allocator.free(buf); var write_index = index_size; - const index_buf = @bytesToSlice(?[*]u8, buf); + const index_buf = mem.bytesAsSlice(?[*]u8, buf); var i: usize = 0; for (slices) |slice| { diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig index ac8589f2ce..85a0e4c9d2 100644 --- a/lib/std/fifo.zig +++ b/lib/std/fifo.zig @@ -101,7 +101,7 @@ pub fn LinearFifo( } } { // set unused area to undefined - const unused = @sliceToBytes(self.buf[self.count..]); + const unused = mem.sliceAsBytes(self.buf[self.count..]); @memset(unused.ptr, undefined, unused.len); } } @@ -166,12 +166,12 @@ pub fn LinearFifo( { // set old range to undefined. Note: may be wrapped around const slice = self.readableSliceMut(0); if (slice.len >= count) { - const unused = @sliceToBytes(slice[0..count]); + const unused = mem.sliceAsBytes(slice[0..count]); @memset(unused.ptr, undefined, unused.len); } else { - const unused = @sliceToBytes(slice[0..]); + const unused = mem.sliceAsBytes(slice[0..]); @memset(unused.ptr, undefined, unused.len); - const unused2 = @sliceToBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]); + const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]); @memset(unused2.ptr, undefined, unused2.len); } } diff --git a/lib/std/fs/watch.zig b/lib/std/fs/watch.zig index c904f110e2..0ff8c47ecf 100644 --- a/lib/std/fs/watch.zig +++ b/lib/std/fs/watch.zig @@ -26,7 +26,7 @@ fn eqlString(a: []const u16, b: []const u16) bool { } fn hashString(s: []const u16) u32 { - return @truncate(u32, std.hash.Wyhash.hash(0, @sliceToBytes(s))); + return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceAsBytes(s))); } const WatchEventError = error{ diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 1bce45081d..135d7297a2 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -283,14 +283,14 @@ const WasmPageAllocator = struct { fn getBit(self: FreeBlock, idx: usize) PageStatus { const bit_offset = 0; - return @intToEnum(PageStatus, Io.get(@sliceToBytes(self.data), idx, bit_offset)); + return @intToEnum(PageStatus, Io.get(mem.sliceAsBytes(self.data), idx, bit_offset)); } fn setBits(self: FreeBlock, start_idx: usize, len: usize, val: PageStatus) void { const bit_offset = 0; var i: usize = 0; while (i < len) : (i += 1) { - Io.set(@sliceToBytes(self.data), start_idx + i, bit_offset, @enumToInt(val)); + Io.set(mem.sliceAsBytes(self.data), start_idx + i, bit_offset, @enumToInt(val)); } } @@ -552,7 +552,7 @@ pub const ArenaAllocator = struct { if (len >= actual_min_size) break; } const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len); - const buf_node_slice = @bytesToSlice(BufNode, buf[0..@sizeOf(BufNode)]); + const buf_node_slice = mem.bytesAsSlice(BufNode, buf[0..@sizeOf(BufNode)]); const buf_node = &buf_node_slice[0]; buf_node.* = BufNode{ .data = buf, diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig index ab02d20eed..4f3bac3c21 100644 --- a/lib/std/io/in_stream.zig +++ b/lib/std/io/in_stream.zig @@ -235,7 +235,7 @@ pub fn InStream(comptime ReadError: type) type { // Only extern and packed structs have defined in-memory layout. comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto); var res: [1]T = undefined; - try self.readNoEof(@sliceToBytes(res[0..])); + try self.readNoEof(mem.sliceAsBytes(res[0..])); return res[0]; } diff --git a/lib/std/mem.zig b/lib/std/mem.zig index f4c117e537..01e289988b 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -132,7 +132,7 @@ pub const Allocator = struct { // their own frame with @Frame(func). return @intToPtr([*]T, @ptrToInt(byte_slice.ptr))[0..n]; } else { - return @bytesToSlice(T, @alignCast(a, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(a, byte_slice)); } } @@ -173,7 +173,7 @@ pub const Allocator = struct { return @as([*]align(new_alignment) T, undefined)[0..0]; } - const old_byte_slice = @sliceToBytes(old_mem); + const old_byte_slice = mem.sliceAsBytes(old_mem); const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); @@ -181,7 +181,7 @@ pub const Allocator = struct { if (new_n > old_mem.len) { @memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len); } - return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice)); } /// Prefer calling realloc to shrink if you can tolerate failure, such as @@ -221,18 +221,18 @@ pub const Allocator = struct { // new_n <= old_mem.len and the multiplication didn't overflow for that operation. const byte_count = @sizeOf(T) * new_n; - const old_byte_slice = @sliceToBytes(old_mem); + const old_byte_slice = mem.sliceAsBytes(old_mem); @memset(old_byte_slice.ptr + byte_count, undefined, old_byte_slice.len - byte_count); const byte_slice = self.shrinkFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); assert(byte_slice.len == byte_count); - return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice)); } /// Free an array allocated with `alloc`. To free a single item, /// see `destroy`. pub fn free(self: *Allocator, memory: var) void { const Slice = @typeInfo(@TypeOf(memory)).Pointer; - const bytes = @sliceToBytes(memory); + const bytes = mem.sliceAsBytes(memory); const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0; if (bytes_len == 0) return; const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr)); diff --git a/lib/std/net.zig b/lib/std/net.zig index 27056bf1db..19092f25ca 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -120,7 +120,7 @@ pub const Address = extern union { ip_slice[10] = 0xff; ip_slice[11] = 0xff; - const ptr = @sliceToBytes(@as(*const [1]u32, &addr)[0..]); + const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]); ip_slice[12] = ptr[0]; ip_slice[13] = ptr[1]; @@ -164,7 +164,7 @@ pub const Address = extern union { .addr = undefined, }, }; - const out_ptr = @sliceToBytes(@as(*[1]u32, &result.in.addr)[0..]); + const out_ptr = mem.sliceAsBytes(@as(*[1]u32, &result.in.addr)[0..]); var x: u8 = 0; var index: u8 = 0; diff --git a/lib/std/os.zig b/lib/std/os.zig index 0f492a25f2..038839eeaf 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1778,7 +1778,7 @@ pub fn isCygwinPty(handle: fd_t) bool { const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)]; - const name_wide = @bytesToSlice(u16, name_bytes); + const name_wide = mem.bytesAsSlice(u16, name_bytes); return mem.indexOf(u16, name_wide, &[_]u16{ 'm', 's', 'y', 's', '-' }) != null or mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; } diff --git a/lib/std/process.zig b/lib/std/process.zig index 89307b44da..d9ec0a056d 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -436,7 +436,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); errdefer allocator.free(buf); - const result_slice_list = @bytesToSlice([]u8, buf[0..slice_list_bytes]); + const result_slice_list = mem.bytesAsSlice([]u8, buf[0..slice_list_bytes]); const result_contents = buf[slice_list_bytes..]; mem.copy(u8, result_contents, contents_slice); diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index ed24f83c33..85c91602d0 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -243,7 +243,7 @@ pub const Utf16LeIterator = struct { pub fn init(s: []const u16) Utf16LeIterator { return Utf16LeIterator{ - .bytes = @sliceToBytes(s), + .bytes = mem.sliceAsBytes(s), .i = 0, }; } @@ -496,7 +496,7 @@ pub fn utf16leToUtf8(utf8: []u8, utf16le: []const u16) !usize { test "utf16leToUtf8" { var utf16le: [2]u16 = undefined; - const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); + const utf16le_as_bytes = mem.sliceAsBytes(utf16le[0..]); { mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); @@ -606,12 +606,12 @@ test "utf8ToUtf16Le" { { const length = try utf8ToUtf16Le(utf16le[0..], "𐐷"); testing.expectEqual(@as(usize, 2), length); - testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16le[0..])); + testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16le[0..])); } { const length = try utf8ToUtf16Le(utf16le[0..], "\u{10FFFF}"); testing.expectEqual(@as(usize, 2), length); - testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16le[0..])); + testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16le[0..])); } } @@ -619,13 +619,13 @@ test "utf8ToUtf16LeWithNull" { { const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "𐐷"); defer testing.allocator.free(utf16); - testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16[0..])); testing.expect(utf16[2] == 0); } { const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "\u{10FFFF}"); defer testing.allocator.free(utf16); - testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16[0..])); testing.expect(utf16[2] == 0); } } From dff7ca6784d2cf8e46fcfffb5e5e2eb537b71b4d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 14:19:50 -0500 Subject: [PATCH 085/109] annotate TODO comment with bug tracker link --- lib/std/net.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/net.zig b/lib/std/net.zig index 27056bf1db..b60f25e60c 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -18,7 +18,7 @@ pub const Address = extern union { in6: os.sockaddr_in6, un: if (has_unix_sockets) os.sockaddr_un else void, - // TODO this crashed the compiler + // TODO this crashed the compiler. https://github.com/ziglang/zig/issues/3512 //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0); pub fn parseIp(name: []const u8, port: u16) !Address { From 6aecc268fd55d19ef096b320f78343c69c1ed09c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 15:20:36 -0500 Subject: [PATCH 086/109] remove the allocator from std.event.Loop closes #3539 --- lib/std/event/loop.zig | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 8000ab88c6..085e56fc15 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -12,15 +12,18 @@ const maxInt = std.math.maxInt; const Thread = std.Thread; pub const Loop = struct { - allocator: *mem.Allocator, next_tick_queue: std.atomic.Queue(anyframe), os_data: OsData, final_resume_node: ResumeNode, pending_event_count: usize, extra_threads: []*Thread, - // pre-allocated eventfds. all permanently active. - // this is how we send promises to be resumed on other threads. + /// For resources that have the same lifetime as the `Loop`. + /// This is only used by `Loop` for the thread pool and associated resources. + arena: std.heap.ArenaAllocator, + + /// Pre-allocated eventfds. All permanently active. + /// This is how `Loop` sends promises to be resumed on other threads. available_eventfd_resume_nodes: std.atomic.Stack(ResumeNode.EventFd), eventfd_resume_nodes: []std.atomic.Stack(ResumeNode.EventFd).Node, @@ -127,11 +130,9 @@ pub const Loop = struct { /// Thread count is the total thread count. The thread pool size will be /// max(thread_count - 1, 0) pub fn initThreadPool(self: *Loop, thread_count: usize) !void { - // TODO: https://github.com/ziglang/zig/issues/3539 - const allocator = std.heap.page_allocator; self.* = Loop{ + .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator), .pending_event_count = 1, - .allocator = allocator, .os_data = undefined, .next_tick_queue = std.atomic.Queue(anyframe).init(), .extra_threads = undefined, @@ -143,17 +144,17 @@ pub const Loop = struct { .overlapped = ResumeNode.overlapped_init, }, }; + errdefer self.arena.deinit(); + // We need at least one of these in case the fs thread wants to use onNextTick const extra_thread_count = thread_count - 1; const resume_node_count = std.math.max(extra_thread_count, 1); - self.eventfd_resume_nodes = try self.allocator.alloc( + self.eventfd_resume_nodes = try self.arena.allocator.alloc( std.atomic.Stack(ResumeNode.EventFd).Node, resume_node_count, ); - errdefer self.allocator.free(self.eventfd_resume_nodes); - self.extra_threads = try self.allocator.alloc(*Thread, extra_thread_count); - errdefer self.allocator.free(self.extra_threads); + self.extra_threads = try self.arena.allocator.alloc(*Thread, extra_thread_count); try self.initOsData(extra_thread_count); errdefer self.deinitOsData(); @@ -161,7 +162,8 @@ pub const Loop = struct { pub fn deinit(self: *Loop) void { self.deinitOsData(); - self.allocator.free(self.extra_threads); + self.arena.deinit(); + self.* = undefined; } const InitOsDataError = os.EpollCreateError || mem.Allocator.Error || os.EventFdError || @@ -407,7 +409,6 @@ pub const Loop = struct { noasync os.close(self.os_data.final_eventfd); while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd); noasync os.close(self.os_data.epollfd); - self.allocator.free(self.eventfd_resume_nodes); }, .macosx, .freebsd, .netbsd, .dragonfly => { noasync os.close(self.os_data.kqfd); From 570973761a219cde2e7ab0b3a22fe0696a9b1e3e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 15:30:38 -0500 Subject: [PATCH 087/109] add regression test for already fixed bug closes #3586 --- test/stage1/behavior.zig | 1 + test/stage1/behavior/bugs/3586.zig | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 test/stage1/behavior/bugs/3586.zig diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index ea8720d98c..bb801ace1f 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -38,6 +38,7 @@ comptime { _ = @import("behavior/bugs/3112.zig"); _ = @import("behavior/bugs/3367.zig"); _ = @import("behavior/bugs/3384.zig"); + _ = @import("behavior/bugs/3586.zig"); _ = @import("behavior/bugs/3742.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); diff --git a/test/stage1/behavior/bugs/3586.zig b/test/stage1/behavior/bugs/3586.zig new file mode 100644 index 0000000000..7bb1ba5d31 --- /dev/null +++ b/test/stage1/behavior/bugs/3586.zig @@ -0,0 +1,11 @@ +const NoteParams = struct {}; + +const Container = struct { + params: ?NoteParams, +}; + +test "fixed" { + var ctr = Container{ + .params = NoteParams{}, + }; +} From 6305ce828b0685ceb646fae87a963f034d3bcdf0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 19:22:50 -0500 Subject: [PATCH 088/109] fix regression in standardTargetOptions --- lib/std/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 43cc4a2150..6e9031ee31 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -535,7 +535,7 @@ pub const Builder = struct { return Target.Native; } else { const target_str = self.option([]const u8, "target", "the target to build for") orelse return Target.Native; - return Target.parse(target_str) catch unreachable; // TODO better error message for bad target + return Target.parse(.{ .arch_os_abi = target_str }) catch unreachable; // TODO better error message for bad target } } From dca19b67573dc46260b318e9253370fbc628834d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 21 Feb 2020 20:48:50 -0500 Subject: [PATCH 089/109] fix regression in detecting native glibc version closes #4519 --- src/main.cpp | 8 ++++++++ src/target.cpp | 6 ------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d6148d4587..a4ab719123 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -992,6 +992,14 @@ static int main0(int argc, char **argv) { } } else { target_init_default_glibc_version(&target); +#if defined(ZIG_OS_LINUX) + if (target.is_native) { + // TODO self-host glibc version detection, and then this logic can go away + if ((err = glibc_detect_native_version(target.glibc_version))) { + // Fall back to the default version. + } + } +#endif } } else if (target_glibc != nullptr) { fprintf(stderr, "'%s' is not a glibc-compatible target", target_string); diff --git a/src/target.cpp b/src/target.cpp index 0a3fb3da5f..8a68afbd83 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -467,12 +467,6 @@ void get_native_target(ZigTarget *target) { if (target_is_glibc(target)) { target->glibc_version = heap::c_allocator.create(); target_init_default_glibc_version(target); -#ifdef ZIG_OS_LINUX - Error err; - if ((err = glibc_detect_native_version(target->glibc_version))) { - // Fall back to the default version. - } -#endif } } From 0cd89e9176ab36fc5e267120dc4d75cb79d32684 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Feb 2020 13:43:48 -0500 Subject: [PATCH 090/109] std.os.execvpeZ_expandArg0: fix not restoring argv[0] This function expands argv[0] into the absolute path resolved with PATH environment variable before making the execve syscall. However, in case the execve fails, e.g. with ENOENT, it did not restore argv to how it was before it was passed in. This resulted in the caller performing an invalid free. This commit also adds verbose debug info when native system C compiler detection fails. See #4521. --- lib/std/os.zig | 9 ++ src-self-hosted/libc_installation.zig | 152 ++++++++++++++++++++------ src-self-hosted/stage2.zig | 5 +- 3 files changed, 130 insertions(+), 36 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 0f492a25f2..766b678c46 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -955,6 +955,7 @@ pub const Arg0Expand = enum { /// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable, /// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall. +/// If this function returns with an error, `argv[0]` will be restored to the value it was when it was passed in. pub fn execvpeZ_expandArg0( comptime arg0_expand: Arg0Expand, file: [*:0]const u8, @@ -972,6 +973,14 @@ pub fn execvpeZ_expandArg0( var it = mem.tokenize(PATH, ":"); var seen_eacces = false; var err: ExecveError = undefined; + + // In case of expanding arg0 we must put it back if we return with an error. + const prev_arg0 = child_argv[0]; + defer switch (arg0_expand) { + .expand => child_argv[0] = prev_arg0, + .no_expand => {}, + }; + while (it.next()) |search_path| { if (path_buf.len < search_path.len + file_slice.len + 1) return error.NameTooLong; mem.copy(u8, &path_buf, search_path); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 8d7bd1fd4d..85740240ab 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -174,16 +174,23 @@ pub const LibCInstallation = struct { }); } + pub const FindNativeOptions = struct { + allocator: *Allocator, + + /// If enabled, will print human-friendly errors to stderr. + verbose: bool = false, + }; + /// Finds the default, native libc. - pub fn findNative(allocator: *Allocator) FindError!LibCInstallation { + pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { var self: LibCInstallation = .{}; if (is_windows) { if (is_gnu) { var batch = Batch(FindError!void, 3, .auto_async).init(); - batch.add(&async self.findNativeIncludeDirPosix(allocator)); - batch.add(&async self.findNativeCrtDirPosix(allocator)); - batch.add(&async self.findNativeStaticCrtDirPosix(allocator)); + batch.add(&async self.findNativeIncludeDirPosix(args)); + batch.add(&async self.findNativeCrtDirPosix(args)); + batch.add(&async self.findNativeStaticCrtDirPosix(args)); try batch.wait(); } else { var sdk: *ZigWindowsSDK = undefined; @@ -192,11 +199,11 @@ pub const LibCInstallation = struct { defer zig_free_windows_sdk(sdk); var batch = Batch(FindError!void, 5, .auto_async).init(); - batch.add(&async self.findNativeMsvcIncludeDir(allocator, sdk)); - batch.add(&async self.findNativeMsvcLibDir(allocator, sdk)); - batch.add(&async self.findNativeKernel32LibDir(allocator, sdk)); - batch.add(&async self.findNativeIncludeDirWindows(allocator, sdk)); - batch.add(&async self.findNativeCrtDirWindows(allocator, sdk)); + batch.add(&async self.findNativeMsvcIncludeDir(args, sdk)); + batch.add(&async self.findNativeMsvcLibDir(args, sdk)); + batch.add(&async self.findNativeKernel32LibDir(args, sdk)); + batch.add(&async self.findNativeIncludeDirWindows(args, sdk)); + batch.add(&async self.findNativeCrtDirWindows(args, sdk)); try batch.wait(); }, .OutOfMemory => return error.OutOfMemory, @@ -208,11 +215,11 @@ pub const LibCInstallation = struct { try blk: { var batch = Batch(FindError!void, 2, .auto_async).init(); errdefer batch.wait() catch {}; - batch.add(&async self.findNativeIncludeDirPosix(allocator)); + batch.add(&async self.findNativeIncludeDirPosix(args)); if (is_freebsd or is_netbsd) { - self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib"); + self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"); } else if (is_linux or is_dragonfly) { - batch.add(&async self.findNativeCrtDirPosix(allocator)); + batch.add(&async self.findNativeCrtDirPosix(args)); } break :blk batch.wait(); }; @@ -231,7 +238,8 @@ pub const LibCInstallation = struct { self.* = undefined; } - fn findNativeIncludeDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { + fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { + const allocator = args.allocator; const dev_null = if (is_windows) "nul" else "/dev/null"; const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; const argv = [_][]const u8{ @@ -252,15 +260,24 @@ pub const LibCInstallation = struct { .expand_arg0 = .expand, }) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => return error.UnableToSpawnCCompiler, + else => { + printVerboseInvocation(&argv, null, args.verbose, null); + return error.UnableToSpawnCCompiler; + }, }; defer { allocator.free(exec_res.stdout); allocator.free(exec_res.stderr); } switch (exec_res.term) { - .Exited => |code| if (code != 0) return error.CCompilerExitCode, - else => return error.CCompilerCrashed, + .Exited => |code| if (code != 0) { + printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr); + return error.CCompilerExitCode; + }, + else => { + printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr); + return error.CCompilerCrashed; + }, } var it = std.mem.tokenize(exec_res.stderr, "\n\r"); @@ -322,9 +339,11 @@ pub const LibCInstallation = struct { fn findNativeIncludeDirWindows( self: *LibCInstallation, - allocator: *Allocator, + args: FindNativeOptions, sdk: *ZigWindowsSDK, ) FindError!void { + const allocator = args.allocator; + var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -358,7 +377,13 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - fn findNativeCrtDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void { + fn findNativeCrtDirWindows( + self: *LibCInstallation, + args: FindNativeOptions, + sdk: *ZigWindowsSDK, + ) FindError!void { + const allocator = args.allocator; + var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -398,15 +423,31 @@ pub const LibCInstallation = struct { return error.LibCRuntimeNotFound; } - fn findNativeCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { - self.crt_dir = try ccPrintFileName(allocator, "crt1.o", .only_dir); + fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { + self.crt_dir = try ccPrintFileName(.{ + .allocator = args.allocator, + .search_basename = "crt1.o", + .want_dirname = .only_dir, + .verbose = args.verbose, + }); } - fn findNativeStaticCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void { - self.static_crt_dir = try ccPrintFileName(allocator, "crtbegin.o", .only_dir); + fn findNativeStaticCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { + self.static_crt_dir = try ccPrintFileName(.{ + .allocator = args.allocator, + .search_basename = "crtbegin.o", + .want_dirname = .only_dir, + .verbose = args.verbose, + }); } - fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void { + fn findNativeKernel32LibDir( + self: *LibCInstallation, + args: FindNativeOptions, + sdk: *ZigWindowsSDK, + ) FindError!void { + const allocator = args.allocator; + var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); @@ -448,9 +489,11 @@ pub const LibCInstallation = struct { fn findNativeMsvcIncludeDir( self: *LibCInstallation, - allocator: *Allocator, + args: FindNativeOptions, sdk: *ZigWindowsSDK, ) FindError!void { + const allocator = args.allocator; + const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCStdLibHeaderNotFound; const msvc_lib_dir = msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]; const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; @@ -481,9 +524,10 @@ pub const LibCInstallation = struct { fn findNativeMsvcLibDir( self: *LibCInstallation, - allocator: *Allocator, + args: FindNativeOptions, sdk: *ZigWindowsSDK, ) FindError!void { + const allocator = args.allocator; const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCRuntimeNotFound; self.msvc_lib_dir = try std.mem.dupeZ(allocator, u8, msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); } @@ -491,14 +535,19 @@ pub const LibCInstallation = struct { const default_cc_exe = if (is_windows) "cc.exe" else "cc"; -/// caller owns returned memory -fn ccPrintFileName( +pub const CCPrintFileNameOptions = struct { allocator: *Allocator, - o_file: []const u8, + search_basename: []const u8, want_dirname: enum { full_path, only_dir }, -) ![:0]u8 { + verbose: bool = false, +}; + +/// caller owns returned memory +fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { + const allocator = args.allocator; + const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; - const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{o_file}); + const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename}); defer allocator.free(arg1); const argv = [_][]const u8{ cc_exe, arg1 }; @@ -520,16 +569,22 @@ fn ccPrintFileName( allocator.free(exec_res.stderr); } switch (exec_res.term) { - .Exited => |code| if (code != 0) return error.CCompilerExitCode, - else => return error.CCompilerCrashed, + .Exited => |code| if (code != 0) { + printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr); + return error.CCompilerExitCode; + }, + else => { + printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr); + return error.CCompilerCrashed; + }, } var it = std.mem.tokenize(exec_res.stdout, "\n\r"); const line = it.next() orelse return error.LibCRuntimeNotFound; // When this command fails, it returns exit code 0 and duplicates the input file name. // So we detect failure by checking if the output matches exactly the input. - if (std.mem.eql(u8, line, o_file)) return error.LibCRuntimeNotFound; - switch (want_dirname) { + if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound; + switch (args.want_dirname) { .full_path => return std.mem.dupeZ(allocator, u8, line), .only_dir => { const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; @@ -538,6 +593,29 @@ fn ccPrintFileName( } } +fn printVerboseInvocation( + argv: []const []const u8, + search_basename: ?[]const u8, + verbose: bool, + stderr: ?[]const u8, +) void { + if (!verbose) return; + + if (search_basename) |s| { + std.debug.warn("Zig attempted to find the file '{}' by executing this command:\n", .{s}); + } else { + std.debug.warn("Zig attempted to find the path to native system libc headers by executing this command:\n", .{}); + } + for (argv) |arg, i| { + if (i != 0) std.debug.warn(" ", .{}); + std.debug.warn("{}", .{arg}); + } + std.debug.warn("\n", .{}); + if (stderr) |s| { + std.debug.warn("Output:\n==========\n{}\n==========\n", .{s}); + } +} + /// Caller owns returned memory. pub fn detectNativeDynamicLinker(allocator: *Allocator) error{ OutOfMemory, @@ -617,7 +695,11 @@ pub fn detectNativeDynamicLinker(allocator: *Allocator) error{ for (ld_info_list.toSlice()) |ld_info| { const standard_ld_basename = fs.path.basename(ld_info.ld_path); - const full_ld_path = ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) { + const full_ld_path = ccPrintFileName(.{ + .allocator = allocator, + .search_basename = standard_ld_basename, + .want_dirname = .full_path, + }) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.LibCRuntimeNotFound, error.CCompilerExitCode, diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 3aea04b919..dacdb86bcd 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -899,7 +899,10 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [ // ABI warning export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { - var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { + var libc = LibCInstallation.findNative(.{ + .allocator = std.heap.c_allocator, + .verbose = true, + }) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, error.FileSystem => return .FileSystem, error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, From 936d0b18b116ea126893d2f165f9be72f8bef845 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Feb 2020 15:59:13 -0500 Subject: [PATCH 091/109] update std lib to integrate with libc for environ closes #3511 --- lib/std/c.zig | 2 ++ lib/std/os.zig | 49 ++++++++++++++++++++++++++++++++++++++++----- lib/std/process.zig | 33 +++++++++++++++++++++--------- lib/std/start.zig | 10 +++++++-- src/os.cpp | 6 +----- 5 files changed, 78 insertions(+), 22 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 93c6c24664..f6c0e07dbd 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -62,6 +62,8 @@ pub fn versionCheck(glibc_version: builtin.Version) type { }; } +pub extern "c" var environ: [*:null]?[*:0]u8; + pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE; pub extern "c" fn fclose(stream: *FILE) c_int; pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; diff --git a/lib/std/os.zig b/lib/std/os.zig index 766b678c46..a4f148ae00 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -70,6 +70,8 @@ else switch (builtin.os) { pub usingnamespace @import("os/bits.zig"); /// See also `getenv`. Populated by startup code before main(). +/// TODO this is a footgun because the value will be undefined when using `zig build-lib`. +/// https://github.com/ziglang/zig/issues/4524 pub var environ: [][*:0]u8 = undefined; /// Populated by startup code before main(). @@ -922,7 +924,11 @@ pub const execveC = execveZ; /// Like `execve` except the parameters are null-terminated, /// matching the syscall API on all targets. This removes the need for an allocator. /// This function ignores PATH environment variable. See `execvpeZ` for that. -pub fn execveZ(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { +pub fn execveZ( + path: [*:0]const u8, + child_argv: [*:null]const ?[*:0]const u8, + envp: [*:null]const ?[*:0]const u8, +) ExecveError { switch (errno(system.execve(path, child_argv, envp))) { 0 => unreachable, EFAULT => unreachable, @@ -966,7 +972,7 @@ pub fn execvpeZ_expandArg0( envp: [*:null]const ?[*:0]const u8, ) ExecveError { const file_slice = mem.toSliceConst(u8, file); - if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp); + if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp); const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; var path_buf: [MAX_PATH_BYTES]u8 = undefined; @@ -993,7 +999,7 @@ pub fn execvpeZ_expandArg0( .expand => child_argv[0] = full_path, .no_expand => {}, } - err = execveC(full_path, child_argv, envp); + err = execveZ(full_path, child_argv, envp); switch (err) { error.AccessDenied => seen_eacces = true, error.FileNotFound, error.NotDir => {}, @@ -1007,7 +1013,7 @@ pub fn execvpeZ_expandArg0( /// Like `execvpe` except the parameters are null-terminated, /// matching the syscall API on all targets. This removes the need for an allocator. /// This function also uses the PATH environment variable to get the full path to the executable. -/// If `file` is an absolute path, this is the same as `execveC`. +/// If `file` is an absolute path, this is the same as `execveZ`. pub fn execvpeZ( file: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, @@ -1097,8 +1103,37 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) /// Get an environment variable. /// See also `getenvZ`. -/// TODO make this go through libc when we have it pub fn getenv(key: []const u8) ?[]const u8 { + if (builtin.os == .windows) { + // TODO update this to use the ProcessEnvironmentBlock + @compileError("TODO implement std.os.getenv for Windows"); + } + if (builtin.link_libc) { + var small_key_buf: [64]u8 = undefined; + if (key.len < small_key_buf.len) { + mem.copy(u8, &small_key_buf, key); + small_key_buf[key.len] = 0; + const key0 = small_key_buf[0..key.len :0]; + return getenvZ(key0); + } + // Search the entire `environ` because we don't have a null terminated pointer. + var ptr = std.c.environ; + while (ptr.*) |line| : (ptr += 1) { + var line_i: usize = 0; + while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} + const this_key = line[0..line_i]; + + if (!mem.eql(u8, this_key, key)) continue; + + var end_i: usize = line_i; + while (line[end_i] != 0) : (end_i += 1) {} + const value = line[line_i + 1 .. end_i]; + + return value; + } + return null; + } + // TODO see https://github.com/ziglang/zig/issues/4524 for (environ) |ptr| { var line_i: usize = 0; while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} @@ -1120,6 +1155,10 @@ pub const getenvC = getenvZ; /// Get an environment variable with a null-terminated name. /// See also `getenv`. pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { + if (builtin.os == .windows) { + // TODO update this to use the ProcessEnvironmentBlock + @compileError("TODO implement std.os.getenv for Windows"); + } if (builtin.link_libc) { const value = system.getenv(key) orelse return null; return mem.toSliceConst(u8, value); diff --git a/lib/std/process.zig b/lib/std/process.zig index 89307b44da..ba124ff262 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1,5 +1,5 @@ -const builtin = @import("builtin"); const std = @import("std.zig"); +const builtin = std.builtin; const os = std.os; const fs = std.fs; const BufMap = std.BufMap; @@ -31,13 +31,13 @@ test "getCwdAlloc" { testing.allocator.free(cwd); } -/// Caller must free result when done. -/// TODO make this go through libc when we have it +/// Caller owns resulting `BufMap`. pub fn getEnvMap(allocator: *Allocator) !BufMap { var result = BufMap.init(allocator); errdefer result.deinit(); if (builtin.os == .windows) { + // TODO update this to use the ProcessEnvironmentBlock const ptr = try os.windows.GetEnvironmentStringsW(); defer os.windows.FreeEnvironmentStringsW(ptr); @@ -95,15 +95,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { } } return result; - } else { - for (os.environ) |ptr| { + } else if (builtin.link_libc) { + var ptr = std.c.environ; + while (ptr.*) |line| : (ptr += 1) { var line_i: usize = 0; - while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} - const key = ptr[0..line_i]; + while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} + const key = line[0..line_i]; var end_i: usize = line_i; - while (ptr[end_i] != 0) : (end_i += 1) {} - const value = ptr[line_i + 1 .. end_i]; + while (line[end_i] != 0) : (end_i += 1) {} + const value = line[line_i + 1 .. end_i]; + + try result.set(key, value); + } + return result; + } else { + for (os.environ) |line| { + var line_i: usize = 0; + while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} + const key = line[0..line_i]; + + var end_i: usize = line_i; + while (line[end_i] != 0) : (end_i += 1) {} + const value = line[line_i + 1 .. end_i]; try result.set(key, value); } @@ -125,7 +139,6 @@ pub const GetEnvVarOwnedError = error{ }; /// Caller must free returned memory. -/// TODO make this go through libc when we have it pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { if (builtin.os == .windows) { const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); diff --git a/lib/std/start.zig b/lib/std/start.zig index e6c21ba9b8..b58b6e8144 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -21,7 +21,9 @@ comptime { @export(main, .{ .name = "main", .linkage = .Weak }); } } else if (builtin.os == .windows) { - if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) { + if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and + !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) + { @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); } } else if (builtin.os == .uefi) { @@ -34,7 +36,11 @@ comptime { } } -fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, lpReserved: std.os.windows.LPVOID) callconv(.Stdcall) std.os.windows.BOOL { +fn _DllMainCRTStartup( + hinstDLL: std.os.windows.HINSTANCE, + fdwReason: std.os.windows.DWORD, + lpReserved: std.os.windows.LPVOID, +) callconv(.Stdcall) std.os.windows.BOOL { if (@hasDecl(root, "DllMain")) { return root.DllMain(hinstDLL, fdwReason, lpReserved); } diff --git a/src/os.cpp b/src/os.cpp index 268e812050..8e0bcc433b 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock; #include #include -// Apple doesn't provide the environ global variable -#if defined(__APPLE__) && !defined(environ) -#include -#define environ (*_NSGetEnviron()) -#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) +#if !defined(environ) extern char **environ; #endif From cfffb9c5e96eeeae43cd724e2d02ec8c2b7714e0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Feb 2020 17:35:36 -0500 Subject: [PATCH 092/109] improve handling of environment variables on Windows std.os.getenv and std.os.getenvZ have nice compile errors when not linking libc and using Windows. std.os.getenvW is provided as a Windows-only API that does not require an allocator. It uses the Process Environment Block. std.process.getEnvVarOwned is improved to be a simple wrapper on top of std.os.getenvW. std.process.getEnvMap is improved to use the Process Environment Block rather than calling GetEnvironmentVariableW. std.zig.system.NativePaths uses process.getEnvVarOwned instead of std.os.getenvZ, which works on Windows as well as POSIX. --- lib/std/os.zig | 42 ++++++++++++++++++++----- lib/std/os/test.zig | 8 +++++ lib/std/os/windows/bits.zig | 2 +- lib/std/process.zig | 46 +++++++++------------------- lib/std/zig/system.zig | 61 ++++++++++++++++++++++--------------- 5 files changed, 93 insertions(+), 66 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index a4f148ae00..cdb48a05a5 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1104,10 +1104,6 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) /// Get an environment variable. /// See also `getenvZ`. pub fn getenv(key: []const u8) ?[]const u8 { - if (builtin.os == .windows) { - // TODO update this to use the ProcessEnvironmentBlock - @compileError("TODO implement std.os.getenv for Windows"); - } if (builtin.link_libc) { var small_key_buf: [64]u8 = undefined; if (key.len < small_key_buf.len) { @@ -1133,6 +1129,9 @@ pub fn getenv(key: []const u8) ?[]const u8 { } return null; } + if (builtin.os == .windows) { + @compileError("std.os.getenv is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API."); + } // TODO see https://github.com/ziglang/zig/issues/4524 for (environ) |ptr| { var line_i: usize = 0; @@ -1155,17 +1154,44 @@ pub const getenvC = getenvZ; /// Get an environment variable with a null-terminated name. /// See also `getenv`. pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { - if (builtin.os == .windows) { - // TODO update this to use the ProcessEnvironmentBlock - @compileError("TODO implement std.os.getenv for Windows"); - } if (builtin.link_libc) { const value = system.getenv(key) orelse return null; return mem.toSliceConst(u8, value); } + if (builtin.os == .windows) { + @compileError("std.os.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API."); + } return getenv(mem.toSliceConst(u8, key)); } +/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. +/// See also `getenv`. +pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { + if (builtin.os != .windows) { + @compileError("std.os.getenvW is a Windows-only API"); + } + const key_slice = mem.toSliceConst(u16, key); + const ptr = windows.peb().ProcessParameters.Environment; + var i: usize = 0; + while (ptr[i] != 0) { + const key_start = i; + + while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} + const this_key = ptr[key_start..i]; + + if (ptr[i] == '=') i += 1; + + const value_start = i; + while (ptr[i] != 0) : (i += 1) {} + const this_value = ptr[value_start..i :0]; + + if (mem.eql(u16, key_slice, this_key)) return this_value; + + i += 1; // skip over null byte + } + return null; +} + pub const GetCwdError = error{ NameTooLong, CurrentWorkingDirectoryUnlinked, diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 055d049f69..488a557ed6 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -351,3 +351,11 @@ test "mmap" { try fs.cwd().deleteFile(test_out_file); } + +test "getenv" { + if (builtin.os == .windows) { + expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null); + } else { + expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null); + } +} diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 265d3439e2..4e153d40ed 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -1187,7 +1187,7 @@ pub const RTL_USER_PROCESS_PARAMETERS = extern struct { DllPath: UNICODE_STRING, ImagePathName: UNICODE_STRING, CommandLine: UNICODE_STRING, - Environment: [*]WCHAR, + Environment: [*:0]WCHAR, dwX: ULONG, dwY: ULONG, dwXSize: ULONG, diff --git a/lib/std/process.zig b/lib/std/process.zig index ba124ff262..ac75eff725 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -37,14 +37,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { errdefer result.deinit(); if (builtin.os == .windows) { - // TODO update this to use the ProcessEnvironmentBlock - const ptr = try os.windows.GetEnvironmentStringsW(); + const ptr = windows.peb().ProcessParameters.Environment; defer os.windows.FreeEnvironmentStringsW(ptr); var i: usize = 0; - while (true) { - if (ptr[i] == 0) return result; - + while (ptr[i] != 0) { const key_start = i; while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} @@ -64,6 +61,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { try result.setMove(key, value); } + return result; } else if (builtin.os == .wasi) { var environ_count: usize = undefined; var environ_buf_size: usize = undefined; @@ -141,34 +139,18 @@ pub const GetEnvVarOwnedError = error{ /// Caller must free returned memory. pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { if (builtin.os == .windows) { - const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); - defer allocator.free(key_with_null); + const result_w = blk: { + const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); + defer allocator.free(key_w); - var buf = try allocator.alloc(u16, 256); - defer allocator.free(buf); - - while (true) { - const windows_buf_len = math.cast(os.windows.DWORD, buf.len) catch return error.OutOfMemory; - const result = os.windows.GetEnvironmentVariableW( - key_with_null.ptr, - buf.ptr, - windows_buf_len, - ) catch |err| switch (err) { - error.Unexpected => return error.EnvironmentVariableNotFound, - else => |e| return e, - }; - if (result > buf.len) { - buf = try allocator.realloc(buf, result); - continue; - } - - return std.unicode.utf16leToUtf8Alloc(allocator, buf[0..result]) catch |err| switch (err) { - error.DanglingSurrogateHalf => return error.InvalidUtf8, - error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, - error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, - else => |e| return e, - }; - } + break :blk std.os.getenvW(key_w) orelse return error.EnvironmentVariableNotFound; + }; + return std.unicode.utf16leToUtf8Alloc(allocator, result_w) catch |err| switch (err) { + error.DanglingSurrogateHalf => return error.InvalidUtf8, + error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, + error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, + else => |e| return e, + }; } else { const result = os.getenv(key) orelse return error.EnvironmentVariableNotFound; return mem.dupe(allocator, u8, result); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 74a9ffdc70..3931e362c6 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -5,6 +5,8 @@ const ArrayList = std.ArrayList; const assert = std.debug.assert; const process = std.process; +const is_windows = std.Target.current.isWindows(); + pub const NativePaths = struct { include_dirs: ArrayList([:0]u8), lib_dirs: ArrayList([:0]u8), @@ -21,7 +23,9 @@ pub const NativePaths = struct { errdefer self.deinit(); var is_nix = false; - if (std.os.getenvZ("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { + if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { + defer allocator.free(nix_cflags_compile); + is_nix = true; var it = mem.tokenize(nix_cflags_compile, " "); while (true) { @@ -37,8 +41,14 @@ pub const NativePaths = struct { break; } } + } else |err| switch (err) { + error.InvalidUtf8 => {}, + error.EnvironmentVariableNotFound => {}, + error.OutOfMemory => |e| return e, } - if (std.os.getenvZ("NIX_LDFLAGS")) |nix_ldflags| { + if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| { + defer allocator.free(nix_ldflags); + is_nix = true; var it = mem.tokenize(nix_ldflags, " "); while (true) { @@ -57,39 +67,40 @@ pub const NativePaths = struct { break; } } + } else |err| switch (err) { + error.InvalidUtf8 => {}, + error.EnvironmentVariableNotFound => {}, + error.OutOfMemory => |e| return e, } if (is_nix) { return self; } - switch (std.builtin.os) { - .windows => {}, - else => { - const triple = try std.Target.current.linuxTriple(allocator); + if (!is_windows) { + const triple = try std.Target.current.linuxTriple(allocator); - // TODO: $ ld --verbose | grep SEARCH_DIR - // the output contains some paths that end with lib64, maybe include them too? - // TODO: what is the best possible order of things? - // TODO: some of these are suspect and should only be added on some systems. audit needed. + // TODO: $ ld --verbose | grep SEARCH_DIR + // the output contains some paths that end with lib64, maybe include them too? + // TODO: what is the best possible order of things? + // TODO: some of these are suspect and should only be added on some systems. audit needed. - try self.addIncludeDir("/usr/local/include"); - try self.addLibDir("/usr/local/lib"); - try self.addLibDir("/usr/local/lib64"); + try self.addIncludeDir("/usr/local/include"); + try self.addLibDir("/usr/local/lib"); + try self.addLibDir("/usr/local/lib64"); - try self.addIncludeDirFmt("/usr/include/{}", .{triple}); - try self.addLibDirFmt("/usr/lib/{}", .{triple}); + try self.addIncludeDirFmt("/usr/include/{}", .{triple}); + try self.addLibDirFmt("/usr/lib/{}", .{triple}); - try self.addIncludeDir("/usr/include"); - try self.addLibDir("/lib"); - try self.addLibDir("/lib64"); - try self.addLibDir("/usr/lib"); - try self.addLibDir("/usr/lib64"); + try self.addIncludeDir("/usr/include"); + try self.addLibDir("/lib"); + try self.addLibDir("/lib64"); + try self.addLibDir("/usr/lib"); + try self.addLibDir("/usr/lib64"); - // example: on a 64-bit debian-based linux distro, with zlib installed from apt: - // zlib.h is in /usr/include (added above) - // libz.so.1 is in /lib/x86_64-linux-gnu (added here) - try self.addLibDirFmt("/lib/{}", .{triple}); - }, + // example: on a 64-bit debian-based linux distro, with zlib installed from apt: + // zlib.h is in /usr/include (added above) + // libz.so.1 is in /lib/x86_64-linux-gnu (added here) + try self.addLibDirFmt("/lib/{}", .{triple}); } return self; From 767f041068369af021aaca421e8b31ce3aaae631 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Feb 2020 17:49:52 -0500 Subject: [PATCH 093/109] std.process: fix typo --- lib/std/process.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index ac75eff725..81b75faeb1 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -37,7 +37,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { errdefer result.deinit(); if (builtin.os == .windows) { - const ptr = windows.peb().ProcessParameters.Environment; + const ptr = os.windows.peb().ProcessParameters.Environment; defer os.windows.FreeEnvironmentStringsW(ptr); var i: usize = 0; From 94c3dbf9e3f9fcc63b2495adec36e6b4acb1813e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 23 Feb 2020 01:05:39 -0500 Subject: [PATCH 094/109] remove no-longer-valid defer --- lib/std/process.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index 81b75faeb1..b796150b3b 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -38,7 +38,6 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { if (builtin.os == .windows) { const ptr = os.windows.peb().ProcessParameters.Environment; - defer os.windows.FreeEnvironmentStringsW(ptr); var i: usize = 0; while (ptr[i] != 0) { From 597648231b49500bbb8d15daa7f59cd52c1c3279 Mon Sep 17 00:00:00 2001 From: frmdstryr Date: Fri, 21 Feb 2020 22:26:13 -0500 Subject: [PATCH 095/109] Format decmial 0.0 with no precision as just 0 --- lib/std/fmt.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index a0ec668769..0fe096a015 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -757,8 +757,6 @@ pub fn formatFloatDecimal( } else { try output(context, ".0"); } - } else { - try output(context, "0"); } return; @@ -1399,6 +1397,7 @@ test "float.special" { test "float.decimal" { try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); + try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)}); try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)}); // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). From 7664c3bc11988fd1ee2b3f26d1f08ac80d873c64 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Sun, 23 Feb 2020 18:03:50 +0100 Subject: [PATCH 096/109] remove @bytesToSlice, @sliceToBytes from tests, docs --- doc/langref.html.in | 61 +++----------- lib/std/mem.zig | 114 ++++++++++++++++++++++---- lib/std/meta/trait.zig | 16 ++++ test/compile_errors.zig | 10 --- test/runtime_safety.zig | 16 ++-- test/stage1/behavior.zig | 1 - test/stage1/behavior/align.zig | 14 ---- test/stage1/behavior/async_fn.zig | 4 +- test/stage1/behavior/bugs/1851.zig | 2 +- test/stage1/behavior/cast.zig | 20 ----- test/stage1/behavior/eval.zig | 10 --- test/stage1/behavior/misc.zig | 21 ----- test/stage1/behavior/slicetobytes.zig | 29 ------- test/stage1/behavior/struct.zig | 4 +- 14 files changed, 141 insertions(+), 181 deletions(-) delete mode 100644 test/stage1/behavior/slicetobytes.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 71f97b3f06..4ac9cf47e0 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2025,7 +2025,8 @@ test "volatile" { conversions are not possible.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const std = @import("std"); +const assert = std.debug.assert; test "pointer casting" { const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 }; @@ -2034,7 +2035,7 @@ test "pointer casting" { // Even this example is contrived - there are better ways to do the above than // pointer casting. For example, using a slice narrowing cast: - const u32_value = @bytesToSlice(u32, bytes[0..])[0]; + const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0]; assert(u32_value == 0x12121212); // And even another way, the most straightforward way to do it: @@ -2114,16 +2115,16 @@ test "function alignment" { {#link|safety check|Incorrect Pointer Alignment#}:

{#code_begin|test_safety|incorrect alignment#} -const assert = @import("std").debug.assert; +const std = @import("std"); test "pointer alignment safety" { var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; - const bytes = @sliceToBytes(array[0..]); - assert(foo(bytes) == 0x11111111); + const bytes = std.mem.sliceAsBytes(array[0..]); + std.debug.assert(foo(bytes) == 0x11111111); } fn foo(bytes: []u8) u32 { const slice4 = bytes[1..5]; - const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); return int_slice[0]; } {#code_end#} @@ -2249,7 +2250,7 @@ test "slice widening" { // Zig supports slice widening and slice narrowing. Cast a slice of u8 // to a slice of anything else, and Zig will perform the length conversion. const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 }; - const slice = @bytesToSlice(u32, array[0..]); + const slice = mem.bytesAsSlice(u32, array[0..]); assert(slice.len == 2); assert(slice[0] == 0x12121212); assert(slice[1] == 0x13131313); @@ -5186,7 +5187,6 @@ test "coercion of zero bit types" {
  • {#link|@bitCast#} - change type but maintain bit representation
  • {#link|@alignCast#} - make a pointer have more alignment
  • {#link|@boolToInt#} - convert true to 1 and false to 0
  • -
  • {#link|@bytesToSlice#} - convert a slice of bytes to a slice of another type
  • {#link|@enumToInt#} - obtain the integer tag value of an enum or tagged union
  • {#link|@errSetCast#} - convert to a smaller error set
  • {#link|@errorToInt#} - obtain the integer value of an error code
  • @@ -5199,7 +5199,6 @@ test "coercion of zero bit types" {
  • {#link|@intToPtr#} - convert an address to a pointer
  • {#link|@ptrCast#} - convert between pointer types
  • {#link|@ptrToInt#} - obtain the address of a pointer
  • -
  • {#link|@sliceToBytes#} - convert a slice of anything to a slice of bytes
  • {#link|@truncate#} - convert between integer types, chopping off bits
  • {#header_close#} @@ -6929,18 +6928,6 @@ async fn func(y: *i32) void { {#see_also|@bitOffsetOf#} {#header_close#} - {#header_open|@bytesToSlice#} -
    {#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}
    -

    - Converts a slice of bytes or array of bytes into a slice of {#syntax#}Element{#endsyntax#}. - The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter. -

    -

    - Attempting to convert a number of bytes with a length that does not evenly divide into a slice of - elements results in safety-protected {#link|Undefined Behavior#}. -

    - {#header_close#} - {#header_open|@call#}
    {#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}

    @@ -8101,14 +8088,6 @@ test "@setRuntimeSafety" { {#see_also|@bitSizeOf|@typeInfo#} {#header_close#} - {#header_open|@sliceToBytes#} -

    {#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}
    -

    - Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same - {#link|pointer|Pointers#} properties as the parameter. -

    - {#header_close#} - {#header_open|@splat#}
    {#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @TypeOf(scalar)){#endsyntax#}

    @@ -8919,25 +8898,6 @@ pub fn main() void { var b: u32 = 3; var c = @divExact(a, b); std.debug.warn("value: {}\n", .{c}); -} - {#code_end#} - {#header_close#} - {#header_open|Slice Widen Remainder#} -

    At compile-time:

    - {#code_begin|test_err|unable to convert#} -comptime { - var bytes = [5]u8{ 1, 2, 3, 4, 5 }; - var slice = @bytesToSlice(u32, bytes[0..]); -} - {#code_end#} -

    At runtime:

    - {#code_begin|exe_err#} -const std = @import("std"); - -pub fn main() void { - var bytes = [5]u8{ 1, 2, 3, 4, 5 }; - var slice = @bytesToSlice(u32, bytes[0..]); - std.debug.warn("value: {}\n", .{slice[0]}); } {#code_end#} {#header_close#} @@ -9119,14 +9079,15 @@ comptime { {#code_end#}

    At runtime:

    {#code_begin|exe_err#} +const mem = @import("std").mem; pub fn main() !void { var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; - const bytes = @sliceToBytes(array[0..]); + const bytes = mem.sliceAsBytes(array[0..]); if (foo(bytes) != 0x11111111) return error.Wrong; } fn foo(bytes: []u8) u32 { const slice4 = bytes[1..5]; - const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + const int_slice = mem.bytesAsSlice(u32, @alignCast(4, slice4)); return int_slice[0]; } {#code_end#} diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 01e289988b..20ad567431 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1488,28 +1488,34 @@ test "bytesToValue" { //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { - if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) { - @compileError("expected []u8, passed " ++ @typeName(bytesType)); + if (!(trait.isSlice(bytesType) and meta.Child(bytesType) == u8) and !(trait.isPtrTo(.Array)(bytesType) and meta.Child(meta.Child(bytesType)) == u8)) { + @compileError("expected []u8 or *[_]u8, passed " ++ @typeName(bytesType)); } - const alignment = comptime meta.alignment(bytesType); + if (trait.isPtrTo(.Array)(bytesType) and @typeInfo(meta.Child(bytesType)).Array.len % @sizeOf(T) != 0) { + @compileError("number of bytes in " ++ @typeName(bytesType) ++ " is not divisible by size of " ++ @typeName(T)); + } - return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; + const alignment = meta.alignment(bytesType); + + return if (trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; } pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) { + const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes; + // let's not give an undefined pointer to @ptrCast // it may be equal to zero and fail a null check - if (bytes.len == 0) { + if (bytesSlice.len == 0) { return &[0]T{}; } - const bytesType = @TypeOf(bytes); + const bytesType = @TypeOf(bytesSlice); const alignment = comptime meta.alignment(bytesType); const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T; - return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; + return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; } test "bytesAsSlice" { @@ -1520,30 +1526,59 @@ test "bytesAsSlice" { testing.expect(bigToNative(u16, slice[1]) == 0xBEEF); } +test "bytesAsSlice keeps pointer alignment" { + var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; + const numbers = bytesAsSlice(u32, bytes[0..]); + comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); +} + +test "bytesAsSlice on a packed struct" { + const F = packed struct { + a: u8, + }; + + var b = [1]u8{9}; + var f = bytesAsSlice(F, &b); + testing.expect(f[0].a == 9); +} + +test "bytesAsSlice with specified alignment" { + var bytes align(4) = [_]u8{ + 0x33, + 0x33, + 0x33, + 0x33, + }; + const slice: []u32 = std.mem.bytesAsSlice(u32, bytes[0..]); + testing.expect(slice[0] == 0x33333333); +} + //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. fn SliceAsBytesReturnType(comptime sliceType: type) type { - if (comptime !trait.isSlice(sliceType)) { - @compileError("expected []T, passed " ++ @typeName(sliceType)); + if (!trait.isSlice(sliceType) and !trait.isPtrTo(.Array)(sliceType)) { + @compileError("expected []T or *[_]T, passed " ++ @typeName(sliceType)); } - const alignment = comptime meta.alignment(sliceType); + const alignment = meta.alignment(sliceType); - return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; + return if (trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; } pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { + const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice; + // let's not give an undefined pointer to @ptrCast // it may be equal to zero and fail a null check - if (slice.len == 0) { + if (actualSlice.len == 0) { return &[0]u8{}; } - const sliceType = @TypeOf(slice); + const sliceType = @TypeOf(actualSlice); const alignment = comptime meta.alignment(sliceType); const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8; - return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))]; + return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))]; } test "sliceAsBytes" { @@ -1556,6 +1591,57 @@ test "sliceAsBytes" { })); } +test "sliceAsBytes packed struct at runtime and comptime" { + const Foo = packed struct { + a: u4, + b: u4, + }; + const S = struct { + fn doTheTest() void { + var foo: Foo = undefined; + var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]); + slice[0] = 0x13; + switch (builtin.endian) { + .Big => { + testing.expect(foo.a == 0x1); + testing.expect(foo.b == 0x3); + }, + .Little => { + testing.expect(foo.a == 0x3); + testing.expect(foo.b == 0x1); + }, + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "sliceAsBytes and bytesAsSlice back" { + testing.expect(@sizeOf(i32) == 4); + + var big_thing_array = [_]i32{ 1, 2, 3, 4 }; + const big_thing_slice: []i32 = big_thing_array[0..]; + + const bytes = sliceAsBytes(big_thing_slice); + testing.expect(bytes.len == 4 * 4); + + bytes[4] = 0; + bytes[5] = 0; + bytes[6] = 0; + bytes[7] = 0; + testing.expect(big_thing_slice[1] == 0); + + const big_thing_again = bytesAsSlice(i32, bytes); + testing.expect(big_thing_again[2] == 3); + + big_thing_again[2] = -1; + testing.expect(bytes[8] == math.maxInt(u8)); + testing.expect(bytes[9] == math.maxInt(u8)); + testing.expect(bytes[10] == math.maxInt(u8)); + testing.expect(bytes[11] == math.maxInt(u8)); +} + fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { if (trait.isConstPtr(T)) return *const [length]meta.Child(meta.Child(T)); diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index b1fd233ff2..b17a4a2a93 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -135,6 +135,22 @@ test "std.meta.trait.isPtrTo" { testing.expect(!isPtrTo(.Struct)(**struct {})); } +pub fn isSliceOf(comptime id: builtin.TypeId) TraitFn { + const Closure = struct { + pub fn trait(comptime T: type) bool { + if (!comptime isSlice(T)) return false; + return id == @typeId(meta.Child(T)); + } + }; + return Closure.trait; +} + +test "std.meta.trait.isSliceOf" { + testing.expect(!isSliceOf(.Struct)(struct {})); + testing.expect(isSliceOf(.Struct)([]struct {})); + testing.expect(!isSliceOf(.Struct)([][]struct {})); +} + ///////////Strait trait Fns //@TODO: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 1b32786e40..6213e8435f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4747,16 +4747,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'", }); - cases.add("convert fixed size array to slice with invalid size", - \\export fn f() void { - \\ var array: [5]u8 = undefined; - \\ var foo = @bytesToSlice(u32, &array)[0]; - \\} - , &[_][]const u8{ - "tmp.zig:3:15: error: unable to convert [5]u8 to []align(1) u32: size mismatch", - "tmp.zig:3:29: note: u32 has size 4; remaining bytes: 1", - }); - cases.add("non-pure function returns type", \\var a: u32 = 0; \\pub fn List(comptime T: type) type { diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 2217a7f2df..e4ea7f52db 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -553,15 +553,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { ); cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", - \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { - \\ @import("std").os.exit(126); + \\const std = @import("std"); + \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { + \\ std.os.exit(126); \\} \\pub fn main() !void { \\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5}); \\ if (x.len == 0) return error.Whatever; \\} \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { - \\ return @bytesToSlice(i32, slice); + \\ return std.mem.bytesAsSlice(i32, slice); \\} ); @@ -656,17 +657,18 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { ); cases.addRuntimeSafety("@alignCast misaligned", - \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { - \\ @import("std").os.exit(126); + \\const std = @import("std"); + \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { + \\ std.os.exit(126); \\} \\pub fn main() !void { \\ var array align(4) = [_]u32{0x11111111, 0x11111111}; - \\ const bytes = @sliceToBytes(array[0..]); + \\ const bytes = std.mem.sliceAsBytes(array[0..]); \\ if (foo(bytes) != 0x11111111) return error.Wrong; \\} \\fn foo(bytes: []u8) u32 { \\ const slice4 = bytes[1..5]; - \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); \\ return int_slice[0]; \\} ); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index ea8720d98c..6e0d4c5e22 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -92,7 +92,6 @@ comptime { _ = @import("behavior/shuffle.zig"); _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice.zig"); - _ = @import("behavior/slicetobytes.zig"); _ = @import("behavior/struct.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index c83d2379b4..5a5138d567 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -81,20 +81,6 @@ fn testBytesAlign(b: u8) void { expect(ptr.* == 0x33333333); } -test "specifying alignment allows slice cast" { - testBytesAlignSlice(0x33); -} -fn testBytesAlignSlice(b: u8) void { - var bytes align(4) = [_]u8{ - b, - b, - b, - b, - }; - const slice: []u32 = @bytesToSlice(u32, bytes[0..]); - expect(slice[0] == 0x33333333); -} - test "@alignCast pointers" { var x: u32 align(4) = 1; expectsOnly1(&x); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index b04d4e2b5d..6583adec66 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -334,7 +334,7 @@ test "async fn with inferred error set" { var frame: [1]@Frame(middle) = undefined; var fn_ptr = middle; var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined; - _ = @asyncCall(@sliceToBytes(frame[0..]), &result, fn_ptr); + _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr); resume global_frame; std.testing.expectError(error.Fail, result); } @@ -954,7 +954,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" { fn doTheTest() void { var frame: [1]@Frame(middle) = undefined; var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined; - _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle); + _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle); resume global_frame; std.testing.expectError(error.Fail, result); } diff --git a/test/stage1/behavior/bugs/1851.zig b/test/stage1/behavior/bugs/1851.zig index f3e7393b96..d6cf17651d 100644 --- a/test/stage1/behavior/bugs/1851.zig +++ b/test/stage1/behavior/bugs/1851.zig @@ -13,7 +13,7 @@ test "allocation and looping over 3-byte integer" { x[0] = 0xFFFFFF; x[1] = 0xFFFFFF; - const bytes = @sliceToBytes(x); + const bytes = std.mem.sliceAsBytes(x); expect(@TypeOf(bytes) == []align(4) u8); expect(bytes.len == 8); diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index f393bfebb5..76d3b784ec 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -304,20 +304,6 @@ fn cast128Float(x: u128) f128 { return @bitCast(f128, x); } -test "const slice widen cast" { - const bytes align(4) = [_]u8{ - 0x12, - 0x12, - 0x12, - 0x12, - }; - - const u32_value = @bytesToSlice(u32, bytes[0..])[0]; - expect(u32_value == 0x12121212); - - expect(@bitCast(u32, bytes) == 0x12121212); -} - test "single-item pointer of array to slice and to unknown length pointer" { testCastPtrOfArrayToSliceAndPtr(); comptime testCastPtrOfArrayToSliceAndPtr(); @@ -392,12 +378,6 @@ test "comptime_int @intToFloat" { } } -test "@bytesToSlice keeps pointer alignment" { - var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; - const numbers = @bytesToSlice(u32, bytes[0..]); - comptime expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); -} - test "@intCast i32 to u7" { var x: u128 = maxInt(u128); var y: i32 = 120; diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig index ed81fae791..099434a869 100644 --- a/test/stage1/behavior/eval.zig +++ b/test/stage1/behavior/eval.zig @@ -711,16 +711,6 @@ test "bit shift a u1" { expect(y == 1); } -test "@bytesToslice on a packed struct" { - const F = packed struct { - a: u8, - }; - - var b = [1]u8{9}; - var f = @bytesToSlice(F, &b); - expect(f[0].a == 9); -} - test "comptime pointer cast array and then slice" { const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index c77b49f03a..a3a008c1d2 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -3,7 +3,6 @@ const expect = std.testing.expect; const expectEqualSlices = std.testing.expectEqualSlices; const mem = std.mem; const builtin = @import("builtin"); -const maxInt = std.math.maxInt; // normal comment @@ -377,26 +376,6 @@ test "string concatenation" { expect(b[len] == 0); } -test "cast slice to u8 slice" { - expect(@sizeOf(i32) == 4); - var big_thing_array = [_]i32{ 1, 2, 3, 4 }; - const big_thing_slice: []i32 = big_thing_array[0..]; - const bytes = @sliceToBytes(big_thing_slice); - expect(bytes.len == 4 * 4); - bytes[4] = 0; - bytes[5] = 0; - bytes[6] = 0; - bytes[7] = 0; - expect(big_thing_slice[1] == 0); - const big_thing_again = @bytesToSlice(i32, bytes); - expect(big_thing_again[2] == 3); - big_thing_again[2] = -1; - expect(bytes[8] == maxInt(u8)); - expect(bytes[9] == maxInt(u8)); - expect(bytes[10] == maxInt(u8)); - expect(bytes[11] == maxInt(u8)); -} - test "pointer to void return type" { testPointerToVoidReturnType() catch unreachable; } diff --git a/test/stage1/behavior/slicetobytes.zig b/test/stage1/behavior/slicetobytes.zig deleted file mode 100644 index c0eb4a8f9b..0000000000 --- a/test/stage1/behavior/slicetobytes.zig +++ /dev/null @@ -1,29 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const expect = std.testing.expect; - -test "@sliceToBytes packed struct at runtime and comptime" { - const Foo = packed struct { - a: u4, - b: u4, - }; - const S = struct { - fn doTheTest() void { - var foo: Foo = undefined; - var slice = @sliceToBytes(@as(*[1]Foo, &foo)[0..1]); - slice[0] = 0x13; - switch (builtin.endian) { - builtin.Endian.Big => { - expect(foo.a == 0x1); - expect(foo.b == 0x3); - }, - builtin.Endian.Little => { - expect(foo.a == 0x3); - expect(foo.b == 0x1); - }, - } - } - }; - S.doTheTest(); - comptime S.doTheTest(); -} diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 8e5ab29db3..ecec7fe5d6 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -315,7 +315,7 @@ test "packed array 24bits" { var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1); bytes[bytes.len - 1] = 0xaa; - const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; + const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; expect(ptr.a == 0); expect(ptr.b[0].field == 0); expect(ptr.b[1].field == 0); @@ -364,7 +364,7 @@ test "aligned array of packed struct" { } var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned); - const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; + const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0]; expect(ptr.a[0].a == 0xbb); expect(ptr.a[0].b == 0xbb); From 9c35f680f73538b8c36121ff938cc0b19eadbb42 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Sun, 23 Feb 2020 19:03:55 +0100 Subject: [PATCH 097/109] nuke @bytesToSlice, @sliceToBytes in stage1 --- src/all_types.hpp | 28 ----- src/codegen.cpp | 74 -------------- src/ir.cpp | 256 ---------------------------------------------- src/ir_print.cpp | 36 ------- 4 files changed, 394 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index c1348d3abd..117a0004f0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1750,8 +1750,6 @@ enum BuiltinFnId { BuiltinFnIdIntCast, BuiltinFnIdFloatCast, BuiltinFnIdErrSetCast, - BuiltinFnIdToBytes, - BuiltinFnIdFromBytes, BuiltinFnIdIntToFloat, BuiltinFnIdFloatToInt, BuiltinFnIdBoolToInt, @@ -1821,7 +1819,6 @@ enum PanicMsgId { PanicMsgIdDivisionByZero, PanicMsgIdRemainderDivisionByZero, PanicMsgIdExactDivisionRemainder, - PanicMsgIdSliceWidenRemainder, PanicMsgIdUnwrapOptionalFail, PanicMsgIdInvalidErrorCode, PanicMsgIdIncorrectAlignment, @@ -2699,8 +2696,6 @@ enum IrInstSrcId { IrInstSrcIdSaveErrRetAddr, IrInstSrcIdAddImplicitReturnType, IrInstSrcIdErrSetCast, - IrInstSrcIdToBytes, - IrInstSrcIdFromBytes, IrInstSrcIdCheckRuntimeScope, IrInstSrcIdHasDecl, IrInstSrcIdUndeclaredIdent, @@ -2739,7 +2734,6 @@ enum IrInstGenId { IrInstGenIdCall, IrInstGenIdReturn, IrInstGenIdCast, - IrInstGenIdResizeSlice, IrInstGenIdUnreachable, IrInstGenIdAsm, IrInstGenIdTestNonNull, @@ -3271,13 +3265,6 @@ struct IrInstGenCast { CastOp cast_op; }; -struct IrInstGenResizeSlice { - IrInstGen base; - - IrInstGen *operand; - IrInstGen *result_loc; -}; - struct IrInstSrcContainerInitList { IrInstSrc base; @@ -3629,21 +3616,6 @@ struct IrInstSrcErrSetCast { IrInstSrc *target; }; -struct IrInstSrcToBytes { - IrInstSrc base; - - IrInstSrc *target; - ResultLoc *result_loc; -}; - -struct IrInstSrcFromBytes { - IrInstSrc base; - - IrInstSrc *dest_child_type; - IrInstSrc *target; - ResultLoc *result_loc; -}; - struct IrInstSrcIntToFloat { IrInstSrc base; diff --git a/src/codegen.cpp b/src/codegen.cpp index a28d2d469d..c193b4e443 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -972,8 +972,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { return buf_create_from_str("remainder division by zero or negative value"); case PanicMsgIdExactDivisionRemainder: return buf_create_from_str("exact division produced remainder"); - case PanicMsgIdSliceWidenRemainder: - return buf_create_from_str("slice widening size mismatch"); case PanicMsgIdUnwrapOptionalFail: return buf_create_from_str("attempt to unwrap null"); case PanicMsgIdUnreachable: @@ -3085,74 +3083,6 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in } } -static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executable, - IrInstGenResizeSlice *instruction) -{ - ZigType *actual_type = instruction->operand->value->type; - ZigType *wanted_type = instruction->base.value->type; - LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - assert(expr_val); - - LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - assert(wanted_type->id == ZigTypeIdStruct); - assert(wanted_type->data.structure.special == StructSpecialSlice); - assert(actual_type->id == ZigTypeIdStruct); - assert(actual_type->data.structure.special == StructSpecialSlice); - - ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry; - ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; - ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry; - ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; - - - size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index; - size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index; - size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index; - size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index; - - LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); - LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, - get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), ""); - LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc, - (unsigned)wanted_ptr_index, ""); - gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); - - LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); - LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); - uint64_t src_size = type_size(g, actual_child_type); - uint64_t dest_size = type_size(g, wanted_child_type); - - LLVMValueRef new_len; - if (dest_size == 1) { - LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, src_size, false); - new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); - } else if (src_size == 1) { - LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, dest_size, false); - if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); - LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); - LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); - - LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); - - LLVMPositionBuilderAtEnd(g->builder, ok_block); - } - new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); - } else { - zig_unreachable(); - } - - LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, ""); - gen_store_untyped(g, new_len, dest_len_ptr, 0, false); - - return result_loc; -} - static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenCast *cast_instruction) { @@ -6485,8 +6415,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl return ir_render_assert_zero(g, executable, (IrInstGenAssertZero *)instruction); case IrInstGenIdAssertNonNull: return ir_render_assert_non_null(g, executable, (IrInstGenAssertNonNull *)instruction); - case IrInstGenIdResizeSlice: - return ir_render_resize_slice(g, executable, (IrInstGenResizeSlice *)instruction); case IrInstGenIdPtrOfArrayToSlice: return ir_render_ptr_of_array_to_slice(g, executable, (IrInstGenPtrOfArrayToSlice *)instruction); case IrInstGenIdSuspendBegin: @@ -8317,8 +8245,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3); create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4); create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2); - create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); - create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); create_builtin_fn(g, BuiltinFnIdThis, "This", 0); create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2); create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3); diff --git a/src/ir.cpp b/src/ir.cpp index 5f50586f72..80fef04496 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -383,10 +383,6 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrSetCast: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFromBytes: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdToBytes: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToFloat: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFloatToInt: @@ -707,8 +703,6 @@ void destroy_instruction_gen(IrInstGen *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAssertNonNull: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstGenIdResizeSlice: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAlloca: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSuspendBegin: @@ -1563,14 +1557,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { return IrInstSrcIdErrSetCast; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcToBytes *) { - return IrInstSrcIdToBytes; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFromBytes *) { - return IrInstSrcIdFromBytes; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { return IrInstSrcIdCheckRuntimeScope; } @@ -1700,10 +1686,6 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) { return IrInstGenIdCast; } -static constexpr IrInstGenId ir_inst_id(IrInstGenResizeSlice *) { - return IrInstGenIdResizeSlice; -} - static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) { return IrInstGenIdUnreachable; } @@ -2759,21 +2741,6 @@ static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instructi return &inst->base; } -static IrInstGen *ir_build_resize_slice(IrAnalyze *ira, IrInst *source_instruction, - IrInstGen *operand, ZigType *ty, IrInstGen *result_loc) -{ - IrInstGenResizeSlice *instruction = ir_build_inst_gen(&ira->new_irb, - source_instruction->scope, source_instruction->source_node); - instruction->base.value->type = ty; - instruction->operand = operand; - instruction->result_loc = result_loc; - - ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target, IrInstSrc *options) { @@ -3540,32 +3507,6 @@ static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_to_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target, - ResultLoc *result_loc) -{ - IrInstSrcToBytes *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_from_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_child_type, IrInstSrc *target, ResultLoc *result_loc) -{ - IrInstSrcFromBytes *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_child_type = dest_child_type; - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(dest_child_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { @@ -6597,31 +6538,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } - case BuiltinFnIdFromBytes: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdToBytes: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } case BuiltinFnIdIntToFloat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -25489,171 +25405,6 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE return ir_analyze_err_set_cast(ira, &instruction->base.base, target, dest_type); } -static IrInstGen *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstSrcFromBytes *instruction) { - Error err; - - ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->child); - if (type_is_invalid(dest_child_type)) - return ira->codegen->invalid_inst_gen; - - IrInstGen *target = instruction->target->child; - if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_inst_gen; - - bool src_ptr_const; - bool src_ptr_volatile; - uint32_t src_ptr_align; - if (target->value->type->id == ZigTypeIdPointer) { - src_ptr_const = target->value->type->data.pointer.is_const; - src_ptr_volatile = target->value->type->data.pointer.is_volatile; - - if ((err = resolve_ptr_align(ira, target->value->type, &src_ptr_align))) - return ira->codegen->invalid_inst_gen; - } else if (is_slice(target->value->type)) { - ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; - src_ptr_const = src_ptr_type->data.pointer.is_const; - src_ptr_volatile = src_ptr_type->data.pointer.is_volatile; - - if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align))) - return ira->codegen->invalid_inst_gen; - } else { - src_ptr_const = true; - src_ptr_volatile = false; - - if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_inst_gen; - - src_ptr_align = get_abi_alignment(ira->codegen, target->value->type); - } - - if (src_ptr_align != 0) { - if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_inst_gen; - } - - ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type, - src_ptr_const, src_ptr_volatile, PtrLenUnknown, - src_ptr_align, 0, 0, false); - ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); - - ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - src_ptr_const, src_ptr_volatile, PtrLenUnknown, - src_ptr_align, 0, 0, false); - ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); - - IrInstGen *casted_value = ir_implicit_cast2(ira, &instruction->target->base, target, u8_slice); - if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_inst_gen; - - bool have_known_len = false; - uint64_t known_len; - - if (instr_is_comptime(casted_value)) { - ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad); - if (!val) - return ira->codegen->invalid_inst_gen; - - ZigValue *len_val = val->data.x_struct.fields[slice_len_index]; - if (value_is_comptime(len_val)) { - known_len = bigint_as_u64(&len_val->data.x_bigint); - have_known_len = true; - } - } - - IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, - dest_slice_type, nullptr, true, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) { - return result_loc; - } - - if (target->value->type->id == ZigTypeIdPointer && - target->value->type->data.pointer.ptr_len == PtrLenSingle && - target->value->type->data.pointer.child_type->id == ZigTypeIdArray) - { - known_len = target->value->type->data.pointer.child_type->data.array.len; - have_known_len = true; - } else if (casted_value->value->data.rh_slice.id == RuntimeHintSliceIdLen) { - known_len = casted_value->value->data.rh_slice.len; - have_known_len = true; - } - - if (have_known_len) { - if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_inst_gen; - uint64_t child_type_size = type_size(ira->codegen, dest_child_type); - uint64_t remainder = known_len % child_type_size; - if (remainder != 0) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, - buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch", - known_len, buf_ptr(&dest_slice_type->name))); - add_error_note(ira->codegen, msg, instruction->dest_child_type->base.source_node, - buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64, - buf_ptr(&dest_child_type->name), child_type_size, remainder)); - return ira->codegen->invalid_inst_gen; - } - } - - return ir_build_resize_slice(ira, &instruction->base.base, casted_value, dest_slice_type, result_loc); -} - -static IrInstGen *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstSrcToBytes *instruction) { - Error err; - - IrInstGen *target = instruction->target->child; - if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_inst_gen; - - if (!is_slice(target->value->type)) { - ir_add_error(ira, &instruction->target->base, - buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_inst_gen; - } - - ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; - - uint32_t alignment; - if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment))) - return ira->codegen->invalid_inst_gen; - - ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown, - alignment, 0, 0, false); - ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); - - if (instr_is_comptime(target)) { - ZigValue *target_val = ir_resolve_const(ira, target, UndefBad); - if (target_val == nullptr) - return ira->codegen->invalid_inst_gen; - - IrInstGen *result = ir_const(ira, &instruction->base.base, dest_slice_type); - result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2); - - ZigValue *ptr_val = result->value->data.x_struct.fields[slice_ptr_index]; - ZigValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index]; - copy_const_val(ira->codegen, ptr_val, target_ptr_val); - ptr_val->type = dest_ptr_type; - - ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index]; - len_val->special = ConstValSpecialStatic; - len_val->type = ira->codegen->builtin_types.entry_usize; - ZigValue *target_len_val = target_val->data.x_struct.fields[slice_len_index]; - ZigType *elem_type = src_ptr_type->data.pointer.child_type; - BigInt elem_size_bigint; - bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); - bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint); - - return result; - } - - IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, - dest_slice_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { - return result_loc; - } - - return ir_build_resize_slice(ira, &instruction->base.base, target, dest_slice_type, result_loc); -} - static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { Error err; @@ -29783,10 +29534,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_float_cast(ira, (IrInstSrcFloatCast *)instruction); case IrInstSrcIdErrSetCast: return ir_analyze_instruction_err_set_cast(ira, (IrInstSrcErrSetCast *)instruction); - case IrInstSrcIdFromBytes: - return ir_analyze_instruction_from_bytes(ira, (IrInstSrcFromBytes *)instruction); - case IrInstSrcIdToBytes: - return ir_analyze_instruction_to_bytes(ira, (IrInstSrcToBytes *)instruction); case IrInstSrcIdIntToFloat: return ir_analyze_instruction_int_to_float(ira, (IrInstSrcIntToFloat *)instruction); case IrInstSrcIdFloatToInt: @@ -30113,7 +29860,6 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { case IrInstGenIdCmpxchg: case IrInstGenIdAssertZero: case IrInstGenIdAssertNonNull: - case IrInstGenIdResizeSlice: case IrInstGenIdPtrOfArrayToSlice: case IrInstGenIdSlice: case IrInstGenIdOptionalWrap: @@ -30339,8 +30085,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdIntToFloat: case IrInstSrcIdFloatToInt: case IrInstSrcIdBoolToInt: - case IrInstSrcIdFromBytes: - case IrInstSrcIdToBytes: case IrInstSrcIdEnumToInt: case IrInstSrcIdHasDecl: case IrInstSrcIdAlloca: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index c0a127dd16..6d04db6168 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -307,10 +307,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcAddImplicitReturnType"; case IrInstSrcIdErrSetCast: return "SrcErrSetCast"; - case IrInstSrcIdToBytes: - return "SrcToBytes"; - case IrInstSrcIdFromBytes: - return "SrcFromBytes"; case IrInstSrcIdCheckRuntimeScope: return "SrcCheckRuntimeScope"; case IrInstSrcIdHasDecl: @@ -383,8 +379,6 @@ const char* ir_inst_gen_type_str(IrInstGenId id) { return "GenReturn"; case IrInstGenIdCast: return "GenCast"; - case IrInstGenIdResizeSlice: - return "GenResizeSlice"; case IrInstGenIdUnreachable: return "GenUnreachable"; case IrInstGenIdAsm: @@ -1644,20 +1638,6 @@ static void ir_print_err_set_cast(IrPrintSrc *irp, IrInstSrcErrSetCast *instruct fprintf(irp->f, ")"); } -static void ir_print_from_bytes(IrPrintSrc *irp, IrInstSrcFromBytes *instruction) { - fprintf(irp->f, "@bytesToSlice("); - ir_print_other_inst_src(irp, instruction->dest_child_type); - fprintf(irp->f, ", "); - ir_print_other_inst_src(irp, instruction->target); - fprintf(irp->f, ")"); -} - -static void ir_print_to_bytes(IrPrintSrc *irp, IrInstSrcToBytes *instruction) { - fprintf(irp->f, "@sliceToBytes("); - ir_print_other_inst_src(irp, instruction->target); - fprintf(irp->f, ")"); -} - static void ir_print_int_to_float(IrPrintSrc *irp, IrInstSrcIntToFloat *instruction) { fprintf(irp->f, "@intToFloat("); ir_print_other_inst_src(irp, instruction->dest_type); @@ -2142,13 +2122,6 @@ static void ir_print_assert_non_null(IrPrintGen *irp, IrInstGenAssertNonNull *in fprintf(irp->f, ")"); } -static void ir_print_resize_slice(IrPrintGen *irp, IrInstGenResizeSlice *instruction) { - fprintf(irp->f, "@resizeSlice("); - ir_print_other_inst_gen(irp, instruction->operand); - fprintf(irp->f, ")result="); - ir_print_other_inst_gen(irp, instruction->result_loc); -} - static void ir_print_alloca_src(IrPrintSrc *irp, IrInstSrcAlloca *instruction) { fprintf(irp->f, "Alloca(align="); ir_print_other_inst_src(irp, instruction->align); @@ -2793,12 +2766,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdErrSetCast: ir_print_err_set_cast(irp, (IrInstSrcErrSetCast *)instruction); break; - case IrInstSrcIdFromBytes: - ir_print_from_bytes(irp, (IrInstSrcFromBytes *)instruction); - break; - case IrInstSrcIdToBytes: - ir_print_to_bytes(irp, (IrInstSrcToBytes *)instruction); - break; case IrInstSrcIdIntToFloat: ir_print_int_to_float(irp, (IrInstSrcIntToFloat *)instruction); break; @@ -3273,9 +3240,6 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai case IrInstGenIdAssertNonNull: ir_print_assert_non_null(irp, (IrInstGenAssertNonNull *)instruction); break; - case IrInstGenIdResizeSlice: - ir_print_resize_slice(irp, (IrInstGenResizeSlice *)instruction); - break; case IrInstGenIdAlloca: ir_print_alloca_gen(irp, (IrInstGenAlloca *)instruction); break; From 907c5589ae20d1b2a73acf26c9d67139dfe3bfb9 Mon Sep 17 00:00:00 2001 From: Heide Onas Auri <48419392+heidezomp@users.noreply.github.com> Date: Mon, 24 Feb 2020 00:25:52 +0100 Subject: [PATCH 098/109] std.time.Timer.lap: only read system time once (#4533) Calling Timer.lap queried the system time twice; once to compute the lap time and once to reset the timer. This can lead to time discrepancies between actual and computed durations when summing the result of Timer.lap in a loop. This commit fixes that. also fix Timer.read to not require a pointer --- lib/std/time.zig | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/std/time.zig b/lib/std/time.zig index a5f66122cb..63d3ecce18 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -153,15 +153,9 @@ pub const Timer = struct { } /// Reads the timer value since start or the last reset in nanoseconds - pub fn read(self: *Timer) u64 { + pub fn read(self: Timer) u64 { var clock = clockNative() - self.start_time; - if (builtin.os == .windows) { - return @divFloor(clock * ns_per_s, self.frequency); - } - if (comptime std.Target.current.isDarwin()) { - return @divFloor(clock * self.frequency.numer, self.frequency.denom); - } - return clock; + return self.nativeDurationToNanos(clock); } /// Resets the timer value to 0/now. @@ -172,7 +166,7 @@ pub const Timer = struct { /// Returns the current value of the timer in nanoseconds, then resets it pub fn lap(self: *Timer) u64 { var now = clockNative(); - var lap_time = self.read(); + var lap_time = self.nativeDurationToNanos(now - self.start_time); self.start_time = now; return lap_time; } @@ -188,6 +182,16 @@ pub const Timer = struct { os.clock_gettime(monotonic_clock_id, &ts) catch unreachable; return @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec); } + + fn nativeDurationToNanos(self: Timer, duration: u64) u64 { + if (builtin.os == .windows) { + return @divFloor(duration * ns_per_s, self.frequency); + } + if (comptime std.Target.current.isDarwin()) { + return @divFloor(duration * self.frequency.numer, self.frequency.denom); + } + return duration; + } }; test "sleep" { From 5275b012020a7bb5de35120ca3e8f5d8d6ef2109 Mon Sep 17 00:00:00 2001 From: "J.W" Date: Mon, 24 Feb 2020 01:45:37 +0800 Subject: [PATCH 099/109] hashing algorithms: fix logic and index out of bounds --- lib/std/crypto.zig | 31 +++++++++++++++++++++++++++++++ lib/std/crypto/blake2.zig | 4 ++-- lib/std/crypto/md5.zig | 2 +- lib/std/crypto/sha1.zig | 2 +- lib/std/crypto/sha2.zig | 4 ++-- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index 6f4ff863ad..d0ec3277e8 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -57,3 +57,34 @@ test "crypto" { _ = @import("crypto/sha3.zig"); _ = @import("crypto/x25519.zig"); } + +test "issue #4532: no index out of bounds" { + const types = [_]type{ + Md5, + Sha1, + Sha224, + Sha256, + Sha384, + Sha512, + Blake2s224, + Blake2s256, + Blake2b384, + Blake2b512, + }; + + inline for (types) |Hasher| { + var block = [_]u8{'#'} ** Hasher.block_length; + var out1: [Hasher.digest_length]u8 = undefined; + var out2: [Hasher.digest_length]u8 = undefined; + + var h = Hasher.init(); + h.update(block[0..]); + h.final(out1[0..]); + h.reset(); + h.update(block[0..1]); + h.update(block[1..]); + h.final(out2[0..]); + + std.testing.expectEqual(out1, out2); + } +} diff --git a/lib/std/crypto/blake2.zig b/lib/std/crypto/blake2.zig index aa866acbe4..e03d8f7dab 100644 --- a/lib/std/crypto/blake2.zig +++ b/lib/std/crypto/blake2.zig @@ -94,7 +94,7 @@ fn Blake2s(comptime out_len: usize) type { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { + if (d.buf_len != 0 and d.buf_len + b.len >= 64) { off += 64 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); d.t += 64; @@ -331,7 +331,7 @@ fn Blake2b(comptime out_len: usize) type { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { + if (d.buf_len != 0 and d.buf_len + b.len >= 128) { off += 128 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); d.t += 128; diff --git a/lib/std/crypto/md5.zig b/lib/std/crypto/md5.zig index 41ce802dd7..d9dd08c904 100644 --- a/lib/std/crypto/md5.zig +++ b/lib/std/crypto/md5.zig @@ -63,7 +63,7 @@ pub const Md5 = struct { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { + if (d.buf_len != 0 and d.buf_len + b.len >= 64) { off += 64 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); diff --git a/lib/std/crypto/sha1.zig b/lib/std/crypto/sha1.zig index b4d6e5c0cc..5be42180a1 100644 --- a/lib/std/crypto/sha1.zig +++ b/lib/std/crypto/sha1.zig @@ -61,7 +61,7 @@ pub const Sha1 = struct { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { + if (d.buf_len != 0 and d.buf_len + b.len >= 64) { off += 64 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig index 478cadd03c..fd7ad532a3 100644 --- a/lib/std/crypto/sha2.zig +++ b/lib/std/crypto/sha2.zig @@ -116,7 +116,7 @@ fn Sha2_32(comptime params: Sha2Params32) type { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { + if (d.buf_len != 0 and d.buf_len + b.len >= 64) { off += 64 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); @@ -458,7 +458,7 @@ fn Sha2_64(comptime params: Sha2Params64) type { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { + if (d.buf_len != 0 and d.buf_len + b.len >= 128) { off += 128 - d.buf_len; mem.copy(u8, d.buf[d.buf_len..], b[0..off]); From 0972b2a8fefe8f2175dd95d80a53e356c77d1200 Mon Sep 17 00:00:00 2001 From: Bas van den Berg Date: Mon, 24 Feb 2020 20:25:59 +0100 Subject: [PATCH 100/109] implement zeroes for non extern structs and native types --- lib/std/mem.zig | 124 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 8 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 71be738def..8aa0cb2832 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -279,15 +279,69 @@ pub fn set(comptime T: type, dest: []T, value: T) void { /// Zero initializes the type. /// This can be used to zero initialize a C-struct. pub fn zeroes(comptime T: type) T { - if (@sizeOf(T) == 0) return T{}; - - if (comptime meta.containerLayout(T) != .Extern) { - @compileError("TODO: Currently this only works for extern types"); + switch (@typeInfo(T)) { + .ComptimeInt, .Int, .ComptimeFloat, .Float => { + return @as(T, 0); + }, + .Enum, .EnumLiteral => { + return @intToEnum(T, 0); + }, + .Void => { + return {}; + }, + .Bool => { + return false; + }, + .Optional, .Null => { + return null; + }, + .Struct => { + if (@sizeOf(T) == 0) return T{}; + if (comptime meta.containerLayout(T) == .Extern) { + var item: T = undefined; + @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T)); + return item; + } else { + var structure: T = undefined; + comptime var field_i = 0; + inline while (field_i < @memberCount(T)) : (field_i += 1) { + @field(structure, @memberName(T, field_i)) = zeroes(@TypeOf(@field(structure, @memberName(T, field_i)))); + } + return structure; + } + }, + .Pointer => |ptr_info| { + if (ptr_info.is_allowzero) { + return null; + } else { + switch (ptr_info.size) { + .Slice => { + return &[_]ptr_info.child{}; + }, + .One, .Many, .C => { + @compileError("Can't set a non nullable pointer to zero."); + }, + } + } + }, + .Array => |info| { + var array: T = undefined; + for (array) |*element| { + element.* = zeroes(info.child); + } + return array; + }, + .Vector => |info| { + var vector: T = undefined; + for (vector) |*element| { + *element = zeroes(info.child); + } + return vector; + }, + .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => { + @compileError("Can't set a "++ @typeName(T) ++" to zero."); + }, } - - var item: T = undefined; - @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T)); - return item; } test "mem.zeroes" { @@ -301,6 +355,60 @@ test "mem.zeroes" { testing.expect(a.x == 0); testing.expect(a.y == 10); + + const ZigStruct = struct { + const IntegralTypes = struct { + integer_0: i0, + integer_8: i8, + integer_16: i16, + integer_32: i32, + integer_64: i64, + integer_128: i128, + unsigned_0: u0, + unsigned_8: u8, + unsigned_16: u16, + unsigned_32: u32, + unsigned_64: u64, + unsigned_128: u128, + + float_32: f32, + float_64: f64, + }; + + integral_types: IntegralTypes, + + const Pointers = struct { + optional: ?*u8, + slice: []u8, + }; + pointers: Pointers, + + array: [2]u32, + optional_int: ?u8, + empty: void, + }; + + const b = zeroes(ZigStruct); + testing.expectEqual(@as(i8, 0), b.integral_types.integer_0); + testing.expectEqual(@as(i8, 0), b.integral_types.integer_8); + testing.expectEqual(@as(i16, 0), b.integral_types.integer_16); + testing.expectEqual(@as(i32, 0), b.integral_types.integer_32); + testing.expectEqual(@as(i64, 0), b.integral_types.integer_64); + testing.expectEqual(@as(i128, 0), b.integral_types.integer_128); + testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_0); + testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_8); + testing.expectEqual(@as(u16, 0), b.integral_types.unsigned_16); + testing.expectEqual(@as(u32, 0), b.integral_types.unsigned_32); + testing.expectEqual(@as(u64, 0), b.integral_types.unsigned_64); + testing.expectEqual(@as(u128, 0), b.integral_types.unsigned_128); + testing.expectEqual(@as(f32, 0), b.integral_types.float_32); + testing.expectEqual(@as(f64, 0), b.integral_types.float_64); + testing.expectEqual(@as(?*u8, null), b.pointers.optional); + testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice); + for (b.array) |e| { + testing.expectEqual(@as(u32, 0), e); + } + testing.expectEqual(@as(?u8, null), b.optional_int); } pub fn secureZero(comptime T: type, s: []T) void { From 195195d238bb1348dfd3d304b659e2039a1c3d9f Mon Sep 17 00:00:00 2001 From: Bas van den Berg Date: Mon, 24 Feb 2020 20:50:51 +0100 Subject: [PATCH 101/109] vectors do not support iterating, do not support them (for now) --- lib/std/mem.zig | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8aa0cb2832..aeed32b7e7 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -331,14 +331,7 @@ pub fn zeroes(comptime T: type) T { } return array; }, - .Vector => |info| { - var vector: T = undefined; - for (vector) |*element| { - *element = zeroes(info.child); - } - return vector; - }, - .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => { + .Vector, .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => { @compileError("Can't set a "++ @typeName(T) ++" to zero."); }, } From 45da72c5b64069b7d5238465130a50f96678a148 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 24 Feb 2020 23:03:30 +0200 Subject: [PATCH 102/109] remove usages of `@typeId`, `@memberCount`, `@memberName` and `@memberType` --- lib/std/build.zig | 22 ++++---- lib/std/fmt.zig | 15 +++--- lib/std/io.zig | 46 ++++++++--------- lib/std/math.zig | 32 ++++++------ lib/std/math/big/int.zig | 11 ++-- lib/std/math/big/rational.zig | 9 ++-- lib/std/math/ln.zig | 12 ++--- lib/std/math/log.zig | 14 +++--- lib/std/math/log10.zig | 12 ++--- lib/std/math/log2.zig | 12 ++--- lib/std/meta.zig | 5 +- lib/std/meta/trait.zig | 14 +++--- lib/std/special/build_runner.zig | 2 +- lib/std/thread.zig | 4 +- lib/std/zig/ast.zig | 28 +++++------ lib/std/zig/parser_test.zig | 2 +- lib/std/zig/render.zig | 3 +- src-self-hosted/ir.zig | 39 +++++++-------- src-self-hosted/translate_c.zig | 8 +-- test/compile_errors.zig | 78 ----------------------------- test/stage1/behavior/bugs/3742.zig | 2 +- test/stage1/behavior/enum.zig | 4 +- test/stage1/behavior/error.zig | 7 ++- test/stage1/behavior/eval.zig | 4 +- test/stage1/behavior/misc.zig | 35 ------------- test/stage1/behavior/reflection.zig | 30 ----------- test/stage1/behavior/union.zig | 2 +- test/translate_c.zig | 8 +-- 28 files changed, 145 insertions(+), 315 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 6e9031ee31..143d7ce6c0 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -607,13 +607,13 @@ pub const Builder = struct { } fn typeToEnum(comptime T: type) TypeId { - return switch (@typeId(T)) { - builtin.TypeId.Int => TypeId.Int, - builtin.TypeId.Float => TypeId.Float, - builtin.TypeId.Bool => TypeId.Bool, + return switch (@typeInfo(T)) { + .Int => .Int, + .Float => .Float, + .Bool => .Bool, else => switch (T) { - []const u8 => TypeId.String, - []const []const u8 => TypeId.List, + []const u8 => .String, + []const []const u8 => .List, else => @compileError("Unsupported type: " ++ @typeName(T)), }, }; @@ -625,11 +625,11 @@ pub const Builder = struct { pub fn typeIdName(id: TypeId) []const u8 { return switch (id) { - TypeId.Bool => "bool", - TypeId.Int => "int", - TypeId.Float => "float", - TypeId.String => "string", - TypeId.List => "list", + .Bool => "bool", + .Int => "int", + .Float => "float", + .String => "string", + .List => "list", }; } diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 0fe096a015..5c73ed1252 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -405,7 +405,7 @@ pub fn formatType( try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)}); } }, - .Struct => { + .Struct => |StructT| { if (comptime std.meta.trait.hasFn("format")(T)) { return value.format(fmt, options, context, Errors, output); } @@ -416,27 +416,28 @@ pub fn formatType( } comptime var field_i = 0; try output(context, "{"); - inline while (field_i < @memberCount(T)) : (field_i += 1) { + inline for (StructT.fields) |f| { if (field_i == 0) { try output(context, " ."); } else { try output(context, ", ."); } - try output(context, @memberName(T, field_i)); + try output(context, f.name); try output(context, " = "); - try formatType(@field(value, @memberName(T, field_i)), fmt, options, context, Errors, output, max_depth - 1); + try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1); + field_i += 1; } try output(context, " }"); }, .Pointer => |ptr_info| switch (ptr_info.size) { .One => switch (@typeInfo(ptr_info.child)) { - builtin.TypeId.Array => |info| { + .Array => |info| { if (info.child == u8) { return formatText(value, fmt, options, context, Errors, output); } return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); }, - builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { + .Enum, .Union, .Struct => { return formatType(value.*, fmt, options, context, Errors, output, max_depth); }, else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), @@ -509,7 +510,7 @@ fn formatValue( } const T = @TypeOf(value); - switch (@typeId(T)) { + switch (@typeInfo(T)) { .Float => return formatFloatValue(value, fmt, options, context, Errors, output), .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output), .Bool => return output(context, if (value) "true" else "false"), diff --git a/lib/std/io.zig b/lib/std/io.zig index b6e1b12534..943db1a155 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -831,7 +831,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, //@BUG: inferred error issue. See: #1386 fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T { - comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T)); + comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T)); const u8_bit_count = 8; const t_bit_count = comptime meta.bitCount(T); @@ -880,9 +880,9 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, /// Deserializes data into the type pointed to by `ptr` pub fn deserializeInto(self: *Self, ptr: var) !void { const T = @TypeOf(ptr); - comptime assert(trait.is(builtin.TypeId.Pointer)(T)); + comptime assert(trait.is(.Pointer)(T)); - if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) { + if (comptime trait.isSlice(T) or comptime trait.isPtrTo(.Array)(T)) { for (ptr) |*v| try self.deserializeInto(v); return; @@ -891,7 +891,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, comptime assert(trait.isSingleItemPtr(T)); const C = comptime meta.Child(T); - const child_type_id = @typeId(C); + const child_type_id = @typeInfo(C); //custom deserializer: fn(self: *Self, deserializer: var) !void if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self); @@ -902,10 +902,10 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, } switch (child_type_id) { - builtin.TypeId.Void => return, - builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0, - builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C), - builtin.TypeId.Struct => { + .Void => return, + .Bool => ptr.* = (try self.deserializeInt(u1)) > 0, + .Float, .Int => ptr.* = try self.deserializeInt(C), + .Struct => { const info = @typeInfo(C).Struct; inline for (info.fields) |*field_info| { @@ -915,7 +915,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, if (FieldType == void or FieldType == u0) continue; //it doesn't make any sense to read pointers - if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) { + if (comptime trait.is(.Pointer)(FieldType)) { @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++ @typeName(C) ++ " because it " ++ "is of pointer-type " ++ @typeName(FieldType) ++ "."); @@ -924,7 +924,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, try self.deserializeInto(&@field(ptr, name)); } }, - builtin.TypeId.Union => { + .Union => { const info = @typeInfo(C).Union; if (info.tag_type) |TagType| { //we avoid duplicate iteration over the enum tags @@ -948,7 +948,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++ " because it is an untagged union. Use a custom deserialize()."); }, - builtin.TypeId.Optional => { + .Optional => { const OC = comptime meta.Child(C); const exists = (try self.deserializeInt(u1)) > 0; if (!exists) { @@ -960,7 +960,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, const val_ptr = &ptr.*.?; try self.deserializeInto(val_ptr); }, - builtin.TypeId.Enum => { + .Enum => { var value = try self.deserializeInt(@TagType(C)); ptr.* = try meta.intToEnum(C, value); }, @@ -1009,7 +1009,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co fn serializeInt(self: *Self, value: var) Error!void { const T = @TypeOf(value); - comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T)); + comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T)); const t_bit_count = comptime meta.bitCount(T); const u8_bit_count = comptime meta.bitCount(u8); @@ -1058,11 +1058,11 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co return; } - switch (@typeId(T)) { - builtin.TypeId.Void => return, - builtin.TypeId.Bool => try self.serializeInt(@as(u1, @boolToInt(value))), - builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value), - builtin.TypeId.Struct => { + switch (@typeInfo(T)) { + .Void => return, + .Bool => try self.serializeInt(@as(u1, @boolToInt(value))), + .Float, .Int => try self.serializeInt(value), + .Struct => { const info = @typeInfo(T); inline for (info.Struct.fields) |*field_info| { @@ -1072,7 +1072,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co if (FieldType == void or FieldType == u0) continue; //It doesn't make sense to write pointers - if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) { + if (comptime trait.is(.Pointer)(FieldType)) { @compileError("Will not " ++ "serialize field " ++ name ++ " of struct " ++ @typeName(T) ++ " because it " ++ "is of pointer-type " ++ @typeName(FieldType) ++ "."); @@ -1080,7 +1080,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co try self.serialize(@field(value, name)); } }, - builtin.TypeId.Union => { + .Union => { const info = @typeInfo(T).Union; if (info.tag_type) |TagType| { const active_tag = meta.activeTag(value); @@ -1101,7 +1101,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++ " because it is an untagged union. Use a custom serialize()."); }, - builtin.TypeId.Optional => { + .Optional => { if (value == null) { try self.serializeInt(@as(u1, @boolToInt(false))); return; @@ -1112,10 +1112,10 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co const val_ptr = &value.?; try self.serialize(val_ptr.*); }, - builtin.TypeId.Enum => { + .Enum => { try self.serializeInt(@enumToInt(value)); }, - else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."), + else => @compileError("Cannot serialize " ++ @tagName(@typeInfo(T)) ++ " types (unimplemented)."), } } }; diff --git a/lib/std/math.zig b/lib/std/math.zig index 5885964c34..322fdc7755 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1,6 +1,4 @@ -const builtin = @import("builtin"); const std = @import("std.zig"); -const TypeId = builtin.TypeId; const assert = std.debug.assert; const testing = std.testing; @@ -89,7 +87,7 @@ pub const snan = @import("math/nan.zig").snan; pub const inf = @import("math/inf.zig").inf; pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool { - assert(@typeId(T) == TypeId.Float); + assert(@typeInfo(T) == .Float); return fabs(x - y) < epsilon; } @@ -198,7 +196,7 @@ test "" { } pub fn floatMantissaBits(comptime T: type) comptime_int { - assert(@typeId(T) == builtin.TypeId.Float); + assert(@typeInfo(T) == .Float); return switch (T.bit_count) { 16 => 10, @@ -211,7 +209,7 @@ pub fn floatMantissaBits(comptime T: type) comptime_int { } pub fn floatExponentBits(comptime T: type) comptime_int { - assert(@typeId(T) == builtin.TypeId.Float); + assert(@typeInfo(T) == .Float); return switch (T.bit_count) { 16 => 5, @@ -526,7 +524,7 @@ fn testOverflow() void { pub fn absInt(x: var) !@TypeOf(x) { const T = @TypeOf(x); - comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt + comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt comptime assert(T.is_signed); // must pass a signed integer to absInt if (x == minInt(@TypeOf(x))) { @@ -560,7 +558,7 @@ fn testAbsFloat() void { pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (denominator == 0) return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; + if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; return @divTrunc(numerator, denominator); } @@ -581,7 +579,7 @@ fn testDivTrunc() void { pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (denominator == 0) return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; + if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; return @divFloor(numerator, denominator); } @@ -602,7 +600,7 @@ fn testDivFloor() void { pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { @setRuntimeSafety(false); if (denominator == 0) return error.DivisionByZero; - if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; + if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow; const result = @divTrunc(numerator, denominator); if (result * denominator != numerator) return error.UnexpectedRemainder; return result; @@ -727,8 +725,8 @@ test "math.negateCast" { /// Cast an integer to a different integer type. If the value doesn't fit, /// return an error. pub fn cast(comptime T: type, x: var) (error{Overflow}!T) { - comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer - comptime assert(@typeId(@TypeOf(x)) == builtin.TypeId.Int); // must pass an integer + comptime assert(@typeInfo(T) == .Int); // must pass an integer + comptime assert(@typeInfo(@TypeOf(x)) == .Int); // must pass an integer if (maxInt(@TypeOf(x)) > maxInt(T) and x > maxInt(T)) { return error.Overflow; } else if (minInt(@TypeOf(x)) < minInt(T) and x < minInt(T)) { @@ -793,7 +791,7 @@ fn testFloorPowerOfTwo() void { /// Only unsigned integers can be used. Zero is not an allowed input. /// Result is a type with 1 more bit than the input type. pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T.bit_count + 1) { - comptime assert(@typeId(T) == builtin.TypeId.Int); + comptime assert(@typeInfo(T) == .Int); comptime assert(!T.is_signed); assert(value != 0); comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); @@ -805,7 +803,7 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T /// Only unsigned integers can be used. Zero is not an allowed input. /// If the value doesn't fit, returns an error. pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) { - comptime assert(@typeId(T) == builtin.TypeId.Int); + comptime assert(@typeInfo(T) == .Int); comptime assert(!T.is_signed); comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); comptime const overflowBit = @as(PromotedType, 1) << T.bit_count; @@ -878,10 +876,10 @@ test "std.math.log2_int_ceil" { pub fn lossyCast(comptime T: type, value: var) T { switch (@typeInfo(@TypeOf(value))) { - builtin.TypeId.Int => return @intToFloat(T, value), - builtin.TypeId.Float => return @floatCast(T, value), - builtin.TypeId.ComptimeInt => return @as(T, value), - builtin.TypeId.ComptimeFloat => return @as(T, value), + .Int => return @intToFloat(T, value), + .Float => return @floatCast(T, value), + .ComptimeInt => return @as(T, value), + .ComptimeFloat => return @as(T, value), else => @compileError("bad type"), } } diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index d42d9fc676..0ba3382641 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -1,5 +1,4 @@ const std = @import("../../std.zig"); -const builtin = @import("builtin"); const debug = std.debug; const testing = std.testing; const math = std.math; @@ -9,8 +8,6 @@ const ArrayList = std.ArrayList; const maxInt = std.math.maxInt; const minInt = std.math.minInt; -const TypeId = builtin.TypeId; - pub const Limb = usize; pub const DoubleLimb = @IntType(false, 2 * Limb.bit_count); pub const Log2Limb = math.Log2Int(Limb); @@ -270,7 +267,7 @@ pub const Int = struct { const T = @TypeOf(value); switch (@typeInfo(T)) { - TypeId.Int => |info| { + .Int => |info| { const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T; try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb)); @@ -294,7 +291,7 @@ pub const Int = struct { } } }, - TypeId.ComptimeInt => { + .ComptimeInt => { comptime var w_value = if (value < 0) -value else value; const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1; @@ -332,8 +329,8 @@ pub const Int = struct { /// /// Returns an error if self cannot be narrowed into the requested type without truncation. pub fn to(self: Int, comptime T: type) ConvertError!T { - switch (@typeId(T)) { - TypeId.Int => { + switch (@typeInfo(T)) { + .Int => { const UT = @IntType(false, T.bit_count); if (self.bitCountTwosComp() > T.bit_count) { diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig index 438c6c94fc..f54a234075 100644 --- a/lib/std/math/big/rational.zig +++ b/lib/std/math/big/rational.zig @@ -1,5 +1,4 @@ const std = @import("../../std.zig"); -const builtin = @import("builtin"); const debug = std.debug; const math = std.math; const mem = std.mem; @@ -7,8 +6,6 @@ const testing = std.testing; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; -const TypeId = builtin.TypeId; - const bn = @import("int.zig"); const Limb = bn.Limb; const DoubleLimb = bn.DoubleLimb; @@ -129,7 +126,7 @@ pub const Rational = struct { /// completely represent the provided float. pub fn setFloat(self: *Rational, comptime T: type, f: T) !void { // Translated from golang.go/src/math/big/rat.go. - debug.assert(@typeId(T) == builtin.TypeId.Float); + debug.assert(@typeInfo(T) == .Float); const UnsignedIntType = @IntType(false, T.bit_count); const f_bits = @bitCast(UnsignedIntType, f); @@ -187,7 +184,7 @@ pub const Rational = struct { pub fn toFloat(self: Rational, comptime T: type) !T { // Translated from golang.go/src/math/big/rat.go. // TODO: Indicate whether the result is not exact. - debug.assert(@typeId(T) == builtin.TypeId.Float); + debug.assert(@typeInfo(T) == .Float); const fsize = T.bit_count; const BitReprType = @IntType(false, T.bit_count); @@ -653,7 +650,7 @@ test "big.rational gcd one large" { } fn extractLowBits(a: Int, comptime T: type) T { - testing.expect(@typeId(T) == builtin.TypeId.Int); + testing.expect(@typeInfo(T) == .Int); if (T.bit_count <= Limb.bit_count) { return @truncate(T, a.limbs[0]); diff --git a/lib/std/math/ln.zig b/lib/std/math/ln.zig index da3e60202d..555a786907 100644 --- a/lib/std/math/ln.zig +++ b/lib/std/math/ln.zig @@ -7,8 +7,6 @@ const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; -const builtin = @import("builtin"); -const TypeId = builtin.TypeId; /// Returns the natural logarithm of x. /// @@ -19,21 +17,21 @@ const TypeId = builtin.TypeId; /// - ln(nan) = nan pub fn ln(x: var) @TypeOf(x) { const T = @TypeOf(x); - switch (@typeId(T)) { - TypeId.ComptimeFloat => { + switch (@typeInfo(T)) { + .ComptimeFloat => { return @as(comptime_float, ln_64(x)); }, - TypeId.Float => { + .Float => { return switch (T) { f32 => ln_32(x), f64 => ln_64(x), else => @compileError("ln not implemented for " ++ @typeName(T)), }; }, - TypeId.ComptimeInt => { + .ComptimeInt => { return @as(comptime_int, math.floor(ln_64(@as(f64, x)))); }, - TypeId.Int => { + .Int => { return @as(T, math.floor(ln_64(@as(f64, x)))); }, else => @compileError("ln not implemented for " ++ @typeName(T)), diff --git a/lib/std/math/log.zig b/lib/std/math/log.zig index 9d77397e17..6f5025cd50 100644 --- a/lib/std/math/log.zig +++ b/lib/std/math/log.zig @@ -6,8 +6,6 @@ const std = @import("../std.zig"); const math = std.math; -const builtin = @import("builtin"); -const TypeId = builtin.TypeId; const expect = std.testing.expect; /// Returns the logarithm of x for the provided base. @@ -16,24 +14,24 @@ pub fn log(comptime T: type, base: T, x: T) T { return math.log2(x); } else if (base == 10) { return math.log10(x); - } else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.ComptimeFloat) and base == math.e) { + } else if ((@typeInfo(T) == .Float or @typeInfo(T) == .ComptimeFloat) and base == math.e) { return math.ln(x); } const float_base = math.lossyCast(f64, base); - switch (@typeId(T)) { - TypeId.ComptimeFloat => { + switch (@typeInfo(T)) { + .ComptimeFloat => { return @as(comptime_float, math.ln(@as(f64, x)) / math.ln(float_base)); }, - TypeId.ComptimeInt => { + .ComptimeInt => { return @as(comptime_int, math.floor(math.ln(@as(f64, x)) / math.ln(float_base))); }, - builtin.TypeId.Int => { + .Int => { // TODO implement integer log without using float math return @floatToInt(T, math.floor(math.ln(@intToFloat(f64, x)) / math.ln(float_base))); }, - builtin.TypeId.Float => { + .Float => { switch (T) { f32 => return @floatCast(f32, math.ln(@as(f64, x)) / math.ln(float_base)), f64 => return math.ln(x) / math.ln(float_base), diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig index a0deee69d1..7367af28c6 100644 --- a/lib/std/math/log10.zig +++ b/lib/std/math/log10.zig @@ -7,8 +7,6 @@ const std = @import("../std.zig"); const math = std.math; const testing = std.testing; -const builtin = @import("builtin"); -const TypeId = builtin.TypeId; const maxInt = std.math.maxInt; /// Returns the base-10 logarithm of x. @@ -20,21 +18,21 @@ const maxInt = std.math.maxInt; /// - log10(nan) = nan pub fn log10(x: var) @TypeOf(x) { const T = @TypeOf(x); - switch (@typeId(T)) { - TypeId.ComptimeFloat => { + switch (@typeInfo(T)) { + .ComptimeFloat => { return @as(comptime_float, log10_64(x)); }, - TypeId.Float => { + .Float => { return switch (T) { f32 => log10_32(x), f64 => log10_64(x), else => @compileError("log10 not implemented for " ++ @typeName(T)), }; }, - TypeId.ComptimeInt => { + .ComptimeInt => { return @as(comptime_int, math.floor(log10_64(@as(f64, x)))); }, - TypeId.Int => { + .Int => { return @floatToInt(T, math.floor(log10_64(@intToFloat(f64, x)))); }, else => @compileError("log10 not implemented for " ++ @typeName(T)), diff --git a/lib/std/math/log2.zig b/lib/std/math/log2.zig index d3b655a56a..54f8bc2baa 100644 --- a/lib/std/math/log2.zig +++ b/lib/std/math/log2.zig @@ -7,8 +7,6 @@ const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; -const builtin = @import("builtin"); -const TypeId = builtin.TypeId; const maxInt = std.math.maxInt; /// Returns the base-2 logarithm of x. @@ -20,18 +18,18 @@ const maxInt = std.math.maxInt; /// - log2(nan) = nan pub fn log2(x: var) @TypeOf(x) { const T = @TypeOf(x); - switch (@typeId(T)) { - TypeId.ComptimeFloat => { + switch (@typeInfo(T)) { + .ComptimeFloat => { return @as(comptime_float, log2_64(x)); }, - TypeId.Float => { + .Float => { return switch (T) { f32 => log2_32(x), f64 => log2_64(x), else => @compileError("log2 not implemented for " ++ @typeName(T)), }; }, - TypeId.ComptimeInt => comptime { + .ComptimeInt => comptime { var result = 0; var x_shifted = x; while (b: { @@ -40,7 +38,7 @@ pub fn log2(x: var) @TypeOf(x) { }) : (result += 1) {} return result; }, - TypeId.Int => { + .Int => { return math.log2_int(T, x); }, else => @compileError("log2 not implemented for " ++ @typeName(T)), diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 300bca3d0e..e302a80ef1 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -536,9 +536,8 @@ test "intToEnum with error return" { pub const IntToEnumError = error{InvalidEnumTag}; pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag { - comptime var i = 0; - inline while (i != @memberCount(Tag)) : (i += 1) { - const this_tag_value = @field(Tag, @memberName(Tag, i)); + inline for (@typeInfo(Tag).Enum.fields) |f| { + const this_tag_value = @field(Tag, f.name); if (tag_int == @enumToInt(this_tag_value)) { return this_tag_value; } diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index b17a4a2a93..c0fb8c5025 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -1,5 +1,5 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); +const builtin = std.builtin; const mem = std.mem; const debug = std.debug; const testing = std.testing; @@ -54,7 +54,7 @@ pub fn hasFn(comptime name: []const u8) TraitFn { if (!comptime isContainer(T)) return false; if (!comptime @hasDecl(T, name)) return false; const DeclType = @TypeOf(@field(T, name)); - return @typeId(DeclType) == .Fn; + return @typeInfo(DeclType) == .Fn; } }; return Closure.trait; @@ -105,7 +105,7 @@ test "std.meta.trait.hasField" { pub fn is(comptime id: builtin.TypeId) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { - return id == @typeId(T); + return id == @typeInfo(T); } }; return Closure.trait; @@ -123,7 +123,7 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { if (!comptime isSingleItemPtr(T)) return false; - return id == @typeId(meta.Child(T)); + return id == @typeInfo(meta.Child(T)); } }; return Closure.trait; @@ -139,7 +139,7 @@ pub fn isSliceOf(comptime id: builtin.TypeId) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { if (!comptime isSlice(T)) return false; - return id == @typeId(meta.Child(T)); + return id == @typeInfo(meta.Child(T)); } }; return Closure.trait; @@ -285,7 +285,7 @@ test "std.meta.trait.isIndexable" { } pub fn isNumber(comptime T: type) bool { - return switch (@typeId(T)) { + return switch (@typeInfo(T)) { .Int, .Float, .ComptimeInt, .ComptimeFloat => true, else => false, }; @@ -320,7 +320,7 @@ test "std.meta.trait.isConstPtr" { } pub fn isContainer(comptime T: type) bool { - return switch (@typeId(T)) { + return switch (@typeInfo(T)) { .Struct, .Union, .Enum => true, else => false, }; diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig index 45dea79469..e917dcd8af 100644 --- a/lib/std/special/build_runner.zig +++ b/lib/std/special/build_runner.zig @@ -126,7 +126,7 @@ pub fn main() !void { } fn runBuild(builder: *Builder) anyerror!void { - switch (@typeId(@TypeOf(root.build).ReturnType)) { + switch (@typeInfo(@TypeOf(root.build).ReturnType)) { .Void => root.build(builder), .ErrorUnion => try root.build(builder), else => @compileError("expected return type of build to be 'void' or '!void'"), diff --git a/lib/std/thread.zig b/lib/std/thread.zig index c482405c44..500c94c044 100644 --- a/lib/std/thread.zig +++ b/lib/std/thread.zig @@ -158,7 +158,7 @@ pub const Thread = struct { }; fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD { const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; - switch (@typeId(@TypeOf(startFn).ReturnType)) { + switch (@typeInfo(@TypeOf(startFn).ReturnType)) { .Int => { return startFn(arg); }, @@ -201,7 +201,7 @@ pub const Thread = struct { fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 { const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; - switch (@typeId(@TypeOf(startFn).ReturnType)) { + switch (@typeInfo(@TypeOf(startFn).ReturnType)) { .Int => { return startFn(arg); }, diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index f96428a6bc..bc4f6350d6 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -457,10 +457,9 @@ pub const Node = struct { } pub fn iterate(base: *Node, index: usize) ?*Node { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (base.id == @field(Id, @memberName(Id, i))) { - const T = @field(Node, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (base.id == @field(Id, f.name)) { + const T = @field(Node, f.name); return @fieldParentPtr(T, "base", base).iterate(index); } } @@ -468,10 +467,9 @@ pub const Node = struct { } pub fn firstToken(base: *const Node) TokenIndex { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (base.id == @field(Id, @memberName(Id, i))) { - const T = @field(Node, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (base.id == @field(Id, f.name)) { + const T = @field(Node, f.name); return @fieldParentPtr(T, "base", base).firstToken(); } } @@ -479,10 +477,9 @@ pub const Node = struct { } pub fn lastToken(base: *const Node) TokenIndex { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (base.id == @field(Id, @memberName(Id, i))) { - const T = @field(Node, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (base.id == @field(Id, f.name)) { + const T = @field(Node, f.name); return @fieldParentPtr(T, "base", base).lastToken(); } } @@ -490,10 +487,9 @@ pub const Node = struct { } pub fn typeToId(comptime T: type) Id { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (T == @field(Node, @memberName(Id, i))) { - return @field(Id, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (T == @field(Node, f.name)) { + return @field(Id, f.name); } } unreachable; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 5f28dd3b06..9a023bb525 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1410,7 +1410,7 @@ test "zig fmt: same-line comment after non-block if expression" { test "zig fmt: same-line comment on comptime expression" { try testCanonical( \\test "" { - \\ comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt + \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt \\} \\ ); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 069635d42e..ee6ee37d5d 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const assert = std.debug.assert; const mem = std.mem; const ast = std.zig.ast; @@ -14,7 +13,7 @@ pub const Error = error{ /// Returns whether anything changed pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Child.Error || Error)!bool { - comptime assert(@typeId(@TypeOf(stream)) == builtin.TypeId.Pointer); + comptime assert(@typeInfo(@TypeOf(stream)) == .Pointer); var anything_changed: bool = false; diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index a8f4980fa8..576294a7d7 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -76,20 +76,18 @@ pub const Inst = struct { } pub fn typeToId(comptime T: type) Id { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (T == @field(Inst, @memberName(Id, i))) { - return @field(Id, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (T == @field(Inst, f.name)) { + return @field(Id, f.name); } } unreachable; } pub fn dump(base: *const Inst) void { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (base.id == @field(Id, @memberName(Id, i))) { - const T = @field(Inst, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (base.id == @field(Id, f.name)) { + const T = @field(Inst, f.name); std.debug.warn("#{} = {}(", .{ base.debug_id, @tagName(base.id) }); @fieldParentPtr(T, "base", base).dump(); std.debug.warn(")", .{}); @@ -100,10 +98,9 @@ pub const Inst = struct { } pub fn hasSideEffects(base: *const Inst) bool { - comptime var i = 0; - inline while (i < @memberCount(Id)) : (i += 1) { - if (base.id == @field(Id, @memberName(Id, i))) { - const T = @field(Inst, @memberName(Id, i)); + inline for (@typeInfo(Id).Enum.fields) |f| { + if (base.id == @field(Id, f.name)) { + const T = @field(Inst, f.name); return @fieldParentPtr(T, "base", base).hasSideEffects(); } } @@ -1805,21 +1802,19 @@ pub const Builder = struct { }; // Look at the params and ref() other instructions - comptime var i = 0; - inline while (i < @memberCount(I.Params)) : (i += 1) { - const FieldType = comptime @TypeOf(@field(@as(I.Params, undefined), @memberName(I.Params, i))); - switch (FieldType) { - *Inst => @field(inst.params, @memberName(I.Params, i)).ref(self), - *BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self), - ?*Inst => if (@field(inst.params, @memberName(I.Params, i))) |other| other.ref(self), + inline for (@typeInfo(I.Params).Struct.fields) |f| { + switch (f.fiedl_type) { + *Inst => @field(inst.params, f.name).ref(self), + *BasicBlock => @field(inst.params, f.name).ref(self), + ?*Inst => if (@field(inst.params, f.name)) |other| other.ref(self), []*Inst => { // TODO https://github.com/ziglang/zig/issues/1269 - for (@field(inst.params, @memberName(I.Params, i))) |other| + for (@field(inst.params, f.name)) |other| other.ref(self); }, []*BasicBlock => { // TODO https://github.com/ziglang/zig/issues/1269 - for (@field(inst.params, @memberName(I.Params, i))) |other| + for (@field(inst.params, f.name)) |other| other.ref(self); }, Type.Pointer.Mut, @@ -1831,7 +1826,7 @@ pub const Builder = struct { => {}, // it's ok to add more types here, just make sure that // any instructions and basic blocks are ref'd appropriately - else => @compileError("unrecognized type in Params: " ++ @typeName(FieldType)), + else => @compileError("unrecognized type in Params: " ++ @typeName(f.field_type)), } } diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index cd8d0b9d63..b33c758c38 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -5381,15 +5381,15 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, return error.ParseError; } - //if (@typeId(@TypeOf(x)) == .Pointer) + //if (@typeInfo(@TypeOf(x)) == .Pointer) // @ptrCast(dest, x) - //else if (@typeId(@TypeOf(x)) == .Integer) + //else if (@typeInfo(@TypeOf(x)) == .Integer) // @intToPtr(dest, x) //else // @as(dest, x) const if_1 = try transCreateNodeIf(c); - const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeId"); + const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo"); const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); try type_id_1.params.push(&type_of_1.base); try type_of_1.params.push(node_to_cast); @@ -5416,7 +5416,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, if_1.@"else" = else_1; const if_2 = try transCreateNodeIf(c); - const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeId"); + const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeInfo"); const type_of_2 = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); try type_id_2.params.push(&type_of_2.base); try type_of_2.params.push(node_to_cast); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 39c83c4403..a4bb333873 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2942,14 +2942,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:11:13: error: error.B not a member of error set 'Set2'", }); - cases.add("@memberCount of error", - \\comptime { - \\ _ = @memberCount(anyerror); - \\} - , &[_][]const u8{ - "tmp.zig:2:9: error: global error set member count not available at comptime", - }); - cases.add("duplicate error value in error set", \\const Foo = error { \\ Bar, @@ -5964,76 +5956,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments", }); - cases.add("@memberType on unsupported type", - \\comptime { - \\ _ = @memberType(i32, 0); - \\} - , &[_][]const u8{ - "tmp.zig:2:21: error: type 'i32' does not support @memberType", - }); - - cases.add("@memberType on enum", - \\comptime { - \\ _ = @memberType(Foo, 0); - \\} - \\const Foo = enum {A,}; - , &[_][]const u8{ - "tmp.zig:2:21: error: type 'Foo' does not support @memberType", - }); - - cases.add("@memberType struct out of bounds", - \\comptime { - \\ _ = @memberType(Foo, 0); - \\} - \\const Foo = struct {}; - , &[_][]const u8{ - "tmp.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members", - }); - - cases.add("@memberType union out of bounds", - \\comptime { - \\ _ = @memberType(Foo, 1); - \\} - \\const Foo = union {A: void,}; - , &[_][]const u8{ - "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", - }); - - cases.add("@memberName on unsupported type", - \\comptime { - \\ _ = @memberName(i32, 0); - \\} - , &[_][]const u8{ - "tmp.zig:2:21: error: type 'i32' does not support @memberName", - }); - - cases.add("@memberName struct out of bounds", - \\comptime { - \\ _ = @memberName(Foo, 0); - \\} - \\const Foo = struct {}; - , &[_][]const u8{ - "tmp.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members", - }); - - cases.add("@memberName enum out of bounds", - \\comptime { - \\ _ = @memberName(Foo, 1); - \\} - \\const Foo = enum {A,}; - , &[_][]const u8{ - "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", - }); - - cases.add("@memberName union out of bounds", - \\comptime { - \\ _ = @memberName(Foo, 1); - \\} - \\const Foo = union {A:i32,}; - , &[_][]const u8{ - "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members", - }); - cases.add("calling var args extern function, passing array instead of pointer", \\export fn entry() void { \\ foo("hello".*,); diff --git a/test/stage1/behavior/bugs/3742.zig b/test/stage1/behavior/bugs/3742.zig index 01bcb49f3c..f09127a66f 100644 --- a/test/stage1/behavior/bugs/3742.zig +++ b/test/stage1/behavior/bugs/3742.zig @@ -17,7 +17,7 @@ pub const GET = struct { }; pub fn isCommand(comptime T: type) bool { - const tid = @typeId(T); + const tid = @typeInfo(T); return (tid == .Struct or tid == .Enum or tid == .Union) and @hasDecl(T, "Redis") and @hasDecl(T.Redis, "Command"); } diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index 6187cee431..18489ba24b 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -96,8 +96,8 @@ test "enum type" { const bar = Bar.B; expect(bar == Bar.B); - expect(@memberCount(Foo) == 3); - expect(@memberCount(Bar) == 4); + expect(@typeInfo(Foo).Union.fields.len == 3); + expect(@typeInfo(Bar).Enum.fields.len == 4); expect(@sizeOf(Foo) == @sizeOf(FooNoVoid)); expect(@sizeOf(Bar) == 1); } diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig index d4f64b7cff..def7fd679d 100644 --- a/test/stage1/behavior/error.zig +++ b/test/stage1/behavior/error.zig @@ -3,7 +3,6 @@ const expect = std.testing.expect; const expectError = std.testing.expectError; const expectEqual = std.testing.expectEqual; const mem = std.mem; -const builtin = @import("builtin"); pub fn foo() anyerror!i32 { const x = try bar(); @@ -84,8 +83,8 @@ test "error union type " { fn testErrorUnionType() void { const x: anyerror!i32 = 1234; if (x) |value| expect(value == 1234) else |_| unreachable; - expect(@typeId(@TypeOf(x)) == builtin.TypeId.ErrorUnion); - expect(@typeId(@TypeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); + expect(@typeInfo(@TypeOf(x)) == .ErrorUnion); + expect(@typeInfo(@TypeOf(x).ErrorSet) == .ErrorSet); expect(@TypeOf(x).ErrorSet == anyerror); } @@ -100,7 +99,7 @@ const MyErrSet = error{ }; fn testErrorSetType() void { - expect(@memberCount(MyErrSet) == 2); + expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2); const a: MyErrSet!i32 = 5678; const b: MyErrSet!i32 = MyErrSet.OutOfMemory; diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig index 099434a869..8e70e97aaa 100644 --- a/test/stage1/behavior/eval.zig +++ b/test/stage1/behavior/eval.zig @@ -654,8 +654,8 @@ test "call method with comptime pass-by-non-copying-value self parameter" { expect(b == 2); } -test "@tagName of @typeId" { - const str = @tagName(@typeId(u8)); +test "@tagName of @typeInfo" { + const str = @tagName(@typeInfo(u8)); expect(std.mem.eql(u8, str, "Int")); } diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index a3a008c1d2..032f2429ed 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -407,7 +407,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) void { expect(ptr2[1] == 2.0); } -const Tid = builtin.TypeId; const AStruct = struct { x: i32, }; @@ -424,40 +423,6 @@ const AUnion = union { Two: void, }; -test "@typeId" { - comptime { - expect(@typeId(type) == Tid.Type); - expect(@typeId(void) == Tid.Void); - expect(@typeId(bool) == Tid.Bool); - expect(@typeId(noreturn) == Tid.NoReturn); - expect(@typeId(i8) == Tid.Int); - expect(@typeId(u8) == Tid.Int); - expect(@typeId(i64) == Tid.Int); - expect(@typeId(u64) == Tid.Int); - expect(@typeId(f32) == Tid.Float); - expect(@typeId(f64) == Tid.Float); - expect(@typeId(*f32) == Tid.Pointer); - expect(@typeId([2]u8) == Tid.Array); - expect(@typeId(AStruct) == Tid.Struct); - expect(@typeId(@TypeOf(1)) == Tid.ComptimeInt); - expect(@typeId(@TypeOf(1.0)) == Tid.ComptimeFloat); - expect(@typeId(@TypeOf(undefined)) == Tid.Undefined); - expect(@typeId(@TypeOf(null)) == Tid.Null); - expect(@typeId(?i32) == Tid.Optional); - expect(@typeId(anyerror!i32) == Tid.ErrorUnion); - expect(@typeId(anyerror) == Tid.ErrorSet); - expect(@typeId(AnEnum) == Tid.Enum); - expect(@typeId(@TypeOf(AUnionEnum.One)) == Tid.Enum); - expect(@typeId(AUnionEnum) == Tid.Union); - expect(@typeId(AUnion) == Tid.Union); - expect(@typeId(fn () void) == Tid.Fn); - expect(@typeId(@TypeOf(builtin)) == Tid.Type); - // TODO bound fn - // TODO arg tuple - // TODO opaque - } -} - test "@typeName" { const Struct = struct {}; const Union = union { diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig index 37bf2a582c..a32f97e8ac 100644 --- a/test/stage1/behavior/reflection.zig +++ b/test/stage1/behavior/reflection.zig @@ -26,36 +26,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; } -test "reflection: struct member types and names" { - comptime { - expect(@memberCount(Foo) == 3); - - expect(@memberType(Foo, 0) == i32); - expect(@memberType(Foo, 1) == bool); - expect(@memberType(Foo, 2) == void); - - expect(mem.eql(u8, @memberName(Foo, 0), "one")); - expect(mem.eql(u8, @memberName(Foo, 1), "two")); - expect(mem.eql(u8, @memberName(Foo, 2), "three")); - } -} - -test "reflection: enum member types and names" { - comptime { - expect(@memberCount(Bar) == 4); - - expect(@memberType(Bar, 0) == void); - expect(@memberType(Bar, 1) == i32); - expect(@memberType(Bar, 2) == bool); - expect(@memberType(Bar, 3) == f64); - - expect(mem.eql(u8, @memberName(Bar, 0), "One")); - expect(mem.eql(u8, @memberName(Bar, 1), "Two")); - expect(mem.eql(u8, @memberName(Bar, 2), "Three")); - expect(mem.eql(u8, @memberName(Bar, 3), "Four")); - } -} - test "reflection: @field" { var f = Foo{ .one = 42, diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index 4625b7573a..7f49049f58 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -531,7 +531,7 @@ var glbl: Foo1 = undefined; test "global union with single field is correctly initialized" { glbl = Foo1{ - .f = @memberType(Foo1, 0){ .x = 123 }, + .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 }, }; expect(glbl.f.x == 123); } diff --git a/test/translate_c.zig b/test/translate_c.zig index e3c68a6d53..701513153c 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1354,7 +1354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("macro pointer cast", \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) , &[_][]const u8{ - \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE); + \\pub const NRF_GPIO = if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE); }); cases.add("basic macro function", @@ -2538,11 +2538,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\#define FOO(bar) baz((void *)(baz)) \\#define BAR (void*) a , &[_][]const u8{ - \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) { - \\ return baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)); + \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) { + \\ return baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)); \\} , - \\pub const BAR = if (@typeId(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeId(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a); + \\pub const BAR = if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a); }); cases.add("macro conditional operator", From f7aa4f5280e170966e8a7ed92468f76fa87963e1 Mon Sep 17 00:00:00 2001 From: Bas van den Berg Date: Mon, 24 Feb 2020 22:15:04 +0100 Subject: [PATCH 103/109] Processed review comments. Updated documentation, used the typinfo for field access, generate compile error on allowzero and set C poitners to null --- lib/std/mem.zig | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index aeed32b7e7..685bf72c49 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -276,8 +276,12 @@ pub fn set(comptime T: type, dest: []T, value: T) void { d.* = value; } +/// Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function. +/// However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when +/// interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this +/// function used, examine closely - it may be a code smell. /// Zero initializes the type. -/// This can be used to zero initialize a C-struct. +/// This can be used to zero initialize a any type for which it makes sense. Structs will be initialized recursively. pub fn zeroes(comptime T: type) T { switch (@typeInfo(T)) { .ComptimeInt, .Int, .ComptimeFloat, .Float => { @@ -295,7 +299,7 @@ pub fn zeroes(comptime T: type) T { .Optional, .Null => { return null; }, - .Struct => { + .Struct => |struct_info| { if (@sizeOf(T) == 0) return T{}; if (comptime meta.containerLayout(T) == .Extern) { var item: T = undefined; @@ -303,25 +307,23 @@ pub fn zeroes(comptime T: type) T { return item; } else { var structure: T = undefined; - comptime var field_i = 0; - inline while (field_i < @memberCount(T)) : (field_i += 1) { - @field(structure, @memberName(T, field_i)) = zeroes(@TypeOf(@field(structure, @memberName(T, field_i)))); + inline for (struct_info.fields) |field| { + @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name))); } return structure; } }, .Pointer => |ptr_info| { - if (ptr_info.is_allowzero) { - return null; - } else { - switch (ptr_info.size) { - .Slice => { - return &[_]ptr_info.child{}; - }, - .One, .Many, .C => { - @compileError("Can't set a non nullable pointer to zero."); - }, - } + switch (ptr_info.size) { + .Slice => { + return &[_]ptr_info.child{}; + }, + .C => { + return null; + }, + .One, .Many => { + @compileError("Can't set a non nullable pointer to zero."); + }, } }, .Array => |info| { @@ -372,6 +374,7 @@ test "mem.zeroes" { const Pointers = struct { optional: ?*u8, + c_pointer: [*c]u8, slice: []u8, }; pointers: Pointers, @@ -397,6 +400,7 @@ test "mem.zeroes" { testing.expectEqual(@as(f32, 0), b.integral_types.float_32); testing.expectEqual(@as(f64, 0), b.integral_types.float_64); testing.expectEqual(@as(?*u8, null), b.pointers.optional); + testing.expectEqual(@as([*c]u8, null), b.pointers.c_pointer); testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice); for (b.array) |e| { testing.expectEqual(@as(u32, 0), e); From 3458fb891d8c7072a9bff6a32db9f3105ab72aa4 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 24 Feb 2020 23:21:11 +0200 Subject: [PATCH 104/109] remove `@typeId`, `@memberCount`, `@memberName` and `@memberType` from the compiler --- doc/langref.html.in | 84 ++----------- src/all_types.hpp | 34 ------ src/codegen.cpp | 4 - src/ir.cpp | 282 -------------------------------------------- src/ir_print.cpp | 48 -------- 5 files changed, 8 insertions(+), 444 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 4ac9cf47e0..d186e68451 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2810,14 +2810,10 @@ test "@TagType" { assert(@TagType(Small) == u2); } -// @memberCount tells how many fields an enum has: -test "@memberCount" { - assert(@memberCount(Small) == 4); -} - -// @memberName tells the name of a field in an enum: -test "@memberName" { - assert(mem.eql(u8, @memberName(Small, 1), "Two")); +// @typeInfo tells us the field count and the fields name: +test "@typeInfo" { + assert(@typeInfo(Small).Enum.fields.len == 4); + assert(mem.eql(u8, @typeInfo(Small).Enum.fields[0].name, "Two")); } // @tagName gives a []const u8 representation of an enum value: @@ -2825,7 +2821,7 @@ test "@tagName" { assert(mem.eql(u8, @tagName(Small.Three), "Three")); } {#code_end#} - {#see_also|@memberName|@memberCount|@tagName|@sizeOf#} + {#see_also|@typeInfo|@tagName|@sizeOf#} {#header_open|extern enum#}

    @@ -6816,7 +6812,7 @@ async fn func(y: *i32) void { Asserts that {#syntax#}@sizeOf(@TypeOf(value)) == @sizeOf(DestType){#endsyntax#}.

    - Asserts that {#syntax#}@typeId(DestType) != @import("builtin").TypeId.Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this. + Asserts that {#syntax#}@typeInfo(DestType) != .Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this.

    Can be used for these things for example: @@ -7269,7 +7265,7 @@ test "main" {

    Floored division. Rounds toward negative infinity. For unsigned integers it is the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and - {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}. + {#syntax#}!(@typeInfo(T) == .Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.

    • {#syntax#}@divFloor(-5, 3) == -2{#endsyntax#}
    • @@ -7283,7 +7279,7 @@ test "main" {

      Truncated division. Rounds toward zero. For unsigned integers it is the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and - {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}. + {#syntax#}!(@typeInfo(T) == .Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.

      • {#syntax#}@divTrunc(-5, 3) == -1{#endsyntax#}
      • @@ -7679,33 +7675,6 @@ test "@hasDecl" {

        {#header_close#} - {#header_open|@memberCount#} -
        {#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}
        -

        - This function returns the number of members in a struct, enum, or union type. -

        -

        - The result is a compile time constant. -

        -

        - It does not include functions, variables, or constants. -

        - {#header_close#} - {#header_open|@memberName#} -
        {#syntax#}@memberName(comptime T: type, comptime index: usize) [N]u8{#endsyntax#}
        -

        Returns the field name of a struct, union, or enum.

        -

        - The result is a compile time constant. -

        -

        - It does not include functions, variables, or constants. -

        - {#header_close#} - {#header_open|@memberType#} -
        {#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}
        -

        Returns the field type of a struct or union.

        - {#header_close#} - {#header_open|@memcpy#}
        {#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}

        @@ -8401,43 +8370,6 @@ test "integer truncation" {

      • {#link|struct#}
      {#header_close#} - - {#header_open|@typeId#} -
      {#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}
      -

      - Returns which kind of type something is. Possible values: -

      - {#code_begin|syntax#} -pub const TypeId = enum { - Type, - Void, - Bool, - NoReturn, - Int, - Float, - Pointer, - Array, - Struct, - ComptimeFloat, - ComptimeInt, - Undefined, - Null, - Optional, - ErrorUnion, - ErrorSet, - Enum, - Union, - Fn, - BoundFn, - Opaque, - Frame, - AnyFrame, - Vector, - EnumLiteral, -}; - {#code_end#} - {#header_close#} - {#header_open|@typeInfo#}
      {#syntax#}@typeInfo(comptime T: type) @import("std").builtin.TypeInfo{#endsyntax#}

      diff --git a/src/all_types.hpp b/src/all_types.hpp index 117a0004f0..9f20d176bf 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1695,9 +1695,6 @@ enum BuiltinFnId { BuiltinFnIdMemset, BuiltinFnIdSizeof, BuiltinFnIdAlignOf, - BuiltinFnIdMemberCount, - BuiltinFnIdMemberType, - BuiltinFnIdMemberName, BuiltinFnIdField, BuiltinFnIdTypeInfo, BuiltinFnIdType, @@ -1777,7 +1774,6 @@ enum BuiltinFnId { BuiltinFnIdBitOffsetOf, BuiltinFnIdNewStackCall, BuiltinFnIdAsyncCall, - BuiltinFnIdTypeId, BuiltinFnIdShlExact, BuiltinFnIdShrExact, BuiltinFnIdSetEvalBranchQuota, @@ -2638,9 +2634,6 @@ enum IrInstSrcId { IrInstSrcIdMemset, IrInstSrcIdMemcpy, IrInstSrcIdSlice, - IrInstSrcIdMemberCount, - IrInstSrcIdMemberType, - IrInstSrcIdMemberName, IrInstSrcIdBreakpoint, IrInstSrcIdReturnAddress, IrInstSrcIdFrameAddress, @@ -2677,7 +2670,6 @@ enum IrInstSrcId { IrInstSrcIdTypeInfo, IrInstSrcIdType, IrInstSrcIdHasField, - IrInstSrcIdTypeId, IrInstSrcIdSetEvalBranchQuota, IrInstSrcIdPtrType, IrInstSrcIdAlignCast, @@ -3715,26 +3707,6 @@ struct IrInstGenSlice { bool safety_check_on; }; -struct IrInstSrcMemberCount { - IrInstSrc base; - - IrInstSrc *container; -}; - -struct IrInstSrcMemberType { - IrInstSrc base; - - IrInstSrc *container_type; - IrInstSrc *member_index; -}; - -struct IrInstSrcMemberName { - IrInstSrc base; - - IrInstSrc *container_type; - IrInstSrc *member_index; -}; - struct IrInstSrcBreakpoint { IrInstSrc base; }; @@ -4142,12 +4114,6 @@ struct IrInstSrcHasField { IrInstSrc *field_name; }; -struct IrInstSrcTypeId { - IrInstSrc base; - - IrInstSrc *type_value; -}; - struct IrInstSrcSetEvalBranchQuota { IrInstSrc base; diff --git a/src/codegen.cpp b/src/codegen.cpp index 12293cd9b3..c6ee153573 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8152,9 +8152,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3); create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1); create_builtin_fn(g, BuiltinFnIdAlignOf, "alignOf", 1); - create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); - create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); - create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); create_builtin_fn(g, BuiltinFnIdField, "field", 2); create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1); create_builtin_fn(g, BuiltinFnIdType, "Type", 1); @@ -8231,7 +8228,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4); create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX); - create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1); create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2); create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2); create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1); diff --git a/src/ir.cpp b/src/ir.cpp index 80fef04496..6646d0ed55 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -405,12 +405,6 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSlice: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMemberCount: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMemberType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdMemberName: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBreakpoint: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdReturnAddress: @@ -477,8 +471,6 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdHasField: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdTypeId: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetEvalBranchQuota: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAlignCast: @@ -1325,18 +1317,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { return IrInstSrcIdSlice; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberCount *) { - return IrInstSrcIdMemberCount; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberType *) { - return IrInstSrcIdMemberType; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberName *) { - return IrInstSrcIdMemberName; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { return IrInstSrcIdBreakpoint; } @@ -1481,10 +1461,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { return IrInstSrcIdHasField; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeId *) { - return IrInstSrcIdTypeId; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { return IrInstSrcIdSetEvalBranchQuota; } @@ -3749,41 +3725,6 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, return &instruction->base; } -static IrInstSrc *ir_build_member_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *container) { - IrInstSrcMemberCount *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container = container; - - ir_ref_instruction(container, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_member_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container_type, IrInstSrc *member_index) -{ - IrInstSrcMemberType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container_type = container_type; - instruction->member_index = member_index; - - ir_ref_instruction(container_type, irb->current_basic_block); - ir_ref_instruction(member_index, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_member_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *container_type, IrInstSrc *member_index) -{ - IrInstSrcMemberName *instruction = ir_build_instruction(irb, scope, source_node); - instruction->container_type = container_type; - instruction->member_index = member_index; - - ir_ref_instruction(container_type, irb->current_basic_block); - ir_ref_instruction(member_index, irb->current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { IrInstSrcBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); return &instruction->base; @@ -4458,15 +4399,6 @@ static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source return &instruction->base; } -static IrInstSrc *ir_build_type_id(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { - IrInstSrcTypeId *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type_value = type_value; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *new_quota) { @@ -6710,48 +6642,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); } - case BuiltinFnIdMemberCount: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *member_count = ir_build_member_count(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, member_count, lval, result_loc); - } - case BuiltinFnIdMemberType: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - - IrInstSrc *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, member_type, lval, result_loc); - } - case BuiltinFnIdMemberName: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - - IrInstSrc *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, member_name, lval, result_loc); - } case BuiltinFnIdField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -7109,16 +6999,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod } case BuiltinFnIdAsyncCall: return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc); - case BuiltinFnIdTypeId: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *type_id = ir_build_type_id(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, type_id, lval, result_loc); - } case BuiltinFnIdShlExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -24795,19 +24675,6 @@ static IrInstGen *ir_analyze_instruction_type(IrAnalyze *ira, IrInstSrcType *ins return ir_const_type(ira, &instruction->base.base, type); } -static IrInstGen *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstSrcTypeId *instruction) { - IrInstGen *type_value = instruction->type_value->child; - ZigType *type_entry = ir_resolve_type(ira, type_value); - if (type_is_invalid(type_entry)) - return ira->codegen->invalid_inst_gen; - - ZigType *result_type = get_builtin_type(ira->codegen, "TypeId"); - - IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); - bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry)); - return result; -} - static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, IrInstSrcSetEvalBranchQuota *instruction) { @@ -26445,143 +26312,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc); } -static IrInstGen *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstSrcMemberCount *instruction) { - Error err; - IrInstGen *container = instruction->container->child; - if (type_is_invalid(container->value->type)) - return ira->codegen->invalid_inst_gen; - ZigType *container_type = ir_resolve_type(ira, container); - - if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_inst_gen; - - uint64_t result; - if (type_is_invalid(container_type)) { - return ira->codegen->invalid_inst_gen; - } else if (container_type->id == ZigTypeIdEnum) { - result = container_type->data.enumeration.src_field_count; - } else if (container_type->id == ZigTypeIdStruct) { - result = container_type->data.structure.src_field_count; - } else if (container_type->id == ZigTypeIdUnion) { - result = container_type->data.unionation.src_field_count; - } else if (container_type->id == ZigTypeIdErrorSet) { - if (!resolve_inferred_error_set(ira->codegen, container_type, instruction->base.base.source_node)) { - return ira->codegen->invalid_inst_gen; - } - if (type_is_global_error_set(container_type)) { - ir_add_error(ira, &instruction->base.base, buf_sprintf("global error set member count not available at comptime")); - return ira->codegen->invalid_inst_gen; - } - result = container_type->data.error_set.err_count; - } else { - ir_add_error(ira, &instruction->base.base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name))); - return ira->codegen->invalid_inst_gen; - } - - return ir_const_unsigned(ira, &instruction->base.base, result); -} - -static IrInstGen *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstSrcMemberType *instruction) { - Error err; - IrInstGen *container_type_value = instruction->container_type->child; - ZigType *container_type = ir_resolve_type(ira, container_type_value); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_inst_gen; - - if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_inst_gen; - - - uint64_t member_index; - IrInstGen *index_value = instruction->member_index->child; - if (!ir_resolve_usize(ira, index_value, &member_index)) - return ira->codegen->invalid_inst_gen; - - if (container_type->id == ZigTypeIdStruct) { - if (member_index >= container_type->data.structure.src_field_count) { - ir_add_error(ira, &index_value->base, - buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", - member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); - return ira->codegen->invalid_inst_gen; - } - TypeStructField *field = container_type->data.structure.fields[member_index]; - - return ir_const_type(ira, &instruction->base.base, field->type_entry); - } else if (container_type->id == ZigTypeIdUnion) { - if (member_index >= container_type->data.unionation.src_field_count) { - ir_add_error(ira, &index_value->base, - buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", - member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); - return ira->codegen->invalid_inst_gen; - } - TypeUnionField *field = &container_type->data.unionation.fields[member_index]; - - return ir_const_type(ira, &instruction->base.base, field->type_entry); - } else { - ir_add_error(ira, &container_type_value->base, - buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name))); - return ira->codegen->invalid_inst_gen; - } -} - -static IrInstGen *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstSrcMemberName *instruction) { - Error err; - IrInstGen *container_type_value = instruction->container_type->child; - ZigType *container_type = ir_resolve_type(ira, container_type_value); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_inst_gen; - - if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_inst_gen; - - uint64_t member_index; - IrInstGen *index_value = instruction->member_index->child; - if (!ir_resolve_usize(ira, index_value, &member_index)) - return ira->codegen->invalid_inst_gen; - - if (container_type->id == ZigTypeIdStruct) { - if (member_index >= container_type->data.structure.src_field_count) { - ir_add_error(ira, &index_value->base, - buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", - member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); - return ira->codegen->invalid_inst_gen; - } - TypeStructField *field = container_type->data.structure.fields[member_index]; - - IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - init_const_str_lit(ira->codegen, result->value, field->name); - return result; - } else if (container_type->id == ZigTypeIdEnum) { - if (member_index >= container_type->data.enumeration.src_field_count) { - ir_add_error(ira, &index_value->base, - buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", - member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); - return ira->codegen->invalid_inst_gen; - } - TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; - - IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - init_const_str_lit(ira->codegen, result->value, field->name); - return result; - } else if (container_type->id == ZigTypeIdUnion) { - if (member_index >= container_type->data.unionation.src_field_count) { - ir_add_error(ira, &index_value->base, - buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", - member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); - return ira->codegen->invalid_inst_gen; - } - TypeUnionField *field = &container_type->data.unionation.fields[member_index]; - - IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - init_const_str_lit(ira->codegen, result->value, field->name); - return result; - } else { - ir_add_error(ira, &container_type_value->base, - buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name))); - return ira->codegen->invalid_inst_gen; - } -} - static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) { Error err; ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); @@ -29556,12 +29286,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_memcpy(ira, (IrInstSrcMemcpy *)instruction); case IrInstSrcIdSlice: return ir_analyze_instruction_slice(ira, (IrInstSrcSlice *)instruction); - case IrInstSrcIdMemberCount: - return ir_analyze_instruction_member_count(ira, (IrInstSrcMemberCount *)instruction); - case IrInstSrcIdMemberType: - return ir_analyze_instruction_member_type(ira, (IrInstSrcMemberType *)instruction); - case IrInstSrcIdMemberName: - return ir_analyze_instruction_member_name(ira, (IrInstSrcMemberName *)instruction); case IrInstSrcIdBreakpoint: return ir_analyze_instruction_breakpoint(ira, (IrInstSrcBreakpoint *)instruction); case IrInstSrcIdReturnAddress: @@ -29616,8 +29340,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_type(ira, (IrInstSrcType *)instruction); case IrInstSrcIdHasField: return ir_analyze_instruction_has_field(ira, (IrInstSrcHasField *) instruction); - case IrInstSrcIdTypeId: - return ir_analyze_instruction_type_id(ira, (IrInstSrcTypeId *)instruction); case IrInstSrcIdSetEvalBranchQuota: return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction); case IrInstSrcIdPtrType: @@ -30038,9 +29760,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdSplat: case IrInstSrcIdBoolNot: case IrInstSrcIdSlice: - case IrInstSrcIdMemberCount: - case IrInstSrcIdMemberType: - case IrInstSrcIdMemberName: case IrInstSrcIdAlignOf: case IrInstSrcIdReturnAddress: case IrInstSrcIdFrameAddress: @@ -30067,7 +29786,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdTypeInfo: case IrInstSrcIdType: case IrInstSrcIdHasField: - case IrInstSrcIdTypeId: case IrInstSrcIdAlignCast: case IrInstSrcIdImplicitCast: case IrInstSrcIdResolveResult: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 6d04db6168..4f87ff832d 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -191,12 +191,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcMemcpy"; case IrInstSrcIdSlice: return "SrcSlice"; - case IrInstSrcIdMemberCount: - return "SrcMemberCount"; - case IrInstSrcIdMemberType: - return "SrcMemberType"; - case IrInstSrcIdMemberName: - return "SrcMemberName"; case IrInstSrcIdBreakpoint: return "SrcBreakpoint"; case IrInstSrcIdReturnAddress: @@ -269,8 +263,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcType"; case IrInstSrcIdHasField: return "SrcHasField"; - case IrInstSrcIdTypeId: - return "SrcTypeId"; case IrInstSrcIdSetEvalBranchQuota: return "SrcSetEvalBranchQuota"; case IrInstSrcIdPtrType: @@ -1784,28 +1776,6 @@ static void ir_print_slice_gen(IrPrintGen *irp, IrInstGenSlice *instruction) { ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_member_count(IrPrintSrc *irp, IrInstSrcMemberCount *instruction) { - fprintf(irp->f, "@memberCount("); - ir_print_other_inst_src(irp, instruction->container); - fprintf(irp->f, ")"); -} - -static void ir_print_member_type(IrPrintSrc *irp, IrInstSrcMemberType *instruction) { - fprintf(irp->f, "@memberType("); - ir_print_other_inst_src(irp, instruction->container_type); - fprintf(irp->f, ", "); - ir_print_other_inst_src(irp, instruction->member_index); - fprintf(irp->f, ")"); -} - -static void ir_print_member_name(IrPrintSrc *irp, IrInstSrcMemberName *instruction) { - fprintf(irp->f, "@memberName("); - ir_print_other_inst_src(irp, instruction->container_type); - fprintf(irp->f, ", "); - ir_print_other_inst_src(irp, instruction->member_index); - fprintf(irp->f, ")"); -} - static void ir_print_breakpoint(IrPrintSrc *irp, IrInstSrcBreakpoint *instruction) { fprintf(irp->f, "@breakpoint()"); } @@ -2279,12 +2249,6 @@ static void ir_print_has_field(IrPrintSrc *irp, IrInstSrcHasField *instruction) fprintf(irp->f, ")"); } -static void ir_print_type_id(IrPrintSrc *irp, IrInstSrcTypeId *instruction) { - fprintf(irp->f, "@typeId("); - ir_print_other_inst_src(irp, instruction->type_value); - fprintf(irp->f, ")"); -} - static void ir_print_set_eval_branch_quota(IrPrintSrc *irp, IrInstSrcSetEvalBranchQuota *instruction) { fprintf(irp->f, "@setEvalBranchQuota("); ir_print_other_inst_src(irp, instruction->new_quota); @@ -2799,15 +2763,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdSlice: ir_print_slice_src(irp, (IrInstSrcSlice *)instruction); break; - case IrInstSrcIdMemberCount: - ir_print_member_count(irp, (IrInstSrcMemberCount *)instruction); - break; - case IrInstSrcIdMemberType: - ir_print_member_type(irp, (IrInstSrcMemberType *)instruction); - break; - case IrInstSrcIdMemberName: - ir_print_member_name(irp, (IrInstSrcMemberName *)instruction); - break; case IrInstSrcIdBreakpoint: ir_print_breakpoint(irp, (IrInstSrcBreakpoint *)instruction); break; @@ -2907,9 +2862,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdHasField: ir_print_has_field(irp, (IrInstSrcHasField *)instruction); break; - case IrInstSrcIdTypeId: - ir_print_type_id(irp, (IrInstSrcTypeId *)instruction); - break; case IrInstSrcIdSetEvalBranchQuota: ir_print_set_eval_branch_quota(irp, (IrInstSrcSetEvalBranchQuota *)instruction); break; From 538d9a5dd8e0eca02d363bbd5f749405e003f1c6 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 24 Feb 2020 23:39:03 +0200 Subject: [PATCH 105/109] remove uses of `@ArgType` and `@IntType` --- doc/langref.html.in | 29 ++----------------- lib/std/child_process.zig | 2 +- lib/std/debug/leb128.zig | 12 ++++---- lib/std/fmt.zig | 6 ++-- lib/std/fmt/parse_float.zig | 2 +- lib/std/hash/auto_hash.zig | 2 +- lib/std/hash/wyhash.zig | 2 +- lib/std/heap.zig | 2 +- lib/std/io.zig | 10 +++---- lib/std/io/test.zig | 9 +++--- lib/std/math.zig | 22 +++++++------- lib/std/math/big/int.zig | 6 ++-- lib/std/math/big/rational.zig | 6 ++-- lib/std/math/cos.zig | 2 +- lib/std/math/pow.zig | 2 +- lib/std/math/sin.zig | 2 +- lib/std/math/sqrt.zig | 6 ++-- lib/std/math/tan.zig | 2 +- lib/std/mem.zig | 4 +-- lib/std/meta.zig | 9 ++++++ lib/std/os.zig | 2 +- lib/std/os/bits/linux.zig | 2 +- lib/std/packed_int_array.zig | 12 ++++---- lib/std/rand.zig | 20 ++++++------- lib/std/special/c.zig | 2 +- lib/std/special/compiler_rt/addXf3.zig | 14 ++++----- lib/std/special/compiler_rt/compareXf2.zig | 6 ++-- lib/std/special/compiler_rt/divdf3.zig | 8 +++--- lib/std/special/compiler_rt/divsf3.zig | 6 ++-- lib/std/special/compiler_rt/extendXfYf2.zig | 6 ++-- lib/std/special/compiler_rt/fixint.zig | 2 +- lib/std/special/compiler_rt/fixuint.zig | 2 +- lib/std/special/compiler_rt/floatsiXf.zig | 4 +-- lib/std/special/compiler_rt/mulXf3.zig | 6 ++-- lib/std/special/compiler_rt/negXf2.zig | 2 +- lib/std/special/compiler_rt/truncXfYf2.zig | 4 +-- lib/std/special/compiler_rt/udivmod.zig | 4 +-- lib/std/target.zig | 2 +- lib/std/thread.zig | 2 +- src-self-hosted/type.zig | 2 +- test/compile_errors.zig | 32 ++------------------- test/stage1/behavior/bit_shifting.zig | 4 +-- test/stage1/behavior/math.zig | 2 +- test/stage1/behavior/misc.zig | 29 ------------------- test/stage1/behavior/reflection.zig | 6 ++-- 45 files changed, 125 insertions(+), 193 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index d186e68451..55b8d82476 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -550,7 +550,7 @@ pub fn main() void { {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an integer type is {#syntax#}65535{#endsyntax#}.

      - {#see_also|Integers|Floats|void|Errors|@IntType#} + {#see_also|Integers|Floats|void|Errors|@Type#} {#header_close#} {#header_open|Primitive Values#}
      @@ -6667,18 +6667,6 @@ comptime {

      {#see_also|Alignment#} {#header_close#} - {#header_open|@ArgType#} -
      {#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}
      -

      - This builtin function takes a function type and returns the type of the parameter at index {#syntax#}n{#endsyntax#}. -

      -

      - {#syntax#}T{#endsyntax#} must be a function type. -

      -

      - Note: This function is deprecated. Use {#link|@typeInfo#} instead. -

      - {#header_close#} {#header_open|@as#}
      {#syntax#}@as(comptime T: type, expression) T{#endsyntax#}
      @@ -7337,7 +7325,7 @@ test "main" { {#header_close#} {#header_open|@errorToInt#} -
      {#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}
      +
      {#syntax#}@errorToInt(err: var) std.meta.IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}

      Supports the following types:

      @@ -7631,7 +7619,7 @@ test "@hasDecl" { {#header_close#} {#header_open|@intToError#} -
      {#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}
      +
      {#syntax#}@intToError(value: std.meta.IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}

      Converts from the integer representation of an error into {#link|The Global Error Set#} type.

      @@ -7664,17 +7652,6 @@ test "@hasDecl" {

      {#header_close#} - {#header_open|@IntType#} -
      {#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u16) type{#endsyntax#}
      -

      - This function returns an integer type with the given signness and bit count. The maximum - bit count for an integer type is {#syntax#}65535{#endsyntax#}. -

      -

      - Deprecated. Use {#link|@Type#}. -

      - {#header_close#} - {#header_open|@memcpy#}
      {#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}

      diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 171a330bac..bb8ed2e8a0 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -851,7 +851,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { os.exit(1); } -const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); +const ErrInt = std.meta.IntType(false, @sizeOf(anyerror) * 8); fn writeIntFd(fd: i32, value: ErrInt) !void { const file = File{ diff --git a/lib/std/debug/leb128.zig b/lib/std/debug/leb128.zig index dba57e1f97..1d81b9390a 100644 --- a/lib/std/debug/leb128.zig +++ b/lib/std/debug/leb128.zig @@ -2,7 +2,7 @@ const std = @import("std"); const testing = std.testing; pub fn readULEB128(comptime T: type, in_stream: var) !T { - const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count)); var result: T = 0; var shift: usize = 0; @@ -27,7 +27,7 @@ pub fn readULEB128(comptime T: type, in_stream: var) !T { } pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T { - const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count)); var result: T = 0; var shift: usize = 0; @@ -55,8 +55,8 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T { } pub fn readILEB128(comptime T: type, in_stream: var) !T { - const UT = @IntType(false, T.bit_count); - const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + const UT = std.meta.IntType(false, T.bit_count); + const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count)); var result: UT = 0; var shift: usize = 0; @@ -87,8 +87,8 @@ pub fn readILEB128(comptime T: type, in_stream: var) !T { } pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T { - const UT = @IntType(false, T.bit_count); - const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + const UT = std.meta.IntType(false, T.bit_count); + const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count)); var result: UT = 0; var shift: usize = 0; diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 5c73ed1252..b9c6dd0033 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -82,7 +82,7 @@ pub fn format( comptime fmt: []const u8, args: var, ) Errors!void { - const ArgSetType = @IntType(false, 32); + const ArgSetType = u32; if (@typeInfo(@TypeOf(args)) != .Struct) { @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args))); } @@ -944,7 +944,7 @@ fn formatIntSigned( .fill = options.fill, }; - const uint = @IntType(false, @TypeOf(value).bit_count); + const uint = std.meta.IntType(false, @TypeOf(value).bit_count); if (value < 0) { const minus_sign: u8 = '-'; try output(context, @as(*const [1]u8, &minus_sign)[0..]); @@ -972,7 +972,7 @@ fn formatIntUnsigned( assert(base >= 2); var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined; const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count); - const MinInt = @IntType(@TypeOf(value).is_signed, min_int_bits); + const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits); var a: MinInt = value; var index: usize = buf.len; diff --git a/lib/std/fmt/parse_float.zig b/lib/std/fmt/parse_float.zig index 1456dd8e57..aa6e414336 100644 --- a/lib/std/fmt/parse_float.zig +++ b/lib/std/fmt/parse_float.zig @@ -393,7 +393,7 @@ test "fmt.parseFloat" { const epsilon = 1e-7; inline for ([_]type{ f16, f32, f64, f128 }) |T| { - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); testing.expectError(error.InvalidCharacter, parseFloat(T, "")); testing.expectError(error.InvalidCharacter, parseFloat(T, " 1")); diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index adde71875e..1bd7dfc05b 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -93,7 +93,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void { // TODO Check if the situation is better after #561 is resolved. .Int => @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)}), - .Float => |info| hash(hasher, @bitCast(@IntType(false, info.bits), key), strat), + .Float => |info| hash(hasher, @bitCast(std.meta.IntType(false, info.bits), key), strat), .Bool => hash(hasher, @boolToInt(key), strat), .Enum => hash(hasher, @enumToInt(key), strat), diff --git a/lib/std/hash/wyhash.zig b/lib/std/hash/wyhash.zig index 8d11c700cf..8fcbbbce4c 100644 --- a/lib/std/hash/wyhash.zig +++ b/lib/std/hash/wyhash.zig @@ -10,7 +10,7 @@ const primes = [_]u64{ }; fn read_bytes(comptime bytes: u8, data: []const u8) u64 { - const T = @IntType(false, 8 * bytes); + const T = std.meta.IntType(false, 8 * bytes); return mem.readIntSliceLittle(T, data[0..bytes]); } diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 135d7297a2..4295f1393d 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -1015,7 +1015,7 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo // very near usize? if (mem.page_size << 2 > maxInt(usize)) return; - const USizeShift = @IntType(false, std.math.log2(usize.bit_count)); + const USizeShift = std.meta.IntType(false, std.math.log2(usize.bit_count)); const large_align = @as(u29, mem.page_size << 2); var align_mask: usize = undefined; diff --git a/lib/std/io.zig b/lib/std/io.zig index 943db1a155..548f119b4f 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -337,7 +337,7 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type { assert(u_bit_count >= bits); break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count; }; - const Buf = @IntType(false, buf_bit_count); + const Buf = std.meta.IntType(false, buf_bit_count); const BufShift = math.Log2Int(Buf); out_bits.* = @as(usize, 0); @@ -659,7 +659,7 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type { assert(u_bit_count >= bits); break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count; }; - const Buf = @IntType(false, buf_bit_count); + const Buf = std.meta.IntType(false, buf_bit_count); const BufShift = math.Log2Int(Buf); const buf_value = @intCast(Buf, value); @@ -836,7 +836,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, const u8_bit_count = 8; const t_bit_count = comptime meta.bitCount(T); - const U = @IntType(false, t_bit_count); + const U = std.meta.IntType(false, t_bit_count); const Log2U = math.Log2Int(U); const int_size = (U.bit_count + 7) / 8; @@ -851,7 +851,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, if (int_size == 1) { if (t_bit_count == 8) return @bitCast(T, buffer[0]); - const PossiblySignedByte = @IntType(T.is_signed, 8); + const PossiblySignedByte = std.meta.IntType(T.is_signed, 8); return @truncate(T, @bitCast(PossiblySignedByte, buffer[0])); } @@ -1014,7 +1014,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co const t_bit_count = comptime meta.bitCount(T); const u8_bit_count = comptime meta.bitCount(u8); - const U = @IntType(false, t_bit_count); + const U = std.meta.IntType(false, t_bit_count); const Log2U = math.Log2Int(U); const int_size = (U.bit_count + 7) / 8; diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 7716e603a0..dae8940016 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -318,6 +318,7 @@ test "BitStreams with File Stream" { } fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void { + @setEvalBranchQuota(1500); //@NOTE: if this test is taking too long, reduce the maximum tested bitsize const max_test_bitsize = 128; @@ -341,8 +342,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi comptime var i = 0; inline while (i <= max_test_bitsize) : (i += 1) { - const U = @IntType(false, i); - const S = @IntType(true, i); + const U = std.meta.IntType(false, i); + const S = std.meta.IntType(true, i); try serializer.serializeInt(@as(U, i)); if (i != 0) try serializer.serializeInt(@as(S, -1)) else try serializer.serialize(@as(S, 0)); } @@ -350,8 +351,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi i = 0; inline while (i <= max_test_bitsize) : (i += 1) { - const U = @IntType(false, i); - const S = @IntType(true, i); + const U = std.meta.IntType(false, i); + const S = std.meta.IntType(true, i); const x = try deserializer.deserializeInt(U); const y = try deserializer.deserializeInt(S); expect(x == @as(U, i)); diff --git a/lib/std/math.zig b/lib/std/math.zig index 322fdc7755..c99de8f9dc 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -444,7 +444,7 @@ pub fn Log2Int(comptime T: type) type { count += 1; } - return @IntType(false, count); + return std.meta.IntType(false, count); } pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { @@ -460,7 +460,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t if (is_signed) { magnitude_bits += 1; } - return @IntType(is_signed, magnitude_bits); + return std.meta.IntType(is_signed, magnitude_bits); } test "math.IntFittingRange" { @@ -674,13 +674,13 @@ pub fn absCast(x: var) t: { if (@TypeOf(x) == comptime_int) { break :t comptime_int; } else { - break :t @IntType(false, @TypeOf(x).bit_count); + break :t std.meta.IntType(false, @TypeOf(x).bit_count); } } { if (@TypeOf(x) == comptime_int) { return if (x < 0) -x else x; } - const uint = @IntType(false, @TypeOf(x).bit_count); + const uint = std.meta.IntType(false, @TypeOf(x).bit_count); if (x >= 0) return @intCast(uint, x); return @intCast(uint, -(x + 1)) + 1; @@ -701,10 +701,10 @@ test "math.absCast" { /// Returns the negation of the integer parameter. /// Result is a signed integer. -pub fn negateCast(x: var) !@IntType(true, @TypeOf(x).bit_count) { +pub fn negateCast(x: var) !std.meta.IntType(true, @TypeOf(x).bit_count) { if (@TypeOf(x).is_signed) return negate(x); - const int = @IntType(true, @TypeOf(x).bit_count); + const int = std.meta.IntType(true, @TypeOf(x).bit_count); if (x > -minInt(int)) return error.Overflow; if (x == -minInt(int)) return minInt(int); @@ -790,11 +790,11 @@ fn testFloorPowerOfTwo() void { /// Returns the next power of two (if the value is not already a power of two). /// Only unsigned integers can be used. Zero is not an allowed input. /// Result is a type with 1 more bit than the input type. -pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T.bit_count + 1) { +pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.IntType(T.is_signed, T.bit_count + 1) { comptime assert(@typeInfo(T) == .Int); comptime assert(!T.is_signed); assert(value != 0); - comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); + comptime const PromotedType = std.meta.IntType(T.is_signed, T.bit_count + 1); comptime const shiftType = std.math.Log2Int(PromotedType); return @as(PromotedType, 1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1)); } @@ -805,7 +805,7 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) { comptime assert(@typeInfo(T) == .Int); comptime assert(!T.is_signed); - comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); + comptime const PromotedType = std.meta.IntType(T.is_signed, T.bit_count + 1); comptime const overflowBit = @as(PromotedType, 1) << T.bit_count; var x = ceilPowerOfTwoPromote(T, value); if (overflowBit & x != 0) { @@ -947,8 +947,8 @@ test "max value type" { testing.expect(x == 2147483647); } -pub fn mulWide(comptime T: type, a: T, b: T) @IntType(T.is_signed, T.bit_count * 2) { - const ResultInt = @IntType(T.is_signed, T.bit_count * 2); +pub fn mulWide(comptime T: type, a: T, b: T) std.meta.IntType(T.is_signed, T.bit_count * 2) { + const ResultInt = std.meta.IntType(T.is_signed, T.bit_count * 2); return @as(ResultInt, a) * @as(ResultInt, b); } diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 0ba3382641..8fda3f647a 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -9,7 +9,7 @@ const maxInt = std.math.maxInt; const minInt = std.math.minInt; pub const Limb = usize; -pub const DoubleLimb = @IntType(false, 2 * Limb.bit_count); +pub const DoubleLimb = std.meta.IntType(false, 2 * Limb.bit_count); pub const Log2Limb = math.Log2Int(Limb); comptime { @@ -268,7 +268,7 @@ pub const Int = struct { switch (@typeInfo(T)) { .Int => |info| { - const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T; + const UT = if (T.is_signed) std.meta.IntType(false, T.bit_count - 1) else T; try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb)); self.metadata = 0; @@ -331,7 +331,7 @@ pub const Int = struct { pub fn to(self: Int, comptime T: type) ConvertError!T { switch (@typeInfo(T)) { .Int => { - const UT = @IntType(false, T.bit_count); + const UT = std.meta.IntType(false, T.bit_count); if (self.bitCountTwosComp() > T.bit_count) { return error.TargetTooSmall; diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig index f54a234075..a57183a623 100644 --- a/lib/std/math/big/rational.zig +++ b/lib/std/math/big/rational.zig @@ -128,7 +128,7 @@ pub const Rational = struct { // Translated from golang.go/src/math/big/rat.go. debug.assert(@typeInfo(T) == .Float); - const UnsignedIntType = @IntType(false, T.bit_count); + const UnsignedIntType = std.meta.IntType(false, T.bit_count); const f_bits = @bitCast(UnsignedIntType, f); const exponent_bits = math.floatExponentBits(T); @@ -187,7 +187,7 @@ pub const Rational = struct { debug.assert(@typeInfo(T) == .Float); const fsize = T.bit_count; - const BitReprType = @IntType(false, T.bit_count); + const BitReprType = std.meta.IntType(false, T.bit_count); const msize = math.floatMantissaBits(T); const msize1 = msize + 1; @@ -462,7 +462,7 @@ pub const Rational = struct { } }; -const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count); +const SignedDoubleLimb = std.meta.IntType(true, DoubleLimb.bit_count); fn gcd(rma: *Int, x: Int, y: Int) !void { rma.assertWritable(); diff --git a/lib/std/math/cos.zig b/lib/std/math/cos.zig index 248243e288..8a599aece4 100644 --- a/lib/std/math/cos.zig +++ b/lib/std/math/cos.zig @@ -44,7 +44,7 @@ const pi4c = 2.69515142907905952645E-15; const m4pi = 1.273239544735162542821171882678754627704620361328125; fn cos_(comptime T: type, x_: T) T { - const I = @IntType(true, T.bit_count); + const I = std.meta.IntType(true, T.bit_count); var x = x_; if (math.isNan(x) or math.isInf(x)) { diff --git a/lib/std/math/pow.zig b/lib/std/math/pow.zig index 18c9f80634..4f623377e6 100644 --- a/lib/std/math/pow.zig +++ b/lib/std/math/pow.zig @@ -145,7 +145,7 @@ pub fn pow(comptime T: type, x: T, y: T) T { var xe = r2.exponent; var x1 = r2.significand; - var i = @floatToInt(@IntType(true, T.bit_count), yi); + var i = @floatToInt(std.meta.IntType(true, T.bit_count), yi); while (i != 0) : (i >>= 1) { const overflow_shift = math.floatExponentBits(T) + 1; if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) { diff --git a/lib/std/math/sin.zig b/lib/std/math/sin.zig index 00225449bb..0c339ba1f2 100644 --- a/lib/std/math/sin.zig +++ b/lib/std/math/sin.zig @@ -45,7 +45,7 @@ const pi4c = 2.69515142907905952645E-15; const m4pi = 1.273239544735162542821171882678754627704620361328125; fn sin_(comptime T: type, x_: T) T { - const I = @IntType(true, T.bit_count); + const I = std.meta.IntType(true, T.bit_count); var x = x_; if (x == 0 or math.isNan(x)) { diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig index 800a7574ae..e5d8a822f5 100644 --- a/lib/std/math/sqrt.zig +++ b/lib/std/math/sqrt.zig @@ -31,7 +31,7 @@ pub fn sqrt(x: var) Sqrt(@TypeOf(x)) { } } -fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { +fn sqrt_int(comptime T: type, value: T) std.meta.IntType(false, T.bit_count / 2) { var op = value; var res: T = 0; var one: T = 1 << (T.bit_count - 2); @@ -50,7 +50,7 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { one >>= 2; } - const ResultType = @IntType(false, T.bit_count / 2); + const ResultType = std.meta.IntType(false, T.bit_count / 2); return @intCast(ResultType, res); } @@ -66,7 +66,7 @@ test "math.sqrt_int" { /// Returns the return type `sqrt` will return given an operand of type `T`. pub fn Sqrt(comptime T: type) type { return switch (@typeInfo(T)) { - .Int => |int| @IntType(false, int.bits / 2), + .Int => |int| std.meta.IntType(false, int.bits / 2), else => T, }; } diff --git a/lib/std/math/tan.zig b/lib/std/math/tan.zig index 01a0314d74..737f5b0e09 100644 --- a/lib/std/math/tan.zig +++ b/lib/std/math/tan.zig @@ -38,7 +38,7 @@ const pi4c = 2.69515142907905952645E-15; const m4pi = 1.273239544735162542821171882678754627704620361328125; fn tan_(comptime T: type, x_: T) T { - const I = @IntType(true, T.bit_count); + const I = std.meta.IntType(true, T.bit_count); var x = x_; if (x == 0 or math.isNan(x)) { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 20ad567431..4e7beba17d 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -708,7 +708,7 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { assert(buffer.len >= @divExact(T.bit_count, 8)); // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough - const uint = @IntType(false, T.bit_count); + const uint = std.meta.IntType(false, T.bit_count); var bits = @truncate(uint, value); for (buffer) |*b| { b.* = @truncate(u8, bits); @@ -725,7 +725,7 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { assert(buffer.len >= @divExact(T.bit_count, 8)); // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough - const uint = @IntType(false, T.bit_count); + const uint = std.meta.IntType(false, T.bit_count); var bits = @truncate(uint, value); var index: usize = buffer.len; while (index != 0) { diff --git a/lib/std/meta.zig b/lib/std/meta.zig index e302a80ef1..58fd6b9da7 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -580,3 +580,12 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De return &array; } } + +pub fn IntType(comptime is_signed: bool, comptime bit_count: u16) type { + return @Type(TypeInfo{ + .Int = .{ + .is_signed = is_signed, + .bits = bit_count, + }, + }); +} diff --git a/lib/std/os.zig b/lib/std/os.zig index b501c81b36..3b60a08cef 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3349,7 +3349,7 @@ pub fn res_mkquery( // Make a reasonably unpredictable id var ts: timespec = undefined; clock_gettime(CLOCK_REALTIME, &ts) catch {}; - const UInt = @IntType(false, @TypeOf(ts.tv_nsec).bit_count); + const UInt = std.meta.IntType(false, @TypeOf(ts.tv_nsec).bit_count); const unsec = @bitCast(UInt, ts.tv_nsec); const id = @truncate(u32, unsec + unsec / 65536); q[0] = @truncate(u8, id / 256); diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 8077d4b16a..c5a9a7d774 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -1004,7 +1004,7 @@ pub const dl_phdr_info = extern struct { pub const CPU_SETSIZE = 128; pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize; -pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8)); +pub const cpu_count_t = std.meta.IntType(false, std.math.log2(CPU_SETSIZE * 8)); pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t { var sum: cpu_count_t = 0; diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig index 3dfa55e74b..63b6fffa73 100644 --- a/lib/std/packed_int_array.zig +++ b/lib/std/packed_int_array.zig @@ -34,13 +34,13 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type { //we bitcast the desired Int type to an unsigned version of itself // to avoid issues with shifting signed ints. - const UnInt = @IntType(false, int_bits); + const UnInt = std.meta.IntType(false, int_bits); //The maximum container int type - const MinIo = @IntType(false, min_io_bits); + const MinIo = std.meta.IntType(false, min_io_bits); //The minimum container int type - const MaxIo = @IntType(false, max_io_bits); + const MaxIo = std.meta.IntType(false, max_io_bits); return struct { pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int { @@ -322,7 +322,7 @@ test "PackedIntArray" { inline while (bits <= 256) : (bits += 1) { //alternate unsigned and signed const even = bits % 2 == 0; - const I = @IntType(even, bits); + const I = std.meta.IntType(even, bits); const PackedArray = PackedIntArray(I, int_count); const expected_bytes = ((bits * int_count) + 7) / 8; @@ -369,7 +369,7 @@ test "PackedIntSlice" { inline while (bits <= 256) : (bits += 1) { //alternate unsigned and signed const even = bits % 2 == 0; - const I = @IntType(even, bits); + const I = std.meta.IntType(even, bits); const P = PackedIntSlice(I); var data = P.init(&buffer, int_count); @@ -399,7 +399,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" { comptime var bits = 0; inline while (bits <= max_bits) : (bits += 1) { - const Int = @IntType(false, bits); + const Int = std.meta.IntType(false, bits); const PackedArray = PackedIntArray(Int, int_count); var packed_array = @as(PackedArray, undefined); diff --git a/lib/std/rand.zig b/lib/std/rand.zig index 0bdc593545..31891f5f0e 100644 --- a/lib/std/rand.zig +++ b/lib/std/rand.zig @@ -45,8 +45,8 @@ pub const Random = struct { /// Returns a random int `i` such that `0 <= i <= maxInt(T)`. /// `i` is evenly distributed. pub fn int(r: *Random, comptime T: type) T { - const UnsignedT = @IntType(false, T.bit_count); - const ByteAlignedT = @IntType(false, @divTrunc(T.bit_count + 7, 8) * 8); + const UnsignedT = std.meta.IntType(false, T.bit_count); + const ByteAlignedT = std.meta.IntType(false, @divTrunc(T.bit_count + 7, 8) * 8); var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined; r.bytes(rand_bytes[0..]); @@ -85,9 +85,9 @@ pub const Random = struct { comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! assert(0 < less_than); // Small is typically u32 - const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); + const Small = std.meta.IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); // Large is typically u64 - const Large = @IntType(false, Small.bit_count * 2); + const Large = std.meta.IntType(false, Small.bit_count * 2); // adapted from: // http://www.pcg-random.org/posts/bounded-rands.html @@ -99,7 +99,7 @@ pub const Random = struct { // TODO: workaround for https://github.com/ziglang/zig/issues/1770 // should be: // var t: Small = -%less_than; - var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), @as(Small, less_than))); + var t: Small = @bitCast(Small, -%@bitCast(std.meta.IntType(true, Small.bit_count), @as(Small, less_than))); if (t >= less_than) { t -= less_than; @@ -145,7 +145,7 @@ pub const Random = struct { assert(at_least < less_than); if (T.is_signed) { // Two's complement makes this math pretty easy. - const UnsignedT = @IntType(false, T.bit_count); + const UnsignedT = std.meta.IntType(false, T.bit_count); const lo = @bitCast(UnsignedT, at_least); const hi = @bitCast(UnsignedT, less_than); const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo); @@ -163,7 +163,7 @@ pub const Random = struct { assert(at_least < less_than); if (T.is_signed) { // Two's complement makes this math pretty easy. - const UnsignedT = @IntType(false, T.bit_count); + const UnsignedT = std.meta.IntType(false, T.bit_count); const lo = @bitCast(UnsignedT, at_least); const hi = @bitCast(UnsignedT, less_than); const result = lo +% r.uintLessThan(UnsignedT, hi -% lo); @@ -180,7 +180,7 @@ pub const Random = struct { assert(at_least <= at_most); if (T.is_signed) { // Two's complement makes this math pretty easy. - const UnsignedT = @IntType(false, T.bit_count); + const UnsignedT = std.meta.IntType(false, T.bit_count); const lo = @bitCast(UnsignedT, at_least); const hi = @bitCast(UnsignedT, at_most); const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo); @@ -198,7 +198,7 @@ pub const Random = struct { assert(at_least <= at_most); if (T.is_signed) { // Two's complement makes this math pretty easy. - const UnsignedT = @IntType(false, T.bit_count); + const UnsignedT = std.meta.IntType(false, T.bit_count); const lo = @bitCast(UnsignedT, at_least); const hi = @bitCast(UnsignedT, at_most); const result = lo +% r.uintAtMost(UnsignedT, hi -% lo); @@ -281,7 +281,7 @@ pub const Random = struct { /// This function introduces a minor bias. pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { comptime assert(T.is_signed == false); - const T2 = @IntType(false, T.bit_count * 2); + const T2 = std.meta.IntType(false, T.bit_count * 2); // adapted from: // http://www.pcg-random.org/posts/bounded-rands.html diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 0a911ba52b..56ae3d0d8f 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -511,7 +511,7 @@ export fn roundf(a: f32) f32 { fn generic_fmod(comptime T: type, x: T, y: T) T { @setRuntimeSafety(false); - const uint = @IntType(false, T.bit_count); + const uint = std.meta.IntType(false, T.bit_count); const log2uint = math.Log2Int(uint); const digits = if (T == f32) 23 else 52; const exp_bits = if (T == f32) 9 else 12; diff --git a/lib/std/special/compiler_rt/addXf3.zig b/lib/std/special/compiler_rt/addXf3.zig index 4294752baa..8bb9751378 100644 --- a/lib/std/special/compiler_rt/addXf3.zig +++ b/lib/std/special/compiler_rt/addXf3.zig @@ -54,21 +54,21 @@ pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 { } // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 -fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { - const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); +fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 { + const Z = std.meta.IntType(false, T.bit_count); + const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); const significandBits = std.math.floatMantissaBits(T); const implicitBit = @as(Z, 1) << significandBits; - const shift = @clz(@IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit); + const shift = @clz(std.meta.IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit); significand.* <<= @intCast(S, shift); return 1 - shift; } // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 fn addXf3(comptime T: type, a: T, b: T) T { - const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); + const Z = std.meta.IntType(false, T.bit_count); + const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); const typeWidth = T.bit_count; const significandBits = std.math.floatMantissaBits(T); @@ -182,7 +182,7 @@ fn addXf3(comptime T: type, a: T, b: T) T { // If partial cancellation occured, we need to left-shift the result // and adjust the exponent: if (aSignificand < implicitBit << 3) { - const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(@IntType(false, T.bit_count), implicitBit << 3)); + const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.IntType(false, T.bit_count), implicitBit << 3)); aSignificand <<= @intCast(S, shift); aExponent -= shift; } diff --git a/lib/std/special/compiler_rt/compareXf2.zig b/lib/std/special/compiler_rt/compareXf2.zig index 15e49e3cc1..34871a5025 100644 --- a/lib/std/special/compiler_rt/compareXf2.zig +++ b/lib/std/special/compiler_rt/compareXf2.zig @@ -22,8 +22,8 @@ const GE = extern enum(i32) { pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT { @setRuntimeSafety(builtin.is_test); - const srep_t = @IntType(true, T.bit_count); - const rep_t = @IntType(false, T.bit_count); + const srep_t = std.meta.IntType(true, T.bit_count); + const rep_t = std.meta.IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); @@ -68,7 +68,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT { pub fn unordcmp(comptime T: type, a: T, b: T) i32 { @setRuntimeSafety(builtin.is_test); - const rep_t = @IntType(false, T.bit_count); + const rep_t = std.meta.IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); diff --git a/lib/std/special/compiler_rt/divdf3.zig b/lib/std/special/compiler_rt/divdf3.zig index f0c0d1247c..7e870feec9 100644 --- a/lib/std/special/compiler_rt/divdf3.zig +++ b/lib/std/special/compiler_rt/divdf3.zig @@ -7,8 +7,8 @@ const builtin = @import("builtin"); pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, f64.bit_count); - const SignedZ = @IntType(true, f64.bit_count); + const Z = std.meta.IntType(false, f64.bit_count); + const SignedZ = std.meta.IntType(true, f64.bit_count); const typeWidth = f64.bit_count; const significandBits = std.math.floatMantissaBits(f64); @@ -312,9 +312,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { } } -fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { +fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const implicitBit = @as(Z, 1) << significandBits; diff --git a/lib/std/special/compiler_rt/divsf3.zig b/lib/std/special/compiler_rt/divsf3.zig index e51f94e19d..0cb149a610 100644 --- a/lib/std/special/compiler_rt/divsf3.zig +++ b/lib/std/special/compiler_rt/divsf3.zig @@ -7,7 +7,7 @@ const builtin = @import("builtin"); pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, f32.bit_count); + const Z = std.meta.IntType(false, f32.bit_count); const typeWidth = f32.bit_count; const significandBits = std.math.floatMantissaBits(f32); @@ -185,9 +185,9 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { } } -fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { +fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const implicitBit = @as(Z, 1) << significandBits; diff --git a/lib/std/special/compiler_rt/extendXfYf2.zig b/lib/std/special/compiler_rt/extendXfYf2.zig index 4e63d93ac5..58da88e586 100644 --- a/lib/std/special/compiler_rt/extendXfYf2.zig +++ b/lib/std/special/compiler_rt/extendXfYf2.zig @@ -30,11 +30,11 @@ pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { const CHAR_BIT = 8; -fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @typeInfo(src_t).Float.bits)) dst_t { +fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.IntType(false, @typeInfo(src_t).Float.bits)) dst_t { @setRuntimeSafety(builtin.is_test); - const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); - const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); + const src_rep_t = std.meta.IntType(false, @typeInfo(src_t).Float.bits); + const dst_rep_t = std.meta.IntType(false, @typeInfo(dst_t).Float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); const dstSigBits = std.math.floatMantissaBits(dst_t); const SrcShift = std.math.Log2Int(src_rep_t); diff --git a/lib/std/special/compiler_rt/fixint.zig b/lib/std/special/compiler_rt/fixint.zig index 426ee1d58a..3a401c1e6a 100644 --- a/lib/std/special/compiler_rt/fixint.zig +++ b/lib/std/special/compiler_rt/fixint.zig @@ -45,7 +45,7 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t { if (exponent < 0) return 0; // The unsigned result needs to be large enough to handle an fixint_t or rep_t - const fixuint_t = @IntType(false, fixint_t.bit_count); + const fixuint_t = std.meta.IntType(false, fixint_t.bit_count); const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t; var uint_result: UintResultType = undefined; diff --git a/lib/std/special/compiler_rt/fixuint.zig b/lib/std/special/compiler_rt/fixuint.zig index 977d3c16c9..d8e3e9a0e0 100644 --- a/lib/std/special/compiler_rt/fixuint.zig +++ b/lib/std/special/compiler_rt/fixuint.zig @@ -10,7 +10,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t f128 => u128, else => unreachable, }; - const srep_t = @IntType(true, rep_t.bit_count); + const srep_t = @import("std").meta.IntType(true, rep_t.bit_count); const significandBits = switch (fp_t) { f32 => 23, f64 => 52, diff --git a/lib/std/special/compiler_rt/floatsiXf.zig b/lib/std/special/compiler_rt/floatsiXf.zig index ef3aba34d4..550a7ec246 100644 --- a/lib/std/special/compiler_rt/floatsiXf.zig +++ b/lib/std/special/compiler_rt/floatsiXf.zig @@ -5,8 +5,8 @@ const maxInt = std.math.maxInt; fn floatsiXf(comptime T: type, a: i32) T { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); + const Z = std.meta.IntType(false, T.bit_count); + const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); if (a == 0) { return @as(T, 0.0); diff --git a/lib/std/special/compiler_rt/mulXf3.zig b/lib/std/special/compiler_rt/mulXf3.zig index 103692f610..a40c0f1e70 100644 --- a/lib/std/special/compiler_rt/mulXf3.zig +++ b/lib/std/special/compiler_rt/mulXf3.zig @@ -28,7 +28,7 @@ pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 { fn mulXf3(comptime T: type, a: T, b: T) T { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); const typeWidth = T.bit_count; const significandBits = std.math.floatMantissaBits(T); @@ -264,9 +264,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { } } -fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { +fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const implicitBit = @as(Z, 1) << significandBits; diff --git a/lib/std/special/compiler_rt/negXf2.zig b/lib/std/special/compiler_rt/negXf2.zig index c41b1b48d7..d1038d6456 100644 --- a/lib/std/special/compiler_rt/negXf2.zig +++ b/lib/std/special/compiler_rt/negXf2.zig @@ -19,7 +19,7 @@ pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 { } fn negXf2(comptime T: type, a: T) T { - const Z = @IntType(false, T.bit_count); + const Z = std.meta.IntType(false, T.bit_count); const typeWidth = T.bit_count; const significandBits = std.math.floatMantissaBits(T); diff --git a/lib/std/special/compiler_rt/truncXfYf2.zig b/lib/std/special/compiler_rt/truncXfYf2.zig index 0a09dea84c..7c83c66ec0 100644 --- a/lib/std/special/compiler_rt/truncXfYf2.zig +++ b/lib/std/special/compiler_rt/truncXfYf2.zig @@ -36,8 +36,8 @@ pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 { } inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { - const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits); - const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits); + const src_rep_t = std.meta.IntType(false, @typeInfo(src_t).Float.bits); + const dst_rep_t = std.meta.IntType(false, @typeInfo(dst_t).Float.bits); const srcSigBits = std.math.floatMantissaBits(src_t); const dstSigBits = std.math.floatMantissaBits(dst_t); const SrcShift = std.math.Log2Int(src_rep_t); diff --git a/lib/std/special/compiler_rt/udivmod.zig b/lib/std/special/compiler_rt/udivmod.zig index 96fb7b3bdd..1cf2589b16 100644 --- a/lib/std/special/compiler_rt/udivmod.zig +++ b/lib/std/special/compiler_rt/udivmod.zig @@ -10,8 +10,8 @@ const high = 1 - low; pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?*DoubleInt) DoubleInt { @setRuntimeSafety(is_test); - const SingleInt = @IntType(false, @divExact(DoubleInt.bit_count, 2)); - const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); + const SingleInt = @import("std").meta.IntType(false, @divExact(DoubleInt.bit_count, 2)); + const SignedDoubleInt = @import("std").meta.IntType(true, DoubleInt.bit_count); const Log2SingleInt = @import("std").math.Log2Int(SingleInt); const n = @ptrCast(*const [2]SingleInt, &a).*; // TODO issue #421 diff --git a/lib/std/target.zig b/lib/std/target.zig index 83d3dafbc2..cf83bb1f7a 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -222,7 +222,7 @@ pub const Target = union(enum) { pub const needed_bit_count = 154; pub const byte_count = (needed_bit_count + 7) / 8; pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); - pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize))); + pub const Index = std.math.Log2Int(std.meta.IntType(false, usize_count * @bitSizeOf(usize))); pub const ShiftInt = std.math.Log2Int(usize); pub const empty = Set{ .ints = [1]usize{0} ** usize_count }; diff --git a/lib/std/thread.zig b/lib/std/thread.zig index 500c94c044..fcc71ae5a5 100644 --- a/lib/std/thread.zig +++ b/lib/std/thread.zig @@ -148,7 +148,7 @@ pub const Thread = struct { const default_stack_size = 16 * 1024 * 1024; const Context = @TypeOf(context); - comptime assert(@ArgType(@TypeOf(startFn), 0) == Context); + comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context); if (builtin.os == builtin.Os.windows) { const WinThread = struct { diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 67e1aebdca..70ed754cea 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -1042,7 +1042,7 @@ fn hashAny(x: var, comptime seed: u64) u32 { switch (@typeInfo(@TypeOf(x))) { .Int => |info| { comptime var rng = comptime std.rand.DefaultPrng.init(seed); - const unsigned_x = @bitCast(@IntType(false, info.bits), x); + const unsigned_x = @bitCast(std.meta.IntType(false, info.bits), x); if (info.bits <= 32) { return @as(u32, unsigned_x) *% comptime rng.random.scalar(u32); } else { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a4bb333873..eb1f68e163 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1657,7 +1657,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var ptr: [*c]u8 = (1 << 64) + 1; \\} \\export fn b() void { - \\ var x: @IntType(false, 65) = 0x1234; + \\ var x: u65 = 0x1234; \\ var ptr: [*c]u8 = x; \\} , &[_][]const u8{ @@ -1896,7 +1896,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add("exceeded maximum bit width of integer", \\export fn entry1() void { - \\ const T = @IntType(false, 65536); + \\ const T = u65536; \\} \\export fn entry2() void { \\ var x: i65536 = 1; @@ -5598,7 +5598,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); cases.add("globally shadowing a primitive type", - \\const u16 = @intType(false, 8); + \\const u16 = u8; \\export fn entry() void { \\ const a: u16 = 300; \\} @@ -5939,23 +5939,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:1: error: invalid character: '\\t'", }); - cases.add("@ArgType given non function parameter", - \\comptime { - \\ _ = @ArgType(i32, 3); - \\} - , &[_][]const u8{ - "tmp.zig:2:18: error: expected function, found 'i32'", - }); - - cases.add("@ArgType arg index out of bounds", - \\comptime { - \\ _ = @ArgType(@TypeOf(add), 2); - \\} - \\fn add(a: i32, b: i32) i32 { return a + b; } - , &[_][]const u8{ - "tmp.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments", - }); - cases.add("calling var args extern function, passing array instead of pointer", \\export fn entry() void { \\ foo("hello".*,); @@ -6379,15 +6362,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(var) var' is generic", }); - cases.add("getting @ArgType of generic function", - \\fn generic(a: var) void {} - \\comptime { - \\ _ = @ArgType(@TypeOf(generic), 0); - \\} - , &[_][]const u8{ - "tmp.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var) var' is generic", - }); - cases.add("unsupported modifier at start of asm output constraint", \\export fn foo() void { \\ var bar: u32 = 3; diff --git a/test/stage1/behavior/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig index 84d5f8f60e..c71b95e0cc 100644 --- a/test/stage1/behavior/bit_shifting.zig +++ b/test/stage1/behavior/bit_shifting.zig @@ -2,9 +2,9 @@ const std = @import("std"); const expect = std.testing.expect; fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { - expect(Key == @IntType(false, Key.bit_count)); + expect(Key == std.meta.IntType(false, Key.bit_count)); expect(Key.bit_count >= mask_bit_count); - const ShardKey = @IntType(false, mask_bit_count); + const ShardKey = std.meta.IntType(false, mask_bit_count); const shift_amount = Key.bit_count - ShardKey.bit_count; return struct { const Self = @This(); diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index 2283118787..65a7d9e1f1 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -270,7 +270,7 @@ fn testBinaryNot(x: u16) void { } test "small int addition" { - var x: @IntType(false, 2) = 0; + var x: u2 = 0; expect(x == 0); x += 1; diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index 032f2429ed..681f5be500 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -24,35 +24,6 @@ test "call disabled extern fn" { disabledExternFn(); } -test "@IntType builtin" { - expect(@IntType(true, 8) == i8); - expect(@IntType(true, 16) == i16); - expect(@IntType(true, 32) == i32); - expect(@IntType(true, 64) == i64); - - expect(@IntType(false, 8) == u8); - expect(@IntType(false, 16) == u16); - expect(@IntType(false, 32) == u32); - expect(@IntType(false, 64) == u64); - - expect(i8.bit_count == 8); - expect(i16.bit_count == 16); - expect(i32.bit_count == 32); - expect(i64.bit_count == 64); - - expect(i8.is_signed); - expect(i16.is_signed); - expect(i32.is_signed); - expect(i64.is_signed); - expect(isize.is_signed); - - expect(!u8.is_signed); - expect(!u16.is_signed); - expect(!u32.is_signed); - expect(!u64.is_signed); - expect(!usize.is_signed); -} - test "floating point primitive bit counts" { expect(f16.bit_count == 16); expect(f32.bit_count == 32); diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig index a32f97e8ac..ab0a55092c 100644 --- a/test/stage1/behavior/reflection.zig +++ b/test/stage1/behavior/reflection.zig @@ -16,9 +16,9 @@ test "reflection: function return type, var args, and param types" { expect(@TypeOf(dummy).ReturnType == i32); expect(!@TypeOf(dummy).is_var_args); expect(@TypeOf(dummy).arg_count == 3); - expect(@ArgType(@TypeOf(dummy), 0) == bool); - expect(@ArgType(@TypeOf(dummy), 1) == i32); - expect(@ArgType(@TypeOf(dummy), 2) == f32); + expect(@typeInfo(@TypeOf(dummy)).Fn.args[0].arg_type.? == bool); + expect(@typeInfo(@TypeOf(dummy)).Fn.args[1].arg_type.? == i32); + expect(@typeInfo(@TypeOf(dummy)).Fn.args[2].arg_type.? == f32); } } From d56115ef4189a7716d9371ef87df9124a61f5ab1 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 24 Feb 2020 23:50:02 +0200 Subject: [PATCH 106/109] remove `@IntType` and `@ArgType` (mostly) from the compiler --- doc/langref.html.in | 4 +-- src/all_types.hpp | 10 ------- src/codegen.cpp | 2 -- src/ir.cpp | 66 ----------------------------------------- src/ir_print.cpp | 13 -------- test/compile_errors.zig | 1 - 6 files changed, 2 insertions(+), 94 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 55b8d82476..e244d69e25 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2810,10 +2810,10 @@ test "@TagType" { assert(@TagType(Small) == u2); } -// @typeInfo tells us the field count and the fields name: +// @typeInfo tells us the field count and the fields names: test "@typeInfo" { assert(@typeInfo(Small).Enum.fields.len == 4); - assert(mem.eql(u8, @typeInfo(Small).Enum.fields[0].name, "Two")); + assert(mem.eql(u8, @typeInfo(Small).Enum.fields[1].name, "Two")); } // @tagName gives a []const u8 representation of an enum value: diff --git a/src/all_types.hpp b/src/all_types.hpp index 9f20d176bf..022a34038e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1754,7 +1754,6 @@ enum BuiltinFnId { BuiltinFnIdIntToErr, BuiltinFnIdEnumToInt, BuiltinFnIdIntToEnum, - BuiltinFnIdIntType, BuiltinFnIdVectorType, BuiltinFnIdShuffle, BuiltinFnIdSplat, @@ -1781,7 +1780,6 @@ enum BuiltinFnId { BuiltinFnIdOpaqueType, BuiltinFnIdThis, BuiltinFnIdSetAlignStack, - BuiltinFnIdArgType, BuiltinFnIdExport, BuiltinFnIdErrorReturnTrace, BuiltinFnIdAtomicRmw, @@ -2626,7 +2624,6 @@ enum IrInstSrcId { IrInstSrcIdIntToFloat, IrInstSrcIdFloatToInt, IrInstSrcIdBoolToInt, - IrInstSrcIdIntType, IrInstSrcIdVectorType, IrInstSrcIdShuffleVector, IrInstSrcIdSplat, @@ -3628,13 +3625,6 @@ struct IrInstSrcBoolToInt { IrInstSrc *target; }; -struct IrInstSrcIntType { - IrInstSrc base; - - IrInstSrc *is_signed; - IrInstSrc *bit_count; -}; - struct IrInstSrcVectorType { IrInstSrc base; diff --git a/src/codegen.cpp b/src/codegen.cpp index c6ee153573..f9d2566da7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8189,7 +8189,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdIntToEnum, "intToEnum", 2); create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); - create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2); create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4); create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2); @@ -8234,7 +8233,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2); create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0); create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); - create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); create_builtin_fn(g, BuiltinFnIdExport, "export", 2); create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5); diff --git a/src/ir.cpp b/src/ir.cpp index 6646d0ed55..80b8c93abd 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -389,8 +389,6 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBoolToInt: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdIntType: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdVectorType: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdShuffleVector: @@ -1285,10 +1283,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { return IrInstSrcIdBoolToInt; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntType *) { - return IrInstSrcIdIntType; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { return IrInstSrcIdVectorType; } @@ -3518,19 +3512,6 @@ static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_int_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_signed, - IrInstSrc *bit_count) -{ - IrInstSrcIntType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->is_signed = is_signed; - instruction->bit_count = bit_count; - - ir_ref_instruction(is_signed, irb->current_basic_block); - ir_ref_instruction(bit_count, irb->current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, IrInstSrc *elem_type) { @@ -6530,21 +6511,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } - case BuiltinFnIdIntType: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, int_type, lval, result_loc); - } case BuiltinFnIdVectorType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -7074,21 +7040,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); } - case BuiltinFnIdArgType: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false); - return ir_lval_wrap(irb, scope, arg_type, lval, result_loc); - } case BuiltinFnIdExport: { // Cast the options parameter to the options type @@ -25385,20 +25336,6 @@ static IrInstGen *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstSrcBo return ir_resolve_cast(ira, &instruction->base.base, target, u1_type, CastOpBoolToInt); } -static IrInstGen *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstSrcIntType *instruction) { - IrInstGen *is_signed_value = instruction->is_signed->child; - bool is_signed; - if (!ir_resolve_bool(ira, is_signed_value, &is_signed)) - return ira->codegen->invalid_inst_gen; - - IrInstGen *bit_count_value = instruction->bit_count->child; - uint64_t bit_count; - if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u16, &bit_count)) - return ira->codegen->invalid_inst_gen; - - return ir_const_type(ira, &instruction->base.base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); -} - static IrInstGen *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstSrcVectorType *instruction) { uint64_t len; if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) @@ -29270,8 +29207,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_float_to_int(ira, (IrInstSrcFloatToInt *)instruction); case IrInstSrcIdBoolToInt: return ir_analyze_instruction_bool_to_int(ira, (IrInstSrcBoolToInt *)instruction); - case IrInstSrcIdIntType: - return ir_analyze_instruction_int_type(ira, (IrInstSrcIntType *)instruction); case IrInstSrcIdVectorType: return ir_analyze_instruction_vector_type(ira, (IrInstSrcVectorType *)instruction); case IrInstSrcIdShuffleVector: @@ -29754,7 +29689,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdRef: case IrInstSrcIdEmbedFile: case IrInstSrcIdTruncate: - case IrInstSrcIdIntType: case IrInstSrcIdVectorType: case IrInstSrcIdShuffleVector: case IrInstSrcIdSplat: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 4f87ff832d..1cfe904660 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -179,8 +179,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcFloatToInt"; case IrInstSrcIdBoolToInt: return "SrcBoolToInt"; - case IrInstSrcIdIntType: - return "SrcIntType"; case IrInstSrcIdVectorType: return "SrcVectorType"; case IrInstSrcIdBoolNot: @@ -1652,14 +1650,6 @@ static void ir_print_bool_to_int(IrPrintSrc *irp, IrInstSrcBoolToInt *instructio fprintf(irp->f, ")"); } -static void ir_print_int_type(IrPrintSrc *irp, IrInstSrcIntType *instruction) { - fprintf(irp->f, "@IntType("); - ir_print_other_inst_src(irp, instruction->is_signed); - fprintf(irp->f, ", "); - ir_print_other_inst_src(irp, instruction->bit_count); - fprintf(irp->f, ")"); -} - static void ir_print_vector_type(IrPrintSrc *irp, IrInstSrcVectorType *instruction) { fprintf(irp->f, "@Vector("); ir_print_other_inst_src(irp, instruction->len); @@ -2739,9 +2729,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdBoolToInt: ir_print_bool_to_int(irp, (IrInstSrcBoolToInt *)instruction); break; - case IrInstSrcIdIntType: - ir_print_int_type(irp, (IrInstSrcIntType *)instruction); - break; case IrInstSrcIdVectorType: ir_print_vector_type(irp, (IrInstSrcVectorType *)instruction); break; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index eb1f68e163..56df006e82 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1902,7 +1902,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var x: i65536 = 1; \\} , &[_][]const u8{ - "tmp.zig:2:31: error: integer value 65536 cannot be coerced to type 'u16'", "tmp.zig:5:12: error: primitive integer type 'i65536' exceeds maximum bit width of 65535", }); From 544bc42fd9b612462579928298ec467484763ae1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 24 Feb 2020 20:11:33 -0500 Subject: [PATCH 107/109] expose --verbose-llvm-cpu-features to zig build --- lib/std/build.zig | 3 +++ lib/std/special/build_runner.zig | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 6e9031ee31..85aa86fd98 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -38,6 +38,7 @@ pub const Builder = struct { verbose_ir: bool, verbose_llvm_ir: bool, verbose_cimport: bool, + verbose_llvm_cpu_features: bool, invalid_user_input: bool, zig_exe: []const u8, default_step: *Step, @@ -134,6 +135,7 @@ pub const Builder = struct { .verbose_ir = false, .verbose_llvm_ir = false, .verbose_cimport = false, + .verbose_llvm_cpu_features = false, .invalid_user_input = false, .allocator = allocator, .user_input_options = UserInputOptionsMap.init(allocator), @@ -1837,6 +1839,7 @@ pub const LibExeObjStep = struct { if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable; if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; + if (builder.verbose_llvm_cpu_features) zig_args.append("--verbose-llvm-cpu-features") catch unreachable; if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir"); if (self.emit_asm) try zig_args.append("-femit-asm"); diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig index 45dea79469..dc13435cb0 100644 --- a/lib/std/special/build_runner.zig +++ b/lib/std/special/build_runner.zig @@ -96,6 +96,8 @@ pub fn main() !void { builder.verbose_cimport = true; } else if (mem.eql(u8, arg, "--verbose-cc")) { builder.verbose_cc = true; + } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { + builder.verbose_llvm_cpu_features = true; } else if (mem.eql(u8, arg, "--")) { builder.args = argsRest(args, arg_idx); break; @@ -185,16 +187,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { try out_stream.write( \\ \\Advanced Options: - \\ --build-file [file] Override path to build.zig - \\ --cache-dir [path] Override path to zig cache directory - \\ --override-lib-dir [arg] Override path to Zig lib directory - \\ --verbose-tokenize Enable compiler debug output for tokenization - \\ --verbose-ast Enable compiler debug output for parsing into an AST - \\ --verbose-link Enable compiler debug output for linking - \\ --verbose-ir Enable compiler debug output for Zig IR - \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR - \\ --verbose-cimport Enable compiler debug output for C imports - \\ --verbose-cc Enable compiler debug output for C compilation + \\ --build-file [file] Override path to build.zig + \\ --cache-dir [path] Override path to zig cache directory + \\ --override-lib-dir [arg] Override path to Zig lib directory + \\ --verbose-tokenize Enable compiler debug output for tokenization + \\ --verbose-ast Enable compiler debug output for parsing into an AST + \\ --verbose-link Enable compiler debug output for linking + \\ --verbose-ir Enable compiler debug output for Zig IR + \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR + \\ --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 \\ ); } From 6fa143355f256e354a2df67a42e3e9208d1a71e9 Mon Sep 17 00:00:00 2001 From: vegecode Date: Tue, 4 Feb 2020 12:16:20 -0600 Subject: [PATCH 108/109] Add formatted printing directly into std.Buffer --- lib/std/buffer.zig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig index 077b2b615f..6bf03472f6 100644 --- a/lib/std/buffer.zig +++ b/lib/std/buffer.zig @@ -147,6 +147,16 @@ pub const Buffer = struct { try self.resize(m.len); mem.copy(u8, self.list.toSlice(), m); } + + pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void { + try std.fmt.format( + self, + @typeInfo(@TypeOf(Buffer.append)).Fn.return_type.?.ErrorSet, + Buffer.append, + fmt, + args, + ); + } }; test "simple Buffer" { @@ -190,3 +200,11 @@ test "Buffer.initCapacity" { testing.expect(buf.capacity() == old_cap); testing.expect(mem.eql(u8, buf.toSliceConst(), "hello")); } + +test "Buffer.print" { + var buf = try Buffer.init(testing.allocator, ""); + defer buf.deinit(); + + try buf.print("Hello {} the {}", .{ 2, "world" }); + testing.expect(buf.eql("Hello 2 the world")); +} From 7cfe854359bcacb038654903fbe8a17c4144c3d5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 24 Feb 2020 22:34:06 -0500 Subject: [PATCH 109/109] clean up std.Buffer.print --- lib/std/buffer.zig | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig index 6bf03472f6..f808af1485 100644 --- a/lib/std/buffer.zig +++ b/lib/std/buffer.zig @@ -149,13 +149,7 @@ pub const Buffer = struct { } pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void { - try std.fmt.format( - self, - @typeInfo(@TypeOf(Buffer.append)).Fn.return_type.?.ErrorSet, - Buffer.append, - fmt, - args, - ); + return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args); } };