| ... | ... | @@ -23,7 +23,6 @@ const libcFloatSuffix = target_util.libcFloatSuffix; |
| 23 | 23 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; |
| 24 | 24 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 25 | 25 | |
| 26 | | const Mutability = enum { @"const", mut }; |
| 27 | 26 | const BigIntLimb = std.math.big.Limb; |
| 28 | 27 | const BigInt = std.math.big.int; |
| 29 | 28 | |
| ... | ... | @@ -55,6 +54,8 @@ pub const CValue = union(enum) { |
| 55 | 54 | /// Render these bytes literally. |
| 56 | 55 | /// TODO make this a [*:0]const u8 to save memory |
| 57 | 56 | bytes: []const u8, |
| 57 | /// A deferred call_always_tail |
| 58 | call_always_tail: void, |
| 58 | 59 | }; |
| 59 | 60 | |
| 60 | 61 | const BlockData = struct { |
| ... | ... | @@ -62,21 +63,22 @@ const BlockData = struct { |
| 62 | 63 | result: CValue, |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | | const TypedefKind = enum { |
| 66 | | Forward, |
| 67 | | Complete, |
| 68 | | }; |
| 69 | | |
| 70 | 66 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); |
| 71 | 67 | |
| 72 | 68 | pub const LazyFnKey = union(enum) { |
| 73 | 69 | tag_name: Decl.Index, |
| 70 | never_tail: Decl.Index, |
| 71 | never_inline: Decl.Index, |
| 74 | 72 | }; |
| 75 | 73 | pub const LazyFnValue = struct { |
| 76 | 74 | fn_name: []const u8, |
| 77 | | data: union { |
| 75 | data: Data, |
| 76 | |
| 77 | pub const Data = union { |
| 78 | 78 | tag_name: Type, |
| 79 | | }, |
| 79 | never_tail: void, |
| 80 | never_inline: void, |
| 81 | }; |
| 80 | 82 | }; |
| 81 | 83 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); |
| 82 | 84 | |
| ... | ... | @@ -314,7 +316,7 @@ pub const Function = struct { |
| 314 | 316 | const gpa = f.object.dg.gpa; |
| 315 | 317 | try f.allocs.put(gpa, decl_c_value.new_local, true); |
| 316 | 318 | try writer.writeAll("static "); |
| 317 | | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .@"const", alignment, .Complete); |
| 319 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); |
| 318 | 320 | try writer.writeAll(" = "); |
| 319 | 321 | try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); |
| 320 | 322 | try writer.writeAll(";\n "); |
| ... | ... | @@ -348,15 +350,13 @@ pub const Function = struct { |
| 348 | 350 | } |
| 349 | 351 | |
| 350 | 352 | fn allocLocal(f: *Function, inst: Air.Inst.Index, ty: Type) !CValue { |
| 351 | | const result = try f.allocAlignedLocal(ty, .mut, 0); |
| 353 | const result = try f.allocAlignedLocal(ty, .{}, 0); |
| 352 | 354 | log.debug("%{d}: allocating t{d}", .{ inst, result.new_local }); |
| 353 | 355 | return result; |
| 354 | 356 | } |
| 355 | 357 | |
| 356 | 358 | /// Only allocates the local; does not print anything. |
| 357 | | fn allocAlignedLocal(f: *Function, ty: Type, mutability: Mutability, alignment: u32) !CValue { |
| 358 | | _ = mutability; |
| 359 | | |
| 359 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { |
| 360 | 360 | if (f.getFreeLocals().getPtrContext(ty, f.tyHashCtx())) |locals_list| { |
| 361 | 361 | for (locals_list.items, 0..) |local_index, i| { |
| 362 | 362 | const local = &f.locals.items[local_index]; |
| ... | ... | @@ -451,11 +451,9 @@ pub const Function = struct { |
| 451 | 451 | return f.object.dg.fmtIntLiteral(ty, val); |
| 452 | 452 | } |
| 453 | 453 | |
| 454 | | fn getTagNameFn(f: *Function, enum_ty: Type) ![]const u8 { |
| 454 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| 455 | 455 | const gpa = f.object.dg.gpa; |
| 456 | | const owner_decl = enum_ty.getOwnerDecl(); |
| 457 | | |
| 458 | | const gop = try f.lazy_fns.getOrPut(gpa, .{ .tag_name = owner_decl }); |
| 456 | const gop = try f.lazy_fns.getOrPut(gpa, key); |
| 459 | 457 | if (!gop.found_existing) { |
| 460 | 458 | errdefer _ = f.lazy_fns.pop(); |
| 461 | 459 | |
| ... | ... | @@ -464,11 +462,21 @@ pub const Function = struct { |
| 464 | 462 | const arena = promoted.arena.allocator(); |
| 465 | 463 | |
| 466 | 464 | gop.value_ptr.* = .{ |
| 467 | | .fn_name = try std.fmt.allocPrint(arena, "zig_tagName_{}__{d}", .{ |
| 468 | | fmtIdent(mem.span(f.object.dg.module.declPtr(owner_decl).name)), |
| 469 | | @enumToInt(owner_decl), |
| 470 | | }), |
| 471 | | .data = .{ .tag_name = try enum_ty.copy(arena) }, |
| 465 | .fn_name = switch (key) { |
| 466 | .tag_name, |
| 467 | .never_tail, |
| 468 | .never_inline, |
| 469 | => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{ |
| 470 | @tagName(key), |
| 471 | fmtIdent(mem.span(f.object.dg.module.declPtr(owner_decl).name)), |
| 472 | @enumToInt(owner_decl), |
| 473 | }), |
| 474 | }, |
| 475 | .data = switch (key) { |
| 476 | .tag_name => .{ .tag_name = try data.tag_name.copy(arena) }, |
| 477 | .never_tail => .{ .never_tail = data.never_tail }, |
| 478 | .never_inline => .{ .never_inline = data.never_inline }, |
| 479 | }, |
| 472 | 480 | }; |
| 473 | 481 | } |
| 474 | 482 | return gop.value_ptr.fn_name; |
| ... | ... | @@ -1457,24 +1465,31 @@ pub const DeclGen = struct { |
| 1457 | 1465 | } |
| 1458 | 1466 | } |
| 1459 | 1467 | |
| 1460 | | fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void { |
| 1468 | fn renderFunctionSignature( |
| 1469 | dg: *DeclGen, |
| 1470 | w: anytype, |
| 1471 | fn_decl_index: Decl.Index, |
| 1472 | kind: CType.Kind, |
| 1473 | name: union(enum) { |
| 1474 | export_index: u32, |
| 1475 | string: []const u8, |
| 1476 | }, |
| 1477 | ) !void { |
| 1461 | 1478 | const store = &dg.ctypes.set; |
| 1462 | 1479 | const module = dg.module; |
| 1463 | 1480 | |
| 1464 | | const fn_ty = dg.decl.?.ty; |
| 1465 | | const fn_cty_idx = try dg.typeToIndex(fn_ty, switch (kind) { |
| 1466 | | .Forward => .forward, |
| 1467 | | .Complete => .complete, |
| 1468 | | }); |
| 1481 | const fn_decl = module.declPtr(fn_decl_index); |
| 1482 | const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind); |
| 1469 | 1483 | |
| 1470 | | const fn_info = fn_ty.fnInfo(); |
| 1484 | const fn_info = fn_decl.ty.fnInfo(); |
| 1471 | 1485 | if (fn_info.cc == .Naked) { |
| 1472 | 1486 | switch (kind) { |
| 1473 | | .Forward => try w.writeAll("zig_naked_decl "), |
| 1474 | | .Complete => try w.writeAll("zig_naked "), |
| 1487 | .forward => try w.writeAll("zig_naked_decl "), |
| 1488 | .complete => try w.writeAll("zig_naked "), |
| 1489 | else => unreachable, |
| 1475 | 1490 | } |
| 1476 | 1491 | } |
| 1477 | | if (dg.decl.?.val.castTag(.function)) |func_payload| |
| 1492 | if (fn_decl.val.castTag(.function)) |func_payload| |
| 1478 | 1493 | if (func_payload.data.is_cold) try w.writeAll("zig_cold "); |
| 1479 | 1494 | if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn "); |
| 1480 | 1495 | |
| ... | ... | @@ -1485,7 +1500,7 @@ pub const DeclGen = struct { |
| 1485 | 1500 | w, |
| 1486 | 1501 | fn_cty_idx, |
| 1487 | 1502 | .suffix, |
| 1488 | | CQualifiers.init(.{}), |
| 1503 | .{}, |
| 1489 | 1504 | ); |
| 1490 | 1505 | try w.print("{}", .{trailing}); |
| 1491 | 1506 | |
| ... | ... | @@ -1493,16 +1508,37 @@ pub const DeclGen = struct { |
| 1493 | 1508 | try w.print("zig_callconv({s}) ", .{call_conv}); |
| 1494 | 1509 | } |
| 1495 | 1510 | |
| 1496 | | if (fn_info.alignment > 0 and kind == .Complete) { |
| 1497 | | try w.print(" zig_align_fn({})", .{fn_info.alignment}); |
| 1511 | switch (kind) { |
| 1512 | .forward => {}, |
| 1513 | .complete => if (fn_info.alignment > 0) |
| 1514 | try w.print(" zig_align_fn({})", .{fn_info.alignment}), |
| 1515 | else => unreachable, |
| 1498 | 1516 | } |
| 1499 | 1517 | |
| 1500 | | try dg.renderDeclName(w, dg.decl_index.unwrap().?, export_index); |
| 1518 | switch (name) { |
| 1519 | .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index), |
| 1520 | .string => |string| try w.writeAll(string), |
| 1521 | } |
| 1501 | 1522 | |
| 1502 | | try renderTypeSuffix(dg.decl_index, store.*, module, w, fn_cty_idx, .suffix); |
| 1523 | try renderTypeSuffix( |
| 1524 | dg.decl_index, |
| 1525 | store.*, |
| 1526 | module, |
| 1527 | w, |
| 1528 | fn_cty_idx, |
| 1529 | .suffix, |
| 1530 | CQualifiers.init(.{ .@"const" = switch (kind) { |
| 1531 | .forward => false, |
| 1532 | .complete => true, |
| 1533 | else => unreachable, |
| 1534 | } }), |
| 1535 | ); |
| 1503 | 1536 | |
| 1504 | | if (fn_info.alignment > 0 and kind == .Forward) { |
| 1505 | | try w.print(" zig_align_fn({})", .{fn_info.alignment}); |
| 1537 | switch (kind) { |
| 1538 | .forward => if (fn_info.alignment > 0) |
| 1539 | try w.print(" zig_align_fn({})", .{fn_info.alignment}), |
| 1540 | .complete => {}, |
| 1541 | else => unreachable, |
| 1506 | 1542 | } |
| 1507 | 1543 | } |
| 1508 | 1544 | |
| ... | ... | @@ -1533,16 +1569,8 @@ pub const DeclGen = struct { |
| 1533 | 1569 | const store = &dg.ctypes.set; |
| 1534 | 1570 | const module = dg.module; |
| 1535 | 1571 | const idx = try dg.typeToIndex(t, .complete); |
| 1536 | | _ = try renderTypePrefix( |
| 1537 | | dg.decl_index, |
| 1538 | | store.*, |
| 1539 | | module, |
| 1540 | | w, |
| 1541 | | idx, |
| 1542 | | .suffix, |
| 1543 | | CQualifiers.init(.{}), |
| 1544 | | ); |
| 1545 | | try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix); |
| 1572 | _ = try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, .{}); |
| 1573 | try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{}); |
| 1546 | 1574 | } |
| 1547 | 1575 | |
| 1548 | 1576 | const IntCastContext = union(enum) { |
| ... | ... | @@ -1655,9 +1683,9 @@ pub const DeclGen = struct { |
| 1655 | 1683 | w: anytype, |
| 1656 | 1684 | ty: Type, |
| 1657 | 1685 | name: CValue, |
| 1658 | | mutability: Mutability, |
| 1686 | qualifiers: CQualifiers, |
| 1659 | 1687 | alignment: u32, |
| 1660 | | _: TypedefKind, |
| 1688 | kind: CType.Kind, |
| 1661 | 1689 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1662 | 1690 | const store = &dg.ctypes.set; |
| 1663 | 1691 | const module = dg.module; |
| ... | ... | @@ -1668,71 +1696,12 @@ pub const DeclGen = struct { |
| 1668 | 1696 | .gt => try w.print("zig_align({}) ", .{alignment}), |
| 1669 | 1697 | }; |
| 1670 | 1698 | |
| 1671 | | const idx = try dg.typeToIndex(ty, .complete); |
| 1672 | | const trailing = try renderTypePrefix( |
| 1673 | | dg.decl_index, |
| 1674 | | store.*, |
| 1675 | | module, |
| 1676 | | w, |
| 1677 | | idx, |
| 1678 | | .suffix, |
| 1679 | | CQualifiers.init(.{ .@"const" = mutability == .@"const" }), |
| 1680 | | ); |
| 1699 | const idx = try dg.typeToIndex(ty, kind); |
| 1700 | const trailing = |
| 1701 | try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, qualifiers); |
| 1681 | 1702 | try w.print("{}", .{trailing}); |
| 1682 | 1703 | try dg.writeCValue(w, name); |
| 1683 | | try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix); |
| 1684 | | } |
| 1685 | | |
| 1686 | | fn renderTagNameFn(dg: *DeclGen, w: anytype, fn_name: []const u8, enum_ty: Type) !void { |
| 1687 | | const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 1688 | | |
| 1689 | | try w.writeAll("static "); |
| 1690 | | try dg.renderType(w, name_slice_ty); |
| 1691 | | try w.writeByte(' '); |
| 1692 | | try w.writeAll(fn_name); |
| 1693 | | try w.writeByte('('); |
| 1694 | | try dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, .@"const", 0, .Complete); |
| 1695 | | try w.writeAll(") {\n switch (tag) {\n"); |
| 1696 | | for (enum_ty.enumFields().keys(), 0..) |name, index| { |
| 1697 | | const name_z = try dg.gpa.dupeZ(u8, name); |
| 1698 | | defer dg.gpa.free(name_z); |
| 1699 | | const name_bytes = name_z[0 .. name_z.len + 1]; |
| 1700 | | |
| 1701 | | var tag_pl: Value.Payload.U32 = .{ |
| 1702 | | .base = .{ .tag = .enum_field_index }, |
| 1703 | | .data = @intCast(u32, index), |
| 1704 | | }; |
| 1705 | | const tag_val = Value.initPayload(&tag_pl.base); |
| 1706 | | |
| 1707 | | var int_pl: Value.Payload.U64 = undefined; |
| 1708 | | const int_val = tag_val.enumToInt(enum_ty, &int_pl); |
| 1709 | | |
| 1710 | | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; |
| 1711 | | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 1712 | | |
| 1713 | | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes }; |
| 1714 | | const name_val = Value.initPayload(&name_pl.base); |
| 1715 | | |
| 1716 | | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 1717 | | const len_val = Value.initPayload(&len_pl.base); |
| 1718 | | |
| 1719 | | try w.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)}); |
| 1720 | | try dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, .@"const", 0, .Complete); |
| 1721 | | try w.writeAll(" = "); |
| 1722 | | try dg.renderValue(w, name_ty, name_val, .Initializer); |
| 1723 | | try w.writeAll(";\n return ("); |
| 1724 | | try dg.renderType(w, name_slice_ty); |
| 1725 | | try w.print("){{{}, {}}};\n", .{ |
| 1726 | | fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val), |
| 1727 | | }); |
| 1728 | | |
| 1729 | | try w.writeAll(" }\n"); |
| 1730 | | } |
| 1731 | | try w.writeAll(" }\n while ("); |
| 1732 | | try dg.renderValue(w, Type.bool, Value.true, .Other); |
| 1733 | | try w.writeAll(") "); |
| 1734 | | _ = try airBreakpoint(w); |
| 1735 | | try w.writeAll("}\n"); |
| 1704 | try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{}); |
| 1736 | 1705 | } |
| 1737 | 1706 | |
| 1738 | 1707 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { |
| ... | ... | @@ -1771,6 +1740,7 @@ pub const DeclGen = struct { |
| 1771 | 1740 | fmtIdent(ident), |
| 1772 | 1741 | }), |
| 1773 | 1742 | .bytes => |bytes| return w.writeAll(bytes), |
| 1743 | .call_always_tail => return dg.fail("CBE: the result of @call(.always_tail, ...) must be returned directly", .{}), |
| 1774 | 1744 | } |
| 1775 | 1745 | } |
| 1776 | 1746 | |
| ... | ... | @@ -1804,6 +1774,7 @@ pub const DeclGen = struct { |
| 1804 | 1774 | try w.writeAll(bytes); |
| 1805 | 1775 | return w.writeByte(')'); |
| 1806 | 1776 | }, |
| 1777 | .call_always_tail => return dg.writeCValue(w, c_value), |
| 1807 | 1778 | } |
| 1808 | 1779 | } |
| 1809 | 1780 | |
| ... | ... | @@ -1816,7 +1787,16 @@ pub const DeclGen = struct { |
| 1816 | 1787 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { |
| 1817 | 1788 | switch (c_value) { |
| 1818 | 1789 | .none, .constant, .field, .undef => unreachable, |
| 1819 | | .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier, .bytes => { |
| 1790 | .new_local, |
| 1791 | .local, |
| 1792 | .arg, |
| 1793 | .arg_array, |
| 1794 | .decl, |
| 1795 | .identifier, |
| 1796 | .payload_identifier, |
| 1797 | .bytes, |
| 1798 | .call_always_tail, |
| 1799 | => { |
| 1820 | 1800 | try dg.writeCValue(writer, c_value); |
| 1821 | 1801 | try writer.writeAll("->"); |
| 1822 | 1802 | }, |
| ... | ... | @@ -1945,7 +1925,8 @@ pub const DeclGen = struct { |
| 1945 | 1925 | |
| 1946 | 1926 | const CTypeFix = enum { prefix, suffix }; |
| 1947 | 1927 | const CQualifiers = std.enums.EnumSet(enum { @"const", @"volatile", restrict }); |
| 1948 | | const CTypeRenderTrailing = enum { |
| 1928 | const Const = CQualifiers.init(.{ .@"const" = true }); |
| 1929 | const RenderCTypeTrailing = enum { |
| 1949 | 1930 | no_space, |
| 1950 | 1931 | maybe_space, |
| 1951 | 1932 | |
| ... | ... | @@ -2004,8 +1985,8 @@ fn renderTypePrefix( |
| 2004 | 1985 | idx: CType.Index, |
| 2005 | 1986 | parent_fix: CTypeFix, |
| 2006 | 1987 | qualifiers: CQualifiers, |
| 2007 | | ) @TypeOf(w).Error!CTypeRenderTrailing { |
| 2008 | | var trailing = CTypeRenderTrailing.maybe_space; |
| 1988 | ) @TypeOf(w).Error!RenderCTypeTrailing { |
| 1989 | var trailing = RenderCTypeTrailing.maybe_space; |
| 2009 | 1990 | |
| 2010 | 1991 | const cty = store.indexToCType(idx); |
| 2011 | 1992 | switch (cty.tag()) { |
| ... | ... | @@ -2147,7 +2128,7 @@ fn renderTypePrefix( |
| 2147 | 2128 | w, |
| 2148 | 2129 | cty.cast(CType.Payload.Function).?.data.return_type, |
| 2149 | 2130 | .suffix, |
| 2150 | | CQualifiers.init(.{}), |
| 2131 | .{}, |
| 2151 | 2132 | ); |
| 2152 | 2133 | switch (parent_fix) { |
| 2153 | 2134 | .prefix => { |
| ... | ... | @@ -2174,6 +2155,7 @@ fn renderTypeSuffix( |
| 2174 | 2155 | w: anytype, |
| 2175 | 2156 | idx: CType.Index, |
| 2176 | 2157 | parent_fix: CTypeFix, |
| 2158 | qualifiers: CQualifiers, |
| 2177 | 2159 | ) @TypeOf(w).Error!void { |
| 2178 | 2160 | const cty = store.indexToCType(idx); |
| 2179 | 2161 | switch (cty.tag()) { |
| ... | ... | @@ -2220,7 +2202,15 @@ fn renderTypeSuffix( |
| 2220 | 2202 | .pointer_const, |
| 2221 | 2203 | .pointer_volatile, |
| 2222 | 2204 | .pointer_const_volatile, |
| 2223 | | => try renderTypeSuffix(decl, store, mod, w, cty.cast(CType.Payload.Child).?.data, .prefix), |
| 2205 | => try renderTypeSuffix( |
| 2206 | decl, |
| 2207 | store, |
| 2208 | mod, |
| 2209 | w, |
| 2210 | cty.cast(CType.Payload.Child).?.data, |
| 2211 | .prefix, |
| 2212 | .{}, |
| 2213 | ), |
| 2224 | 2214 | |
| 2225 | 2215 | .array, |
| 2226 | 2216 | .vector, |
| ... | ... | @@ -2238,6 +2228,7 @@ fn renderTypeSuffix( |
| 2238 | 2228 | w, |
| 2239 | 2229 | cty.cast(CType.Payload.Sequence).?.data.elem_type, |
| 2240 | 2230 | .suffix, |
| 2231 | .{}, |
| 2241 | 2232 | ); |
| 2242 | 2233 | }, |
| 2243 | 2234 | |
| ... | ... | @@ -2272,17 +2263,10 @@ fn renderTypeSuffix( |
| 2272 | 2263 | for (data.param_types, 0..) |param_type, param_i| { |
| 2273 | 2264 | if (need_comma) try w.writeAll(", "); |
| 2274 | 2265 | need_comma = true; |
| 2275 | | const trailing = try renderTypePrefix( |
| 2276 | | decl, |
| 2277 | | store, |
| 2278 | | mod, |
| 2279 | | w, |
| 2280 | | param_type, |
| 2281 | | .suffix, |
| 2282 | | CQualifiers.init(.{ .@"const" = true }), |
| 2283 | | ); |
| 2284 | | try w.print("{}a{d}", .{ trailing, param_i }); |
| 2285 | | try renderTypeSuffix(decl, store, mod, w, param_type, .suffix); |
| 2266 | const trailing = |
| 2267 | try renderTypePrefix(decl, store, mod, w, param_type, .suffix, qualifiers); |
| 2268 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i }); |
| 2269 | try renderTypeSuffix(decl, store, mod, w, param_type, .suffix, .{}); |
| 2286 | 2270 | } |
| 2287 | 2271 | switch (tag) { |
| 2288 | 2272 | .function => {}, |
| ... | ... | @@ -2296,7 +2280,7 @@ fn renderTypeSuffix( |
| 2296 | 2280 | if (!need_comma) try w.writeAll("void"); |
| 2297 | 2281 | try w.writeByte(')'); |
| 2298 | 2282 | |
| 2299 | | try renderTypeSuffix(decl, store, mod, w, data.return_type, .suffix); |
| 2283 | try renderTypeSuffix(decl, store, mod, w, data.return_type, .suffix, .{}); |
| 2300 | 2284 | }, |
| 2301 | 2285 | } |
| 2302 | 2286 | } |
| ... | ... | @@ -2316,17 +2300,9 @@ fn renderAggregateFields( |
| 2316 | 2300 | .eq => {}, |
| 2317 | 2301 | .gt => try writer.print("zig_align({}) ", .{field.alignas.getAlign()}), |
| 2318 | 2302 | } |
| 2319 | | const trailing = try renderTypePrefix( |
| 2320 | | .none, |
| 2321 | | store, |
| 2322 | | mod, |
| 2323 | | writer, |
| 2324 | | field.type, |
| 2325 | | .suffix, |
| 2326 | | CQualifiers.init(.{}), |
| 2327 | | ); |
| 2303 | const trailing = try renderTypePrefix(.none, store, mod, writer, field.type, .suffix, .{}); |
| 2328 | 2304 | try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) }); |
| 2329 | | try renderTypeSuffix(.none, store, mod, writer, field.type, .suffix); |
| 2305 | try renderTypeSuffix(.none, store, mod, writer, field.type, .suffix, .{}); |
| 2330 | 2306 | try writer.writeAll(";\n"); |
| 2331 | 2307 | } |
| 2332 | 2308 | try writer.writeByteNTimes(' ', indent); |
| ... | ... | @@ -2347,25 +2323,9 @@ pub fn genTypeDecl( |
| 2347 | 2323 | switch (global_cty.tag()) { |
| 2348 | 2324 | .fwd_anon_struct => if (decl != .none) { |
| 2349 | 2325 | try writer.writeAll("typedef "); |
| 2350 | | _ = try renderTypePrefix( |
| 2351 | | .none, |
| 2352 | | global_store, |
| 2353 | | mod, |
| 2354 | | writer, |
| 2355 | | global_idx, |
| 2356 | | .suffix, |
| 2357 | | CQualifiers.init(.{}), |
| 2358 | | ); |
| 2326 | _ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{}); |
| 2359 | 2327 | try writer.writeByte(' '); |
| 2360 | | _ = try renderTypePrefix( |
| 2361 | | decl, |
| 2362 | | decl_store, |
| 2363 | | mod, |
| 2364 | | writer, |
| 2365 | | decl_idx, |
| 2366 | | .suffix, |
| 2367 | | CQualifiers.init(.{}), |
| 2368 | | ); |
| 2328 | _ = try renderTypePrefix(decl, decl_store, mod, writer, decl_idx, .suffix, .{}); |
| 2369 | 2329 | try writer.writeAll(";\n"); |
| 2370 | 2330 | }, |
| 2371 | 2331 | |
| ... | ... | @@ -2383,15 +2343,7 @@ pub fn genTypeDecl( |
| 2383 | 2343 | .fwd_union, |
| 2384 | 2344 | => { |
| 2385 | 2345 | const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data; |
| 2386 | | _ = try renderTypePrefix( |
| 2387 | | .none, |
| 2388 | | global_store, |
| 2389 | | mod, |
| 2390 | | writer, |
| 2391 | | global_idx, |
| 2392 | | .suffix, |
| 2393 | | CQualifiers.init(.{}), |
| 2394 | | ); |
| 2346 | _ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{}); |
| 2395 | 2347 | try writer.writeAll("; // "); |
| 2396 | 2348 | try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer); |
| 2397 | 2349 | try writer.writeByte('\n'); |
| ... | ... | @@ -2467,7 +2419,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2467 | 2419 | const name_val = Value.initPayload(&name_pl.base); |
| 2468 | 2420 | |
| 2469 | 2421 | try writer.writeAll("static "); |
| 2470 | | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .@"const", 0, .Complete); |
| 2422 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete); |
| 2471 | 2423 | try writer.writeAll(" = "); |
| 2472 | 2424 | try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer); |
| 2473 | 2425 | try writer.writeAll(";\n"); |
| ... | ... | @@ -2480,7 +2432,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2480 | 2432 | const name_array_ty = Type.initPayload(&name_array_ty_pl.base); |
| 2481 | 2433 | |
| 2482 | 2434 | try writer.writeAll("static "); |
| 2483 | | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .@"const", 0, .Complete); |
| 2435 | try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, Const, 0, .complete); |
| 2484 | 2436 | try writer.writeAll(" = {"); |
| 2485 | 2437 | for (o.dg.module.error_name_list.items, 0..) |name, value| { |
| 2486 | 2438 | if (value != 0) try writer.writeByte(','); |
| ... | ... | @@ -2503,7 +2455,7 @@ fn genExports(o: *Object) !void { |
| 2503 | 2455 | if (o.dg.module.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| { |
| 2504 | 2456 | for (exports.items[1..], 1..) |@"export", i| { |
| 2505 | 2457 | try fwd_decl_writer.writeAll("zig_export("); |
| 2506 | | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, i)); |
| 2458 | try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @intCast(u32, i) }); |
| 2507 | 2459 | try fwd_decl_writer.print(", {s}, {s});\n", .{ |
| 2508 | 2460 | fmtStringLiteral(exports.items[0].options.name), |
| 2509 | 2461 | fmtStringLiteral(@"export".options.name), |
| ... | ... | @@ -2513,13 +2465,85 @@ fn genExports(o: *Object) !void { |
| 2513 | 2465 | } |
| 2514 | 2466 | |
| 2515 | 2467 | pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2516 | | const writer = o.writer(); |
| 2517 | | switch (lazy_fn.key_ptr.*) { |
| 2518 | | .tag_name => _ = try o.dg.renderTagNameFn( |
| 2519 | | writer, |
| 2520 | | lazy_fn.value_ptr.fn_name, |
| 2521 | | lazy_fn.value_ptr.data.tag_name, |
| 2522 | | ), |
| 2468 | const w = o.writer(); |
| 2469 | const key = lazy_fn.key_ptr.*; |
| 2470 | const val = lazy_fn.value_ptr; |
| 2471 | const fn_name = val.fn_name; |
| 2472 | switch (key) { |
| 2473 | .tag_name => { |
| 2474 | const enum_ty = val.data.tag_name; |
| 2475 | |
| 2476 | const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 2477 | |
| 2478 | try w.writeAll("static "); |
| 2479 | try o.dg.renderType(w, name_slice_ty); |
| 2480 | try w.writeByte(' '); |
| 2481 | try w.writeAll(fn_name); |
| 2482 | try w.writeByte('('); |
| 2483 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete); |
| 2484 | try w.writeAll(") {\n switch (tag) {\n"); |
| 2485 | for (enum_ty.enumFields().keys(), 0..) |name, index| { |
| 2486 | const name_z = try o.dg.gpa.dupeZ(u8, name); |
| 2487 | defer o.dg.gpa.free(name_z); |
| 2488 | const name_bytes = name_z[0 .. name_z.len + 1]; |
| 2489 | |
| 2490 | var tag_pl: Value.Payload.U32 = .{ |
| 2491 | .base = .{ .tag = .enum_field_index }, |
| 2492 | .data = @intCast(u32, index), |
| 2493 | }; |
| 2494 | const tag_val = Value.initPayload(&tag_pl.base); |
| 2495 | |
| 2496 | var int_pl: Value.Payload.U64 = undefined; |
| 2497 | const int_val = tag_val.enumToInt(enum_ty, &int_pl); |
| 2498 | |
| 2499 | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; |
| 2500 | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 2501 | |
| 2502 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes }; |
| 2503 | const name_val = Value.initPayload(&name_pl.base); |
| 2504 | |
| 2505 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 2506 | const len_val = Value.initPayload(&len_pl.base); |
| 2507 | |
| 2508 | try w.print(" case {}: {{\n static ", .{try o.dg.fmtIntLiteral(enum_ty, int_val)}); |
| 2509 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); |
| 2510 | try w.writeAll(" = "); |
| 2511 | try o.dg.renderValue(w, name_ty, name_val, .Initializer); |
| 2512 | try w.writeAll(";\n return ("); |
| 2513 | try o.dg.renderType(w, name_slice_ty); |
| 2514 | try w.print("){{{}, {}}};\n", .{ |
| 2515 | fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val), |
| 2516 | }); |
| 2517 | |
| 2518 | try w.writeAll(" }\n"); |
| 2519 | } |
| 2520 | try w.writeAll(" }\n while ("); |
| 2521 | try o.dg.renderValue(w, Type.bool, Value.true, .Other); |
| 2522 | try w.writeAll(") "); |
| 2523 | _ = try airBreakpoint(w); |
| 2524 | try w.writeAll("}\n"); |
| 2525 | }, |
| 2526 | .never_tail, .never_inline => |fn_decl_index| { |
| 2527 | const fn_decl = o.dg.module.declPtr(fn_decl_index); |
| 2528 | const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete); |
| 2529 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; |
| 2530 | |
| 2531 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2532 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| 2533 | try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{ .string = fn_name }); |
| 2534 | try fwd_decl_writer.writeAll(";\n"); |
| 2535 | |
| 2536 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| 2537 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ .string = fn_name }); |
| 2538 | try w.writeAll(" {\n return "); |
| 2539 | try o.dg.renderDeclName(w, fn_decl_index, 0); |
| 2540 | try w.writeByte('('); |
| 2541 | for (0..fn_info.param_types.len) |arg| { |
| 2542 | if (arg > 0) try w.writeAll(", "); |
| 2543 | try o.dg.writeCValue(w, .{ .arg = arg }); |
| 2544 | } |
| 2545 | try w.writeAll(");\n}\n"); |
| 2546 | }, |
| 2523 | 2547 | } |
| 2524 | 2548 | } |
| 2525 | 2549 | |
| ... | ... | @@ -2529,6 +2553,7 @@ pub fn genFunc(f: *Function) !void { |
| 2529 | 2553 | |
| 2530 | 2554 | const o = &f.object; |
| 2531 | 2555 | const gpa = o.dg.gpa; |
| 2556 | const decl_index = o.dg.decl_index.unwrap().?; |
| 2532 | 2557 | const tv: TypedValue = .{ |
| 2533 | 2558 | .ty = o.dg.decl.?.ty, |
| 2534 | 2559 | .val = o.dg.decl.?.val, |
| ... | ... | @@ -2540,13 +2565,13 @@ pub fn genFunc(f: *Function) !void { |
| 2540 | 2565 | const is_global = o.dg.declIsGlobal(tv); |
| 2541 | 2566 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2542 | 2567 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2543 | | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0); |
| 2568 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); |
| 2544 | 2569 | try fwd_decl_writer.writeAll(";\n"); |
| 2545 | 2570 | try genExports(o); |
| 2546 | 2571 | |
| 2547 | 2572 | try o.indent_writer.insertNewline(); |
| 2548 | 2573 | if (!is_global) try o.writer().writeAll("static "); |
| 2549 | | try o.dg.renderFunctionSignature(o.writer(), .Complete, 0); |
| 2574 | try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 }); |
| 2550 | 2575 | try o.writer().writeByte(' '); |
| 2551 | 2576 | |
| 2552 | 2577 | // In case we need to use the header, populate it with a copy of the function |
| ... | ... | @@ -2600,9 +2625,9 @@ pub fn genFunc(f: *Function) !void { |
| 2600 | 2625 | w, |
| 2601 | 2626 | local.ty, |
| 2602 | 2627 | .{ .local = local_index }, |
| 2603 | | .mut, |
| 2628 | .{}, |
| 2604 | 2629 | local.alignment, |
| 2605 | | .Complete, |
| 2630 | .complete, |
| 2606 | 2631 | ); |
| 2607 | 2632 | try w.writeAll(";\n "); |
| 2608 | 2633 | } |
| ... | ... | @@ -2628,7 +2653,7 @@ pub fn genDecl(o: *Object) !void { |
| 2628 | 2653 | if (tv.val.tag() == .extern_fn) { |
| 2629 | 2654 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2630 | 2655 | try fwd_decl_writer.writeAll("zig_extern "); |
| 2631 | | try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, 0); |
| 2656 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 }); |
| 2632 | 2657 | try fwd_decl_writer.writeAll(";\n"); |
| 2633 | 2658 | try genExports(o); |
| 2634 | 2659 | } else if (tv.val.castTag(.variable)) |var_payload| { |
| ... | ... | @@ -2639,7 +2664,7 @@ pub fn genDecl(o: *Object) !void { |
| 2639 | 2664 | |
| 2640 | 2665 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2641 | 2666 | if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 2642 | | try o.dg.renderTypeAndName(fwd_decl_writer, decl.ty, decl_c_value, .mut, decl.@"align", .Complete); |
| 2667 | try o.dg.renderTypeAndName(fwd_decl_writer, decl.ty, decl_c_value, .{}, decl.@"align", .complete); |
| 2643 | 2668 | try fwd_decl_writer.writeAll(";\n"); |
| 2644 | 2669 | try genExports(o); |
| 2645 | 2670 | |
| ... | ... | @@ -2649,7 +2674,7 @@ pub fn genDecl(o: *Object) !void { |
| 2649 | 2674 | if (!is_global) try w.writeAll("static "); |
| 2650 | 2675 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); |
| 2651 | 2676 | if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section}); |
| 2652 | | try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .mut, decl.@"align", .Complete); |
| 2677 | try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete); |
| 2653 | 2678 | if (decl.@"linksection" != null) try w.writeAll(", read, write)"); |
| 2654 | 2679 | try w.writeAll(" = "); |
| 2655 | 2680 | try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer); |
| ... | ... | @@ -2660,13 +2685,13 @@ pub fn genDecl(o: *Object) !void { |
| 2660 | 2685 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2661 | 2686 | |
| 2662 | 2687 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2663 | | try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .@"const", decl.@"align", .Complete); |
| 2688 | try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, decl.@"align", .complete); |
| 2664 | 2689 | try fwd_decl_writer.writeAll(";\n"); |
| 2665 | 2690 | |
| 2666 | 2691 | const w = o.writer(); |
| 2667 | 2692 | if (!is_global) try w.writeAll("static "); |
| 2668 | 2693 | if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section}); |
| 2669 | | try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .@"const", decl.@"align", .Complete); |
| 2694 | try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, decl.@"align", .complete); |
| 2670 | 2695 | if (decl.@"linksection" != null) try w.writeAll(", read)"); |
| 2671 | 2696 | try w.writeAll(" = "); |
| 2672 | 2697 | try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer); |
| ... | ... | @@ -2689,7 +2714,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2689 | 2714 | const is_global = dg.declIsGlobal(tv); |
| 2690 | 2715 | if (is_global) { |
| 2691 | 2716 | try writer.writeAll("zig_extern "); |
| 2692 | | try dg.renderFunctionSignature(writer, .Complete, 0); |
| 2717 | try dg.renderFunctionSignature(writer, dg.decl_index.unwrap().?, .complete, .{ .export_index = 0 }); |
| 2693 | 2718 | try dg.fwd_decl.appendSlice(";\n"); |
| 2694 | 2719 | } |
| 2695 | 2720 | }, |
| ... | ... | @@ -2879,10 +2904,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2879 | 2904 | |
| 2880 | 2905 | .dbg_block_begin, |
| 2881 | 2906 | .dbg_block_end, |
| 2882 | | => CValue{ .none = {} }, |
| 2907 | => .none, |
| 2883 | 2908 | |
| 2884 | 2909 | .call => try airCall(f, inst, .auto), |
| 2885 | | .call_always_tail => try airCall(f, inst, .always_tail), |
| 2910 | .call_always_tail => .call_always_tail, |
| 2886 | 2911 | .call_never_tail => try airCall(f, inst, .never_tail), |
| 2887 | 2912 | .call_never_inline => try airCall(f, inst, .never_inline), |
| 2888 | 2913 | |
| ... | ... | @@ -3199,9 +3224,12 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3199 | 3224 | return CValue{ .undef = inst_ty }; |
| 3200 | 3225 | } |
| 3201 | 3226 | |
| 3202 | | const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut; |
| 3203 | 3227 | const target = f.object.dg.module.getTarget(); |
| 3204 | | const local = try f.allocAlignedLocal(elem_type, mutability, inst_ty.ptrAlignment(target)); |
| 3228 | const local = try f.allocAlignedLocal( |
| 3229 | elem_type, |
| 3230 | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), |
| 3231 | inst_ty.ptrAlignment(target), |
| 3232 | ); |
| 3205 | 3233 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3206 | 3234 | const gpa = f.object.dg.module.gpa; |
| 3207 | 3235 | try f.allocs.put(gpa, local.new_local, false); |
| ... | ... | @@ -3216,9 +3244,12 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3216 | 3244 | return CValue{ .undef = inst_ty }; |
| 3217 | 3245 | } |
| 3218 | 3246 | |
| 3219 | | const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut; |
| 3220 | 3247 | const target = f.object.dg.module.getTarget(); |
| 3221 | | const local = try f.allocAlignedLocal(elem_ty, mutability, inst_ty.ptrAlignment(target)); |
| 3248 | const local = try f.allocAlignedLocal( |
| 3249 | elem_ty, |
| 3250 | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), |
| 3251 | inst_ty.ptrAlignment(target), |
| 3252 | ); |
| 3222 | 3253 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3223 | 3254 | const gpa = f.object.dg.module.gpa; |
| 3224 | 3255 | try f.allocs.put(gpa, local.new_local, false); |
| ... | ... | @@ -3336,10 +3367,19 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3336 | 3367 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; |
| 3337 | 3368 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); |
| 3338 | 3369 | |
| 3339 | | if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3340 | | var deref = is_ptr; |
| 3370 | const is_naked = if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention() == .Naked else false; |
| 3371 | const peek_operand = f.value_map.get(un_op); |
| 3372 | if (if (peek_operand) |operand| operand == .call_always_tail else false) { |
| 3373 | try reap(f, inst, &.{un_op}); |
| 3374 | if (is_naked) { |
| 3375 | try f.writeCValue(writer, peek_operand.?, .Other); |
| 3376 | unreachable; |
| 3377 | } |
| 3378 | _ = try airCall(f, Air.refToIndex(un_op).?, .always_tail); |
| 3379 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3341 | 3380 | const operand = try f.resolveInst(un_op); |
| 3342 | 3381 | try reap(f, inst, &.{un_op}); |
| 3382 | var deref = is_ptr; |
| 3343 | 3383 | const is_array = lowersToArray(ret_ty, target); |
| 3344 | 3384 | const ret_val = if (is_array) ret_val: { |
| 3345 | 3385 | const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator())); |
| ... | ... | @@ -3368,9 +3408,8 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3368 | 3408 | } |
| 3369 | 3409 | } else { |
| 3370 | 3410 | try reap(f, inst, &.{un_op}); |
| 3371 | | if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() != .Naked) |
| 3372 | | // Not even allowed to return void in a naked function. |
| 3373 | | try writer.writeAll("return;\n"); |
| 3411 | // Not even allowed to return void in a naked function. |
| 3412 | if (!is_naked) try writer.writeAll("return;\n"); |
| 3374 | 3413 | } |
| 3375 | 3414 | return CValue.none; |
| 3376 | 3415 | } |
| ... | ... | @@ -4004,13 +4043,6 @@ fn airCall( |
| 4004 | 4043 | const target = module.getTarget(); |
| 4005 | 4044 | const writer = f.object.writer(); |
| 4006 | 4045 | |
| 4007 | | switch (modifier) { |
| 4008 | | .auto => {}, |
| 4009 | | .always_tail => return f.fail("TODO: C backend: call with always_tail attribute", .{}), |
| 4010 | | .never_tail => return f.fail("TODO: C backend: call with never_tail attribute", .{}), |
| 4011 | | .never_inline => return f.fail("TODO: C backend: call with never_inline attribute", .{}), |
| 4012 | | else => unreachable, |
| 4013 | | } |
| 4014 | 4046 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 4015 | 4047 | const extra = f.air.extraData(Air.Call, pl_op.payload); |
| 4016 | 4048 | const args = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra.end..][0..extra.data.args_len]); |
| ... | ... | @@ -4060,7 +4092,10 @@ fn airCall( |
| 4060 | 4092 | var lowered_ret_buf: LowerFnRetTyBuffer = undefined; |
| 4061 | 4093 | const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target); |
| 4062 | 4094 | |
| 4063 | | const result_local: CValue = if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) |
| 4095 | const result_local: CValue = if (modifier == .always_tail) r: { |
| 4096 | try writer.writeAll("zig_always_tail return "); |
| 4097 | break :r .none; |
| 4098 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) |
| 4064 | 4099 | .none |
| 4065 | 4100 | else if (f.liveness.isUnused(inst)) r: { |
| 4066 | 4101 | try writer.writeByte('('); |
| ... | ... | @@ -4074,26 +4109,33 @@ fn airCall( |
| 4074 | 4109 | break :r local; |
| 4075 | 4110 | }; |
| 4076 | 4111 | |
| 4077 | | var is_extern = false; |
| 4078 | | var name: [*:0]const u8 = ""; |
| 4079 | 4112 | callee: { |
| 4080 | 4113 | known: { |
| 4081 | 4114 | const fn_decl = fn_decl: { |
| 4082 | 4115 | const callee_val = f.air.value(pl_op.operand) orelse break :known; |
| 4083 | 4116 | break :fn_decl switch (callee_val.tag()) { |
| 4084 | | .extern_fn => blk: { |
| 4085 | | is_extern = true; |
| 4086 | | break :blk callee_val.castTag(.extern_fn).?.data.owner_decl; |
| 4087 | | }, |
| 4117 | .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl, |
| 4088 | 4118 | .function => callee_val.castTag(.function).?.data.owner_decl, |
| 4089 | 4119 | .decl_ref => callee_val.castTag(.decl_ref).?.data, |
| 4090 | 4120 | else => break :known, |
| 4091 | 4121 | }; |
| 4092 | 4122 | }; |
| 4093 | | name = module.declPtr(fn_decl).name; |
| 4094 | | try f.object.dg.renderDeclName(writer, fn_decl, 0); |
| 4123 | switch (modifier) { |
| 4124 | .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0), |
| 4125 | inline .never_tail, .never_inline => |mod| try writer.writeAll(try f.getLazyFnName( |
| 4126 | @unionInit(LazyFnKey, @tagName(mod), fn_decl), |
| 4127 | @unionInit(LazyFnValue.Data, @tagName(mod), {}), |
| 4128 | )), |
| 4129 | else => unreachable, |
| 4130 | } |
| 4095 | 4131 | break :callee; |
| 4096 | 4132 | } |
| 4133 | switch (modifier) { |
| 4134 | .auto, .always_tail => {}, |
| 4135 | .never_tail => return f.fail("CBE: runtime callee with never_tail attribute unsupported", .{}), |
| 4136 | .never_inline => return f.fail("CBE: runtime callee with never_inline attribute unsupported", .{}), |
| 4137 | else => unreachable, |
| 4138 | } |
| 4097 | 4139 | // Fall back to function pointer call. |
| 4098 | 4140 | try f.writeCValue(writer, callee, .Other); |
| 4099 | 4141 | } |
| ... | ... | @@ -4704,14 +4746,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4704 | 4746 | try writer.writeAll("register "); |
| 4705 | 4747 | const alignment = 0; |
| 4706 | 4748 | const local_value = try f.allocLocalValue(output_ty, alignment); |
| 4707 | | try f.object.dg.renderTypeAndName( |
| 4708 | | writer, |
| 4709 | | output_ty, |
| 4710 | | local_value, |
| 4711 | | .mut, |
| 4712 | | alignment, |
| 4713 | | .Complete, |
| 4714 | | ); |
| 4749 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); |
| 4715 | 4750 | try writer.writeAll(" __asm(\""); |
| 4716 | 4751 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| 4717 | 4752 | try writer.writeAll("\")"); |
| ... | ... | @@ -4743,14 +4778,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4743 | 4778 | if (is_reg) try writer.writeAll("register "); |
| 4744 | 4779 | const alignment = 0; |
| 4745 | 4780 | const local_value = try f.allocLocalValue(input_ty, alignment); |
| 4746 | | try f.object.dg.renderTypeAndName( |
| 4747 | | writer, |
| 4748 | | input_ty, |
| 4749 | | local_value, |
| 4750 | | .@"const", |
| 4751 | | alignment, |
| 4752 | | .Complete, |
| 4753 | | ); |
| 4781 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); |
| 4754 | 4782 | if (is_reg) { |
| 4755 | 4783 | try writer.writeAll(" __asm(\""); |
| 4756 | 4784 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | ... | @@ -6278,7 +6306,9 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6278 | 6306 | const writer = f.object.writer(); |
| 6279 | 6307 | const local = try f.allocLocal(inst, inst_ty); |
| 6280 | 6308 | try f.writeCValue(writer, local, .Other); |
| 6281 | | try writer.print(" = {s}(", .{try f.getTagNameFn(enum_ty)}); |
| 6309 | try writer.print(" = {s}(", .{ |
| 6310 | try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl() }, .{ .tag_name = enum_ty }), |
| 6311 | }); |
| 6282 | 6312 | try f.writeCValue(writer, operand, .Other); |
| 6283 | 6313 | try writer.writeAll(");\n"); |
| 6284 | 6314 | |