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 {...@@ -134,7 +134,7 @@ pub const Function = struct {
134 const val = f.air.value(inst).?;134 const val = f.air.value(inst).?;
135 return f.object.dg.renderValue(w, ty, val);135 return f.object.dg.renderValue(w, ty, val);
136 },136 },
137 else => return DeclGen.writeCValue(w, c_value),137 else => return f.object.dg.writeCValue(w, c_value),
138 }138 }
139 }139 }
140140
...@@ -202,12 +202,13 @@ pub const DeclGen = struct {...@@ -202,12 +202,13 @@ pub const DeclGen = struct {
202 // Determine if we must pointer cast.202 // Determine if we must pointer cast.
203 assert(decl.has_tv);203 assert(decl.has_tv);
204 if (ty.eql(decl.ty)) {204 if (ty.eql(decl.ty)) {
205 try writer.print("&{s}", .{decl.name});205 try writer.writeByte('&');
206 } else {206 } else {
207 try writer.writeAll("(");207 try writer.writeAll("(");
208 try dg.renderType(writer, ty);208 try dg.renderType(writer, ty);
209 try writer.print(")&{s}", .{decl.name});209 try writer.writeAll(")&");
210 }210 }
211 try dg.renderDeclName(decl, writer);
211 }212 }
212213
213 fn renderValue(214 fn renderValue(
...@@ -260,11 +261,11 @@ pub const DeclGen = struct {...@@ -260,11 +261,11 @@ pub const DeclGen = struct {
260 },261 },
261 .function => {262 .function => {
262 const func = val.castTag(.function).?.data;263 const func = val.castTag(.function).?.data;
263 try writer.print("{s}", .{func.owner_decl.name});264 try dg.renderDeclName(func.owner_decl, writer);
264 },265 },
265 .extern_fn => {266 .extern_fn => {
266 const decl = val.castTag(.extern_fn).?.data;267 const decl = val.castTag(.extern_fn).?.data;
267 try writer.print("{s}", .{decl.name});268 try dg.renderDeclName(decl, writer);
268 },269 },
269 else => unreachable,270 else => unreachable,
270 },271 },
...@@ -386,27 +387,15 @@ pub const DeclGen = struct {...@@ -386,27 +387,15 @@ pub const DeclGen = struct {
386 .one => try writer.writeAll("1"),387 .one => try writer.writeAll("1"),
387 .decl_ref => {388 .decl_ref => {
388 const decl = val.castTag(.decl_ref).?.data;389 const decl = val.castTag(.decl_ref).?.data;
389 decl.alive = true;390 return dg.renderDeclValue(writer, ty, val, decl);
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 }
400 },391 },
401 .function => {392 .function => {
402 const decl = val.castTag(.function).?.data.owner_decl;393 const decl = val.castTag(.function).?.data.owner_decl;
403 decl.alive = true;394 return dg.renderDeclValue(writer, ty, val, decl);
404 try writer.print("{s}", .{decl.name});
405 },395 },
406 .extern_fn => {396 .extern_fn => {
407 const decl = val.castTag(.extern_fn).?.data;397 const decl = val.castTag(.extern_fn).?.data;
408 decl.alive = true;398 return dg.renderDeclValue(writer, ty, val, decl);
409 try writer.print("{s}", .{decl.name});
410 },399 },
411 else => unreachable,400 else => unreachable,
412 },401 },
...@@ -459,8 +448,9 @@ pub const DeclGen = struct {...@@ -459,8 +448,9 @@ pub const DeclGen = struct {
459 }448 }
460 }449 }
461 try dg.renderType(w, dg.decl.ty.fnReturnType());450 try dg.renderType(w, dg.decl.ty.fnReturnType());
462 const decl_name = mem.span(dg.decl.name);451 try w.writeAll(" ");
463 try w.print(" {s}(", .{decl_name});452 try dg.renderDeclName(dg.decl, w);
453 try w.writeAll("(");
464 const param_len = dg.decl.ty.fnParamLen();454 const param_len = dg.decl.ty.fnParamLen();
465 const is_var_args = dg.decl.ty.fnIsVarArgs();455 const is_var_args = dg.decl.ty.fnIsVarArgs();
466 if (param_len == 0 and !is_var_args)456 if (param_len == 0 and !is_var_args)
...@@ -634,7 +624,9 @@ pub const DeclGen = struct {...@@ -634,7 +624,9 @@ pub const DeclGen = struct {
634 const name_index = buffer.items.len;624 const name_index = buffer.items.len;
635 if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| {625 if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| {
636 const func = inf_err_set_payload.data.func;626 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");
638 } else {630 } else {
639 try bw.print("zig_E_{s}_{s};\n", .{631 try bw.print("zig_E_{s}_{s};\n", .{
640 typeToCIdentifier(err_set_type), typeToCIdentifier(child_type),632 typeToCIdentifier(err_set_type), typeToCIdentifier(child_type),
...@@ -768,7 +760,7 @@ pub const DeclGen = struct {...@@ -768,7 +760,7 @@ pub const DeclGen = struct {
768 .Const => try w.writeAll("const "),760 .Const => try w.writeAll("const "),
769 .Mut => {},761 .Mut => {},
770 }762 }
771 try writeCValue(w, name);763 try dg.writeCValue(w, name);
772 try w.writeAll(")(");764 try w.writeAll(")(");
773 const param_len = render_ty.fnParamLen();765 const param_len = render_ty.fnParamLen();
774 const is_var_args = render_ty.fnIsVarArgs();766 const is_var_args = render_ty.fnIsVarArgs();
...@@ -796,7 +788,7 @@ pub const DeclGen = struct {...@@ -796,7 +788,7 @@ pub const DeclGen = struct {
796 .Mut => "",788 .Mut => "",
797 };789 };
798 try w.print(" {s}", .{const_prefix});790 try w.print(" {s}", .{const_prefix});
799 try writeCValue(w, name);791 try dg.writeCValue(w, name);
800 }792 }
801 try w.writeAll(suffix.items);793 try w.writeAll(suffix.items);
802 }794 }
...@@ -816,18 +808,34 @@ pub const DeclGen = struct {...@@ -816,18 +808,34 @@ pub const DeclGen = struct {
816 }808 }
817 }809 }
818810
819 fn writeCValue(w: anytype, c_value: CValue) !void {811 fn writeCValue(dg: DeclGen, w: anytype, c_value: CValue) !void {
820 switch (c_value) {812 switch (c_value) {
821 .none => unreachable,813 .none => unreachable,
822 .local => |i| return w.print("t{d}", .{i}),814 .local => |i| return w.print("t{d}", .{i}),
823 .local_ref => |i| return w.print("&t{d}", .{i}),815 .local_ref => |i| return w.print("&t{d}", .{i}),
824 .constant => unreachable,816 .constant => unreachable,
825 .arg => |i| return w.print("a{d}", .{i}),817 .arg => |i| return w.print("a{d}", .{i}),
826 .decl => |decl| return w.writeAll(mem.span(decl.name)),818 .decl => |decl| return dg.renderDeclName(decl, w),
827 .decl_ref => |decl| return w.print("&{s}", .{decl.name}),819 .decl_ref => |decl| {
820 try w.writeByte('&');
821 return dg.renderDeclName(decl, w);
822 },
828 .bytes => |bytes| return w.writeAll(bytes),823 .bytes => |bytes| return w.writeAll(bytes),
829 }824 }
830 }825 }
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 }
831};839};
832840
833pub fn genFunc(f: *Function) !void {841pub fn genFunc(f: *Function) !void {
...@@ -868,22 +876,33 @@ pub fn genDecl(o: *Object) !void {...@@ -868,22 +876,33 @@ pub fn genDecl(o: *Object) !void {
868 try writer.writeAll(";\n");876 try writer.writeAll(";\n");
869 } else if (tv.val.castTag(.variable)) |var_payload| {877 } else if (tv.val.castTag(.variable)) |var_payload| {
870 const variable: *Module.Var = var_payload.data;878 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;
872 const fwd_decl_writer = o.dg.fwd_decl.writer();880 const fwd_decl_writer = o.dg.fwd_decl.writer();
873 if (is_global or variable.is_extern) {881 if (is_global) {
874 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");882 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
875 }883 }
876 if (variable.is_threadlocal) {884 if (variable.is_threadlocal) {
877 try fwd_decl_writer.writeAll("zig_threadlocal ");885 try fwd_decl_writer.writeAll("zig_threadlocal ");
878 }886 }
879 try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty);887 try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty);
880 const decl_name = mem.span(o.dg.decl.name);888 try fwd_decl_writer.writeAll(" ");
881 try fwd_decl_writer.print(" {s};\n", .{decl_name});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
883 try o.indent_writer.insertNewline();896 try o.indent_writer.insertNewline();
884 const w = o.writer();897 const w = o.writer();
885 try o.dg.renderType(w, o.dg.decl.ty);898 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(" = ");
887 if (variable.init.tag() != .unreachable_value) {906 if (variable.init.tag() != .unreachable_value) {
888 try o.dg.renderValue(w, tv.ty, variable.init);907 try o.dg.renderValue(w, tv.ty, variable.init);
889 }908 }
...@@ -1562,7 +1581,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -1562,7 +1581,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
1562 else1581 else
1563 unreachable;1582 unreachable;
15641583
1565 try writer.writeAll(mem.spanZ(fn_decl.name));1584 try f.object.dg.renderDeclName(fn_decl, writer);
1566 } else {1585 } else {
1567 const callee = try f.resolveInst(pl_op.operand);1586 const callee = try f.resolveInst(pl_op.operand);
1568 try f.writeCValue(writer, callee);1587 try f.writeCValue(writer, callee);