authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-03 21:12:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-03 21:12:52-07:00
logc41b989ab8c553bdba8e1aab606edbe27d730a3a
tree574a7ced579139e4f9613f420224be18ead52370
parenta41f812bdba09fbe6962ba0cf33c0d14ca7f839f

C backend: improved Decl name lowering

Decl names are now rendered fully qualified, so that e.g. "main" in two different files does not conflict with each other. Additionally, they are now mangled so as to not generate invalid C identifier names.

1 files changed, 53 insertions(+), 34 deletions(-)

src/codegen/c.zig+53-34
......@@ -134,7 +134,7 @@ pub const Function = struct {
134134 const val = f.air.value(inst).?;
135135 return f.object.dg.renderValue(w, ty, val);
136136 },
137 else => return DeclGen.writeCValue(w, c_value),
137 else => return f.object.dg.writeCValue(w, c_value),
138138 }
139139 }
140140
......@@ -202,12 +202,13 @@ pub const DeclGen = struct {
202202 // Determine if we must pointer cast.
203203 assert(decl.has_tv);
204204 if (ty.eql(decl.ty)) {
205 try writer.print("&{s}", .{decl.name});
205 try writer.writeByte('&');
206206 } else {
207207 try writer.writeAll("(");
208208 try dg.renderType(writer, ty);
209 try writer.print(")&{s}", .{decl.name});
209 try writer.writeAll(")&");
210210 }
211 try dg.renderDeclName(decl, writer);
211212 }
212213
213214 fn renderValue(
......@@ -260,11 +261,11 @@ pub const DeclGen = struct {
260261 },
261262 .function => {
262263 const func = val.castTag(.function).?.data;
263 try writer.print("{s}", .{func.owner_decl.name});
264 try dg.renderDeclName(func.owner_decl, writer);
264265 },
265266 .extern_fn => {
266267 const decl = val.castTag(.extern_fn).?.data;
267 try writer.print("{s}", .{decl.name});
268 try dg.renderDeclName(decl, writer);
268269 },
269270 else => unreachable,
270271 },
......@@ -386,27 +387,15 @@ pub const DeclGen = struct {
386387 .one => try writer.writeAll("1"),
387388 .decl_ref => {
388389 const decl = val.castTag(.decl_ref).?.data;
389 decl.alive = true;
390
391 // Determine if we must pointer cast.
392 assert(decl.has_tv);
393 if (ty.eql(decl.ty)) {
394 try writer.print("&{s}", .{decl.name});
395 } else {
396 try writer.writeAll("(");
397 try dg.renderType(writer, ty);
398 try writer.print(")&{s}", .{decl.name});
399 }
390 return dg.renderDeclValue(writer, ty, val, decl);
400391 },
401392 .function => {
402393 const decl = val.castTag(.function).?.data.owner_decl;
403 decl.alive = true;
404 try writer.print("{s}", .{decl.name});
394 return dg.renderDeclValue(writer, ty, val, decl);
405395 },
406396 .extern_fn => {
407397 const decl = val.castTag(.extern_fn).?.data;
408 decl.alive = true;
409 try writer.print("{s}", .{decl.name});
398 return dg.renderDeclValue(writer, ty, val, decl);
410399 },
411400 else => unreachable,
412401 },
......@@ -459,8 +448,9 @@ pub const DeclGen = struct {
459448 }
460449 }
461450 try dg.renderType(w, dg.decl.ty.fnReturnType());
462 const decl_name = mem.span(dg.decl.name);
463 try w.print(" {s}(", .{decl_name});
451 try w.writeAll(" ");
452 try dg.renderDeclName(dg.decl, w);
453 try w.writeAll("(");
464454 const param_len = dg.decl.ty.fnParamLen();
465455 const is_var_args = dg.decl.ty.fnIsVarArgs();
466456 if (param_len == 0 and !is_var_args)
......@@ -634,7 +624,9 @@ pub const DeclGen = struct {
634624 const name_index = buffer.items.len;
635625 if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| {
636626 const func = inf_err_set_payload.data.func;
637 try bw.print("zig_E_{s};\n", .{func.owner_decl.name});
627 try bw.writeAll("zig_E_");
628 try dg.renderDeclName(func.owner_decl, bw);
629 try bw.writeAll(";\n");
638630 } else {
639631 try bw.print("zig_E_{s}_{s};\n", .{
640632 typeToCIdentifier(err_set_type), typeToCIdentifier(child_type),
......@@ -768,7 +760,7 @@ pub const DeclGen = struct {
768760 .Const => try w.writeAll("const "),
769761 .Mut => {},
770762 }
771 try writeCValue(w, name);
763 try dg.writeCValue(w, name);
772764 try w.writeAll(")(");
773765 const param_len = render_ty.fnParamLen();
774766 const is_var_args = render_ty.fnIsVarArgs();
......@@ -796,7 +788,7 @@ pub const DeclGen = struct {
796788 .Mut => "",
797789 };
798790 try w.print(" {s}", .{const_prefix});
799 try writeCValue(w, name);
791 try dg.writeCValue(w, name);
800792 }
801793 try w.writeAll(suffix.items);
802794 }
......@@ -816,18 +808,34 @@ pub const DeclGen = struct {
816808 }
817809 }
818810
819 fn writeCValue(w: anytype, c_value: CValue) !void {
811 fn writeCValue(dg: DeclGen, w: anytype, c_value: CValue) !void {
820812 switch (c_value) {
821813 .none => unreachable,
822814 .local => |i| return w.print("t{d}", .{i}),
823815 .local_ref => |i| return w.print("&t{d}", .{i}),
824816 .constant => unreachable,
825817 .arg => |i| return w.print("a{d}", .{i}),
826 .decl => |decl| return w.writeAll(mem.span(decl.name)),
827 .decl_ref => |decl| return w.print("&{s}", .{decl.name}),
818 .decl => |decl| return dg.renderDeclName(decl, w),
819 .decl_ref => |decl| {
820 try w.writeByte('&');
821 return dg.renderDeclName(decl, w);
822 },
828823 .bytes => |bytes| return w.writeAll(bytes),
829824 }
830825 }
826
827 fn renderDeclName(dg: DeclGen, decl: *Decl, writer: anytype) !void {
828 if (dg.module.decl_exports.get(decl)) |exports| {
829 return writer.writeAll(exports[0].options.name);
830 } else if (decl.val.tag() == .extern_fn) {
831 return writer.writeAll(mem.spanZ(decl.name));
832 } else {
833 const gpa = dg.module.gpa;
834 const name = try decl.getFullyQualifiedName(gpa);
835 defer gpa.free(name);
836 return writer.print("{}", .{fmtIdent(name)});
837 }
838 }
831839};
832840
833841pub fn genFunc(f: *Function) !void {
......@@ -868,22 +876,33 @@ pub fn genDecl(o: *Object) !void {
868876 try writer.writeAll(";\n");
869877 } else if (tv.val.castTag(.variable)) |var_payload| {
870878 const variable: *Module.Var = var_payload.data;
871 const is_global = o.dg.declIsGlobal(tv);
879 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
872880 const fwd_decl_writer = o.dg.fwd_decl.writer();
873 if (is_global or variable.is_extern) {
881 if (is_global) {
874882 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
875883 }
876884 if (variable.is_threadlocal) {
877885 try fwd_decl_writer.writeAll("zig_threadlocal ");
878886 }
879887 try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty);
880 const decl_name = mem.span(o.dg.decl.name);
881 try fwd_decl_writer.print(" {s};\n", .{decl_name});
888 try fwd_decl_writer.writeAll(" ");
889 if (is_global) {
890 try fwd_decl_writer.writeAll(mem.span(o.dg.decl.name));
891 } else {
892 try o.dg.renderDeclName(o.dg.decl, fwd_decl_writer);
893 }
894 try fwd_decl_writer.writeAll(";\n");
882895
883896 try o.indent_writer.insertNewline();
884897 const w = o.writer();
885898 try o.dg.renderType(w, o.dg.decl.ty);
886 try w.print(" {s} = ", .{decl_name});
899 try w.writeAll(" ");
900 if (is_global) {
901 try w.writeAll(mem.span(o.dg.decl.name));
902 } else {
903 try o.dg.renderDeclName(o.dg.decl, w);
904 }
905 try w.writeAll(" = ");
887906 if (variable.init.tag() != .unreachable_value) {
888907 try o.dg.renderValue(w, tv.ty, variable.init);
889908 }
......@@ -1562,7 +1581,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
15621581 else
15631582 unreachable;
15641583
1565 try writer.writeAll(mem.spanZ(fn_decl.name));
1584 try f.object.dg.renderDeclName(fn_decl, writer);
15661585 } else {
15671586 const callee = try f.resolveInst(pl_op.operand);
15681587 try f.writeCValue(writer, callee);