| ... | ... | @@ -291,6 +291,19 @@ pub const Function = struct { |
| 291 | 291 | } |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { |
| 295 | switch (c_value) { |
| 296 | .constant => |inst| { |
| 297 | const ty = f.air.typeOf(inst); |
| 298 | const val = f.air.value(inst).?; |
| 299 | try w.writeAll("(*"); |
| 300 | try f.object.dg.renderValue(w, ty, val); |
| 301 | return w.writeByte(')'); |
| 302 | }, |
| 303 | else => return f.object.dg.writeCValueDeref(w, c_value), |
| 304 | } |
| 305 | } |
| 306 | |
| 294 | 307 | fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 295 | 308 | return f.object.dg.fail(format, args); |
| 296 | 309 | } |
| ... | ... | @@ -1259,6 +1272,28 @@ pub const DeclGen = struct { |
| 1259 | 1272 | } |
| 1260 | 1273 | } |
| 1261 | 1274 | |
| 1275 | fn writeCValueDeref(dg: DeclGen, w: anytype, c_value: CValue) !void { |
| 1276 | switch (c_value) { |
| 1277 | .none => unreachable, |
| 1278 | .local => |i| return w.print("(*t{d})", .{i}), |
| 1279 | .local_ref => |i| return w.print("t{d}", .{i}), |
| 1280 | .constant => unreachable, |
| 1281 | .arg => |i| return w.print("(*a{d})", .{i}), |
| 1282 | .decl => |decl| { |
| 1283 | try w.writeAll("(*"); |
| 1284 | try dg.renderDeclName(decl, w); |
| 1285 | return w.writeByte(')'); |
| 1286 | }, |
| 1287 | .decl_ref => |decl| return dg.renderDeclName(decl, w), |
| 1288 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), |
| 1289 | .bytes => |bytes| { |
| 1290 | try w.writeAll("(*"); |
| 1291 | try w.writeAll(bytes); |
| 1292 | return w.writeByte(')'); |
| 1293 | }, |
| 1294 | } |
| 1295 | } |
| 1296 | |
| 1262 | 1297 | fn renderDeclName(dg: DeclGen, decl: *Decl, writer: anytype) !void { |
| 1263 | 1298 | if (dg.module.decl_exports.get(decl)) |exports| { |
| 1264 | 1299 | return writer.writeAll(exports[0].options.name); |
| ... | ... | @@ -1493,10 +1528,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1493 | 1528 | .optional_payload_ptr => try airOptionalPayload(f, inst), |
| 1494 | 1529 | .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst), |
| 1495 | 1530 | |
| 1496 | | .is_err => try airIsErr(f, inst, "", ".", "!="), |
| 1497 | | .is_non_err => try airIsErr(f, inst, "", ".", "=="), |
| 1498 | | .is_err_ptr => try airIsErr(f, inst, "*", "->", "!="), |
| 1499 | | .is_non_err_ptr => try airIsErr(f, inst, "*", "->", "=="), |
| 1531 | .is_err => try airIsErr(f, inst, false, "!="), |
| 1532 | .is_non_err => try airIsErr(f, inst, false, "=="), |
| 1533 | .is_err_ptr => try airIsErr(f, inst, true, "!="), |
| 1534 | .is_non_err_ptr => try airIsErr(f, inst, true, "=="), |
| 1500 | 1535 | |
| 1501 | 1536 | .is_null => try airIsNull(f, inst, "==", ""), |
| 1502 | 1537 | .is_non_null => try airIsNull(f, inst, "!=", ""), |
| ... | ... | @@ -1800,8 +1835,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 1800 | 1835 | try f.writeCValue(writer, local); |
| 1801 | 1836 | try writer.writeAll("));\n"); |
| 1802 | 1837 | } else { |
| 1803 | | try writer.writeAll(" = *"); |
| 1804 | | try f.writeCValue(writer, operand); |
| 1838 | try writer.writeAll(" = "); |
| 1839 | try f.writeCValueDeref(writer, operand); |
| 1805 | 1840 | try writer.writeAll(";\n"); |
| 1806 | 1841 | } |
| 1807 | 1842 | }, |
| ... | ... | @@ -1916,33 +1951,15 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue, dest_child_type: Type) !CVa |
| 1916 | 1951 | return CValue.none; |
| 1917 | 1952 | |
| 1918 | 1953 | const writer = f.object.writer(); |
| 1919 | | switch (dest_ptr) { |
| 1920 | | .local_ref => |i| { |
| 1921 | | const dest: CValue = .{ .local = i }; |
| 1922 | | try writer.writeAll("memset(&"); |
| 1923 | | try f.writeCValue(writer, dest); |
| 1924 | | try writer.writeAll(", 0xaa, sizeof("); |
| 1925 | | try f.writeCValue(writer, dest); |
| 1926 | | try writer.writeAll("));\n"); |
| 1927 | | }, |
| 1928 | | .decl_ref => |decl| { |
| 1929 | | const dest: CValue = .{ .decl = decl }; |
| 1930 | | try writer.writeAll("memset(&"); |
| 1931 | | try f.writeCValue(writer, dest); |
| 1932 | | try writer.writeAll(", 0xaa, sizeof("); |
| 1933 | | try f.writeCValue(writer, dest); |
| 1934 | | try writer.writeAll("));\n"); |
| 1935 | | }, |
| 1936 | | else => { |
| 1937 | | const indirection = if (dest_child_type.zigTypeTag() == .Array) "" else "*"; |
| 1938 | | |
| 1939 | | try writer.writeAll("memset("); |
| 1940 | | try f.writeCValue(writer, dest_ptr); |
| 1941 | | try writer.print(", 0xaa, sizeof({s}", .{indirection}); |
| 1942 | | try f.writeCValue(writer, dest_ptr); |
| 1943 | | try writer.writeAll("));\n"); |
| 1944 | | }, |
| 1954 | try writer.writeAll("memset("); |
| 1955 | try f.writeCValue(writer, dest_ptr); |
| 1956 | try writer.writeAll(", 0xaa, sizeof("); |
| 1957 | if (dest_child_type.zigTypeTag() == .Array) { |
| 1958 | try f.writeCValue(writer, dest_ptr); |
| 1959 | } else { |
| 1960 | try f.writeCValueDeref(writer, dest_ptr); |
| 1945 | 1961 | } |
| 1962 | try writer.writeAll("));\n"); |
| 1946 | 1963 | return CValue.none; |
| 1947 | 1964 | } |
| 1948 | 1965 | |
| ... | ... | @@ -2004,8 +2021,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2004 | 2021 | try f.writeCValue(writer, array_src); |
| 2005 | 2022 | try writer.writeAll("));\n"); |
| 2006 | 2023 | } else { |
| 2007 | | try writer.writeAll("*"); |
| 2008 | | try f.writeCValue(writer, dest_ptr); |
| 2024 | try f.writeCValueDeref(writer, dest_ptr); |
| 2009 | 2025 | try writer.writeAll(" = "); |
| 2010 | 2026 | try f.writeCValue(writer, src_val); |
| 2011 | 2027 | try writer.writeAll(";\n"); |
| ... | ... | @@ -2852,16 +2868,15 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2852 | 2868 | return operand; |
| 2853 | 2869 | } |
| 2854 | 2870 | |
| 2855 | | try writer.writeAll("("); |
| 2856 | | try f.writeCValue(writer, operand); |
| 2857 | | try writer.writeAll(")->is_null = false;\n"); |
| 2871 | try f.writeCValueDeref(writer, operand); |
| 2872 | try writer.writeAll(".is_null = false;\n"); |
| 2858 | 2873 | |
| 2859 | 2874 | const inst_ty = f.air.typeOfIndex(inst); |
| 2860 | 2875 | const local = try f.allocLocal(inst_ty, .Const); |
| 2861 | | try writer.writeAll(" = &("); |
| 2862 | | try f.writeCValue(writer, operand); |
| 2876 | try writer.writeAll(" = &"); |
| 2877 | try f.writeCValueDeref(writer, operand); |
| 2863 | 2878 | |
| 2864 | | try writer.writeAll(")->payload;\n"); |
| 2879 | try writer.writeAll(".payload;\n"); |
| 2865 | 2880 | return local; |
| 2866 | 2881 | } |
| 2867 | 2882 | |
| ... | ... | @@ -2912,18 +2927,10 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 2912 | 2927 | |
| 2913 | 2928 | const inst_ty = f.air.typeOfIndex(inst); |
| 2914 | 2929 | const local = try f.allocLocal(inst_ty, .Const); |
| 2915 | | switch (struct_ptr) { |
| 2916 | | .local_ref => |i| { |
| 2917 | | try writer.print(" = {s}t{d}.{s}{ };\n", .{ |
| 2918 | | addrof, i, payload, fmtIdent(field_name), |
| 2919 | | }); |
| 2920 | | }, |
| 2921 | | else => { |
| 2922 | | try writer.print(" = {s}", .{addrof}); |
| 2923 | | try f.writeCValue(writer, struct_ptr); |
| 2924 | | try writer.print("->{s}{ };\n", .{ payload, fmtIdent(field_name) }); |
| 2925 | | }, |
| 2926 | | } |
| 2930 | |
| 2931 | try writer.print(" = {s}", .{addrof}); |
| 2932 | try f.writeCValueDeref(writer, struct_ptr); |
| 2933 | try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) }); |
| 2927 | 2934 | return local; |
| 2928 | 2935 | } |
| 2929 | 2936 | |
| ... | ... | @@ -2975,13 +2982,14 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2975 | 2982 | } |
| 2976 | 2983 | } |
| 2977 | 2984 | |
| 2978 | | const maybe_deref = if (operand_ty.zigTypeTag() == .Pointer) "->" else "."; |
| 2979 | | |
| 2980 | 2985 | const local = try f.allocLocal(inst_ty, .Const); |
| 2981 | | try writer.writeAll(" = ("); |
| 2982 | | try f.writeCValue(writer, operand); |
| 2983 | | |
| 2984 | | try writer.print("){s}error;\n", .{maybe_deref}); |
| 2986 | try writer.writeAll(" = "); |
| 2987 | if (operand_ty.zigTypeTag() == .Pointer) { |
| 2988 | try f.writeCValueDeref(writer, operand); |
| 2989 | } else { |
| 2990 | try f.writeCValue(writer, operand); |
| 2991 | } |
| 2992 | try writer.writeAll(".error;\n"); |
| 2985 | 2993 | return local; |
| 2986 | 2994 | } |
| 2987 | 2995 | |
| ... | ... | @@ -3069,8 +3077,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3069 | 3077 | fn airIsErr( |
| 3070 | 3078 | f: *Function, |
| 3071 | 3079 | inst: Air.Inst.Index, |
| 3072 | | deref_prefix: [*:0]const u8, |
| 3073 | | deref_suffix: [*:0]const u8, |
| 3080 | is_ptr: bool, |
| 3074 | 3081 | op_str: [*:0]const u8, |
| 3075 | 3082 | ) !CValue { |
| 3076 | 3083 | if (f.liveness.isUnused(inst)) |
| ... | ... | @@ -3082,15 +3089,16 @@ fn airIsErr( |
| 3082 | 3089 | const operand_ty = f.air.typeOf(un_op); |
| 3083 | 3090 | const local = try f.allocLocal(Type.initTag(.bool), .Const); |
| 3084 | 3091 | const payload_ty = operand_ty.errorUnionPayload(); |
| 3085 | | if (!payload_ty.hasRuntimeBits()) { |
| 3086 | | try writer.print(" = {s}", .{deref_prefix}); |
| 3087 | | try f.writeCValue(writer, operand); |
| 3088 | | try writer.print(" {s} 0;\n", .{op_str}); |
| 3092 | try writer.writeAll(" = "); |
| 3093 | if (is_ptr) { |
| 3094 | try f.writeCValueDeref(writer, operand); |
| 3089 | 3095 | } else { |
| 3090 | | try writer.writeAll(" = "); |
| 3091 | 3096 | try f.writeCValue(writer, operand); |
| 3092 | | try writer.print("{s}error {s} 0;\n", .{ deref_suffix, op_str }); |
| 3093 | 3097 | } |
| 3098 | if (payload_ty.hasRuntimeBits()) { |
| 3099 | try writer.writeAll(".error"); |
| 3100 | } |
| 3101 | try writer.print(" {s} 0;\n", .{op_str}); |
| 3094 | 3102 | return local; |
| 3095 | 3103 | } |
| 3096 | 3104 | |