| ... | @@ -1072,7 +1072,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1072,7 +1072,7 @@ pub const Attribute = union(Kind) { |
| 1072 | _: std.fmt.FormatOptions, | 1072 | _: std.fmt.FormatOptions, |
| 1073 | writer: anytype, | 1073 | writer: anytype, |
| 1074 | ) @TypeOf(writer).Error!void { | 1074 | ) @TypeOf(writer).Error!void { |
| 1075 | if (comptime std.mem.indexOfNone(u8, fmt_str, "\"")) |_| | 1075 | if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_| |
| 1076 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); | 1076 | @compileError("invalid format string: '" ++ fmt_str ++ "'"); |
| 1077 | const attribute = data.attribute_index.toAttribute(data.builder); | 1077 | const attribute = data.attribute_index.toAttribute(data.builder); |
| 1078 | switch (attribute) { | 1078 | switch (attribute) { |
| ... | @@ -1154,17 +1154,72 @@ pub const Attribute = union(Kind) { | ... | @@ -1154,17 +1154,72 @@ pub const Attribute = union(Kind) { |
| 1154 | .sret, | 1154 | .sret, |
| 1155 | .elementtype, | 1155 | .elementtype, |
| 1156 | => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }), | 1156 | => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }), |
| 1157 | .@"align" => @panic("todo"), | 1157 | .@"align" => |alignment| try writer.print("{}", .{alignment}), |
| 1158 | .dereferenceable, | 1158 | .dereferenceable, |
| 1159 | .dereferenceable_or_null, | 1159 | .dereferenceable_or_null, |
| 1160 | => @panic("todo"), | 1160 | => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }), |
| 1161 | .nofpclass => @panic("todo"), | 1161 | .nofpclass => |fpclass| { |
| 1162 | .alignstack => @panic("todo"), | 1162 | const Int = @typeInfo(FpClass).Struct.backing_integer.?; |
| 1163 | .allockind => @panic("todo"), | 1163 | try writer.print("{s}(", .{@tagName(attribute)}); |
| 1164 | .allocsize => @panic("todo"), | 1164 | var any = false; |
| 1165 | .memory => @panic("todo"), | 1165 | var remaining: Int = @bitCast(fpclass); |
| 1166 | .uwtable => @panic("todo"), | 1166 | inline for (@typeInfo(FpClass).Struct.decls) |decl| { |
| 1167 | .vscale_range => @panic("todo"), | 1167 | if (!decl.is_pub) continue; |
| | 1168 | const pattern: Int = @bitCast(@field(FpClass, decl.name)); |
| | 1169 | if (remaining & pattern == pattern) { |
| | 1170 | if (!any) { |
| | 1171 | try writer.writeByte(' '); |
| | 1172 | any = true; |
| | 1173 | } |
| | 1174 | try writer.writeAll(decl.name); |
| | 1175 | remaining &= ~pattern; |
| | 1176 | } |
| | 1177 | } |
| | 1178 | try writer.writeByte(')'); |
| | 1179 | }, |
| | 1180 | .alignstack => |alignment| try writer.print( |
| | 1181 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null) |
| | 1182 | "{s}={d}" |
| | 1183 | else |
| | 1184 | "{s}({d})", |
| | 1185 | .{ @tagName(attribute), alignment.toByteUnits() orelse return }, |
| | 1186 | ), |
| | 1187 | .allockind => |allockind| { |
| | 1188 | try writer.print("{s}(\"", .{@tagName(attribute)}); |
| | 1189 | var any = false; |
| | 1190 | inline for (@typeInfo(AllocKind).Struct.fields) |field| { |
| | 1191 | if (comptime std.mem.eql(u8, field.name, "_")) continue; |
| | 1192 | if (@field(allockind, field.name)) { |
| | 1193 | if (!any) { |
| | 1194 | try writer.writeByte(','); |
| | 1195 | any = true; |
| | 1196 | } |
| | 1197 | try writer.writeAll(field.name); |
| | 1198 | } |
| | 1199 | } |
| | 1200 | try writer.writeAll("\")"); |
| | 1201 | }, |
| | 1202 | .allocsize => |allocsize| { |
| | 1203 | try writer.print("{s}({d}", .{ @tagName(attribute), allocsize.elem_size }); |
| | 1204 | if (allocsize.num_elems != AllocSize.none) |
| | 1205 | try writer.print(",{d}", .{allocsize.num_elems}); |
| | 1206 | try writer.writeByte(')'); |
| | 1207 | }, |
| | 1208 | .memory => |memory| try writer.print("{s}({s}, argmem: {s}, inaccessiblemem: {s})", .{ |
| | 1209 | @tagName(attribute), |
| | 1210 | @tagName(memory.other), |
| | 1211 | @tagName(memory.argmem), |
| | 1212 | @tagName(memory.inaccessiblemem), |
| | 1213 | }), |
| | 1214 | .uwtable => |uwtable| if (uwtable != .none) { |
| | 1215 | try writer.writeAll(@tagName(attribute)); |
| | 1216 | if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)}); |
| | 1217 | }, |
| | 1218 | .vscale_range => |vscale_range| try writer.print("{s}({d},{d})", .{ |
| | 1219 | @tagName(attribute), |
| | 1220 | vscale_range.min.toByteUnits().?, |
| | 1221 | vscale_range.max.toByteUnits() orelse 0, |
| | 1222 | }), |
| 1168 | .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) { | 1223 | .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) { |
| 1169 | try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)}); | 1224 | try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)}); |
| 1170 | if (string_attr.value != .empty) | 1225 | if (string_attr.value != .empty) |
| ... | @@ -1314,11 +1369,6 @@ pub const Attribute = union(Kind) { | ... | @@ -1314,11 +1369,6 @@ pub const Attribute = union(Kind) { |
| 1314 | positive_infinity: bool = false, | 1369 | positive_infinity: bool = false, |
| 1315 | _: u22 = 0, | 1370 | _: u22 = 0, |
| 1316 | | 1371 | |
| 1317 | pub const nan = FpClass{ .signaling_nan = true, .quiet_nan = true }; | | |
| 1318 | pub const inf = FpClass{ .negative_infinity = true, .positive_infinity = true }; | | |
| 1319 | pub const norm = FpClass{ .positive_normal = true, .negative_normal = true }; | | |
| 1320 | pub const sub = FpClass{ .positive_subnormal = true, .negative_subnormal = true }; | | |
| 1321 | pub const zero = FpClass{ .positive_zero = true, .negative_zero = true }; | | |
| 1322 | pub const all = FpClass{ | 1372 | pub const all = FpClass{ |
| 1323 | .signaling_nan = true, | 1373 | .signaling_nan = true, |
| 1324 | .quiet_nan = true, | 1374 | .quiet_nan = true, |
| ... | @@ -1331,16 +1381,26 @@ pub const Attribute = union(Kind) { | ... | @@ -1331,16 +1381,26 @@ pub const Attribute = union(Kind) { |
| 1331 | .positive_normal = true, | 1381 | .positive_normal = true, |
| 1332 | .positive_infinity = true, | 1382 | .positive_infinity = true, |
| 1333 | }; | 1383 | }; |
| | 1384 | |
| | 1385 | pub const nan = FpClass{ .signaling_nan = true, .quiet_nan = true }; |
| 1334 | pub const snan = FpClass{ .signaling_nan = true }; | 1386 | pub const snan = FpClass{ .signaling_nan = true }; |
| 1335 | pub const qnan = FpClass{ .quiet_nan = true }; | 1387 | pub const qnan = FpClass{ .quiet_nan = true }; |
| | 1388 | |
| | 1389 | pub const inf = FpClass{ .negative_infinity = true, .positive_infinity = true }; |
| 1336 | pub const ninf = FpClass{ .negative_infinity = true }; | 1390 | pub const ninf = FpClass{ .negative_infinity = true }; |
| 1337 | pub const nnorm = FpClass{ .negative_normal = true }; | 1391 | pub const pinf = FpClass{ .positive_infinity = true }; |
| 1338 | pub const nsub = FpClass{ .negative_subnormal = true }; | 1392 | |
| | 1393 | pub const zero = FpClass{ .positive_zero = true, .negative_zero = true }; |
| 1339 | pub const nzero = FpClass{ .negative_zero = true }; | 1394 | pub const nzero = FpClass{ .negative_zero = true }; |
| 1340 | pub const pzero = FpClass{ .positive_zero = true }; | 1395 | pub const pzero = FpClass{ .positive_zero = true }; |
| | 1396 | |
| | 1397 | pub const sub = FpClass{ .positive_subnormal = true, .negative_subnormal = true }; |
| | 1398 | pub const nsub = FpClass{ .negative_subnormal = true }; |
| 1341 | pub const psub = FpClass{ .positive_subnormal = true }; | 1399 | pub const psub = FpClass{ .positive_subnormal = true }; |
| | 1400 | |
| | 1401 | pub const norm = FpClass{ .positive_normal = true, .negative_normal = true }; |
| | 1402 | pub const nnorm = FpClass{ .negative_normal = true }; |
| 1342 | pub const pnorm = FpClass{ .positive_normal = true }; | 1403 | pub const pnorm = FpClass{ .positive_normal = true }; |
| 1343 | pub const pinf = FpClass{ .positive_infinity = true }; | | |
| 1344 | }; | 1404 | }; |
| 1345 | | 1405 | |
| 1346 | pub const AllocKind = packed struct(u32) { | 1406 | pub const AllocKind = packed struct(u32) { |
| ... | @@ -1924,7 +1984,7 @@ pub const CallConv = enum(u10) { | ... | @@ -1924,7 +1984,7 @@ pub const CallConv = enum(u10) { |
| 1924 | writer: anytype, | 1984 | writer: anytype, |
| 1925 | ) @TypeOf(writer).Error!void { | 1985 | ) @TypeOf(writer).Error!void { |
| 1926 | switch (self) { | 1986 | switch (self) { |
| 1927 | .ccc => {}, | 1987 | default => {}, |
| 1928 | .fastcc, | 1988 | .fastcc, |
| 1929 | .coldcc, | 1989 | .coldcc, |
| 1930 | .ghccc, | 1990 | .ghccc, |
| ... | @@ -2445,6 +2505,7 @@ pub const Function = struct { | ... | @@ -2445,6 +2505,7 @@ pub const Function = struct { |
| 2445 | .br_cond, | 2505 | .br_cond, |
| 2446 | .ret, | 2506 | .ret, |
| 2447 | .@"ret void", | 2507 | .@"ret void", |
| | 2508 | .@"switch", |
| 2448 | .@"unreachable", | 2509 | .@"unreachable", |
| 2449 | => true, | 2510 | => true, |
| 2450 | else => false, | 2511 | else => false, |
| ... | @@ -2462,6 +2523,7 @@ pub const Function = struct { | ... | @@ -2462,6 +2523,7 @@ pub const Function = struct { |
| 2462 | .@"store atomic", | 2523 | .@"store atomic", |
| 2463 | .@"store atomic volatile", | 2524 | .@"store atomic volatile", |
| 2464 | .@"store volatile", | 2525 | .@"store volatile", |
| | 2526 | .@"switch", |
| 2465 | .@"unreachable", | 2527 | .@"unreachable", |
| 2466 | => false, | 2528 | => false, |
| 2467 | .call, | 2529 | .call, |
| ... | @@ -2472,6 +2534,7 @@ pub const Function = struct { | ... | @@ -2472,6 +2534,7 @@ pub const Function = struct { |
| 2472 | .@"notail call fast", | 2534 | .@"notail call fast", |
| 2473 | .@"tail call", | 2535 | .@"tail call", |
| 2474 | .@"tail call fast", | 2536 | .@"tail call fast", |
| | 2537 | .unimplemented, |
| 2475 | => self.typeOfWip(wip) != .void, | 2538 | => self.typeOfWip(wip) != .void, |
| 2476 | else => true, | 2539 | else => true, |
| 2477 | }; | 2540 | }; |
| ... | @@ -4165,7 +4228,7 @@ pub const WipFunction = struct { | ... | @@ -4165,7 +4228,7 @@ pub const WipFunction = struct { |
| 4165 | callee: Value, | 4228 | callee: Value, |
| 4166 | args: []const Value, | 4229 | args: []const Value, |
| 4167 | name: []const u8, | 4230 | name: []const u8, |
| 4168 | ) if (build_options.have_llvm) Allocator.Error!Value else Value { | 4231 | ) Allocator.Error!Value { |
| 4169 | const ret_ty = ty.functionReturn(self.builder); | 4232 | const ret_ty = ty.functionReturn(self.builder); |
| 4170 | assert(ty.isFunction(self.builder)); | 4233 | assert(ty.isFunction(self.builder)); |
| 4171 | assert(callee.typeOfWip(self).isPointer(self.builder)); | 4234 | assert(callee.typeOfWip(self).isPointer(self.builder)); |
| ... | @@ -4238,6 +4301,20 @@ pub const WipFunction = struct { | ... | @@ -4238,6 +4301,20 @@ pub const WipFunction = struct { |
| 4238 | return instruction.toValue(); | 4301 | return instruction.toValue(); |
| 4239 | } | 4302 | } |
| 4240 | | 4303 | |
| | 4304 | pub fn callAsm( |
| | 4305 | self: *WipFunction, |
| | 4306 | function_attributes: FunctionAttributes, |
| | 4307 | ty: Type, |
| | 4308 | kind: Constant.Asm.Info, |
| | 4309 | assembly: String, |
| | 4310 | constraints: String, |
| | 4311 | args: []const Value, |
| | 4312 | name: []const u8, |
| | 4313 | ) Allocator.Error!Value { |
| | 4314 | const callee = try self.builder.asmValue(ty, kind, assembly, constraints); |
| | 4315 | return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name); |
| | 4316 | } |
| | 4317 | |
| 4241 | pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value { | 4318 | pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value { |
| 4242 | try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0); | 4319 | try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0); |
| 4243 | const instruction = try self.addInst(name, .{ | 4320 | const instruction = try self.addInst(name, .{ |
| ... | @@ -5216,7 +5293,7 @@ pub const Constant = enum(u32) { | ... | @@ -5216,7 +5293,7 @@ pub const Constant = enum(u32) { |
| 5216 | | 5293 | |
| 5217 | const first_global: Constant = @enumFromInt(1 << 30); | 5294 | const first_global: Constant = @enumFromInt(1 << 30); |
| 5218 | | 5295 | |
| 5219 | pub const Tag = enum(u6) { | 5296 | pub const Tag = enum(u7) { |
| 5220 | positive_integer, | 5297 | positive_integer, |
| 5221 | negative_integer, | 5298 | negative_integer, |
| 5222 | half, | 5299 | half, |
| ... | @@ -5276,6 +5353,22 @@ pub const Constant = enum(u32) { | ... | @@ -5276,6 +5353,22 @@ pub const Constant = enum(u32) { |
| 5276 | @"and", | 5353 | @"and", |
| 5277 | @"or", | 5354 | @"or", |
| 5278 | xor, | 5355 | xor, |
| | 5356 | @"asm", |
| | 5357 | @"asm sideeffect", |
| | 5358 | @"asm alignstack", |
| | 5359 | @"asm sideeffect alignstack", |
| | 5360 | @"asm inteldialect", |
| | 5361 | @"asm sideeffect inteldialect", |
| | 5362 | @"asm alignstack inteldialect", |
| | 5363 | @"asm sideeffect alignstack inteldialect", |
| | 5364 | @"asm unwind", |
| | 5365 | @"asm sideeffect unwind", |
| | 5366 | @"asm alignstack unwind", |
| | 5367 | @"asm sideeffect alignstack unwind", |
| | 5368 | @"asm inteldialect unwind", |
| | 5369 | @"asm sideeffect inteldialect unwind", |
| | 5370 | @"asm alignstack inteldialect unwind", |
| | 5371 | @"asm sideeffect alignstack inteldialect unwind", |
| 5279 | }; | 5372 | }; |
| 5280 | | 5373 | |
| 5281 | pub const Item = struct { | 5374 | pub const Item = struct { |
| ... | @@ -5371,6 +5464,19 @@ pub const Constant = enum(u32) { | ... | @@ -5371,6 +5464,19 @@ pub const Constant = enum(u32) { |
| 5371 | rhs: Constant, | 5464 | rhs: Constant, |
| 5372 | }; | 5465 | }; |
| 5373 | | 5466 | |
| | 5467 | pub const Asm = extern struct { |
| | 5468 | type: Type, |
| | 5469 | assembly: String, |
| | 5470 | constraints: String, |
| | 5471 | |
| | 5472 | pub const Info = packed struct { |
| | 5473 | sideeffect: bool = false, |
| | 5474 | alignstack: bool = false, |
| | 5475 | inteldialect: bool = false, |
| | 5476 | unwind: bool = false, |
| | 5477 | }; |
| | 5478 | }; |
| | 5479 | |
| 5374 | pub fn unwrap(self: Constant) union(enum) { | 5480 | pub fn unwrap(self: Constant) union(enum) { |
| 5375 | constant: u30, | 5481 | constant: u30, |
| 5376 | global: Global.Index, | 5482 | global: Global.Index, |
| ... | @@ -5489,6 +5595,23 @@ pub const Constant = enum(u32) { | ... | @@ -5489,6 +5595,23 @@ pub const Constant = enum(u32) { |
| 5489 | .@"or", | 5595 | .@"or", |
| 5490 | .xor, | 5596 | .xor, |
| 5491 | => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder), | 5597 | => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder), |
| | 5598 | .@"asm", |
| | 5599 | .@"asm sideeffect", |
| | 5600 | .@"asm alignstack", |
| | 5601 | .@"asm sideeffect alignstack", |
| | 5602 | .@"asm inteldialect", |
| | 5603 | .@"asm sideeffect inteldialect", |
| | 5604 | .@"asm alignstack inteldialect", |
| | 5605 | .@"asm sideeffect alignstack inteldialect", |
| | 5606 | .@"asm unwind", |
| | 5607 | .@"asm sideeffect unwind", |
| | 5608 | .@"asm alignstack unwind", |
| | 5609 | .@"asm sideeffect alignstack unwind", |
| | 5610 | .@"asm inteldialect unwind", |
| | 5611 | .@"asm sideeffect inteldialect unwind", |
| | 5612 | .@"asm alignstack inteldialect unwind", |
| | 5613 | .@"asm sideeffect alignstack inteldialect unwind", |
| | 5614 | => .ptr, |
| 5492 | }; | 5615 | }; |
| 5493 | }, | 5616 | }, |
| 5494 | .global => |global| return builder.ptrTypeAssumeCapacity( | 5617 | .global => |global| return builder.ptrTypeAssumeCapacity( |
| ... | @@ -5836,6 +5959,30 @@ pub const Constant = enum(u32) { | ... | @@ -5836,6 +5959,30 @@ pub const Constant = enum(u32) { |
| 5836 | extra.rhs.fmt(data.builder), | 5959 | extra.rhs.fmt(data.builder), |
| 5837 | }); | 5960 | }); |
| 5838 | }, | 5961 | }, |
| | 5962 | .@"asm", |
| | 5963 | .@"asm sideeffect", |
| | 5964 | .@"asm alignstack", |
| | 5965 | .@"asm sideeffect alignstack", |
| | 5966 | .@"asm inteldialect", |
| | 5967 | .@"asm sideeffect inteldialect", |
| | 5968 | .@"asm alignstack inteldialect", |
| | 5969 | .@"asm sideeffect alignstack inteldialect", |
| | 5970 | .@"asm unwind", |
| | 5971 | .@"asm sideeffect unwind", |
| | 5972 | .@"asm alignstack unwind", |
| | 5973 | .@"asm sideeffect alignstack unwind", |
| | 5974 | .@"asm inteldialect unwind", |
| | 5975 | .@"asm sideeffect inteldialect unwind", |
| | 5976 | .@"asm alignstack inteldialect unwind", |
| | 5977 | .@"asm sideeffect alignstack inteldialect unwind", |
| | 5978 | => |tag| { |
| | 5979 | const extra = data.builder.constantExtraData(Asm, item.data); |
| | 5980 | try writer.print("{s} {\"}, {\"}", .{ |
| | 5981 | @tagName(tag), |
| | 5982 | extra.assembly.fmt(data.builder), |
| | 5983 | extra.constraints.fmt(data.builder), |
| | 5984 | }); |
| | 5985 | }, |
| 5839 | } | 5986 | } |
| 5840 | }, | 5987 | }, |
| 5841 | .global => |global| try writer.print("{}", .{global.fmt(data.builder)}), | 5988 | .global => |global| try writer.print("{}", .{global.fmt(data.builder)}), |
| ... | @@ -6972,6 +7119,27 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant) | ... | @@ -6972,6 +7119,27 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant) |
| 6972 | return (try self.binConst(tag, lhs, rhs)).toValue(); | 7119 | return (try self.binConst(tag, lhs, rhs)).toValue(); |
| 6973 | } | 7120 | } |
| 6974 | | 7121 | |
| | 7122 | pub fn asmConst( |
| | 7123 | self: *Builder, |
| | 7124 | ty: Type, |
| | 7125 | info: Constant.Asm.Info, |
| | 7126 | assembly: String, |
| | 7127 | constraints: String, |
| | 7128 | ) Allocator.Error!Constant { |
| | 7129 | try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0); |
| | 7130 | return self.asmConstAssumeCapacity(ty, info, assembly, constraints); |
| | 7131 | } |
| | 7132 | |
| | 7133 | pub fn asmValue( |
| | 7134 | self: *Builder, |
| | 7135 | ty: Type, |
| | 7136 | info: Constant.Asm.Info, |
| | 7137 | assembly: String, |
| | 7138 | constraints: String, |
| | 7139 | ) Allocator.Error!Value { |
| | 7140 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); |
| | 7141 | } |
| | 7142 | |
| 6975 | pub fn dump(self: *Builder) void { | 7143 | pub fn dump(self: *Builder) void { |
| 6976 | if (self.useLibLlvm()) | 7144 | if (self.useLibLlvm()) |
| 6977 | self.llvm.module.?.dump() | 7145 | self.llvm.module.?.dump() |
| ... | @@ -7303,7 +7471,15 @@ pub fn printUnbuffered( | ... | @@ -7303,7 +7471,15 @@ pub fn printUnbuffered( |
| 7303 | arg.fmt(function_index, self), | 7471 | arg.fmt(function_index, self), |
| 7304 | }); | 7472 | }); |
| 7305 | } | 7473 | } |
| 7306 | try writer.print("){}\n", .{extra.data.attributes.func(self).fmt(self)}); | 7474 | try writer.writeByte(')'); |
| | 7475 | const call_function_attributes = extra.data.attributes.func(self); |
| | 7476 | if (call_function_attributes != .none) try writer.print(" #{d}", .{ |
| | 7477 | (try attribute_groups.getOrPutValue( |
| | 7478 | self.gpa, |
| | 7479 | call_function_attributes, |
| | 7480 | {}, |
| | 7481 | )).index, |
| | 7482 | }); |
| 7307 | }, | 7483 | }, |
| 7308 | .extractelement => |tag| { | 7484 | .extractelement => |tag| { |
| 7309 | const extra = | 7485 | const extra = |
| ... | @@ -7401,13 +7577,19 @@ pub fn printUnbuffered( | ... | @@ -7401,13 +7577,19 @@ pub fn printUnbuffered( |
| 7401 | => |tag| { | 7577 | => |tag| { |
| 7402 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); | 7578 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 7403 | const ty = instruction_index.typeOf(function_index, self); | 7579 | const ty = instruction_index.typeOf(function_index, self); |
| 7404 | try writer.print(" %{} = call {%} @{s}{m}({%}, {%})\n", .{ | 7580 | try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{ |
| 7405 | instruction_index.name(&function).fmt(self), | 7581 | instruction_index.name(&function).fmt(self), |
| 7406 | ty.fmt(self), | 7582 | ty.fmt(self), |
| 7407 | @tagName(tag), | 7583 | @tagName(tag), |
| 7408 | ty.fmt(self), | 7584 | ty.fmt(self), |
| 7409 | extra.lhs.fmt(function_index, self), | 7585 | extra.lhs.fmt(function_index, self), |
| 7410 | extra.rhs.fmt(function_index, self), | 7586 | extra.rhs.fmt(function_index, self), |
| | 7587 | switch (tag) { |
| | 7588 | .@"llvm.smul.fix.sat.", |
| | 7589 | .@"llvm.umul.fix.sat.", |
| | 7590 | => ", i32 0", |
| | 7591 | else => "", |
| | 7592 | }, |
| 7411 | }); | 7593 | }); |
| 7412 | }, | 7594 | }, |
| 7413 | .load, | 7595 | .load, |
| ... | @@ -7494,7 +7676,7 @@ pub fn printUnbuffered( | ... | @@ -7494,7 +7676,7 @@ pub fn printUnbuffered( |
| 7494 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); | 7676 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); |
| 7495 | const blocks = | 7677 | const blocks = |
| 7496 | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); | 7678 | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); |
| 7497 | try writer.print(" {s} {%}, {%} [", .{ | 7679 | try writer.print(" {s} {%}, {%} [\n", .{ |
| 7498 | @tagName(tag), | 7680 | @tagName(tag), |
| 7499 | extra.data.val.fmt(function_index, self), | 7681 | extra.data.val.fmt(function_index, self), |
| 7500 | extra.data.default.toInst(&function).fmt(function_index, self), | 7682 | extra.data.default.toInst(&function).fmt(function_index, self), |
| ... | @@ -7507,14 +7689,22 @@ pub fn printUnbuffered( | ... | @@ -7507,14 +7689,22 @@ pub fn printUnbuffered( |
| 7507 | }, | 7689 | }, |
| 7508 | .unimplemented => |tag| { | 7690 | .unimplemented => |tag| { |
| 7509 | const ty: Type = @enumFromInt(instruction.data); | 7691 | const ty: Type = @enumFromInt(instruction.data); |
| 7510 | try writer.writeAll(" "); | 7692 | if (true) { |
| 7511 | switch (ty) { | 7693 | try writer.writeAll(" "); |
| | 7694 | switch (ty) { |
| | 7695 | .none, .void => {}, |
| | 7696 | else => try writer.print("%{} = ", .{ |
| | 7697 | instruction_index.name(&function).fmt(self), |
| | 7698 | }), |
| | 7699 | } |
| | 7700 | try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) }); |
| | 7701 | } else switch (ty) { |
| 7512 | .none, .void => {}, | 7702 | .none, .void => {}, |
| 7513 | else => try writer.print("%{} = ", .{ | 7703 | else => try writer.print(" %{} = load {%}, ptr undef\n", .{ |
| 7514 | instruction_index.name(&function).fmt(self), | 7704 | instruction_index.name(&function).fmt(self), |
| | 7705 | ty.fmt(self), |
| 7515 | }), | 7706 | }), |
| 7516 | } | 7707 | } |
| 7517 | try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) }); | | |
| 7518 | }, | 7708 | }, |
| 7519 | .va_arg => |tag| { | 7709 | .va_arg => |tag| { |
| 7520 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); | 7710 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); |
| ... | @@ -7534,7 +7724,7 @@ pub fn printUnbuffered( | ... | @@ -7534,7 +7724,7 @@ pub fn printUnbuffered( |
| 7534 | | 7724 | |
| 7535 | for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group| | 7725 | for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group| |
| 7536 | try writer.print( | 7726 | try writer.print( |
| 7537 | \\attribute #{d} = {{{"} }} | 7727 | \\attributes #{d} = {{{#"} }} |
| 7538 | \\ | 7728 | \\ |
| 7539 | , .{ attribute_group_index, attribute_group.fmt(self) }); | 7729 | , .{ attribute_group_index, attribute_group.fmt(self) }); |
| 7540 | } | 7730 | } |
| ... | @@ -9080,30 +9270,30 @@ fn binConstAssumeCapacity( | ... | @@ -9080,30 +9270,30 @@ fn binConstAssumeCapacity( |
| 9080 | => {}, | 9270 | => {}, |
| 9081 | else => unreachable, | 9271 | else => unreachable, |
| 9082 | } | 9272 | } |
| 9083 | const Key = struct { tag: Constant.Tag, bin: Constant.Binary }; | 9273 | const Key = struct { tag: Constant.Tag, extra: Constant.Binary }; |
| 9084 | const Adapter = struct { | 9274 | const Adapter = struct { |
| 9085 | builder: *const Builder, | 9275 | builder: *const Builder, |
| 9086 | pub fn hash(_: @This(), key: Key) u32 { | 9276 | pub fn hash(_: @This(), key: Key) u32 { |
| 9087 | return @truncate(std.hash.Wyhash.hash( | 9277 | return @truncate(std.hash.Wyhash.hash( |
| 9088 | std.hash.uint32(@intFromEnum(key.tag)), | 9278 | std.hash.uint32(@intFromEnum(key.tag)), |
| 9089 | std.mem.asBytes(&key.bin), | 9279 | std.mem.asBytes(&key.extra), |
| 9090 | )); | 9280 | )); |
| 9091 | } | 9281 | } |
| 9092 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | 9282 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 9093 | if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; | 9283 | if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; |
| 9094 | const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; | 9284 | const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; |
| 9095 | const rhs_extra = ctx.builder.constantExtraData(Constant.Binary, rhs_data); | 9285 | const rhs_extra = ctx.builder.constantExtraData(Constant.Binary, rhs_data); |
| 9096 | return std.meta.eql(lhs_key.bin, rhs_extra); | 9286 | return std.meta.eql(lhs_key.extra, rhs_extra); |
| 9097 | } | 9287 | } |
| 9098 | }; | 9288 | }; |
| 9099 | const data = Key{ .tag = tag, .bin = .{ .lhs = lhs, .rhs = rhs } }; | 9289 | const data = Key{ .tag = tag, .extra = .{ .lhs = lhs, .rhs = rhs } }; |
| 9100 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); | 9290 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| 9101 | if (!gop.found_existing) { | 9291 | if (!gop.found_existing) { |
| 9102 | gop.key_ptr.* = {}; | 9292 | gop.key_ptr.* = {}; |
| 9103 | gop.value_ptr.* = {}; | 9293 | gop.value_ptr.* = {}; |
| 9104 | self.constant_items.appendAssumeCapacity(.{ | 9294 | self.constant_items.appendAssumeCapacity(.{ |
| 9105 | .tag = tag, | 9295 | .tag = tag, |
| 9106 | .data = self.addConstantExtraAssumeCapacity(data.bin), | 9296 | .data = self.addConstantExtraAssumeCapacity(data.extra), |
| 9107 | }); | 9297 | }); |
| 9108 | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) { | 9298 | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity(switch (tag) { |
| 9109 | .add => &llvm.Value.constAdd, | 9299 | .add => &llvm.Value.constAdd, |
| ... | @@ -9121,6 +9311,61 @@ fn binConstAssumeCapacity( | ... | @@ -9121,6 +9311,61 @@ fn binConstAssumeCapacity( |
| 9121 | return @enumFromInt(gop.index); | 9311 | return @enumFromInt(gop.index); |
| 9122 | } | 9312 | } |
| 9123 | | 9313 | |
| | 9314 | fn asmConstAssumeCapacity( |
| | 9315 | self: *Builder, |
| | 9316 | ty: Type, |
| | 9317 | info: Constant.Asm.Info, |
| | 9318 | assembly: String, |
| | 9319 | constraints: String, |
| | 9320 | ) Constant { |
| | 9321 | const Key = struct { tag: Constant.Tag, extra: Constant.Asm }; |
| | 9322 | const Adapter = struct { |
| | 9323 | builder: *const Builder, |
| | 9324 | pub fn hash(_: @This(), key: Key) u32 { |
| | 9325 | return @truncate(std.hash.Wyhash.hash( |
| | 9326 | std.hash.uint32(@intFromEnum(key.tag)), |
| | 9327 | std.mem.asBytes(&key.extra), |
| | 9328 | )); |
| | 9329 | } |
| | 9330 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| | 9331 | if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; |
| | 9332 | const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; |
| | 9333 | const rhs_extra = ctx.builder.constantExtraData(Constant.Asm, rhs_data); |
| | 9334 | return std.meta.eql(lhs_key.extra, rhs_extra); |
| | 9335 | } |
| | 9336 | }; |
| | 9337 | |
| | 9338 | const data = Key{ |
| | 9339 | .tag = @enumFromInt(@intFromEnum(Constant.Tag.@"asm") + @as(u4, @bitCast(info))), |
| | 9340 | .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints }, |
| | 9341 | }; |
| | 9342 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| | 9343 | if (!gop.found_existing) { |
| | 9344 | gop.key_ptr.* = {}; |
| | 9345 | gop.value_ptr.* = {}; |
| | 9346 | self.constant_items.appendAssumeCapacity(.{ |
| | 9347 | .tag = data.tag, |
| | 9348 | .data = self.addConstantExtraAssumeCapacity(data.extra), |
| | 9349 | }); |
| | 9350 | if (self.useLibLlvm()) { |
| | 9351 | const assembly_slice = assembly.slice(self).?; |
| | 9352 | const constraints_slice = constraints.slice(self).?; |
| | 9353 | self.llvm.constants.appendAssumeCapacity(llvm.getInlineAsm( |
| | 9354 | ty.toLlvm(self), |
| | 9355 | assembly_slice.ptr, |
| | 9356 | assembly_slice.len, |
| | 9357 | constraints_slice.ptr, |
| | 9358 | constraints_slice.len, |
| | 9359 | llvm.Bool.fromBool(info.sideeffect), |
| | 9360 | llvm.Bool.fromBool(info.alignstack), |
| | 9361 | if (info.inteldialect) .Intel else .ATT, |
| | 9362 | llvm.Bool.fromBool(info.unwind), |
| | 9363 | )); |
| | 9364 | } |
| | 9365 | } |
| | 9366 | return @enumFromInt(gop.index); |
| | 9367 | } |
| | 9368 | |
| 9124 | fn ensureUnusedConstantCapacity( | 9369 | fn ensureUnusedConstantCapacity( |
| 9125 | self: *Builder, | 9370 | self: *Builder, |
| 9126 | count: usize, | 9371 | count: usize, |
| ... | @@ -9211,7 +9456,7 @@ fn addConstantExtraAssumeCapacity(self: *Builder, extra: anytype) Constant.Item. | ... | @@ -9211,7 +9456,7 @@ fn addConstantExtraAssumeCapacity(self: *Builder, extra: anytype) Constant.Item. |
| 9211 | const value = @field(extra, field.name); | 9456 | const value = @field(extra, field.name); |
| 9212 | self.constant_extra.appendAssumeCapacity(switch (field.type) { | 9457 | self.constant_extra.appendAssumeCapacity(switch (field.type) { |
| 9213 | u32 => value, | 9458 | u32 => value, |
| 9214 | Type, Constant, Function.Index, Function.Block.Index => @intFromEnum(value), | 9459 | String, Type, Constant, Function.Index, Function.Block.Index => @intFromEnum(value), |
| 9215 | Constant.GetElementPtr.Info => @bitCast(value), | 9460 | Constant.GetElementPtr.Info => @bitCast(value), |
| 9216 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 9461 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 9217 | }); | 9462 | }); |
| ... | @@ -9250,7 +9495,7 @@ fn constantExtraDataTrail( | ... | @@ -9250,7 +9495,7 @@ fn constantExtraDataTrail( |
| 9250 | inline for (fields, self.constant_extra.items[index..][0..fields.len]) |field, value| | 9495 | inline for (fields, self.constant_extra.items[index..][0..fields.len]) |field, value| |
| 9251 | @field(result, field.name) = switch (field.type) { | 9496 | @field(result, field.name) = switch (field.type) { |
| 9252 | u32 => value, | 9497 | u32 => value, |
| 9253 | Type, Constant, Function.Index, Function.Block.Index => @enumFromInt(value), | 9498 | String, Type, Constant, Function.Index, Function.Block.Index => @enumFromInt(value), |
| 9254 | Constant.GetElementPtr.Info => @bitCast(value), | 9499 | Constant.GetElementPtr.Info => @bitCast(value), |
| 9255 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 9500 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 9256 | }; | 9501 | }; |