authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-09-19 11:51:32+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 20:50:55-07:00
log9a54ff72df5cc8631c467f3478117eb85a952ced
treec303fa7cdde3c8165d034da1ed8357175c260e3d
parent1ad905c71e0896295d4781853cd577bbe1b4111a

stage2: implement cImport


4 files changed, 92 insertions(+), 7 deletions(-)

src/AstGen.zig+6
...@@ -7269,6 +7269,7 @@ fn builtinCall(...@@ -7269,6 +7269,7 @@ fn builtinCall(
7269 return rvalue(gz, rl, result, node);7269 return rvalue(gz, rl, result, node);
7270 },7270 },
7271 .c_define => {7271 .c_define => {
7272 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
7272 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]);7273 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]);
7273 const value = try comptimeExpr(gz, scope, .none, params[1]);7274 const value = try comptimeExpr(gz, scope, .none, params[1]);
7274 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{7275 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
...@@ -7641,6 +7642,8 @@ fn simpleCBuiltin(...@@ -7641,6 +7642,8 @@ fn simpleCBuiltin(
7641 operand_node: Ast.Node.Index,7642 operand_node: Ast.Node.Index,
7642 tag: Zir.Inst.Extended,7643 tag: Zir.Inst.Extended,
7643) InnerError!Zir.Inst.Ref {7644) InnerError!Zir.Inst.Ref {
7645 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
7646 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
7644 const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node);7647 const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node);
7645 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{7648 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
7646 .node = gz.nodeIndexToRelative(node),7649 .node = gz.nodeIndexToRelative(node),
...@@ -7698,6 +7701,7 @@ fn cImport(...@@ -7698,6 +7701,7 @@ fn cImport(
76987701
7699 var block_scope = gz.makeSubBlock(scope);7702 var block_scope = gz.makeSubBlock(scope);
7700 block_scope.force_comptime = true;7703 block_scope.force_comptime = true;
7704 block_scope.c_import = true;
7701 defer block_scope.instructions.deinit(gpa);7705 defer block_scope.instructions.deinit(gpa);
77027706
7703 const block_inst = try gz.addBlock(.c_import, node);7707 const block_inst = try gz.addBlock(.c_import, node);
...@@ -9025,6 +9029,7 @@ const GenZir = struct {...@@ -9025,6 +9029,7 @@ const GenZir = struct {
9025 base: Scope = Scope{ .tag = base_tag },9029 base: Scope = Scope{ .tag = base_tag },
9026 force_comptime: bool,9030 force_comptime: bool,
9027 in_defer: bool,9031 in_defer: bool,
9032 c_import: bool = false,
9028 /// How decls created in this scope should be named.9033 /// How decls created in this scope should be named.
9029 anon_name_strategy: Zir.Inst.NameStrategy = .anon,9034 anon_name_strategy: Zir.Inst.NameStrategy = .anon,
9030 /// The containing decl AST node.9035 /// The containing decl AST node.
...@@ -9070,6 +9075,7 @@ const GenZir = struct {...@@ -9070,6 +9075,7 @@ const GenZir = struct {
9070 return .{9075 return .{
9071 .force_comptime = gz.force_comptime,9076 .force_comptime = gz.force_comptime,
9072 .in_defer = gz.in_defer,9077 .in_defer = gz.in_defer,
9078 .c_import = gz.c_import,
9073 .decl_node_index = gz.decl_node_index,9079 .decl_node_index = gz.decl_node_index,
9074 .decl_line = gz.decl_line,9080 .decl_line = gz.decl_line,
9075 .parent = scope,9081 .parent = scope,
src/Compilation.zig+1-1
...@@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
26442644
2645 const dep_basename = std.fs.path.basename(out_dep_path);2645 const dep_basename = std.fs.path.basename(out_dep_path);
2646 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);2646 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
2647 try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);2647 if (build_options.is_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
26482648
2649 const digest = man.final();2649 const digest = man.final();
2650 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });2650 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
src/Module.zig+3
...@@ -1325,6 +1325,8 @@ pub const Scope = struct {...@@ -1325,6 +1325,8 @@ pub const Scope = struct {
1325 /// when null, it is determined by build mode, changed by @setRuntimeSafety1325 /// when null, it is determined by build mode, changed by @setRuntimeSafety
1326 want_safety: ?bool = null,1326 want_safety: ?bool = null,
13271327
1328 c_import_buf: ?*std.ArrayList(u8) = null,
1329
1328 const Param = struct {1330 const Param = struct {
1329 /// `noreturn` means `anytype`.1331 /// `noreturn` means `anytype`.
1330 ty: Type,1332 ty: Type,
...@@ -1377,6 +1379,7 @@ pub const Scope = struct {...@@ -1377,6 +1379,7 @@ pub const Scope = struct {
1377 .runtime_loop = parent.runtime_loop,1379 .runtime_loop = parent.runtime_loop,
1378 .runtime_index = parent.runtime_index,1380 .runtime_index = parent.runtime_index,
1379 .want_safety = parent.want_safety,1381 .want_safety = parent.want_safety,
1382 .c_import_buf = parent.c_import_buf,
1380 };1383 };
1381 }1384 }
13821385
src/Sema.zig+82-6
...@@ -2138,10 +2138,72 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com...@@ -2138,10 +2138,72 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com
2138 const tracy = trace(@src());2138 const tracy = trace(@src());
2139 defer tracy.end();2139 defer tracy.end();
21402140
2141 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2141 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
2142 const src = inst_data.src();2142 const src = pl_node.src();
2143 const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
2144 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
2145
2146 // we check this here to avoid undefined symbols
2147 if (!@import("build_options").have_llvm)
2148 return sema.mod.fail(&parent_block.base, src, "cannot do C import on Zig compiler not built with LLVM-extension", .{});
2149
2150 var c_import_buf = std.ArrayList(u8).init(sema.gpa);
2151 defer c_import_buf.deinit();
2152
2153 var child_block: Scope.Block = .{
2154 .parent = parent_block,
2155 .sema = sema,
2156 .src_decl = parent_block.src_decl,
2157 .instructions = .{},
2158 .inlining = parent_block.inlining,
2159 .is_comptime = parent_block.is_comptime,
2160 .c_import_buf = &c_import_buf,
2161 };
2162 defer child_block.instructions.deinit(sema.gpa);
2163
2164 _ = try sema.analyzeBody(&child_block, body);
2165
2166 const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err|
2167 return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
21432168
2144 return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirCImport", .{});2169 if (c_import_res.errors.len != 0) {
2170 const msg = try sema.mod.errMsg(&child_block.base, src, "C import failed", .{});
2171 errdefer msg.destroy(sema.gpa);
2172
2173 if (!sema.mod.comp.bin_file.options.link_libc)
2174 try sema.mod.errNote(&child_block.base, src, msg, "libc headers not available; compilation does not link against libc", .{});
2175
2176 for (c_import_res.errors) |_| {
2177 // TODO integrate with LazySrcLoc
2178 // try sema.mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]});
2179 // if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
2180 // clang_err.line + 1,
2181 // clang_err.column + 1,
2182 }
2183 @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
2184 return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg);
2185 }
2186 const c_import_pkg = @import("Package.zig").createWithDir(
2187 sema.gpa,
2188 sema.mod.comp.local_cache_directory,
2189 null,
2190 std.fs.path.basename(c_import_res.out_zig_path),
2191 ) catch |err| switch (err) {
2192 error.OutOfMemory => return error.OutOfMemory,
2193 else => unreachable, // we pass null for root_src_dir_path
2194 };
2195 const std_pkg = sema.mod.main_pkg.table.get("std").?;
2196 const builtin_pkg = sema.mod.main_pkg.table.get("builtin").?;
2197 try c_import_pkg.add(sema.gpa, "builtin", builtin_pkg);
2198 try c_import_pkg.add(sema.gpa, "std", std_pkg);
2199
2200 const result = sema.mod.importPkg(c_import_pkg) catch |err|
2201 return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)});
2202
2203 try sema.mod.semaFile(result.file);
2204 const file_root_decl = result.file.root_decl.?;
2205 try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl);
2206 return sema.addType(file_root_decl.ty);
2145}2207}
21462208
2147fn zirSuspendBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {2209fn zirSuspendBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -8226,7 +8288,10 @@ fn zirCUndef(...@@ -8226,7 +8288,10 @@ fn zirCUndef(
8226) CompileError!Air.Inst.Ref {8288) CompileError!Air.Inst.Ref {
8227 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8289 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8228 const src: LazySrcLoc = .{ .node_offset = extra.node };8290 const src: LazySrcLoc = .{ .node_offset = extra.node };
8229 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCUndef", .{});8291
8292 const name = try sema.resolveConstString(block, src, extra.operand);
8293 try block.c_import_buf.?.writer().print("#undefine {s}\n", .{name});
8294 return Air.Inst.Ref.void_value;
8230}8295}
82318296
8232fn zirCInclude(8297fn zirCInclude(
...@@ -8236,7 +8301,10 @@ fn zirCInclude(...@@ -8236,7 +8301,10 @@ fn zirCInclude(
8236) CompileError!Air.Inst.Ref {8301) CompileError!Air.Inst.Ref {
8237 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8302 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8238 const src: LazySrcLoc = .{ .node_offset = extra.node };8303 const src: LazySrcLoc = .{ .node_offset = extra.node };
8239 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCInclude", .{});8304
8305 const name = try sema.resolveConstString(block, src, extra.operand);
8306 try block.c_import_buf.?.writer().print("#include <{s}>\n", .{name});
8307 return Air.Inst.Ref.void_value;
8240}8308}
82418309
8242fn zirCDefine(8310fn zirCDefine(
...@@ -8246,7 +8314,15 @@ fn zirCDefine(...@@ -8246,7 +8314,15 @@ fn zirCDefine(
8246) CompileError!Air.Inst.Ref {8314) CompileError!Air.Inst.Ref {
8247 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;8315 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
8248 const src: LazySrcLoc = .{ .node_offset = extra.node };8316 const src: LazySrcLoc = .{ .node_offset = extra.node };
8249 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCDefine", .{});8317
8318 const name = try sema.resolveConstString(block, src, extra.lhs);
8319 if (sema.typeOf(extra.rhs).zigTypeTag() != .Void) {
8320 const value = try sema.resolveConstString(block, src, extra.rhs);
8321 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });
8322 } else {
8323 try block.c_import_buf.?.writer().print("#define {s}\n", .{name});
8324 }
8325 return Air.Inst.Ref.void_value;
8250}8326}
82518327
8252fn zirWasmMemorySize(8328fn zirWasmMemorySize(