| ... | @@ -258,6 +258,20 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { | ... | @@ -258,6 +258,20 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { |
| 258 | return .{ .data = ident }; | 258 | return .{ .data = ident }; |
| 259 | } | 259 | } |
| 260 | | 260 | |
| | 261 | // Returns true if `formatIdent` would make any edits to ident. |
| | 262 | // This must be kept in sync with `formatIdent`. |
| | 263 | pub fn isMangledIdent(ident: []const u8, solo: bool) bool { |
| | 264 | if (solo and isReservedIdent(ident)) return true; |
| | 265 | for (ident, 0..) |c, i| { |
| | 266 | switch (c) { |
| | 267 | 'a'...'z', 'A'...'Z', '_' => {}, |
| | 268 | '0'...'9' => if (i == 0) return true, |
| | 269 | else => return true, |
| | 270 | } |
| | 271 | } |
| | 272 | return false; |
| | 273 | } |
| | 274 | |
| 261 | /// This data is available when outputting .c code for a `InternPool.Index` | 275 | /// This data is available when outputting .c code for a `InternPool.Index` |
| 262 | /// that corresponds to `func`. | 276 | /// that corresponds to `func`. |
| 263 | /// It is not available when generating .h file. | 277 | /// It is not available when generating .h file. |
| ... | @@ -526,6 +540,7 @@ pub const DeclGen = struct { | ... | @@ -526,6 +540,7 @@ pub const DeclGen = struct { |
| 526 | is_naked_fn: bool, | 540 | is_naked_fn: bool, |
| 527 | /// This is a borrowed reference from `link.C`. | 541 | /// This is a borrowed reference from `link.C`. |
| 528 | fwd_decl: std.ArrayList(u8), | 542 | fwd_decl: std.ArrayList(u8), |
| | 543 | |
| 529 | error_msg: ?*Module.ErrorMsg, | 544 | error_msg: ?*Module.ErrorMsg, |
| 530 | ctypes: CType.Store, | 545 | ctypes: CType.Store, |
| 531 | /// Keeps track of anonymous decls that need to be rendered before this | 546 | /// Keeps track of anonymous decls that need to be rendered before this |
| ... | @@ -1598,7 +1613,7 @@ pub const DeclGen = struct { | ... | @@ -1598,7 +1613,7 @@ pub const DeclGen = struct { |
| 1598 | | 1613 | |
| 1599 | switch (name) { | 1614 | switch (name) { |
| 1600 | .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index), | 1615 | .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index), |
| 1601 | .string => |string| try w.writeAll(string), | 1616 | .string => |string| try w.print("{ }", .{fmtIdent(string)}), |
| 1602 | } | 1617 | } |
| 1603 | | 1618 | |
| 1604 | try renderTypeSuffix( | 1619 | try renderTypeSuffix( |
| ... | @@ -1813,9 +1828,17 @@ pub const DeclGen = struct { | ... | @@ -1813,9 +1828,17 @@ pub const DeclGen = struct { |
| 1813 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { | 1828 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { |
| 1814 | const mod = dg.module; | 1829 | const mod = dg.module; |
| 1815 | return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { | 1830 | return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { |
| 1816 | .variable => |variable| mod.decl_exports.contains(variable.decl), | 1831 | .variable => |variable| { |
| | 1832 | if (mod.decl_exports.get(variable.decl)) |exports| { |
| | 1833 | return !isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true); |
| | 1834 | } else return false; |
| | 1835 | }, |
| 1817 | .extern_func => true, | 1836 | .extern_func => true, |
| 1818 | .func => |func| mod.decl_exports.contains(func.owner_decl), | 1837 | .func => |func| { |
| | 1838 | if (mod.decl_exports.get(func.owner_decl)) |exports| { |
| | 1839 | return !isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true); |
| | 1840 | } else return false; |
| | 1841 | }, |
| 1819 | else => unreachable, | 1842 | else => unreachable, |
| 1820 | }; | 1843 | }; |
| 1821 | } | 1844 | } |
| ... | @@ -1925,9 +1948,9 @@ pub const DeclGen = struct { | ... | @@ -1925,9 +1948,9 @@ pub const DeclGen = struct { |
| 1925 | try mod.markDeclAlive(decl); | 1948 | try mod.markDeclAlive(decl); |
| 1926 | | 1949 | |
| 1927 | if (mod.decl_exports.get(decl_index)) |exports| { | 1950 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 1928 | try writer.print("{}", .{exports.items[export_index].opts.name.fmt(&mod.intern_pool)}); | 1951 | try writer.print("{ }", .{fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name))}); |
| 1929 | } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| { | 1952 | } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| { |
| 1930 | try writer.print("{}", .{mod.declPtr(extern_decl_index).name.fmt(&mod.intern_pool)}); | 1953 | try writer.print("{ }", .{fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name))}); |
| 1931 | } else { | 1954 | } else { |
| 1932 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | 1955 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), |
| 1933 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | 1956 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| ... | @@ -2564,16 +2587,19 @@ fn genExports(o: *Object) !void { | ... | @@ -2564,16 +2587,19 @@ fn genExports(o: *Object) !void { |
| 2564 | const fwd = o.dg.fwd_decl.writer(); | 2587 | const fwd = o.dg.fwd_decl.writer(); |
| 2565 | | 2588 | |
| 2566 | const exports = mod.decl_exports.get(decl_index) orelse return; | 2589 | const exports = mod.decl_exports.get(decl_index) orelse return; |
| 2567 | if (exports.items.len < 2) return; | 2590 | |
| | 2591 | const is_mangled = isMangledIdent(ip.stringToSlice(exports.items[0].opts.name), true); |
| | 2592 | if (exports.items.len < 2 and !is_mangled) return; |
| 2568 | | 2593 | |
| 2569 | switch (ip.indexToKey(tv.val.toIntern())) { | 2594 | switch (ip.indexToKey(tv.val.toIntern())) { |
| 2570 | .func => { | 2595 | .func => { |
| 2571 | for (exports.items[1..], 1..) |@"export", i| { | 2596 | const start_i = 1 - @intFromBool(is_mangled); |
| | 2597 | for (exports.items[start_i..], start_i..) |@"export", i| { |
| 2572 | try fwd.writeAll("zig_export("); | 2598 | try fwd.writeAll("zig_export("); |
| 2573 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn "); | 2599 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn "); |
| 2574 | try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) }); | 2600 | try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) }); |
| 2575 | try fwd.print(", {s}, {s});\n", .{ | 2601 | try fwd.print(", { }, {s});\n", .{ |
| 2576 | fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), | 2602 | fmtIdent(ip.stringToSlice(exports.items[0].opts.name)), |
| 2577 | fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null), | 2603 | fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null), |
| 2578 | }); | 2604 | }); |
| 2579 | } | 2605 | } |
| ... | @@ -2583,7 +2609,8 @@ fn genExports(o: *Object) !void { | ... | @@ -2583,7 +2609,8 @@ fn genExports(o: *Object) !void { |
| 2583 | unreachable; | 2609 | unreachable; |
| 2584 | }, | 2610 | }, |
| 2585 | .variable => |variable| { | 2611 | .variable => |variable| { |
| 2586 | for (exports.items[1..], 1..) |@"export", i| { | 2612 | const start_i = 1 - @intFromBool(is_mangled); |
| | 2613 | for (exports.items[start_i..], start_i..) |@"export", i| { |
| 2587 | try fwd.writeAll("zig_export("); | 2614 | try fwd.writeAll("zig_export("); |
| 2588 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage "); | 2615 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage "); |
| 2589 | const alias = ip.stringToSlice(@"export".opts.name); | 2616 | const alias = ip.stringToSlice(@"export".opts.name); |
| ... | @@ -2595,8 +2622,8 @@ fn genExports(o: *Object) !void { | ... | @@ -2595,8 +2622,8 @@ fn genExports(o: *Object) !void { |
| 2595 | decl.alignment, | 2622 | decl.alignment, |
| 2596 | .complete, | 2623 | .complete, |
| 2597 | ); | 2624 | ); |
| 2598 | try fwd.print(", {s}, {s});\n", .{ | 2625 | try fwd.print(", { }, {s});\n", .{ |
| 2599 | fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), | 2626 | fmtIdent(ip.stringToSlice(exports.items[0].opts.name)), |
| 2600 | fmtStringLiteral(alias, null), | 2627 | fmtStringLiteral(alias, null), |
| 2601 | }); | 2628 | }); |
| 2602 | } | 2629 | } |
| ... | @@ -6861,9 +6888,9 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6861,9 +6888,9 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6861 | try f.writeCValue(writer, accum, .Other); | 6888 | try f.writeCValue(writer, accum, .Other); |
| 6862 | switch (op) { | 6889 | switch (op) { |
| 6863 | .float_op => |func| { | 6890 | .float_op => |func| { |
| 6864 | try writer.writeAll(" = zig_libc_name_"); | 6891 | try writer.writeAll(" = zig_float_fn_"); |
| 6865 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 6892 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 6866 | try writer.print("({s})(", .{func.operation}); | 6893 | try writer.print("_{s}(", .{func.operation}); |
| 6867 | try f.writeCValue(writer, accum, .FunctionArgument); | 6894 | try f.writeCValue(writer, accum, .FunctionArgument); |
| 6868 | try writer.writeAll(", "); | 6895 | try writer.writeAll(", "); |
| 6869 | try f.writeCValue(writer, operand, .Other); | 6896 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -7195,11 +7222,9 @@ fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, oper | ... | @@ -7195,11 +7222,9 @@ fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, oper |
| 7195 | const v = try Vectorize.start(f, inst, writer, ty); | 7222 | const v = try Vectorize.start(f, inst, writer, ty); |
| 7196 | try f.writeCValue(writer, local, .Other); | 7223 | try f.writeCValue(writer, local, .Other); |
| 7197 | try v.elem(f, writer); | 7224 | try v.elem(f, writer); |
| 7198 | try writer.writeAll(" = zig_libc_name_"); | 7225 | try writer.writeAll(" = zig_float_fn_"); |
| 7199 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 7226 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 7200 | try writer.writeByte('('); | 7227 | try writer.print("_{s}(", .{operation}); |
| 7201 | try writer.writeAll(operation); | | |
| 7202 | try writer.writeAll(")("); | | |
| 7203 | try f.writeCValue(writer, operand, .FunctionArgument); | 7228 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 7204 | try v.elem(f, writer); | 7229 | try v.elem(f, writer); |
| 7205 | try writer.writeAll(");\n"); | 7230 | try writer.writeAll(");\n"); |
| ... | @@ -7234,11 +7259,9 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7234,11 +7259,9 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7234 | const v = try Vectorize.start(f, inst, writer, inst_ty); | 7259 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| 7235 | try f.writeCValue(writer, local, .Other); | 7260 | try f.writeCValue(writer, local, .Other); |
| 7236 | try v.elem(f, writer); | 7261 | try v.elem(f, writer); |
| 7237 | try writer.writeAll(" = zig_libc_name_"); | 7262 | try writer.writeAll(" = zig_float_fn_"); |
| 7238 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | 7263 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); |
| 7239 | try writer.writeByte('('); | 7264 | try writer.print("_{s}(", .{operation}); |
| 7240 | try writer.writeAll(operation); | | |
| 7241 | try writer.writeAll(")("); | | |
| 7242 | try f.writeCValue(writer, lhs, .FunctionArgument); | 7265 | try f.writeCValue(writer, lhs, .FunctionArgument); |
| 7243 | try v.elem(f, writer); | 7266 | try v.elem(f, writer); |
| 7244 | try writer.writeAll(", "); | 7267 | try writer.writeAll(", "); |
| ... | @@ -7268,9 +7291,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7268,9 +7291,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7268 | const v = try Vectorize.start(f, inst, writer, inst_ty); | 7291 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| 7269 | try f.writeCValue(writer, local, .Other); | 7292 | try f.writeCValue(writer, local, .Other); |
| 7270 | try v.elem(f, writer); | 7293 | try v.elem(f, writer); |
| 7271 | try writer.writeAll(" = zig_libc_name_"); | 7294 | try writer.writeAll(" = zig_float_fn_"); |
| 7272 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | 7295 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); |
| 7273 | try writer.writeAll("(fma)("); | 7296 | try writer.writeAll("_fma("); |
| 7274 | try f.writeCValue(writer, mulend1, .FunctionArgument); | 7297 | try f.writeCValue(writer, mulend1, .FunctionArgument); |
| 7275 | try v.elem(f, writer); | 7298 | try v.elem(f, writer); |
| 7276 | try writer.writeAll(", "); | 7299 | try writer.writeAll(", "); |