delete @cImport from the language

closes #20630
This commit is contained in:
Andrew Kelley
2026-04-15 17:35:01 -07:00
parent 0dd99c37cc
commit 67a5b6e5e8
47 changed files with 67 additions and 844 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ contact_links:
about: "Please use one of the community spaces instead for questions or general discussions." about: "Please use one of the community spaces instead for questions or general discussions."
url: https://ziglang.org/community url: https://ziglang.org/community
- name: C Translation - name: C Translation
about: "Issues related to `zig translate-c` and `@cImport` are tracked separately." about: "Issues related to `zig translate-c` are tracked separately."
url: https://codeberg.org/ziglang/translate-c url: https://codeberg.org/ziglang/translate-c
- name: Copilot and Other LLMs - name: Copilot and Other LLMs
about: "Please do not use GitHub Copilot or any other LLM to write an issue." about: "Please do not use GitHub Copilot or any other LLM to write an issue."
-7
View File
@@ -735,11 +735,6 @@ if(MSVC OR MINGW)
endif() endif()
# "-Dno-langref" is hardcoded because stage2 builds lack the `@cImport`
# feature, which some of the doctests rely on.
# To obtain this document, run `zig build` against stage3 rather than stage2.
# Note that the `langref` step can be used to isolate this task.
set(ZIG_BUILD_ARGS set(ZIG_BUILD_ARGS
--zig-lib-dir "${PROJECT_SOURCE_DIR}/lib" --zig-lib-dir "${PROJECT_SOURCE_DIR}/lib"
@@ -749,8 +744,6 @@ set(ZIG_BUILD_ARGS
-Denable-llvm -Denable-llvm
"-Dconfig_h=${ZIG_CONFIG_H_OUT}" "-Dconfig_h=${ZIG_CONFIG_H_OUT}"
-Dno-langref
) )
set(ZIG_EXTRA_BUILD_ARGS "" CACHE STRING "Extra zig build args") set(ZIG_EXTRA_BUILD_ARGS "" CACHE STRING "Extra zig build args")
+13 -20
View File
@@ -658,38 +658,31 @@ WebAssembly-related.
### Improving Translate-C ### Improving Translate-C
`translate-c` is a feature provided by Zig that converts C source code into `translate-c` is a feature provided by Zig that converts C source code into Zig
Zig source code. It powers the `zig translate-c` command as well as source code. It powers the `zig translate-c` command, allowing Zig code to not
[@cImport](https://ziglang.org/documentation/master/#cImport), allowing Zig only take advantage of function prototypes defined in C header files, but also
code to not only take advantage of function prototypes defined in .h files, `static inline` functions written in C, and even some macros.
but also `static inline` functions written in C, and even some macros.
This feature used to work by using libclang API to parse and semantically This feature used to work by using libclang API to parse and semantically
analyze C/C++ files, and then based on the provided AST and type information, analyze C/C++ files, and then based on the provided AST and type information,
generating Zig AST, and finally using the mechanisms of `zig fmt` to render the generating Zig AST, and finally using the mechanisms of `zig fmt` to render the
Zig AST to a file. Zig AST to a file.
However, C translation is in a transitional period right now. It used to be However, it is now based on [arocc](https://github.com/Vexu/arocc/), a
based on Clang, but is now based on Aro: third-party C compiler written in Zig. Test coverage, bug reports, and official
implementation live in this repository: [ziglang/translate-c](https://codeberg.org/ziglang/translate-c/)
[Pull Request: update aro and translate-c to latest; delete clang translate-c](https://github.com/ziglang/zig/pull/24497) This package is currently vendored into the Zig source tree. The TranslateC
build step takes advantage of this to provide the ability to setup C
Test coverage as well as bug reports have been moved to this repository: translation in one's build.zig script.
[ziglang/translate-c](https://codeberg.org/ziglang/translate-c/)
In the future, [@cImport will move to the build system](https://github.com/ziglang/zig/issues/20630),
but for now, the translate-c logic is copy-pasted from that project into
[ziglang/zig](https://codeberg.org/ziglang/zig/), powering both `zig translate-c`
and `@cImport`.
Please see the readme of the translate-c project for how to contribute. Once an Please see the readme of the translate-c project for how to contribute. Once an
issue is resolved (and test coverage added) there, the changes can be issue is resolved (and test coverage added) there, the changes can be
immediately backported to the zig compiler. immediately backported to the zig compiler.
Once we fix the problems people are facing from this transition from Clang to However, in the future, this build step will be removed in favor of explicit
Aro, we can move on to enhancing the translate-c package such that `@cImport` dependency on the translate-c package via build system / package manager. At
becomes redundant and can therefore be eliminated from the language. that point, Zig will stop vendoring arocc.
### Autodoc ### Autodoc
+2 -163
View File
@@ -1032,9 +1032,8 @@
{#header_close#} {#header_close#}
{#header_open|Local Variables#} {#header_open|Local Variables#}
<p> <p>Local variables occur inside {#link|Functions#}, {#link|comptime#}
Local variables occur inside {#link|Functions#}, {#link|comptime#} blocks, and {#link|@cImport#} blocks. blocks, and labeled {#link|Blocks#}.</p>
</p>
<p> <p>
When a local variable is {#syntax#}const{#endsyntax#}, it means that after initialization, the variable's When a local variable is {#syntax#}const{#endsyntax#}, it means that after initialization, the variable's
value will not change. If the initialization value of a {#syntax#}const{#endsyntax#} variable is value will not change. If the initialization value of a {#syntax#}const{#endsyntax#} variable is
@@ -4573,62 +4572,6 @@ comptime {
{#header_close#} {#header_close#}
{#header_open|@cDefine#}
<pre>{#syntax#}@cDefine(comptime name: []const u8, value) void{#endsyntax#}</pre>
<p>
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
</p>
<p>
This appends <code>#define $name $value</code> to the {#syntax#}@cImport{#endsyntax#}
temporary buffer.
</p>
<p>
To define without a value, like this:
</p>
<pre><code class="c">#define _GNU_SOURCE</code></pre>
<p>
Use the void value, like this:
</p>
<pre>{#syntax#}@cDefine("_GNU_SOURCE", {}){#endsyntax#}</pre>
{#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}
{#header_close#}
{#header_open|@cImport#}
<pre>{#syntax#}@cImport(expression) type{#endsyntax#}</pre>
<p>
This function parses C code and imports the functions, types, variables,
and compatible macro definitions into a new empty struct type, and then
returns that type.
</p>
<p>
{#syntax#}expression{#endsyntax#} is interpreted at compile time. The builtin functions
{#syntax#}@cInclude{#endsyntax#}, {#syntax#}@cDefine{#endsyntax#}, and {#syntax#}@cUndef{#endsyntax#} work
within this expression, appending to a temporary buffer which is then parsed as C code.
</p>
<p>
Usually you should only have one {#syntax#}@cImport{#endsyntax#} in your entire application, because it saves the compiler
from invoking clang multiple times, and prevents inline functions from being duplicated.
</p>
<p>
Reasons for having multiple {#syntax#}@cImport{#endsyntax#} expressions would be:
</p>
<ul>
<li>To avoid a symbol collision, for example if foo.h and bar.h both <code>#define CONNECTION_COUNT</code></li>
<li>To analyze the C code with different preprocessor defines</li>
</ul>
{#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
{#header_close#}
{#header_open|@cInclude#}
<pre>{#syntax#}@cInclude(comptime path: []const u8) void{#endsyntax#}</pre>
<p>
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
</p>
<p>
This appends <code>#include &lt;$path&gt;\n</code> to the {#syntax#}c_import{#endsyntax#}
temporary buffer.
</p>
{#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
{#header_close#}
{#header_open|@clz#} {#header_open|@clz#}
<pre>{#syntax#}@clz(operand: anytype) anytype{#endsyntax#}</pre> <pre>{#syntax#}@clz(operand: anytype) anytype{#endsyntax#}</pre>
<p>{#syntax#}@TypeOf(operand){#endsyntax#} must be an integer type or an integer vector type.</p> <p>{#syntax#}@TypeOf(operand){#endsyntax#} must be an integer type or an integer vector type.</p>
@@ -4758,18 +4701,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#see_also|@clz|@popCount#} {#see_also|@clz|@popCount#}
{#header_close#} {#header_close#}
{#header_open|@cUndef#}
<pre>{#syntax#}@cUndef(comptime name: []const u8) void{#endsyntax#}</pre>
<p>
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
</p>
<p>
This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
temporary buffer.
</p>
{#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
{#header_close#}
{#header_open|@cVaArg#} {#header_open|@cVaArg#}
<pre>{#syntax#}@cVaArg(operand: *std.builtin.VaList, comptime T: type) T{#endsyntax#}</pre> <pre>{#syntax#}@cVaArg(operand: *std.builtin.VaList, comptime T: type) T{#endsyntax#}</pre>
<p> <p>
@@ -6784,35 +6715,6 @@ const builtin = @import("builtin");
</p> </p>
{#see_also|Primitive Types#} {#see_also|Primitive Types#}
{#header_close#} {#header_close#}
{#header_open|Import from C Header File#}
<p>
The {#syntax#}@cImport{#endsyntax#} builtin function can be used
to directly import symbols from <code class="file">.h</code> files:
</p>
{#code|cImport_builtin.zig#}
<p>
The {#syntax#}@cImport{#endsyntax#} function takes an expression as a parameter.
This expression is evaluated at compile-time and is used to control
preprocessor directives and include multiple <code class="file">.h</code> files:
</p>
{#syntax_block|zig|@cImport Expression#}
const builtin = @import("builtin");
const c = @cImport({
@cDefine("NDEBUG", builtin.mode == .ReleaseFast);
if (something) {
@cDefine("_GNU_SOURCE", {});
}
@cInclude("stdlib.h");
if (something) {
@cUndef("_GNU_SOURCE");
}
@cInclude("soundio.h");
});
{#end_syntax_block#}
{#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
{#header_close#}
{#header_open|C Translation CLI#} {#header_open|C Translation CLI#}
<p> <p>
@@ -6872,42 +6774,8 @@ $ zig translate-c -cflags -fshort-enums -- varycflags.h|grep -B1 do_something
pub const enum_FOO = u8; pub const enum_FOO = u8;
pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#} pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#}
{#header_close#} {#header_close#}
{#header_open|@cImport vs translate-c#}
<p>{#syntax#}@cImport{#endsyntax#} and <kbd>zig translate-c</kbd> use the same underlying
C translation functionality, so on a technical level they are equivalent. In practice,
{#syntax#}@cImport{#endsyntax#} is useful as a way to quickly and easily access numeric constants, typedefs,
and record types without needing any extra setup. If you need to pass {#link|cflags|Using -target and -cflags#}
to clang, or if you would like to edit the translated code, it is recommended to use
<kbd>zig translate-c</kbd> and save the results to a file. Common reasons for editing
the generated code include: changing {#syntax#}anytype{#endsyntax#} parameters in function-like macros to more
specific types; changing {#syntax#}[*c]T{#endsyntax#} pointers to {#syntax#}[*]T{#endsyntax#} or
{#syntax#}*T{#endsyntax#} pointers for improved type safety; and
{#link|enabling or disabling runtime safety|@setRuntimeSafety#} within specific functions.
</p>
{#header_close#} {#header_close#}
{#see_also|Targets|C Type Primitives|Pointers|C Pointers|Import from C Header File|@cInclude|@cImport|@setRuntimeSafety#}
{#header_close#}
{#header_open|C Translation Caching#}
<p>
The C translation feature (whether used via <kbd>zig translate-c</kbd> or
{#syntax#}@cImport{#endsyntax#}) integrates with the Zig caching system. Subsequent runs with
the same source file, target, and cflags will use the cache instead of repeatedly translating
the same code.
</p>
<p>
To see where the cached files are stored when compiling code that uses {#syntax#}@cImport{#endsyntax#},
use the <kbd>--verbose-cimport</kbd> flag:
</p>
{#code|verbose_cimport_flag.zig#}
<p>
<code class="file">cimport.h</code> contains the file to translate (constructed from calls to
{#syntax#}@cInclude{#endsyntax#}, {#syntax#}@cDefine{#endsyntax#}, and {#syntax#}@cUndef{#endsyntax#}),
<code class="file">cimport.h.d</code> is the list of file dependencies, and
<code class="file">cimport.zig</code> contains the translated output.
</p>
{#see_also|Import from C Header File|C Translation CLI|@cInclude|@cImport#}
{#header_close#}
{#header_open|Translation failures#} {#header_open|Translation failures#}
<p> <p>
Some C constructs cannot be translated to Zig - for example, <em>goto</em>, Some C constructs cannot be translated to Zig - for example, <em>goto</em>,
@@ -6933,35 +6801,6 @@ pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#}
</p> </p>
{#see_also|opaque|extern|@compileError#} {#see_also|opaque|extern|@compileError#}
{#header_close#} {#header_close#}
{#header_open|C Macros#}
<p>
C Translation makes a best-effort attempt to translate function-like macros into equivalent
Zig functions. Since C macros operate at the level of lexical tokens, not all C macros
can be translated to Zig. Macros that cannot be translated will be demoted to
{#syntax#}@compileError{#endsyntax#}. Note that C code which <em>uses</em> macros will be
translated without any additional issues (since Zig operates on the pre-processed source
with macros expanded). It is merely the macros themselves which may not be translatable to
Zig.
</p>
<p>Consider the following example:</p>
{#syntax_block|c|macro.c#}
#define MAKELOCAL(NAME, INIT) int NAME = INIT
int foo(void) {
MAKELOCAL(a, 1);
MAKELOCAL(b, 2);
return a + b;
}
{#end_syntax_block#}
{#shell_samp#}$ zig translate-c macro.c > macro.zig{#end_shell_samp#}
{#code|macro.zig#}
<p>Note that {#syntax#}foo{#endsyntax#} was translated correctly despite using a non-translatable
macro. {#syntax#}MAKELOCAL{#endsyntax#} was demoted to {#syntax#}@compileError{#endsyntax#} since
it cannot be expressed as a Zig function; this simply means that you cannot directly use
{#syntax#}MAKELOCAL{#endsyntax#} from Zig.
</p>
{#see_also|@compileError#}
{#header_close#}
{#header_open|C Pointers#} {#header_open|C Pointers#}
<p> <p>
-12
View File
@@ -1,12 +0,0 @@
const c = @cImport({
// See https://github.com/ziglang/zig/issues/515
@cDefine("_NO_CRT_STDIO_INLINE", "1");
@cInclude("stdio.h");
});
pub fn main() void {
if (@import("builtin").os.tag == .netbsd) return; // https://github.com/Vexu/arocc/issues/960
_ = c.printf("hello\n");
}
// exe=succeed
// link_libc
-10
View File
@@ -1,10 +0,0 @@
pub export fn foo() c_int {
var a: c_int = 1;
_ = &a;
var b: c_int = 2;
_ = &b;
return a + b;
}
pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected token .Equal"); // macro.c:1:9
// syntax
-1
View File
@@ -10,4 +10,3 @@ test "variadic function" {
// test // test
// link_libc // link_libc
// verbose_cimport
-12
View File
@@ -1,12 +0,0 @@
const c = @cImport({
@cDefine("_NO_CRT_STDIO_INLINE", "1");
@cInclude("stdio.h");
});
pub fn main() void {
if (@import("builtin").os.tag == .netbsd) return; // https://github.com/Vexu/arocc/issues/960
_ = c;
}
// exe=succeed
// link_libc
// verbose_cimport
-2
View File
@@ -333,8 +333,6 @@ pub fn main(init: process.Init.Minimal) !void {
builder.verbose_llvm_ir = arg["--verbose-llvm-ir=".len..]; builder.verbose_llvm_ir = arg["--verbose-llvm-ir=".len..];
} else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) { } else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) {
builder.verbose_llvm_bc = arg["--verbose-llvm-bc=".len..]; builder.verbose_llvm_bc = arg["--verbose-llvm-bc=".len..];
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
builder.verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-cc")) { } else if (mem.eql(u8, arg, "--verbose-cc")) {
builder.verbose_cc = true; builder.verbose_cc = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
-3
View File
@@ -38,7 +38,6 @@ verbose_cc: bool,
verbose_air: bool, verbose_air: bool,
verbose_llvm_ir: ?[]const u8, verbose_llvm_ir: ?[]const u8,
verbose_llvm_bc: ?[]const u8, verbose_llvm_bc: ?[]const u8,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool, verbose_llvm_cpu_features: bool,
reference_trace: ?u32 = null, reference_trace: ?u32 = null,
invalid_user_input: bool, invalid_user_input: bool,
@@ -278,7 +277,6 @@ pub fn create(
.verbose_air = false, .verbose_air = false,
.verbose_llvm_ir = null, .verbose_llvm_ir = null,
.verbose_llvm_bc = null, .verbose_llvm_bc = null,
.verbose_cimport = false,
.verbose_llvm_cpu_features = false, .verbose_llvm_cpu_features = false,
.invalid_user_input = false, .invalid_user_input = false,
.allocator = arena, .allocator = arena,
@@ -377,7 +375,6 @@ fn createChildOnly(
.verbose_air = parent.verbose_air, .verbose_air = parent.verbose_air,
.verbose_llvm_ir = parent.verbose_llvm_ir, .verbose_llvm_ir = parent.verbose_llvm_ir,
.verbose_llvm_bc = parent.verbose_llvm_bc, .verbose_llvm_bc = parent.verbose_llvm_bc,
.verbose_cimport = parent.verbose_cimport,
.verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
.reference_trace = parent.reference_trace, .reference_trace = parent.reference_trace,
.invalid_user_input = false, .invalid_user_input = false,
-1
View File
@@ -1393,7 +1393,6 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
try zig_args.append("--debug-incremental"); try zig_args.append("--debug-incremental");
} }
if (b.verbose_cimport) try zig_args.append("--verbose-cimport");
if (b.verbose_air) try zig_args.append("--verbose-air"); if (b.verbose_air) try zig_args.append("--verbose-air");
if (b.verbose_llvm_ir) |path| try zig_args.append(b.fmt("--verbose-llvm-ir={s}", .{path})); if (b.verbose_llvm_ir) |path| try zig_args.append(b.fmt("--verbose-llvm-ir={s}", .{path}));
if (b.verbose_llvm_bc) |path| try zig_args.append(b.fmt("--verbose-llvm-bc={s}", .{path})); if (b.verbose_llvm_bc) |path| try zig_args.append(b.fmt("--verbose-llvm-bc={s}", .{path}));
-10
View File
@@ -796,11 +796,6 @@ pub const SimpleComptimeReason = enum(u32) {
operand_branchHint, operand_branchHint,
operand_setRuntimeSafety, operand_setRuntimeSafety,
operand_embedFile, operand_embedFile,
operand_cImport,
operand_cDefine_macro_name,
operand_cDefine_macro_value,
operand_cInclude_file_name,
operand_cUndef_macro_name,
operand_shuffle_mask, operand_shuffle_mask,
operand_atomicRmw_operation, operand_atomicRmw_operation,
operand_reduce_operation, operand_reduce_operation,
@@ -891,11 +886,6 @@ pub const SimpleComptimeReason = enum(u32) {
.operand_branchHint => "operand to '@branchHint' must be comptime-known", .operand_branchHint => "operand to '@branchHint' must be comptime-known",
.operand_setRuntimeSafety => "operand to '@setRuntimeSafety' must be comptime-known", .operand_setRuntimeSafety => "operand to '@setRuntimeSafety' must be comptime-known",
.operand_embedFile => "operand to '@embedFile' must be comptime-known", .operand_embedFile => "operand to '@embedFile' must be comptime-known",
.operand_cImport => "operand to '@cImport' is evaluated at comptime",
.operand_cDefine_macro_name => "'@cDefine' macro name must be comptime-known",
.operand_cDefine_macro_value => "'@cDefine' macro value must be comptime-known",
.operand_cInclude_file_name => "'@cInclude' file name must be comptime-known",
.operand_cUndef_macro_name => "'@cUndef' macro name must be comptime-known",
.operand_shuffle_mask => "'@shuffle' mask must be comptime-known", .operand_shuffle_mask => "'@shuffle' mask must be comptime-known",
.operand_atomicRmw_operation => "'@atomicRmw' operation must be comptime-known", .operand_atomicRmw_operation => "'@atomicRmw' operation must be comptime-known",
.operand_reduce_operation => "'@reduce' operation must be comptime-known", .operand_reduce_operation => "'@reduce' operation must be comptime-known",
+1 -74
View File
@@ -2870,7 +2870,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.mul_add, .mul_add,
.max, .max,
.min, .min,
.c_import,
.@"resume", .@"resume",
.ret_err_value_code, .ret_err_value_code,
.ret_ptr, .ret_ptr,
@@ -8955,7 +8954,6 @@ fn typeOf(
var typeof_scope = gz.makeSubBlock(scope); var typeof_scope = gz.makeSubBlock(scope);
typeof_scope.is_comptime = false; typeof_scope.is_comptime = false;
typeof_scope.is_typeof = true; typeof_scope.is_typeof = true;
typeof_scope.c_import = false;
defer typeof_scope.unstack(); defer typeof_scope.unstack();
const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node); const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node);
@@ -9055,8 +9053,7 @@ fn builtinCall(
const builtin_name = tree.tokenSlice(builtin_token); const builtin_name = tree.tokenSlice(builtin_token);
// We handle the different builtins manually because they have different semantics depending // We handle the different builtins manually because they have different semantics depending
// on the function. For example, `@as` and others participate in result location semantics, // on the function. For example, `@as` and others participate in result location semantics.
// and `@cImport` creates a special scope that collects a .c source code text buffer.
// Also, some builtins have a variable number of parameters. // Also, some builtins have a variable number of parameters.
const info = BuiltinFn.list.get(builtin_name) orelse { const info = BuiltinFn.list.get(builtin_name) orelse {
@@ -9175,7 +9172,6 @@ fn builtinCall(
.bit_cast => return bitCast( gz, scope, ri, node, params[0]), .bit_cast => return bitCast( gz, scope, ri, node, params[0]),
.TypeOf => return typeOf( gz, scope, ri, node, params), .TypeOf => return typeOf( gz, scope, ri, node, params),
.union_init => return unionInit(gz, scope, ri, node, params), .union_init => return unionInit(gz, scope, ri, node, params),
.c_import => return cImport( gz, scope, node, params[0]),
.min => return minMax( gz, scope, ri, node, params, .min), .min => return minMax( gz, scope, ri, node, params, .min),
.max => return minMax( gz, scope, ri, node, params, .max), .max => return minMax( gz, scope, ri, node, params, .max),
// zig fmt: on // zig fmt: on
@@ -9484,9 +9480,6 @@ fn builtinCall(
.bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of), .bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of),
.offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .offset_of), .offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .offset_of),
.c_undef => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_undef),
.c_include => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_include),
.cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1), .cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1),
.cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0), .cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0),
// zig fmt: on // zig fmt: on
@@ -9509,17 +9502,6 @@ fn builtinCall(
}); });
return rvalue(gz, ri, result, node); return rvalue(gz, ri, result, node);
}, },
.c_define => {
if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .operand_cDefine_macro_name);
const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1], .operand_cDefine_macro_value);
const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = name,
.rhs = value,
});
return rvalue(gz, ri, result, node);
},
.splat => { .splat => {
const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name); const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
const elem_type = try gz.addUnNode(.splat_op_result_ty, result_type, node); const elem_type = try gz.addUnNode(.splat_op_result_ty, result_type, node);
@@ -9951,30 +9933,6 @@ fn divBuiltin(
return rvalue(gz, ri, result, node); return rvalue(gz, ri, result, node);
} }
fn simpleCBuiltin(
gz: *GenZir,
scope: *Scope,
ri: ResultInfo,
node: Ast.Node.Index,
operand_node: Ast.Node.Index,
tag: Zir.Inst.Extended,
) InnerError!Zir.Inst.Ref {
const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
const operand = try comptimeExpr(
gz,
scope,
.{ .rl = .{ .coerced_ty = .slice_const_u8_type } },
operand_node,
if (tag == .c_undef) .operand_cUndef_macro_name else .operand_cInclude_file_name,
);
_ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
});
return rvalue(gz, ri, .void_value, node);
}
fn offsetOf( fn offsetOf(
gz: *GenZir, gz: *GenZir,
scope: *Scope, scope: *Scope,
@@ -10024,35 +9982,6 @@ fn shiftOp(
return rvalue(gz, ri, result, node); return rvalue(gz, ri, result, node);
} }
fn cImport(
gz: *GenZir,
scope: *Scope,
node: Ast.Node.Index,
body_node: Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const gpa = astgen.gpa;
if (gz.c_import) return gz.astgen.failNode(node, "cannot nest @cImport", .{});
var block_scope = gz.makeSubBlock(scope);
block_scope.is_comptime = true;
block_scope.c_import = true;
defer block_scope.unstack();
const block_inst = try gz.makeBlockInst(.c_import, node);
const block_result = try fullBodyExpr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node, .normal);
_ = try gz.addUnNode(.ensure_result_used, block_result, node);
if (!gz.refIsNoReturn(block_result)) {
_ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
}
try block_scope.setBlockBody(block_inst);
// block_scope unstacked now, can add new instructions to gz
try gz.instructions.append(gpa, block_inst);
return block_inst.toRef();
}
fn overflowArithmetic( fn overflowArithmetic(
gz: *GenZir, gz: *GenZir,
scope: *Scope, scope: *Scope,
@@ -11339,7 +11268,6 @@ const GenZir = struct {
/// This is set to true for a `GenZir` of a `block_inline`, indicating that /// This is set to true for a `GenZir` of a `block_inline`, indicating that
/// exits from this block should use `break_inline` rather than `break`. /// exits from this block should use `break_inline` rather than `break`.
is_inline: bool = false, is_inline: bool = false,
c_import: bool = false,
/// The containing decl AST node. /// The containing decl AST node.
decl_node_index: Ast.Node.Index, decl_node_index: Ast.Node.Index,
/// The containing decl line index, absolute. /// The containing decl line index, absolute.
@@ -11427,7 +11355,6 @@ const GenZir = struct {
return .{ return .{
.is_comptime = gz.is_comptime, .is_comptime = gz.is_comptime,
.is_typeof = gz.is_typeof, .is_typeof = gz.is_typeof,
.c_import = gz.c_import,
.decl_node_index = gz.decl_node_index, .decl_node_index = gz.decl_node_index,
.decl_line = gz.decl_line, .decl_line = gz.decl_line,
.parent = scope, .parent = scope,
-11
View File
@@ -842,10 +842,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
_ = try astrl.expr(args[2], block, ResultInfo.type_only); _ = try astrl.expr(args[2], block, ResultInfo.type_only);
return false; return false;
}, },
.c_import => {
_ = try astrl.expr(args[0], block, ResultInfo.none);
return false;
},
.min, .max => { .min, .max => {
for (args) |arg_node| { for (args) |arg_node| {
_ = try astrl.expr(arg_node, block, ResultInfo.none); _ = try astrl.expr(arg_node, block, ResultInfo.none);
@@ -907,8 +903,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
.error_name, .error_name,
.set_runtime_safety, .set_runtime_safety,
.Tuple, .Tuple,
.c_undef,
.c_include,
.wasm_memory_size, .wasm_memory_size,
.splat, .splat,
.set_float_mode, .set_float_mode,
@@ -986,11 +980,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
_ = try astrl.expr(args[1], block, ResultInfo.type_only); _ = try astrl.expr(args[1], block, ResultInfo.type_only);
return false; return false;
}, },
.c_define => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.none);
return false;
},
.reduce => { .reduce => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only); _ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.none); _ = try astrl.expr(args[1], block, ResultInfo.none);
-32
View File
@@ -20,9 +20,6 @@ pub const Tag = enum {
bit_reverse, bit_reverse,
offset_of, offset_of,
call, call,
c_define,
c_import,
c_include,
clz, clz,
cmpxchg_strong, cmpxchg_strong,
cmpxchg_weak, cmpxchg_weak,
@@ -30,7 +27,6 @@ pub const Tag = enum {
compile_log, compile_log,
const_cast, const_cast,
ctz, ctz,
c_undef,
c_va_arg, c_va_arg,
c_va_copy, c_va_copy,
c_va_end, c_va_end,
@@ -306,27 +302,6 @@ pub const list = list: {
.param_count = 3, .param_count = 3,
}, },
}, },
.{
"@cDefine",
.{
.tag = .c_define,
.param_count = 2,
},
},
.{
"@cImport",
.{
.tag = .c_import,
.param_count = 1,
},
},
.{
"@cInclude",
.{
.tag = .c_include,
.param_count = 1,
},
},
.{ .{
"@clz", "@clz",
.{ .{
@@ -376,13 +351,6 @@ pub const list = list: {
.param_count = 1, .param_count = 1,
}, },
}, },
.{
"@cUndef",
.{
.tag = .c_undef,
.param_count = 1,
},
},
.{ .{
"@cVaArg", "@cVaArg",
.{ .{
-16
View File
@@ -1016,9 +1016,6 @@ pub const Inst = struct {
/// Implements the `@max` builtin for 2 args. /// Implements the `@max` builtin for 2 args.
/// Uses the `pl_node` union field with payload `Bin` /// Uses the `pl_node` union field with payload `Bin`
max, max,
/// Implements the `@cImport` builtin.
/// Uses the `pl_node` union field with payload `Block`.
c_import,
/// Allocates stack local memory. /// Allocates stack local memory.
/// Uses the `un_node` union field. The operand is the type of the allocated object. /// Uses the `un_node` union field. The operand is the type of the allocated object.
@@ -1297,7 +1294,6 @@ pub const Inst = struct {
.memset, .memset,
.memmove, .memmove,
.min, .min,
.c_import,
.@"resume", .@"resume",
.ret_err_value_code, .ret_err_value_code,
.extended, .extended,
@@ -1577,7 +1573,6 @@ pub const Inst = struct {
.builtin_call, .builtin_call,
.max, .max,
.min, .min,
.c_import,
.@"resume", .@"resume",
.ret_err_value_code, .ret_err_value_code,
.@"break", .@"break",
@@ -1857,7 +1852,6 @@ pub const Inst = struct {
.memset = .pl_node, .memset = .pl_node,
.memmove = .pl_node, .memmove = .pl_node,
.min = .pl_node, .min = .pl_node,
.c_import = .pl_node,
.alloc = .un_node, .alloc = .un_node,
.alloc_mut = .un_node, .alloc_mut = .un_node,
@@ -2018,12 +2012,6 @@ pub const Inst = struct {
/// `small` is unused. /// `small` is unused.
round_op_ty, round_op_ty,
/// `operand` is payload index to `UnNode`. /// `operand` is payload index to `UnNode`.
c_undef,
/// `operand` is payload index to `UnNode`.
c_include,
/// `operand` is payload index to `BinNode`.
c_define,
/// `operand` is payload index to `UnNode`.
wasm_memory_size, wasm_memory_size,
/// `operand` is payload index to `BinNode`. /// `operand` is payload index to `BinNode`.
wasm_memory_grow, wasm_memory_grow,
@@ -4360,9 +4348,6 @@ fn findTrackableInner(
.mul_with_overflow, .mul_with_overflow,
.shl_with_overflow, .shl_with_overflow,
.round_op, .round_op,
.c_undef,
.c_include,
.c_define,
.wasm_memory_size, .wasm_memory_size,
.wasm_memory_grow, .wasm_memory_grow,
.prefetch, .prefetch,
@@ -4532,7 +4517,6 @@ fn findTrackableInner(
.block, .block,
.block_inline, .block_inline,
.c_import,
.typeof_builtin, .typeof_builtin,
.loop, .loop,
=> { => {
+6 -103
View File
@@ -172,7 +172,6 @@ verbose_intern_pool: bool,
verbose_generic_instances: bool, verbose_generic_instances: bool,
verbose_llvm_ir: ?[]const u8, verbose_llvm_ir: ?[]const u8,
verbose_llvm_bc: ?[]const u8, verbose_llvm_bc: ?[]const u8,
verbose_cimport: bool,
verbose_llvm_cpu_features: bool, verbose_llvm_cpu_features: bool,
verbose_link: bool, verbose_link: bool,
link_depfile: ?[]const u8, link_depfile: ?[]const u8,
@@ -1681,7 +1680,6 @@ pub const CreateOptions = struct {
verbose_llvm_ir: ?[]const u8 = null, verbose_llvm_ir: ?[]const u8 = null,
verbose_llvm_bc: ?[]const u8 = null, verbose_llvm_bc: ?[]const u8 = null,
link_depfile: ?[]const u8 = null, link_depfile: ?[]const u8 = null,
verbose_cimport: bool = false,
verbose_llvm_cpu_features: bool = false, verbose_llvm_cpu_features: bool = false,
debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null, debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
debug_compile_errors: bool = false, debug_compile_errors: bool = false,
@@ -2254,7 +2252,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
.verbose_llvm_ir = options.verbose_llvm_ir, .verbose_llvm_ir = options.verbose_llvm_ir,
.verbose_llvm_bc = options.verbose_llvm_bc, .verbose_llvm_bc = options.verbose_llvm_bc,
.link_depfile = options.link_depfile, .link_depfile = options.link_depfile,
.verbose_cimport = options.verbose_cimport,
.verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
.verbose_link = options.verbose_link, .verbose_link = options.verbose_link,
.disable_c_depfile = options.disable_c_depfile, .disable_c_depfile = options.disable_c_depfile,
@@ -4095,27 +4092,6 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error); try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error);
added_any_analysis_error = true; added_any_analysis_error = true;
if (zcu.cimport_errors.get(anal_unit)) |errors| {
for (errors.getMessages()) |err_msg_index| {
const err_msg = errors.getErrorMessage(err_msg_index);
try bundle.addRootErrorMessage(.{
.msg = try bundle.addString(errors.nullTerminatedString(err_msg.msg)),
.src_loc = if (err_msg.src_loc != .none) blk: {
const src_loc = errors.getSourceLocation(err_msg.src_loc);
break :blk try bundle.addSourceLocation(.{
.src_path = try bundle.addString(errors.nullTerminatedString(src_loc.src_path)),
.span_start = src_loc.span_start,
.span_main = src_loc.span_main,
.span_end = src_loc.span_end,
.line = src_loc.line,
.column = src_loc.column,
.source_line = if (src_loc.source_line != 0) try bundle.addString(errors.nullTerminatedString(src_loc.source_line)) else 0,
});
} else .none,
});
}
}
} }
try zcu.addDependencyLoopErrors(&bundle); try zcu.addDependencyLoopErrors(&bundle);
for (zcu.failed_codegen.values()) |error_msg| { for (zcu.failed_codegen.values()) |error_msg| {
@@ -5048,7 +5024,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
.verbose_generic_instances = comp.verbose_intern_pool, .verbose_generic_instances = comp.verbose_intern_pool,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.environ_map = comp.environ_map, .environ_map = comp.environ_map,
}) catch |err| switch (err) { }) catch |err| switch (err) {
@@ -5100,8 +5075,8 @@ pub fn obtainCObjectCacheManifest(
) Cache.Manifest { ) Cache.Manifest {
var man = comp.cache_parent.obtain(); var man = comp.cache_parent.obtain();
// Only things that need to be added on top of the base hash, and only things // Only things that need to be added on top of the base hash, and only
// that apply both to @cImport and compiling C objects. No linking stuff here! // things that apply to compiling C objects. No linking stuff here!
// Also nothing that applies only to compiling .zig code. // Also nothing that applies only to compiling .zig code.
cache_helpers.addModule(&man.hash, owner_mod); cache_helpers.addModule(&man.hash, owner_mod);
man.hash.addListOfBytes(comp.global_cc_argv); man.hash.addListOfBytes(comp.global_cc_argv);
@@ -5126,13 +5101,13 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest
return man; return man;
} }
pub const CImportResult = struct { pub const TranslateCResult = struct {
// Only valid if `errors` is not empty // Only valid if `errors` is not empty
digest: [Cache.bin_digest_len]u8, digest: [Cache.bin_digest_len]u8,
cache_hit: bool, cache_hit: bool,
errors: std.zig.ErrorBundle, errors: std.zig.ErrorBundle,
pub fn deinit(result: *CImportResult, gpa: mem.Allocator) void { pub fn deinit(result: *TranslateCResult, gpa: mem.Allocator) void {
result.errors.deinit(gpa); result.errors.deinit(gpa);
} }
}; };
@@ -5142,15 +5117,12 @@ pub fn translateC(
arena: Allocator, arena: Allocator,
man: *Cache.Manifest, man: *Cache.Manifest,
ext: FileExt, ext: FileExt,
source: union(enum) { source_path: []const u8,
path: []const u8,
c_src: []const u8,
},
translated_basename: []const u8, translated_basename: []const u8,
owner_mod: *Package.Module, owner_mod: *Package.Module,
prog_node: std.Progress.Node, prog_node: std.Progress.Node,
environ_map: *const std.process.Environ.Map, environ_map: *const std.process.Environ.Map,
) !CImportResult { ) !TranslateCResult {
dev.check(.translate_c_command); dev.check(.translate_c_command);
const gpa = comp.gpa; const gpa = comp.gpa;
@@ -5166,17 +5138,6 @@ pub fn translateC(
defer cache_tmp_dir.close(io); defer cache_tmp_dir.close(io);
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename });
const source_path = switch (source) {
.c_src => |c_src| path: {
const cimport_basename = "cimport.h";
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path});
if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path});
try cache_dir.writeFile(io, .{ .sub_path = out_h_sub_path, .data = c_src });
break :path out_h_path;
},
.path => |p| p,
};
const out_dep_path: ?[]const u8 = blk: { const out_dep_path: ?[]const u8 = blk: {
if (comp.disable_c_depfile) break :blk null; if (comp.disable_c_depfile) break :blk null;
@@ -5219,15 +5180,12 @@ pub fn translateC(
try argv.appendSlice(comp.global_cc_argv); try argv.appendSlice(comp.global_cc_argv);
try argv.appendSlice(owner_mod.cc_argv); try argv.appendSlice(owner_mod.cc_argv);
try argv.appendSlice(&.{ source_path, "-o", translated_path }); try argv.appendSlice(&.{ source_path, "-o", translated_path });
if (comp.verbose_cimport) try dumpArgv(io, argv.items);
} }
var stdout: []u8 = undefined; var stdout: []u8 = undefined;
try @import("main.zig").translateC(gpa, arena, io, argv.items, environ_map, prog_node, comp.thread_limit, &stdout); try @import("main.zig").translateC(gpa, arena, io, argv.items, environ_map, prog_node, comp.thread_limit, &stdout);
if (out_dep_path) |dep_file_path| add_deps: { if (out_dep_path) |dep_file_path| add_deps: {
if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_file_path});
const dep_basename = fs.path.basename(dep_file_path); const dep_basename = fs.path.basename(dep_file_path);
// Add the files depended on to the cache system, if a dep file was emitted // Add the files depended on to the cache system, if a dep file was emitted
man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) { man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) {
@@ -5274,7 +5232,6 @@ pub fn translateC(
const hex_digest = Cache.binToHex(bin_digest); const hex_digest = Cache.binToHex(bin_digest);
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path });
try renameTmpIntoCache(io, comp.dirs.local_cache, tmp_sub_path, o_sub_path); try renameTmpIntoCache(io, comp.dirs.local_cache, tmp_sub_path, o_sub_path);
return .{ return .{
@@ -5284,58 +5241,6 @@ pub fn translateC(
}; };
} }
/// Caller owns returned memory.
pub fn cImport(
comp: *Compilation,
c_src: []const u8,
owner_mod: *Package.Module,
prog_node: std.Progress.Node,
) !CImportResult {
dev.check(.translate_c_command);
const translated_basename = "cimport.zig";
var man = comp.obtainCObjectCacheManifest(owner_mod);
defer man.deinit();
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish c-import from compiling C objects
man.hash.addBytes(c_src);
const result: CImportResult = if (try man.hit()) .{
.digest = man.finalBin(),
.cache_hit = true,
.errors = ErrorBundle.empty,
} else result: {
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();
break :result try translateC(
comp,
arena,
&man,
.c,
.{ .c_src = c_src },
translated_basename,
owner_mod,
prog_node,
comp.environ_map,
);
};
if (result.errors.errorMessageCount() == 0 and man.have_exclusive_lock) {
// Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is
// possible we had a hit and the manifest is dirty, for example if the file mtime changed but
// the contents were the same, we hit the cache but the manifest is dirty and we need to update
// it to prevent doing a full file content comparison the next time around.
man.writeManifest() catch |err| {
log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)});
};
}
return result;
}
fn workerUpdateCObject( fn workerUpdateCObject(
comp: *Compilation, comp: *Compilation,
c_object: *CObject, c_object: *CObject,
@@ -7492,7 +7397,6 @@ fn buildOutputFromZig(
.verbose_generic_instances = comp.verbose_intern_pool, .verbose_generic_instances = comp.verbose_intern_pool,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = true, .skip_linker_dependencies = true,
@@ -7630,7 +7534,6 @@ pub fn build_crt_file(
.verbose_generic_instances = comp.verbose_generic_instances, .verbose_generic_instances = comp.verbose_generic_instances,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = true, .skip_linker_dependencies = true,
-186
View File
@@ -385,8 +385,6 @@ pub const Block = struct {
/// What mode to generate float operations in, set by @setFloatMode /// What mode to generate float operations in, set by @setFloatMode
float_mode: std.builtin.FloatMode = .strict, float_mode: std.builtin.FloatMode = .strict,
c_import_buf: ?*std.array_list.Managed(u8) = null,
/// If not `null`, this boolean is set when a `dbg_var_ptr`, `dbg_var_val`, or `dbg_arg_inline`. /// If not `null`, this boolean is set when a `dbg_var_ptr`, `dbg_var_val`, or `dbg_arg_inline`.
/// instruction is emitted. It signals that the innermost lexically /// instruction is emitted. It signals that the innermost lexically
/// enclosing `block`/`block_inline` should be translated into a real AIR /// enclosing `block`/`block_inline` should be translated into a real AIR
@@ -526,7 +524,6 @@ pub const Block = struct {
.runtime_index = parent.runtime_index, .runtime_index = parent.runtime_index,
.want_safety = parent.want_safety, .want_safety = parent.want_safety,
.float_mode = parent.float_mode, .float_mode = parent.float_mode,
.c_import_buf = parent.c_import_buf,
.error_return_trace_index = parent.error_return_trace_index, .error_return_trace_index = parent.error_return_trace_index,
.need_debug_scope = parent.need_debug_scope, .need_debug_scope = parent.need_debug_scope,
.src_base_inst = parent.src_base_inst, .src_base_inst = parent.src_base_inst,
@@ -1189,7 +1186,6 @@ fn analyzeBodyInner(
.bool_not => try sema.zirBoolNot(block, inst), .bool_not => try sema.zirBoolNot(block, inst),
.bool_br_and => try sema.zirBoolBr(block, inst, false), .bool_br_and => try sema.zirBoolBr(block, inst, false),
.bool_br_or => try sema.zirBoolBr(block, inst, true), .bool_br_or => try sema.zirBoolBr(block, inst, true),
.c_import => try sema.zirCImport(block, inst),
.call => try sema.zirCall(block, inst, .direct), .call => try sema.zirCall(block, inst, .direct),
.field_call => try sema.zirCall(block, inst, .field), .field_call => try sema.zirCall(block, inst, .field),
.cmp_lt => try sema.zirCmp(block, inst, .lt), .cmp_lt => try sema.zirCmp(block, inst, .lt),
@@ -1414,9 +1410,6 @@ fn analyzeBodyInner(
.sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), .sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
.mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), .mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
.shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), .shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
.c_undef => try sema.zirCUndef( block, extended),
.c_include => try sema.zirCInclude( block, extended),
.c_define => try sema.zirCDefine( block, extended),
.wasm_memory_size => try sema.zirWasmMemorySize( block, extended), .wasm_memory_size => try sema.zirWasmMemorySize( block, extended),
.wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
.prefetch => try sema.zirPrefetch( block, extended), .prefetch => try sema.zirPrefetch( block, extended),
@@ -5212,136 +5205,6 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
return sema.resolveAnalyzedBlock(parent_block, src, &child_block, merges, false); return sema.resolveAnalyzedBlock(parent_block, src, &child_block, merges, false);
} }
fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
const pt = sema.pt;
const zcu = pt.zcu;
const comp = zcu.comp;
const gpa = comp.gpa;
const io = comp.io;
const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const src = parent_block.nodeOffset(pl_node.src_node);
const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
const body = sema.code.bodySlice(extra.end, extra.data.body_len);
var c_import_buf = std.array_list.Managed(u8).init(gpa);
defer c_import_buf.deinit();
var child_block: Block = .{
.parent = parent_block,
.sema = sema,
.namespace = parent_block.namespace,
.instructions = .empty,
.inlining = parent_block.inlining,
.comptime_reason = .{ .reason = .{
.src = src,
.r = .{ .simple = .operand_cImport },
} },
.c_import_buf = &c_import_buf,
.runtime_cond = parent_block.runtime_cond,
.runtime_loop = parent_block.runtime_loop,
.runtime_index = parent_block.runtime_index,
.src_base_inst = parent_block.src_base_inst,
.type_name_ctx = parent_block.type_name_ctx,
};
defer child_block.instructions.deinit(gpa);
_ = try sema.analyzeInlineBody(&child_block, body, inst);
const prog_node = zcu.cur_sema_prog_node.start("@cImport", 0);
defer prog_node.end();
var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule(), prog_node) catch |err|
return sema.fail(&child_block, src, "C import failed: {t}", .{err});
defer c_import_res.deinit(gpa);
if (c_import_res.errors.errorMessageCount() != 0) {
const msg = msg: {
const msg = try sema.errMsg(src, "C import failed", .{});
errdefer msg.destroy(gpa);
if (!comp.config.link_libc)
try sema.errNote(src, msg, "libc headers not available; compilation does not link against libc", .{});
const gop = try zcu.cimport_errors.getOrPut(gpa, sema.owner);
if (!gop.found_existing) {
gop.value_ptr.* = c_import_res.errors;
c_import_res.errors = std.zig.ErrorBundle.empty;
}
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&child_block, msg);
}
const parent_mod = parent_block.ownerModule();
const digest = Cache.binToHex(c_import_res.digest);
const new_file_index = file: {
const c_import_zig_path = try comp.arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ digest);
const c_import_mod = Package.Module.create(comp.arena, .{
.paths = .{
.root = try .fromRoot(comp.arena, comp.dirs, .local_cache, c_import_zig_path),
.root_src_path = "cimport.zig",
},
.fully_qualified_name = c_import_zig_path,
.cc_argv = parent_mod.cc_argv,
.inherited = .{},
.global = comp.config,
.parent = parent_mod,
}) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
// None of these are possible because we are creating a package with
// the exact same configuration as the parent package, which already
// passed these checks.
error.ValgrindUnsupportedOnTarget => unreachable,
error.TargetRequiresSingleThreaded => unreachable,
error.BackendRequiresSingleThreaded => unreachable,
error.TargetRequiresPic => unreachable,
error.PieRequiresPic => unreachable,
error.DynamicLinkingRequiresPic => unreachable,
error.TargetHasNoRedZone => unreachable,
error.StackCheckUnsupportedByTarget => unreachable,
error.StackProtectorUnsupportedByTarget => unreachable,
error.StackProtectorUnavailableWithoutLibC => unreachable,
};
const c_import_file_path: Compilation.Path = try c_import_mod.root.join(gpa, comp.dirs, "cimport.zig");
errdefer c_import_file_path.deinit(gpa);
const c_import_file = try gpa.create(Zcu.File);
errdefer gpa.destroy(c_import_file);
const c_import_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{
.bin_digest = c_import_file_path.digest(),
.file = c_import_file,
.root_type = .none,
});
c_import_file.* = .{
.status = .never_loaded,
.stat = undefined,
.is_builtin = false,
.path = c_import_file_path,
.source = null,
.tree = null,
.zir = null,
.zoir = null,
.mod = c_import_mod,
.sub_file_path = "cimport.zig",
.module_changed = false,
.prev_zir = null,
.zoir_invalidated = false,
};
try zcu.alive_files.putNoClobber(zcu.gpa, c_import_file_index, undefined);
break :file c_import_file_index;
};
pt.updateFile(new_file_index, zcu.fileByIndex(new_file_index)) catch |err|
return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
try pt.ensureFilePopulated(new_file_index);
const ty: Type = .fromInterned(zcu.fileRootType(new_file_index));
try sema.addTypeReferenceEntry(src, ty);
return .fromType(ty);
}
fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const src = parent_block.nodeOffset(inst_data.src_node); const src = parent_block.nodeOffset(inst_data.src_node);
@@ -5388,7 +5251,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
.is_typeof = parent_block.is_typeof, .is_typeof = parent_block.is_typeof,
.want_safety = parent_block.want_safety, .want_safety = parent_block.want_safety,
.float_mode = parent_block.float_mode, .float_mode = parent_block.float_mode,
.c_import_buf = parent_block.c_import_buf,
.runtime_cond = parent_block.runtime_cond, .runtime_cond = parent_block.runtime_cond,
.runtime_loop = parent_block.runtime_loop, .runtime_loop = parent_block.runtime_loop,
.runtime_index = parent_block.runtime_index, .runtime_index = parent_block.runtime_index,
@@ -24690,54 +24552,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
); );
} }
fn zirCUndef(
sema: *Sema,
block: *Block,
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src = block.builtinCallArgSrc(extra.node, 0);
const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });
try block.c_import_buf.?.print("#undef {s}\n", .{name});
return .void_value;
}
fn zirCInclude(
sema: *Sema,
block: *Block,
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src = block.builtinCallArgSrc(extra.node, 0);
const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });
try block.c_import_buf.?.print("#include <{s}>\n", .{name});
return .void_value;
}
fn zirCDefine(
sema: *Sema,
block: *Block,
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const name_src = block.builtinCallArgSrc(extra.node, 0);
const val_src = block.builtinCallArgSrc(extra.node, 1);
const name = try sema.resolveConstString(block, name_src, extra.lhs, .{ .simple = .operand_cDefine_macro_name });
const rhs = sema.resolveInst(extra.rhs);
if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {
const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });
try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value });
} else {
try block.c_import_buf.?.print("#define {s}\n", .{name});
}
return .void_value;
}
fn zirWasmMemorySize( fn zirWasmMemorySize(
sema: *Sema, sema: *Sema,
block: *Block, block: *Block,
-3
View File
@@ -1,6 +1,3 @@
//! We do this instead of @cImport because the self-hosted compiler is easier
//! to bootstrap if it does not depend on translate-c.
/// Do not compare directly to .True, use toBool() instead. /// Do not compare directly to .True, use toBool() instead.
pub const Bool = enum(c_int) { pub const Bool = enum(c_int) {
False, False,
-1
View File
@@ -1112,7 +1112,6 @@ fn buildSharedLib(
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.version = version, .version = version,
-1
View File
@@ -1257,7 +1257,6 @@ fn buildSharedLib(
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.version = version, .version = version,
-2
View File
@@ -271,7 +271,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = true, .skip_linker_dependencies = true,
@@ -465,7 +464,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = true, .skip_linker_dependencies = true,
-1
View File
@@ -296,7 +296,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = skip_linker_dependencies, .skip_linker_dependencies = skip_linker_dependencies,
-1
View File
@@ -157,7 +157,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.skip_linker_dependencies = true, .skip_linker_dependencies = true,
-1
View File
@@ -253,7 +253,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
.verbose_link = comp.verbose_link, .verbose_link = comp.verbose_link,
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.c_source_files = &.{ .c_source_files = &.{
-1
View File
@@ -755,7 +755,6 @@ fn buildSharedLib(
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.version = version, .version = version,
-1
View File
@@ -683,7 +683,6 @@ fn buildSharedLib(
.verbose_air = comp.verbose_air, .verbose_air = comp.verbose_air,
.verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_ir = comp.verbose_llvm_ir,
.verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_llvm_bc = comp.verbose_llvm_bc,
.verbose_cimport = comp.verbose_cimport,
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
.clang_passthrough_mode = comp.clang_passthrough_mode, .clang_passthrough_mode = comp.clang_passthrough_mode,
.soname = soname, .soname = soname,
+5 -13
View File
@@ -860,7 +860,6 @@ fn buildOutputType(
var verbose_llvm_ir: ?[]const u8 = null; var verbose_llvm_ir: ?[]const u8 = null;
var verbose_llvm_bc: ?[]const u8 = null; var verbose_llvm_bc: ?[]const u8 = null;
var link_depfile: ?[]const u8 = null; var link_depfile: ?[]const u8 = null;
var verbose_cimport = false;
var verbose_llvm_cpu_features = false; var verbose_llvm_cpu_features = false;
var time_report = false; var time_report = false;
var stack_report = false; var stack_report = false;
@@ -1742,8 +1741,6 @@ fn buildOutputType(
verbose_llvm_ir = rest; verbose_llvm_ir = rest;
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| { } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| {
verbose_llvm_bc = rest; verbose_llvm_bc = rest;
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
verbose_llvm_cpu_features = true; verbose_llvm_cpu_features = true;
} else if (mem.cutPrefix(u8, arg, "-T")) |rest| { } else if (mem.cutPrefix(u8, arg, "-T")) |rest| {
@@ -3650,7 +3647,6 @@ fn buildOutputType(
.verbose_llvm_ir = verbose_llvm_ir, .verbose_llvm_ir = verbose_llvm_ir,
.verbose_llvm_bc = verbose_llvm_bc, .verbose_llvm_bc = verbose_llvm_bc,
.link_depfile = link_depfile, .link_depfile = link_depfile,
.verbose_cimport = verbose_cimport,
.verbose_llvm_cpu_features = verbose_llvm_cpu_features, .verbose_llvm_cpu_features = verbose_llvm_cpu_features,
.time_report = time_report, .time_report = time_report,
.stack_report = stack_report, .stack_report = stack_report,
@@ -4289,7 +4285,7 @@ fn serve(
var arena_instance = std.heap.ArenaAllocator.init(gpa); var arena_instance = std.heap.ArenaAllocator.init(gpa);
defer arena_instance.deinit(); defer arena_instance.deinit();
const arena = arena_instance.allocator(); const arena = arena_instance.allocator();
var output: Compilation.CImportResult = undefined; var output: Compilation.TranslateCResult = undefined;
try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node, environ_map); try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node, environ_map);
defer output.deinit(gpa); defer output.deinit(gpa);
@@ -4713,7 +4709,7 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)
fn cmdTranslateC( fn cmdTranslateC(
comp: *Compilation, comp: *Compilation,
arena: Allocator, arena: Allocator,
fancy_output: ?*Compilation.CImportResult, fancy_output: ?*Compilation.TranslateCResult,
file_system_inputs: ?*std.ArrayList(u8), file_system_inputs: ?*std.ArrayList(u8),
prog_node: std.Progress.Node, prog_node: std.Progress.Node,
environ_map: *process.Environ.Map, environ_map: *process.Environ.Map,
@@ -4735,7 +4731,7 @@ fn cmdTranslateC(
Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err|
fatal("unable to process '{s}': {t}", .{ c_source_file.src_path, err }); fatal("unable to process '{s}': {t}", .{ c_source_file.src_path, err });
const result: Compilation.CImportResult = if (try man.hit()) .{ const result: Compilation.TranslateCResult = if (try man.hit()) .{
.digest = man.finalBin(), .digest = man.finalBin(),
.cache_hit = true, .cache_hit = true,
.errors = std.zig.ErrorBundle.empty, .errors = std.zig.ErrorBundle.empty,
@@ -4744,7 +4740,7 @@ fn cmdTranslateC(
arena, arena,
&man, &man,
Compilation.classifyFileExt(c_source_file.src_path), Compilation.classifyFileExt(c_source_file.src_path),
.{ .path = c_source_file.src_path }, c_source_file.src_path,
translated_basename, translated_basename,
comp.root_mod, comp.root_mod,
prog_node, prog_node,
@@ -4976,7 +4972,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
var verbose_generic_instances = false; var verbose_generic_instances = false;
var verbose_llvm_ir: ?[]const u8 = null; var verbose_llvm_ir: ?[]const u8 = null;
var verbose_llvm_bc: ?[]const u8 = null; var verbose_llvm_bc: ?[]const u8 = null;
var verbose_cimport = false;
var verbose_llvm_cpu_features = false; var verbose_llvm_cpu_features = false;
var fetch_only = false; var fetch_only = false;
var fetch_mode: Package.Fetch.JobQueue.Mode = .needed; var fetch_mode: Package.Fetch.JobQueue.Mode = .needed;
@@ -5141,8 +5136,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
verbose_llvm_ir = rest; verbose_llvm_ir = rest;
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| { } else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| {
verbose_llvm_bc = rest; verbose_llvm_bc = rest;
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
verbose_llvm_cpu_features = true; verbose_llvm_cpu_features = true;
} else if (mem.eql(u8, arg, "--color")) { } else if (mem.eql(u8, arg, "--color")) {
@@ -5542,7 +5535,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
.verbose_generic_instances = verbose_generic_instances, .verbose_generic_instances = verbose_generic_instances,
.verbose_llvm_ir = verbose_llvm_ir, .verbose_llvm_ir = verbose_llvm_ir,
.verbose_llvm_bc = verbose_llvm_bc, .verbose_llvm_bc = verbose_llvm_bc,
.verbose_cimport = verbose_cimport,
.verbose_llvm_cpu_features = verbose_llvm_cpu_features, .verbose_llvm_cpu_features = verbose_llvm_cpu_features,
.cache_mode = .whole, .cache_mode = .whole,
.reference_trace = reference_trace, .reference_trace = reference_trace,
@@ -5550,7 +5542,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
.environ_map = environ_map, .environ_map = environ_map,
}) catch |err| switch (err) { }) catch |err| switch (err) {
error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}), error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),
else => fatal("failed to create compilation: {s}", .{@errorName(err)}), else => fatal("failed to create compilation: {t}", .{err}),
}; };
defer comp.destroy(); defer comp.destroy();
-4
View File
@@ -429,7 +429,6 @@ const Writer = struct {
.block_inline, .block_inline,
.suspend_block, .suspend_block,
.loop, .loop,
.c_import,
.typeof_builtin, .typeof_builtin,
=> try self.writeBlock(stream, inst), => try self.writeBlock(stream, inst),
@@ -555,8 +554,6 @@ const Writer = struct {
.tuple_decl => try self.writeTupleDecl(stream, extended), .tuple_decl => try self.writeTupleDecl(stream, extended),
.c_undef,
.c_include,
.set_float_mode, .set_float_mode,
.wasm_memory_size, .wasm_memory_size,
.int_from_error, .int_from_error,
@@ -579,7 +576,6 @@ const Writer = struct {
}, },
.builtin_extern, .builtin_extern,
.c_define,
.error_cast, .error_cast,
.wasm_memory_grow, .wasm_memory_grow,
.prefetch, .prefetch,
-13
View File
@@ -1,13 +0,0 @@
const b = @cDefine("foo", "1");
const c = @cImport({
_ = @TypeOf(@cDefine("foo", "1"));
});
const d = @cImport({
_ = @cImport(@cDefine("foo", "1"));
});
// error
//
// :1:11: error: C define valid only inside C import block
// :3:17: error: C define valid only inside C import block
// :6:9: error: cannot nest @cImport
@@ -1,13 +0,0 @@
const c = @cImport({
if (foo == 0) {}
});
extern var foo: i32;
export fn entry() void {
_ = c;
}
// error
//
// :2:13: error: unable to evaluate comptime expression
// :2:9: note: operation is runtime due to this operand
// :1:11: note: operand to '@cImport' is evaluated at comptime
-6
View File
@@ -36,9 +36,6 @@
.compile_asm = .{ .compile_asm = .{
.path = "compile_asm", .path = "compile_asm",
}, },
.issue_794 = .{
.path = "issue_794",
},
.issue_5825 = .{ .issue_5825 = .{
.path = "issue_5825", .path = "issue_5825",
}, },
@@ -84,9 +81,6 @@
.dep_shared_builtin = .{ .dep_shared_builtin = .{
.path = "dep_shared_builtin", .path = "dep_shared_builtin",
}, },
.dep_lazypath = .{
.path = "dep_lazypath",
},
.dirname = .{ .dirname = .{
.path = "dirname", .path = "dirname",
}, },
-42
View File
@@ -1,42 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;
const optimize: std.builtin.OptimizeMode = .Debug;
{
const write_files = b.addWriteFiles();
const generated_main_c = write_files.add("main.c", "");
const exe = b.addExecutable(.{
.name = "test",
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.root_module.addCSourceFiles(.{
.root = generated_main_c.dirname(),
.files = &.{"main.c"},
});
b.step("csourcefiles", "").dependOn(&exe.step);
test_step.dependOn(&exe.step);
}
{
const write_files = b.addWriteFiles();
const dir = write_files.addCopyDirectory(b.path("inc"), "", .{});
const exe = b.addExecutable(.{
.name = "test",
.root_module = b.createModule(.{
.root_source_file = b.path("inctest.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.root_module.addIncludePath(dir);
b.step("copydir", "").dependOn(&exe.step);
test_step.dependOn(&exe.step);
}
}
-1
View File
@@ -1 +0,0 @@
#define foo_value 42
-8
View File
@@ -1,8 +0,0 @@
const std = @import("std");
const c = @cImport({
@cInclude("foo.h");
});
comptime {
std.debug.assert(c.foo_value == 42);
}
pub fn main() void {}
+32
View File
@@ -180,12 +180,44 @@ pub fn build(b: *std.Build) void {
} }
} }
const malloc_translation = b.addTranslateC(.{
.root_source_file = b.path("include_malloc.h"),
.target = target,
.optimize = .Debug,
.link_libc = true,
});
const stdlib_translation = b.addTranslateC(.{
.root_source_file = b.path("include_stdlib.h"),
.target = target,
.optimize = .Debug,
.link_libc = true,
});
const string_translation = b.addTranslateC(.{
.root_source_file = b.path("include_string.h"),
.target = target,
.optimize = .Debug,
.link_libc = true,
});
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = t, .name = t,
.root_module = b.createModule(.{ .root_module = b.createModule(.{
.root_source_file = b.path("glibc_runtime_check.zig"), .root_source_file = b.path("glibc_runtime_check.zig"),
.target = target, .target = target,
.link_libc = true, .link_libc = true,
.imports = &.{
.{
.name = "malloc.h",
.module = malloc_translation.createModule(),
},
.{
.name = "stdlib.h",
.module = stdlib_translation.createModule(),
},
.{
.name = "string.h",
.module = string_translation.createModule(),
},
},
}), }),
}); });
// We disable UBSAN for these tests as the libc being tested here is // We disable UBSAN for these tests as the libc being tested here is
@@ -8,17 +8,9 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const c_malloc = @cImport( const c_malloc = @import("malloc.h"); // for reallocarray
@cInclude("malloc.h"), // for reallocarray const c_stdlib = @import("stdlib.h"); // for atexit
); const c_string = @import("string.h"); // for strlcpy
const c_stdlib = @cImport(
@cInclude("stdlib.h"), // for atexit
);
const c_string = @cImport(
@cInclude("string.h"), // for strlcpy
);
// Version of glibc this test is being built to run against // Version of glibc this test is being built to run against
const glibc_ver = builtin.os.versionRange().gnuLibCVersion().?; const glibc_ver = builtin.os.versionRange().gnuLibCVersion().?;
@@ -0,0 +1 @@
#include <malloc.h>
@@ -0,0 +1 @@
#include <stdlib.h>
@@ -0,0 +1 @@
#include <string.h>
@@ -1 +0,0 @@
#define NUMBER 1234
-17
View File
@@ -1,17 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;
const test_artifact = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
}) });
test_artifact.root_module.addIncludePath(b.path("a_directory"));
// TODO: actually check the output
_ = test_artifact.getEmittedBin();
test_step.dependOn(&test_artifact.step);
}
-7
View File
@@ -1,7 +0,0 @@
const c = @cImport(@cInclude("foo.h"));
const std = @import("std");
const testing = std.testing;
test "c import" {
try comptime testing.expect(c.NUMBER == 1234);
}
-1
View File
@@ -108,7 +108,6 @@ const cases = [_]Case{
.os_tag = .freestanding, .os_tag = .freestanding,
}, },
}, },
.{ .src_path = "issue_12471/main.zig" },
.{ .src_path = "guess_number/main.zig" }, .{ .src_path = "guess_number/main.zig" },
.{ .src_path = "main_return_error/error_u8.zig" }, .{ .src_path = "main_return_error/error_u8.zig" },
.{ .src_path = "main_return_error/error_u8_non_zero.zig" }, .{ .src_path = "main_return_error/error_u8_non_zero.zig" },
@@ -1,12 +0,0 @@
const c = @cImport({
@cDefine("FOO", "FOO");
@cDefine("BAR", "FOO");
@cDefine("BAZ", "QUX");
@cDefine("QUX", "QUX");
});
pub fn main() u8 {
_ = c;
return 0;
}
+1 -14
View File
@@ -185,10 +185,6 @@ fn printOutput(
try shell_out.print("-fno-llvm", .{}); try shell_out.print("-fno-llvm", .{});
} }
} }
if (code.verbose_cimport) {
try build_args.append("--verbose-cimport");
try shell_out.print("--verbose-cimport ", .{});
}
for (code.additional_options) |option| { for (code.additional_options) |option| {
try build_args.append(option); try build_args.append(option);
try shell_out.print("{s} ", .{option}); try shell_out.print("{s} ", .{option});
@@ -223,11 +219,7 @@ fn printOutput(
} }
const exec_result = run(arena, io, environ_map, tmp_dir_path, build_args.items) catch const exec_result = run(arena, io, environ_map, tmp_dir_path, build_args.items) catch
fatal("example failed to compile", .{}); fatal("example failed to compile", .{});
_ = exec_result;
if (code.verbose_cimport) {
const escaped_build_stderr = try escapeHtml(arena, exec_result.stderr);
try shell_out.writeAll(escaped_build_stderr);
}
if (code.target_str) |triple| { if (code.target_str) |triple| {
if (mem.startsWith(u8, triple, "wasm32") or if (mem.startsWith(u8, triple, "wasm32") or
@@ -853,7 +845,6 @@ const Code = struct {
link_libc: bool, link_libc: bool,
link_mode: ?std.builtin.LinkMode, link_mode: ?std.builtin.LinkMode,
disable_cache: bool, disable_cache: bool,
verbose_cimport: bool,
just_check_syntax: bool, just_check_syntax: bool,
additional_options: []const []const u8, additional_options: []const []const u8,
use_llvm: ?bool, use_llvm: ?bool,
@@ -915,7 +906,6 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
var target_str: ?[]const u8 = null; var target_str: ?[]const u8 = null;
var link_libc = false; var link_libc = false;
var disable_cache = false; var disable_cache = false;
var verbose_cimport = false;
var use_llvm: ?bool = null; var use_llvm: ?bool = null;
while (it.next()) |prefixed_line| { while (it.next()) |prefixed_line| {
@@ -940,8 +930,6 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
link_libc = true; link_libc = true;
} else if (mem.eql(u8, line, "disable_cache")) { } else if (mem.eql(u8, line, "disable_cache")) {
disable_cache = true; disable_cache = true;
} else if (mem.eql(u8, line, "verbose_cimport")) {
verbose_cimport = true;
} else { } else {
fatal("unrecognized manifest line: {s}", .{line}); fatal("unrecognized manifest line: {s}", .{line});
} }
@@ -956,7 +944,6 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code {
.link_libc = link_libc, .link_libc = link_libc,
.link_mode = link_mode, .link_mode = link_mode,
.disable_cache = disable_cache, .disable_cache = disable_cache,
.verbose_cimport = verbose_cimport,
.just_check_syntax = just_check_syntax, .just_check_syntax = just_check_syntax,
.use_llvm = use_llvm, .use_llvm = use_llvm,
}; };
-5
View File
@@ -249,7 +249,6 @@ const Code = struct {
link_libc: bool, link_libc: bool,
link_mode: ?std.builtin.LinkMode, link_mode: ?std.builtin.LinkMode,
disable_cache: bool, disable_cache: bool,
verbose_cimport: bool,
additional_options: []const []const u8, additional_options: []const []const u8,
const Id = union(enum) { const Id = union(enum) {
@@ -326,7 +325,6 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
var link_libc = false; var link_libc = false;
var link_mode: ?std.builtin.LinkMode = null; var link_mode: ?std.builtin.LinkMode = null;
var disable_cache = false; var disable_cache = false;
var verbose_cimport = false;
var additional_options = std.array_list.Managed([]const u8).init(arena); var additional_options = std.array_list.Managed([]const u8).init(arena);
const source_token = while (true) { const source_token = while (true) {
@@ -340,8 +338,6 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
mode = .ReleaseSafe; mode = .ReleaseSafe;
} else if (mem.eql(u8, end_tag_name, "code_disable_cache")) { } else if (mem.eql(u8, end_tag_name, "code_disable_cache")) {
disable_cache = true; disable_cache = true;
} else if (mem.eql(u8, end_tag_name, "code_verbose_cimport")) {
verbose_cimport = true;
} else if (mem.eql(u8, end_tag_name, "code_link_object")) { } else if (mem.eql(u8, end_tag_name, "code_link_object")) {
_ = try eatToken(tokenizer, .separator); _ = try eatToken(tokenizer, .separator);
const obj_tok = try eatToken(tokenizer, .tag_content); const obj_tok = try eatToken(tokenizer, .tag_content);
@@ -419,7 +415,6 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp
if (link_libc) try code.print("// link_libc\n", .{}); if (link_libc) try code.print("// link_libc\n", .{});
if (disable_cache) try code.print("// disable_cache\n", .{}); if (disable_cache) try code.print("// disable_cache\n", .{});
if (verbose_cimport) try code.print("// verbose_cimport\n", .{});
if (link_mode) |m| if (link_mode) |m|
try code.print("// link_mode={s}\n", .{@tagName(m)}); try code.print("// link_mode={s}\n", .{@tagName(m)});