| ... | @@ -291,6 +291,19 @@ pub const Function = struct { | ... | @@ -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 | fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 307 | fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 295 | return f.object.dg.fail(format, args); | 308 | return f.object.dg.fail(format, args); |
| 296 | } | 309 | } |
| ... | @@ -1259,6 +1272,28 @@ pub const DeclGen = struct { | ... | @@ -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 | fn renderDeclName(dg: DeclGen, decl: *Decl, writer: anytype) !void { | 1297 | fn renderDeclName(dg: DeclGen, decl: *Decl, writer: anytype) !void { |
| 1263 | if (dg.module.decl_exports.get(decl)) |exports| { | 1298 | if (dg.module.decl_exports.get(decl)) |exports| { |
| 1264 | return writer.writeAll(exports[0].options.name); | 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,10 +1528,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1493 | .optional_payload_ptr => try airOptionalPayload(f, inst), | 1528 | .optional_payload_ptr => try airOptionalPayload(f, inst), |
| 1494 | .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst), | 1529 | .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst), |
| 1495 | | 1530 | |
| 1496 | .is_err => try airIsErr(f, inst, "", ".", "!="), | 1531 | .is_err => try airIsErr(f, inst, false, "!="), |
| 1497 | .is_non_err => try airIsErr(f, inst, "", ".", "=="), | 1532 | .is_non_err => try airIsErr(f, inst, false, "=="), |
| 1498 | .is_err_ptr => try airIsErr(f, inst, "*", "->", "!="), | 1533 | .is_err_ptr => try airIsErr(f, inst, true, "!="), |
| 1499 | .is_non_err_ptr => try airIsErr(f, inst, "*", "->", "=="), | 1534 | .is_non_err_ptr => try airIsErr(f, inst, true, "=="), |
| 1500 | | 1535 | |
| 1501 | .is_null => try airIsNull(f, inst, "==", ""), | 1536 | .is_null => try airIsNull(f, inst, "==", ""), |
| 1502 | .is_non_null => try airIsNull(f, inst, "!=", ""), | 1537 | .is_non_null => try airIsNull(f, inst, "!=", ""), |
| ... | @@ -1800,8 +1835,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -1800,8 +1835,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 1800 | try f.writeCValue(writer, local); | 1835 | try f.writeCValue(writer, local); |
| 1801 | try writer.writeAll("));\n"); | 1836 | try writer.writeAll("));\n"); |
| 1802 | } else { | 1837 | } else { |
| 1803 | try writer.writeAll(" = *"); | 1838 | try writer.writeAll(" = "); |
| 1804 | try f.writeCValue(writer, operand); | 1839 | try f.writeCValueDeref(writer, operand); |
| 1805 | try writer.writeAll(";\n"); | 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,33 +1951,15 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue, dest_child_type: Type) !CVa |
| 1916 | return CValue.none; | 1951 | return CValue.none; |
| 1917 | | 1952 | |
| 1918 | const writer = f.object.writer(); | 1953 | const writer = f.object.writer(); |
| 1919 | switch (dest_ptr) { | 1954 | try writer.writeAll("memset("); |
| 1920 | .local_ref => |i| { | 1955 | try f.writeCValue(writer, dest_ptr); |
| 1921 | const dest: CValue = .{ .local = i }; | 1956 | try writer.writeAll(", 0xaa, sizeof("); |
| 1922 | try writer.writeAll("memset(&"); | 1957 | if (dest_child_type.zigTypeTag() == .Array) { |
| 1923 | try f.writeCValue(writer, dest); | 1958 | try f.writeCValue(writer, dest_ptr); |
| 1924 | try writer.writeAll(", 0xaa, sizeof("); | 1959 | } else { |
| 1925 | try f.writeCValue(writer, dest); | 1960 | try f.writeCValueDeref(writer, dest_ptr); |
| 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 | }, | | |
| 1945 | } | 1961 | } |
| | 1962 | try writer.writeAll("));\n"); |
| 1946 | return CValue.none; | 1963 | return CValue.none; |
| 1947 | } | 1964 | } |
| 1948 | | 1965 | |
| ... | @@ -2004,8 +2021,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -2004,8 +2021,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2004 | try f.writeCValue(writer, array_src); | 2021 | try f.writeCValue(writer, array_src); |
| 2005 | try writer.writeAll("));\n"); | 2022 | try writer.writeAll("));\n"); |
| 2006 | } else { | 2023 | } else { |
| 2007 | try writer.writeAll("*"); | 2024 | try f.writeCValueDeref(writer, dest_ptr); |
| 2008 | try f.writeCValue(writer, dest_ptr); | | |
| 2009 | try writer.writeAll(" = "); | 2025 | try writer.writeAll(" = "); |
| 2010 | try f.writeCValue(writer, src_val); | 2026 | try f.writeCValue(writer, src_val); |
| 2011 | try writer.writeAll(";\n"); | 2027 | try writer.writeAll(";\n"); |
| ... | @@ -2852,16 +2868,15 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -2852,16 +2868,15 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2852 | return operand; | 2868 | return operand; |
| 2853 | } | 2869 | } |
| 2854 | | 2870 | |
| 2855 | try writer.writeAll("("); | 2871 | try f.writeCValueDeref(writer, operand); |
| 2856 | try f.writeCValue(writer, operand); | 2872 | try writer.writeAll(".is_null = false;\n"); |
| 2857 | try writer.writeAll(")->is_null = false;\n"); | | |
| 2858 | | 2873 | |
| 2859 | const inst_ty = f.air.typeOfIndex(inst); | 2874 | const inst_ty = f.air.typeOfIndex(inst); |
| 2860 | const local = try f.allocLocal(inst_ty, .Const); | 2875 | const local = try f.allocLocal(inst_ty, .Const); |
| 2861 | try writer.writeAll(" = &("); | 2876 | try writer.writeAll(" = &"); |
| 2862 | try f.writeCValue(writer, operand); | 2877 | try f.writeCValueDeref(writer, operand); |
| 2863 | | 2878 | |
| 2864 | try writer.writeAll(")->payload;\n"); | 2879 | try writer.writeAll(".payload;\n"); |
| 2865 | return local; | 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,18 +2927,10 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc |
| 2912 | | 2927 | |
| 2913 | const inst_ty = f.air.typeOfIndex(inst); | 2928 | const inst_ty = f.air.typeOfIndex(inst); |
| 2914 | const local = try f.allocLocal(inst_ty, .Const); | 2929 | const local = try f.allocLocal(inst_ty, .Const); |
| 2915 | switch (struct_ptr) { | 2930 | |
| 2916 | .local_ref => |i| { | 2931 | try writer.print(" = {s}", .{addrof}); |
| 2917 | try writer.print(" = {s}t{d}.{s}{ };\n", .{ | 2932 | try f.writeCValueDeref(writer, struct_ptr); |
| 2918 | addrof, i, payload, fmtIdent(field_name), | 2933 | try writer.print(".{s}{ };\n", .{ 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 | } | | |
| 2927 | return local; | 2934 | return local; |
| 2928 | } | 2935 | } |
| 2929 | | 2936 | |
| ... | @@ -2975,13 +2982,14 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -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 | const local = try f.allocLocal(inst_ty, .Const); | 2985 | const local = try f.allocLocal(inst_ty, .Const); |
| 2981 | try writer.writeAll(" = ("); | 2986 | try writer.writeAll(" = "); |
| 2982 | try f.writeCValue(writer, operand); | 2987 | if (operand_ty.zigTypeTag() == .Pointer) { |
| 2983 | | 2988 | try f.writeCValueDeref(writer, operand); |
| 2984 | try writer.print("){s}error;\n", .{maybe_deref}); | 2989 | } else { |
| | 2990 | try f.writeCValue(writer, operand); |
| | 2991 | } |
| | 2992 | try writer.writeAll(".error;\n"); |
| 2985 | return local; | 2993 | return local; |
| 2986 | } | 2994 | } |
| 2987 | | 2995 | |
| ... | @@ -3069,8 +3077,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3069,8 +3077,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3069 | fn airIsErr( | 3077 | fn airIsErr( |
| 3070 | f: *Function, | 3078 | f: *Function, |
| 3071 | inst: Air.Inst.Index, | 3079 | inst: Air.Inst.Index, |
| 3072 | deref_prefix: [*:0]const u8, | 3080 | is_ptr: bool, |
| 3073 | deref_suffix: [*:0]const u8, | | |
| 3074 | op_str: [*:0]const u8, | 3081 | op_str: [*:0]const u8, |
| 3075 | ) !CValue { | 3082 | ) !CValue { |
| 3076 | if (f.liveness.isUnused(inst)) | 3083 | if (f.liveness.isUnused(inst)) |
| ... | @@ -3082,15 +3089,16 @@ fn airIsErr( | ... | @@ -3082,15 +3089,16 @@ fn airIsErr( |
| 3082 | const operand_ty = f.air.typeOf(un_op); | 3089 | const operand_ty = f.air.typeOf(un_op); |
| 3083 | const local = try f.allocLocal(Type.initTag(.bool), .Const); | 3090 | const local = try f.allocLocal(Type.initTag(.bool), .Const); |
| 3084 | const payload_ty = operand_ty.errorUnionPayload(); | 3091 | const payload_ty = operand_ty.errorUnionPayload(); |
| 3085 | if (!payload_ty.hasRuntimeBits()) { | 3092 | try writer.writeAll(" = "); |
| 3086 | try writer.print(" = {s}", .{deref_prefix}); | 3093 | if (is_ptr) { |
| 3087 | try f.writeCValue(writer, operand); | 3094 | try f.writeCValueDeref(writer, operand); |
| 3088 | try writer.print(" {s} 0;\n", .{op_str}); | | |
| 3089 | } else { | 3095 | } else { |
| 3090 | try writer.writeAll(" = "); | | |
| 3091 | try f.writeCValue(writer, operand); | 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 | return local; | 3102 | return local; |
| 3095 | } | 3103 | } |
| 3096 | | 3104 | |