| author | |
| committer | |
| log | cd7998096b624b326dddcbb2752fe4bcdac8df9f |
| tree | 3a67b92da2378f614bc52bf23133bcf22b5a5c4b |
| parent | d34201c8491007c5a24b4175a5170a5b6cc3d55e |
| parent | 3e1dd93bb2ac7e9d99fb340f1f4ca6868a52cb6b |
| signature |
llvm: convert more things to use Builder
* finish converting intrinsics
* finish converting attributes
* finish converting instructions
* finish converting globals
* pass behavior tests with no dependence on the llvm api (`-fno-libllvm`)6 files changed, 4018 insertions(+), 3498 deletions(-)
src/codegen/llvm.zig+927-1583| ... | ... | @@ -764,7 +764,6 @@ pub const Object = struct { |
| 764 | 764 | builder: Builder, |
| 765 | 765 | |
| 766 | 766 | module: *Module, |
| 767 | llvm_module: *llvm.Module, | |
| 768 | 767 | di_builder: ?*llvm.DIBuilder, |
| 769 | 768 | /// One of these mappings: |
| 770 | 769 | /// - *Module.File => *DIFile |
| ... | ... | @@ -824,7 +823,7 @@ pub const Object = struct { |
| 824 | 823 | var builder = try Builder.init(.{ |
| 825 | 824 | .allocator = gpa, |
| 826 | 825 | .use_lib_llvm = options.use_lib_llvm, |
| 827 | .strip = options.strip, | |
| 826 | .strip = options.strip or !options.use_lib_llvm, // TODO | |
| 828 | 827 | .name = options.root_name, |
| 829 | 828 | .target = options.target, |
| 830 | 829 | .triple = llvm_target_triple, |
| ... | ... | @@ -945,9 +944,8 @@ pub const Object = struct { |
| 945 | 944 | .gpa = gpa, |
| 946 | 945 | .builder = builder, |
| 947 | 946 | .module = options.module.?, |
| 948 | .llvm_module = builder.llvm.module.?, | |
| 949 | 947 | .di_map = .{}, |
| 950 | .di_builder = builder.llvm.di_builder, | |
| 948 | .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO | |
| 951 | 949 | .di_compile_unit = builder.llvm.di_compile_unit, |
| 952 | 950 | .target_machine = target_machine, |
| 953 | 951 | .target_data = target_data, |
| ... | ... | @@ -963,14 +961,17 @@ pub const Object = struct { |
| 963 | 961 | } |
| 964 | 962 | |
| 965 | 963 | pub fn deinit(self: *Object, gpa: Allocator) void { |
| 966 | self.di_map.deinit(gpa); | |
| 967 | self.di_type_map.deinit(gpa); | |
| 968 | self.target_data.dispose(); | |
| 969 | self.target_machine.dispose(); | |
| 964 | if (self.builder.useLibLlvm()) { | |
| 965 | self.di_map.deinit(gpa); | |
| 966 | self.di_type_map.deinit(gpa); | |
| 967 | self.target_data.dispose(); | |
| 968 | self.target_machine.dispose(); | |
| 969 | } | |
| 970 | 970 | self.decl_map.deinit(gpa); |
| 971 | 971 | self.named_enum_map.deinit(gpa); |
| 972 | 972 | self.type_map.deinit(gpa); |
| 973 | 973 | self.extern_collisions.deinit(gpa); |
| 974 | self.builder.deinit(); | |
| 974 | 975 | self.* = undefined; |
| 975 | 976 | } |
| 976 | 977 | |
| ... | ... | @@ -991,9 +992,8 @@ pub const Object = struct { |
| 991 | 992 | } |
| 992 | 993 | |
| 993 | 994 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| 994 | // If o.error_name_table is null, there was no instruction that actually referenced the error table. | |
| 995 | const error_name_table_ptr_global = o.error_name_table; | |
| 996 | if (error_name_table_ptr_global == .none) return; | |
| 995 | // If o.error_name_table is null, then it was not referenced by any instructions. | |
| 996 | if (o.error_name_table == .none) return; | |
| 997 | 997 | |
| 998 | 998 | const mod = o.module; |
| 999 | 999 | |
| ... | ... | @@ -1003,72 +1003,42 @@ pub const Object = struct { |
| 1003 | 1003 | |
| 1004 | 1004 | // TODO: Address space |
| 1005 | 1005 | const slice_ty = Type.slice_const_u8_sentinel_0; |
| 1006 | const slice_alignment = slice_ty.abiAlignment(mod); | |
| 1007 | 1006 | const llvm_usize_ty = try o.lowerType(Type.usize); |
| 1008 | 1007 | const llvm_slice_ty = try o.lowerType(slice_ty); |
| 1009 | 1008 | const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty); |
| 1010 | 1009 | |
| 1011 | 1010 | llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty); |
| 1012 | for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| { | |
| 1013 | const name = try o.builder.string(mod.intern_pool.stringToSlice(name_nts)); | |
| 1014 | const str_init = try o.builder.stringNullConst(name); | |
| 1015 | const str_ty = str_init.typeOf(&o.builder); | |
| 1016 | const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), ""); | |
| 1017 | str_llvm_global.setInitializer(str_init.toLlvm(&o.builder)); | |
| 1018 | str_llvm_global.setLinkage(.Private); | |
| 1019 | str_llvm_global.setGlobalConstant(.True); | |
| 1020 | str_llvm_global.setUnnamedAddr(.True); | |
| 1021 | str_llvm_global.setAlignment(1); | |
| 1022 | ||
| 1023 | var str_global = Builder.Global{ | |
| 1024 | .linkage = .private, | |
| 1025 | .unnamed_addr = .unnamed_addr, | |
| 1026 | .type = str_ty, | |
| 1027 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 1028 | }; | |
| 1029 | var str_variable = Builder.Variable{ | |
| 1030 | .global = @enumFromInt(o.builder.globals.count()), | |
| 1031 | .mutability = .constant, | |
| 1032 | .init = str_init, | |
| 1033 | .alignment = comptime Builder.Alignment.fromByteUnits(1), | |
| 1034 | }; | |
| 1035 | try o.builder.llvm.globals.append(o.gpa, str_llvm_global); | |
| 1036 | const global_index = try o.builder.addGlobal(.empty, str_global); | |
| 1037 | try o.builder.variables.append(o.gpa, str_variable); | |
| 1011 | for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| { | |
| 1012 | const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name)); | |
| 1013 | const name_init = try o.builder.stringNullConst(name_string); | |
| 1014 | const name_variable_index = | |
| 1015 | try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); | |
| 1016 | try name_variable_index.setInitializer(name_init, &o.builder); | |
| 1017 | name_variable_index.setLinkage(.private, &o.builder); | |
| 1018 | name_variable_index.setMutability(.constant, &o.builder); | |
| 1019 | name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 1020 | name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); | |
| 1038 | 1021 | |
| 1039 | 1022 | llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ |
| 1040 | global_index.toConst(), | |
| 1041 | try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len), | |
| 1023 | name_variable_index.toConst(&o.builder), | |
| 1024 | try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len), | |
| 1042 | 1025 | }); |
| 1043 | 1026 | } |
| 1044 | 1027 | |
| 1045 | const error_name_table_init = try o.builder.arrayConst(llvm_table_ty, llvm_errors); | |
| 1046 | const error_name_table_global = o.llvm_module.addGlobal(llvm_table_ty.toLlvm(&o.builder), ""); | |
| 1047 | error_name_table_global.setInitializer(error_name_table_init.toLlvm(&o.builder)); | |
| 1048 | error_name_table_global.setLinkage(.Private); | |
| 1049 | error_name_table_global.setGlobalConstant(.True); | |
| 1050 | error_name_table_global.setUnnamedAddr(.True); | |
| 1051 | error_name_table_global.setAlignment(slice_alignment); // TODO: Dont hardcode | |
| 1052 | ||
| 1053 | var global = Builder.Global{ | |
| 1054 | .linkage = .private, | |
| 1055 | .unnamed_addr = .unnamed_addr, | |
| 1056 | .type = llvm_table_ty, | |
| 1057 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 1058 | }; | |
| 1059 | var variable = Builder.Variable{ | |
| 1060 | .global = @enumFromInt(o.builder.globals.count()), | |
| 1061 | .mutability = .constant, | |
| 1062 | .init = error_name_table_init, | |
| 1063 | .alignment = Builder.Alignment.fromByteUnits(slice_alignment), | |
| 1064 | }; | |
| 1065 | try o.builder.llvm.globals.append(o.gpa, error_name_table_global); | |
| 1066 | _ = try o.builder.addGlobal(.empty, global); | |
| 1067 | try o.builder.variables.append(o.gpa, variable); | |
| 1028 | const table_variable_index = try o.builder.addVariable(.empty, llvm_table_ty, .default); | |
| 1029 | try table_variable_index.setInitializer( | |
| 1030 | try o.builder.arrayConst(llvm_table_ty, llvm_errors), | |
| 1031 | &o.builder, | |
| 1032 | ); | |
| 1033 | table_variable_index.setLinkage(.private, &o.builder); | |
| 1034 | table_variable_index.setMutability(.constant, &o.builder); | |
| 1035 | table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 1036 | table_variable_index.setAlignment( | |
| 1037 | Builder.Alignment.fromByteUnits(slice_ty.abiAlignment(mod)), | |
| 1038 | &o.builder, | |
| 1039 | ); | |
| 1068 | 1040 | |
| 1069 | const error_name_table_ptr = error_name_table_global; | |
| 1070 | error_name_table_ptr_global.ptr(&o.builder).init = variable.global.toConst(); | |
| 1071 | error_name_table_ptr_global.toLlvm(&o.builder).setInitializer(error_name_table_ptr); | |
| 1041 | try o.error_name_table.setInitializer(table_variable_index.toConst(&o.builder), &o.builder); | |
| 1072 | 1042 | } |
| 1073 | 1043 | |
| 1074 | 1044 | fn genCmpLtErrorsLenFunction(o: *Object) !void { |
| ... | ... | @@ -1112,7 +1082,8 @@ pub const Object = struct { |
| 1112 | 1082 | // Same logic as below but for externs instead of exports. |
| 1113 | 1083 | const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue; |
| 1114 | 1084 | const other_global = object.builder.getGlobal(decl_name) orelse continue; |
| 1115 | if (other_global.eql(global, &object.builder)) continue; | |
| 1085 | if (other_global.toConst().getBase(&object.builder) == | |
| 1086 | global.toConst().getBase(&object.builder)) continue; | |
| 1116 | 1087 | |
| 1117 | 1088 | try global.replace(other_global, &object.builder); |
| 1118 | 1089 | } |
| ... | ... | @@ -1120,13 +1091,14 @@ pub const Object = struct { |
| 1120 | 1091 | |
| 1121 | 1092 | for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| { |
| 1122 | 1093 | const global = object.decl_map.get(decl_index) orelse continue; |
| 1094 | const global_base = global.toConst().getBase(&object.builder); | |
| 1123 | 1095 | for (export_list.items) |exp| { |
| 1124 | 1096 | // Detect if the LLVM global has already been created as an extern. In such |
| 1125 | 1097 | // case, we need to replace all uses of it with this exported global. |
| 1126 | 1098 | const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue; |
| 1127 | 1099 | |
| 1128 | 1100 | const other_global = object.builder.getGlobal(exp_name) orelse continue; |
| 1129 | if (other_global.eql(global, &object.builder)) continue; | |
| 1101 | if (other_global.toConst().getBase(&object.builder) == global_base) continue; | |
| 1130 | 1102 | |
| 1131 | 1103 | try global.takeName(other_global, &object.builder); |
| 1132 | 1104 | try other_global.replace(global, &object.builder); |
| ... | ... | @@ -1181,17 +1153,7 @@ pub const Object = struct { |
| 1181 | 1153 | } |
| 1182 | 1154 | } |
| 1183 | 1155 | |
| 1184 | if (comp.verbose_llvm_bc) |path| { | |
| 1185 | const path_z = try comp.gpa.dupeZ(u8, path); | |
| 1186 | defer comp.gpa.free(path_z); | |
| 1187 | ||
| 1188 | const error_code = self.llvm_module.writeBitcodeToFile(path_z); | |
| 1189 | if (error_code != 0) { | |
| 1190 | log.err("dump LLVM module failed bc={s}: {d}", .{ | |
| 1191 | path, error_code, | |
| 1192 | }); | |
| 1193 | } | |
| 1194 | } | |
| 1156 | if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path); | |
| 1195 | 1157 | |
| 1196 | 1158 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); |
| 1197 | 1159 | defer arena_allocator.deinit(); |
| ... | ... | @@ -1200,20 +1162,10 @@ pub const Object = struct { |
| 1200 | 1162 | const mod = comp.bin_file.options.module.?; |
| 1201 | 1163 | const cache_dir = mod.zig_cache_artifact_directory; |
| 1202 | 1164 | |
| 1203 | if (std.debug.runtime_safety) { | |
| 1204 | var error_message: [*:0]const u8 = undefined; | |
| 1205 | // verifyModule always allocs the error_message even if there is no error | |
| 1206 | defer llvm.disposeMessage(error_message); | |
| 1207 | ||
| 1208 | if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) { | |
| 1209 | std.debug.print("\n{s}\n", .{error_message}); | |
| 1210 | ||
| 1211 | if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| { | |
| 1212 | _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message); | |
| 1213 | } | |
| 1214 | ||
| 1215 | @panic("LLVM module verification failed"); | |
| 1216 | } | |
| 1165 | if (std.debug.runtime_safety and !try self.builder.verify()) { | |
| 1166 | if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| | |
| 1167 | _ = self.builder.printToFileZ(emit_llvm_ir_path); | |
| 1168 | @panic("LLVM module verification failed"); | |
| 1217 | 1169 | } |
| 1218 | 1170 | |
| 1219 | 1171 | var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| |
| ... | ... | @@ -1233,12 +1185,20 @@ pub const Object = struct { |
| 1233 | 1185 | emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, |
| 1234 | 1186 | }); |
| 1235 | 1187 | |
| 1188 | if (emit_asm_path == null and emit_bin_path == null and | |
| 1189 | emit_llvm_ir_path == null and emit_llvm_bc_path == null) return; | |
| 1190 | ||
| 1191 | if (!self.builder.useLibLlvm()) { | |
| 1192 | log.err("emitting without libllvm not implemented", .{}); | |
| 1193 | return error.FailedToEmit; | |
| 1194 | } | |
| 1195 | ||
| 1236 | 1196 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 1237 | 1197 | // So we call the entire pipeline multiple times if this is requested. |
| 1238 | 1198 | var error_message: [*:0]const u8 = undefined; |
| 1239 | 1199 | if (emit_asm_path != null and emit_bin_path != null) { |
| 1240 | 1200 | if (self.target_machine.emitToFile( |
| 1241 | self.llvm_module, | |
| 1201 | self.builder.llvm.module.?, | |
| 1242 | 1202 | &error_message, |
| 1243 | 1203 | comp.bin_file.options.optimize_mode == .Debug, |
| 1244 | 1204 | comp.bin_file.options.optimize_mode == .ReleaseSmall, |
| ... | ... | @@ -1262,7 +1222,7 @@ pub const Object = struct { |
| 1262 | 1222 | } |
| 1263 | 1223 | |
| 1264 | 1224 | if (self.target_machine.emitToFile( |
| 1265 | self.llvm_module, | |
| 1225 | self.builder.llvm.module.?, | |
| 1266 | 1226 | &error_message, |
| 1267 | 1227 | comp.bin_file.options.optimize_mode == .Debug, |
| 1268 | 1228 | comp.bin_file.options.optimize_mode == .ReleaseSmall, |
| ... | ... | @@ -1305,37 +1265,28 @@ pub const Object = struct { |
| 1305 | 1265 | .err_msg = null, |
| 1306 | 1266 | }; |
| 1307 | 1267 | |
| 1308 | const function = try o.resolveLlvmFunction(decl_index); | |
| 1309 | const global = function.ptrConst(&o.builder).global; | |
| 1310 | const llvm_func = global.toLlvm(&o.builder); | |
| 1268 | const function_index = try o.resolveLlvmFunction(decl_index); | |
| 1311 | 1269 | |
| 1312 | var attributes = try function.ptrConst(&o.builder).attributes.toWip(&o.builder); | |
| 1270 | var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); | |
| 1313 | 1271 | defer attributes.deinit(&o.builder); |
| 1314 | 1272 | |
| 1315 | 1273 | if (func.analysis(ip).is_noinline) { |
| 1316 | 1274 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1317 | o.addFnAttr(llvm_func, "noinline"); | |
| 1318 | 1275 | } else { |
| 1319 | 1276 | _ = try attributes.removeFnAttr(.@"noinline"); |
| 1320 | Object.removeFnAttr(llvm_func, "noinline"); | |
| 1321 | 1277 | } |
| 1322 | 1278 | |
| 1323 | 1279 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { |
| 1324 | 1280 | try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder); |
| 1325 | 1281 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1326 | o.addFnAttrInt(llvm_func, "alignstack", alignment); | |
| 1327 | o.addFnAttr(llvm_func, "noinline"); | |
| 1328 | 1282 | } else { |
| 1329 | 1283 | _ = try attributes.removeFnAttr(.alignstack); |
| 1330 | Object.removeFnAttr(llvm_func, "alignstack"); | |
| 1331 | 1284 | } |
| 1332 | 1285 | |
| 1333 | 1286 | if (func.analysis(ip).is_cold) { |
| 1334 | 1287 | try attributes.addFnAttr(.cold, &o.builder); |
| 1335 | o.addFnAttr(llvm_func, "cold"); | |
| 1336 | 1288 | } else { |
| 1337 | 1289 | _ = try attributes.removeFnAttr(.cold); |
| 1338 | Object.removeFnAttr(llvm_func, "cold"); | |
| 1339 | 1290 | } |
| 1340 | 1291 | |
| 1341 | 1292 | // TODO: disable this if safety is off for the function scope |
| ... | ... | @@ -1346,10 +1297,6 @@ pub const Object = struct { |
| 1346 | 1297 | .kind = try o.builder.string("stack-protector-buffer-size"), |
| 1347 | 1298 | .value = try o.builder.fmt("{d}", .{ssp_buf_size}), |
| 1348 | 1299 | } }, &o.builder); |
| 1349 | var buf: [12]u8 = undefined; | |
| 1350 | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; | |
| 1351 | o.addFnAttr(llvm_func, "sspstrong"); | |
| 1352 | o.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg); | |
| 1353 | 1300 | } |
| 1354 | 1301 | |
| 1355 | 1302 | // TODO: disable this if safety is off for the function scope |
| ... | ... | @@ -1358,26 +1305,21 @@ pub const Object = struct { |
| 1358 | 1305 | .kind = try o.builder.string("probe-stack"), |
| 1359 | 1306 | .value = try o.builder.string("__zig_probe_stack"), |
| 1360 | 1307 | } }, &o.builder); |
| 1361 | o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); | |
| 1362 | 1308 | } else if (target.os.tag == .uefi) { |
| 1363 | 1309 | try attributes.addFnAttr(.{ .string = .{ |
| 1364 | 1310 | .kind = try o.builder.string("no-stack-arg-probe"), |
| 1365 | 1311 | .value = .empty, |
| 1366 | 1312 | } }, &o.builder); |
| 1367 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); | |
| 1368 | 1313 | } |
| 1369 | 1314 | |
| 1370 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| { | |
| 1371 | function.ptr(&o.builder).section = try o.builder.string(section); | |
| 1372 | llvm_func.setSection(section); | |
| 1373 | } | |
| 1315 | if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| | |
| 1316 | function_index.setSection(try o.builder.string(section), &o.builder); | |
| 1374 | 1317 | |
| 1375 | 1318 | var deinit_wip = true; |
| 1376 | var wip = try Builder.WipFunction.init(&o.builder, function); | |
| 1319 | var wip = try Builder.WipFunction.init(&o.builder, function_index); | |
| 1377 | 1320 | defer if (deinit_wip) wip.deinit(); |
| 1378 | 1321 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 1379 | 1322 | |
| 1380 | const builder = wip.llvm.builder; | |
| 1381 | 1323 | var llvm_arg_i: u32 = 0; |
| 1382 | 1324 | |
| 1383 | 1325 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| ... | ... | @@ -1389,14 +1331,8 @@ pub const Object = struct { |
| 1389 | 1331 | } else .none; |
| 1390 | 1332 | |
| 1391 | 1333 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { |
| 1392 | .signed => { | |
| 1393 | try attributes.addRetAttr(.signext, &o.builder); | |
| 1394 | o.addAttr(llvm_func, 0, "signext"); | |
| 1395 | }, | |
| 1396 | .unsigned => { | |
| 1397 | try attributes.addRetAttr(.zeroext, &o.builder); | |
| 1398 | o.addAttr(llvm_func, 0, "zeroext"); | |
| 1399 | }, | |
| 1334 | .signed => try attributes.addRetAttr(.signext, &o.builder), | |
| 1335 | .unsigned => try attributes.addRetAttr(.zeroext, &o.builder), | |
| 1400 | 1336 | }; |
| 1401 | 1337 | |
| 1402 | 1338 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and |
| ... | ... | @@ -1437,7 +1373,7 @@ pub const Object = struct { |
| 1437 | 1373 | } else { |
| 1438 | 1374 | args.appendAssumeCapacity(param); |
| 1439 | 1375 | |
| 1440 | try o.addByValParamAttrsOld(&attributes, llvm_func, param_ty, param_index, fn_info, llvm_arg_i); | |
| 1376 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, llvm_arg_i); | |
| 1441 | 1377 | } |
| 1442 | 1378 | llvm_arg_i += 1; |
| 1443 | 1379 | }, |
| ... | ... | @@ -1447,7 +1383,7 @@ pub const Object = struct { |
| 1447 | 1383 | const param = wip.arg(llvm_arg_i); |
| 1448 | 1384 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1449 | 1385 | |
| 1450 | try o.addByRefParamAttrsOld(&attributes, llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); | |
| 1386 | try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); | |
| 1451 | 1387 | llvm_arg_i += 1; |
| 1452 | 1388 | |
| 1453 | 1389 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -1463,7 +1399,6 @@ pub const Object = struct { |
| 1463 | 1399 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1464 | 1400 | |
| 1465 | 1401 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| 1466 | o.addArgAttr(llvm_func, llvm_arg_i, "noundef"); | |
| 1467 | 1402 | llvm_arg_i += 1; |
| 1468 | 1403 | |
| 1469 | 1404 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -1479,11 +1414,7 @@ pub const Object = struct { |
| 1479 | 1414 | llvm_arg_i += 1; |
| 1480 | 1415 | |
| 1481 | 1416 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1482 | const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(mod) * 8)); | |
| 1483 | const alignment = Builder.Alignment.fromByteUnits(@max( | |
| 1484 | param_ty.abiAlignment(mod), | |
| 1485 | o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)), | |
| 1486 | )); | |
| 1417 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | |
| 1487 | 1418 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1488 | 1419 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1489 | 1420 | |
| ... | ... | @@ -1500,23 +1431,19 @@ pub const Object = struct { |
| 1500 | 1431 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1501 | 1432 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1502 | 1433 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 1503 | o.addArgAttr(llvm_func, llvm_arg_i, "noalias"); | |
| 1504 | 1434 | } |
| 1505 | 1435 | } |
| 1506 | 1436 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1507 | 1437 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 1508 | o.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); | |
| 1509 | 1438 | } |
| 1510 | 1439 | if (ptr_info.flags.is_const) { |
| 1511 | 1440 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 1512 | o.addArgAttr(llvm_func, llvm_arg_i, "readonly"); | |
| 1513 | 1441 | } |
| 1514 | 1442 | const elem_align = Builder.Alignment.fromByteUnits( |
| 1515 | 1443 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 1516 | 1444 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| 1517 | 1445 | ); |
| 1518 | 1446 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1519 | o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); | |
| 1520 | 1447 | const ptr_param = wip.arg(llvm_arg_i); |
| 1521 | 1448 | llvm_arg_i += 1; |
| 1522 | 1449 | const len_param = wip.arg(llvm_arg_i); |
| ... | ... | @@ -1590,7 +1517,7 @@ pub const Object = struct { |
| 1590 | 1517 | } |
| 1591 | 1518 | } |
| 1592 | 1519 | |
| 1593 | function.ptr(&o.builder).attributes = try attributes.finish(&o.builder); | |
| 1520 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 1594 | 1521 | |
| 1595 | 1522 | var di_file: ?*llvm.DIFile = null; |
| 1596 | 1523 | var di_scope: ?*llvm.DIScope = null; |
| ... | ... | @@ -1609,7 +1536,7 @@ pub const Object = struct { |
| 1609 | 1536 | const subprogram = dib.createFunction( |
| 1610 | 1537 | di_file.?.toScope(), |
| 1611 | 1538 | ip.stringToSlice(decl.name), |
| 1612 | llvm_func.getValueName(), | |
| 1539 | function_index.name(&o.builder).slice(&o.builder).?, | |
| 1613 | 1540 | di_file.?, |
| 1614 | 1541 | line_number, |
| 1615 | 1542 | decl_di_ty, |
| ... | ... | @@ -1622,7 +1549,7 @@ pub const Object = struct { |
| 1622 | 1549 | ); |
| 1623 | 1550 | try o.di_map.put(gpa, decl, subprogram.toNode()); |
| 1624 | 1551 | |
| 1625 | llvm_func.fnSetSubprogram(subprogram); | |
| 1552 | function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram); | |
| 1626 | 1553 | |
| 1627 | 1554 | di_scope = subprogram.toScope(); |
| 1628 | 1555 | } |
| ... | ... | @@ -1633,7 +1560,6 @@ pub const Object = struct { |
| 1633 | 1560 | .liveness = liveness, |
| 1634 | 1561 | .dg = &dg, |
| 1635 | 1562 | .wip = wip, |
| 1636 | .builder = builder, | |
| 1637 | 1563 | .ret_ptr = ret_ptr, |
| 1638 | 1564 | .args = args.items, |
| 1639 | 1565 | .arg_index = 0, |
| ... | ... | @@ -1694,8 +1620,7 @@ pub const Object = struct { |
| 1694 | 1620 | const gpa = mod.gpa; |
| 1695 | 1621 | // If the module does not already have the function, we ignore this function call |
| 1696 | 1622 | // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`. |
| 1697 | const global = self.decl_map.get(decl_index) orelse return; | |
| 1698 | const llvm_global = global.toLlvm(&self.builder); | |
| 1623 | const global_index = self.decl_map.get(decl_index) orelse return; | |
| 1699 | 1624 | const decl = mod.declPtr(decl_index); |
| 1700 | 1625 | if (decl.isExtern(mod)) { |
| 1701 | 1626 | const decl_name = decl_name: { |
| ... | ... | @@ -1713,114 +1638,91 @@ pub const Object = struct { |
| 1713 | 1638 | }; |
| 1714 | 1639 | |
| 1715 | 1640 | if (self.builder.getGlobal(decl_name)) |other_global| { |
| 1716 | if (other_global.toLlvm(&self.builder) != llvm_global) { | |
| 1641 | if (other_global != global_index) { | |
| 1717 | 1642 | try self.extern_collisions.put(gpa, decl_index, {}); |
| 1718 | 1643 | } |
| 1719 | 1644 | } |
| 1720 | 1645 | |
| 1721 | try global.rename(decl_name, &self.builder); | |
| 1722 | global.ptr(&self.builder).unnamed_addr = .default; | |
| 1723 | llvm_global.setUnnamedAddr(.False); | |
| 1724 | global.ptr(&self.builder).linkage = .external; | |
| 1725 | llvm_global.setLinkage(.External); | |
| 1726 | if (mod.wantDllExports()) { | |
| 1727 | global.ptr(&self.builder).dll_storage_class = .default; | |
| 1728 | llvm_global.setDLLStorageClass(.Default); | |
| 1729 | } | |
| 1646 | try global_index.rename(decl_name, &self.builder); | |
| 1647 | global_index.setLinkage(.external, &self.builder); | |
| 1648 | global_index.setUnnamedAddr(.default, &self.builder); | |
| 1649 | if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); | |
| 1730 | 1650 | if (self.di_map.get(decl)) |di_node| { |
| 1731 | 1651 | const decl_name_slice = decl_name.slice(&self.builder).?; |
| 1732 | 1652 | if (try decl.isFunction(mod)) { |
| 1733 | 1653 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1734 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len); | |
| 1654 | const linkage_name = llvm.MDString.get( | |
| 1655 | self.builder.llvm.context, | |
| 1656 | decl_name_slice.ptr, | |
| 1657 | decl_name_slice.len, | |
| 1658 | ); | |
| 1735 | 1659 | di_func.replaceLinkageName(linkage_name); |
| 1736 | 1660 | } else { |
| 1737 | 1661 | const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node); |
| 1738 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len); | |
| 1662 | const linkage_name = llvm.MDString.get( | |
| 1663 | self.builder.llvm.context, | |
| 1664 | decl_name_slice.ptr, | |
| 1665 | decl_name_slice.len, | |
| 1666 | ); | |
| 1739 | 1667 | di_global.replaceLinkageName(linkage_name); |
| 1740 | 1668 | } |
| 1741 | 1669 | } |
| 1742 | 1670 | if (decl.val.getVariable(mod)) |decl_var| { |
| 1743 | if (decl_var.is_threadlocal) { | |
| 1744 | global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local = | |
| 1745 | .generaldynamic; | |
| 1746 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | |
| 1747 | } else { | |
| 1748 | global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local = | |
| 1749 | .default; | |
| 1750 | llvm_global.setThreadLocalMode(.NotThreadLocal); | |
| 1751 | } | |
| 1752 | if (decl_var.is_weak_linkage) { | |
| 1753 | global.ptr(&self.builder).linkage = .extern_weak; | |
| 1754 | llvm_global.setLinkage(.ExternalWeak); | |
| 1755 | } | |
| 1671 | global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( | |
| 1672 | if (decl_var.is_threadlocal) .generaldynamic else .default, | |
| 1673 | &self.builder, | |
| 1674 | ); | |
| 1675 | if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder); | |
| 1756 | 1676 | } |
| 1757 | global.ptr(&self.builder).updateAttributes(); | |
| 1758 | 1677 | } else if (exports.len != 0) { |
| 1759 | const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exports[0].opts.name)); | |
| 1760 | try global.rename(exp_name, &self.builder); | |
| 1761 | global.ptr(&self.builder).unnamed_addr = .default; | |
| 1762 | llvm_global.setUnnamedAddr(.False); | |
| 1763 | if (mod.wantDllExports()) { | |
| 1764 | global.ptr(&self.builder).dll_storage_class = .dllexport; | |
| 1765 | llvm_global.setDLLStorageClass(.DLLExport); | |
| 1766 | } | |
| 1678 | const main_exp_name = try self.builder.string( | |
| 1679 | mod.intern_pool.stringToSlice(exports[0].opts.name), | |
| 1680 | ); | |
| 1681 | try global_index.rename(main_exp_name, &self.builder); | |
| 1682 | global_index.setUnnamedAddr(.default, &self.builder); | |
| 1683 | if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &self.builder); | |
| 1767 | 1684 | if (self.di_map.get(decl)) |di_node| { |
| 1768 | const exp_name_slice = exp_name.slice(&self.builder).?; | |
| 1685 | const main_exp_name_slice = main_exp_name.slice(&self.builder).?; | |
| 1769 | 1686 | if (try decl.isFunction(mod)) { |
| 1770 | 1687 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1771 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len); | |
| 1688 | const linkage_name = llvm.MDString.get( | |
| 1689 | self.builder.llvm.context, | |
| 1690 | main_exp_name_slice.ptr, | |
| 1691 | main_exp_name_slice.len, | |
| 1692 | ); | |
| 1772 | 1693 | di_func.replaceLinkageName(linkage_name); |
| 1773 | 1694 | } else { |
| 1774 | 1695 | const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node); |
| 1775 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len); | |
| 1696 | const linkage_name = llvm.MDString.get( | |
| 1697 | self.builder.llvm.context, | |
| 1698 | main_exp_name_slice.ptr, | |
| 1699 | main_exp_name_slice.len, | |
| 1700 | ); | |
| 1776 | 1701 | di_global.replaceLinkageName(linkage_name); |
| 1777 | 1702 | } |
| 1778 | 1703 | } |
| 1779 | switch (exports[0].opts.linkage) { | |
| 1704 | global_index.setLinkage(switch (exports[0].opts.linkage) { | |
| 1780 | 1705 | .Internal => unreachable, |
| 1781 | .Strong => { | |
| 1782 | global.ptr(&self.builder).linkage = .external; | |
| 1783 | llvm_global.setLinkage(.External); | |
| 1784 | }, | |
| 1785 | .Weak => { | |
| 1786 | global.ptr(&self.builder).linkage = .weak_odr; | |
| 1787 | llvm_global.setLinkage(.WeakODR); | |
| 1788 | }, | |
| 1789 | .LinkOnce => { | |
| 1790 | global.ptr(&self.builder).linkage = .linkonce_odr; | |
| 1791 | llvm_global.setLinkage(.LinkOnceODR); | |
| 1792 | }, | |
| 1793 | } | |
| 1794 | switch (exports[0].opts.visibility) { | |
| 1795 | .default => { | |
| 1796 | global.ptr(&self.builder).visibility = .default; | |
| 1797 | llvm_global.setVisibility(.Default); | |
| 1798 | }, | |
| 1799 | .hidden => { | |
| 1800 | global.ptr(&self.builder).visibility = .hidden; | |
| 1801 | llvm_global.setVisibility(.Hidden); | |
| 1802 | }, | |
| 1803 | .protected => { | |
| 1804 | global.ptr(&self.builder).visibility = .protected; | |
| 1805 | llvm_global.setVisibility(.Protected); | |
| 1806 | }, | |
| 1807 | } | |
| 1808 | if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| { | |
| 1809 | switch (global.ptrConst(&self.builder).kind) { | |
| 1810 | inline .variable, .function => |impl_index| impl_index.ptr(&self.builder).section = | |
| 1706 | .Strong => .external, | |
| 1707 | .Weak => .weak_odr, | |
| 1708 | .LinkOnce => .linkonce_odr, | |
| 1709 | }, &self.builder); | |
| 1710 | global_index.setVisibility(switch (exports[0].opts.visibility) { | |
| 1711 | .default => .default, | |
| 1712 | .hidden => .hidden, | |
| 1713 | .protected => .protected, | |
| 1714 | }, &self.builder); | |
| 1715 | if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| | |
| 1716 | switch (global_index.ptrConst(&self.builder).kind) { | |
| 1717 | inline .variable, .function => |impl_index| impl_index.setSection( | |
| 1811 | 1718 | try self.builder.string(section), |
| 1812 | else => unreachable, | |
| 1813 | } | |
| 1814 | llvm_global.setSection(section); | |
| 1815 | } | |
| 1816 | if (decl.val.getVariable(mod)) |decl_var| { | |
| 1817 | if (decl_var.is_threadlocal) { | |
| 1818 | global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local = | |
| 1819 | .generaldynamic; | |
| 1820 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | |
| 1821 | } | |
| 1822 | } | |
| 1823 | global.ptr(&self.builder).updateAttributes(); | |
| 1719 | &self.builder, | |
| 1720 | ), | |
| 1721 | .alias, .replaced => unreachable, | |
| 1722 | }; | |
| 1723 | if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal) | |
| 1724 | global_index.ptrConst(&self.builder).kind | |
| 1725 | .variable.setThreadLocal(.generaldynamic, &self.builder); | |
| 1824 | 1726 | |
| 1825 | 1727 | // If a Decl is exported more than one time (which is rare), |
| 1826 | 1728 | // we add aliases for all but the first export. |
| ... | ... | @@ -1829,49 +1731,48 @@ pub const Object = struct { |
| 1829 | 1731 | // Until then we iterate over existing aliases and make them point |
| 1830 | 1732 | // to the correct decl, or otherwise add a new alias. Old aliases are leaked. |
| 1831 | 1733 | for (exports[1..]) |exp| { |
| 1832 | const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name); | |
| 1833 | ||
| 1834 | if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| { | |
| 1835 | alias.setAliasee(llvm_global); | |
| 1836 | } else { | |
| 1837 | _ = self.llvm_module.addAlias( | |
| 1838 | global.ptrConst(&self.builder).type.toLlvm(&self.builder), | |
| 1839 | 0, | |
| 1840 | llvm_global, | |
| 1841 | exp_name_z, | |
| 1842 | ); | |
| 1734 | const exp_name = try self.builder.string(mod.intern_pool.stringToSlice(exp.opts.name)); | |
| 1735 | if (self.builder.getGlobal(exp_name)) |global| { | |
| 1736 | switch (global.ptrConst(&self.builder).kind) { | |
| 1737 | .alias => |alias| { | |
| 1738 | alias.setAliasee(global_index.toConst(), &self.builder); | |
| 1739 | continue; | |
| 1740 | }, | |
| 1741 | .variable, .function => {}, | |
| 1742 | .replaced => unreachable, | |
| 1743 | } | |
| 1843 | 1744 | } |
| 1745 | const alias_index = try self.builder.addAlias( | |
| 1746 | .empty, | |
| 1747 | global_index.typeOf(&self.builder), | |
| 1748 | .default, | |
| 1749 | global_index.toConst(), | |
| 1750 | ); | |
| 1751 | try alias_index.rename(exp_name, &self.builder); | |
| 1844 | 1752 | } |
| 1845 | 1753 | } else { |
| 1846 | const fqn = try self.builder.string(mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod))); | |
| 1847 | try global.rename(fqn, &self.builder); | |
| 1848 | global.ptr(&self.builder).linkage = .internal; | |
| 1849 | llvm_global.setLinkage(.Internal); | |
| 1850 | if (mod.wantDllExports()) { | |
| 1851 | global.ptr(&self.builder).dll_storage_class = .default; | |
| 1852 | llvm_global.setDLLStorageClass(.Default); | |
| 1853 | } | |
| 1854 | global.ptr(&self.builder).unnamed_addr = .unnamed_addr; | |
| 1855 | llvm_global.setUnnamedAddr(.True); | |
| 1754 | const fqn = try self.builder.string( | |
| 1755 | mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)), | |
| 1756 | ); | |
| 1757 | try global_index.rename(fqn, &self.builder); | |
| 1758 | global_index.setLinkage(.internal, &self.builder); | |
| 1759 | if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); | |
| 1760 | global_index.setUnnamedAddr(.unnamed_addr, &self.builder); | |
| 1856 | 1761 | if (decl.val.getVariable(mod)) |decl_var| { |
| 1857 | const single_threaded = mod.comp.bin_file.options.single_threaded; | |
| 1858 | if (decl_var.is_threadlocal and !single_threaded) { | |
| 1859 | global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local = | |
| 1860 | .generaldynamic; | |
| 1861 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | |
| 1862 | } else { | |
| 1863 | global.ptrConst(&self.builder).kind.variable.ptr(&self.builder).thread_local = | |
| 1864 | .default; | |
| 1865 | llvm_global.setThreadLocalMode(.NotThreadLocal); | |
| 1866 | } | |
| 1762 | global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( | |
| 1763 | if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded) | |
| 1764 | .generaldynamic | |
| 1765 | else | |
| 1766 | .default, | |
| 1767 | &self.builder, | |
| 1768 | ); | |
| 1867 | 1769 | } |
| 1868 | global.ptr(&self.builder).updateAttributes(); | |
| 1869 | 1770 | } |
| 1870 | 1771 | } |
| 1871 | 1772 | |
| 1872 | 1773 | pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void { |
| 1873 | 1774 | const global = self.decl_map.get(decl_index) orelse return; |
| 1874 | global.toLlvm(&self.builder).deleteGlobal(); | |
| 1775 | global.delete(&self.builder); | |
| 1875 | 1776 | } |
| 1876 | 1777 | |
| 1877 | 1778 | fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile { |
| ... | ... | @@ -2907,8 +2808,12 @@ pub const Object = struct { |
| 2907 | 2808 | /// If the llvm function does not exist, create it. |
| 2908 | 2809 | /// Note that this can be called before the function's semantic analysis has |
| 2909 | 2810 | /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. |
| 2910 | fn resolveLlvmFunction(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Function.Index { | |
| 2811 | fn resolveLlvmFunction( | |
| 2812 | o: *Object, | |
| 2813 | decl_index: Module.Decl.Index, | |
| 2814 | ) Allocator.Error!Builder.Function.Index { | |
| 2911 | 2815 | const mod = o.module; |
| 2816 | const ip = &mod.intern_pool; | |
| 2912 | 2817 | const gpa = o.gpa; |
| 2913 | 2818 | const decl = mod.declPtr(decl_index); |
| 2914 | 2819 | const zig_fn_type = decl.ty; |
| ... | ... | @@ -2920,46 +2825,31 @@ pub const Object = struct { |
| 2920 | 2825 | const target = mod.getTarget(); |
| 2921 | 2826 | const sret = firstParamSRet(fn_info, mod); |
| 2922 | 2827 | |
| 2923 | const fn_type = try o.lowerType(zig_fn_type); | |
| 2924 | ||
| 2925 | const ip = &mod.intern_pool; | |
| 2926 | const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))); | |
| 2927 | ||
| 2928 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | |
| 2929 | const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.slice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace)); | |
| 2930 | ||
| 2931 | var global = Builder.Global{ | |
| 2932 | .type = fn_type, | |
| 2933 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | |
| 2934 | }; | |
| 2935 | var function = Builder.Function{ | |
| 2936 | .global = @enumFromInt(o.builder.globals.count()), | |
| 2937 | }; | |
| 2828 | const function_index = try o.builder.addFunction( | |
| 2829 | try o.lowerType(zig_fn_type), | |
| 2830 | try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))), | |
| 2831 | toLlvmAddressSpace(decl.@"addrspace", target), | |
| 2832 | ); | |
| 2833 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; | |
| 2938 | 2834 | |
| 2939 | 2835 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 2940 | 2836 | defer attributes.deinit(&o.builder); |
| 2941 | 2837 | |
| 2942 | 2838 | const is_extern = decl.isExtern(mod); |
| 2943 | 2839 | if (!is_extern) { |
| 2944 | global.linkage = .internal; | |
| 2945 | llvm_fn.setLinkage(.Internal); | |
| 2946 | global.unnamed_addr = .unnamed_addr; | |
| 2947 | llvm_fn.setUnnamedAddr(.True); | |
| 2840 | function_index.setLinkage(.internal, &o.builder); | |
| 2841 | function_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 2948 | 2842 | } else { |
| 2949 | 2843 | if (target.isWasm()) { |
| 2950 | 2844 | try attributes.addFnAttr(.{ .string = .{ |
| 2951 | 2845 | .kind = try o.builder.string("wasm-import-name"), |
| 2952 | 2846 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| 2953 | 2847 | } }, &o.builder); |
| 2954 | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); | |
| 2955 | 2848 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2956 | if (!std.mem.eql(u8, lib_name, "c")) { | |
| 2957 | try attributes.addFnAttr(.{ .string = .{ | |
| 2958 | .kind = try o.builder.string("wasm-import-module"), | |
| 2959 | .value = try o.builder.string(lib_name), | |
| 2960 | } }, &o.builder); | |
| 2961 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); | |
| 2962 | } | |
| 2849 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ | |
| 2850 | .kind = try o.builder.string("wasm-import-module"), | |
| 2851 | .value = try o.builder.string(lib_name), | |
| 2852 | } }, &o.builder); | |
| 2963 | 2853 | } |
| 2964 | 2854 | } |
| 2965 | 2855 | } |
| ... | ... | @@ -2969,12 +2859,9 @@ pub const Object = struct { |
| 2969 | 2859 | // Sret pointers must not be address 0 |
| 2970 | 2860 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2971 | 2861 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 2972 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); // Sret pointers must not be address 0 | |
| 2973 | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); | |
| 2974 | 2862 | |
| 2975 | 2863 | const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); |
| 2976 | 2864 | try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder); |
| 2977 | llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder)); | |
| 2978 | 2865 | |
| 2979 | 2866 | llvm_arg_i += 1; |
| 2980 | 2867 | } |
| ... | ... | @@ -2984,42 +2871,26 @@ pub const Object = struct { |
| 2984 | 2871 | |
| 2985 | 2872 | if (err_return_tracing) { |
| 2986 | 2873 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 2987 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | |
| 2988 | 2874 | llvm_arg_i += 1; |
| 2989 | 2875 | } |
| 2990 | 2876 | |
| 2991 | 2877 | switch (fn_info.cc) { |
| 2992 | .Unspecified, .Inline => { | |
| 2993 | function.call_conv = .fastcc; | |
| 2994 | llvm_fn.setFunctionCallConv(.Fast); | |
| 2995 | }, | |
| 2996 | .Naked => { | |
| 2997 | try attributes.addFnAttr(.naked, &o.builder); | |
| 2998 | o.addFnAttr(llvm_fn, "naked"); | |
| 2999 | }, | |
| 2878 | .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder), | |
| 2879 | .Naked => try attributes.addFnAttr(.naked, &o.builder), | |
| 3000 | 2880 | .Async => { |
| 3001 | function.call_conv = .fastcc; | |
| 3002 | llvm_fn.setFunctionCallConv(.Fast); | |
| 2881 | function_index.setCallConv(.fastcc, &o.builder); | |
| 3003 | 2882 | @panic("TODO: LLVM backend lower async function"); |
| 3004 | 2883 | }, |
| 3005 | else => { | |
| 3006 | function.call_conv = toLlvmCallConv(fn_info.cc, target); | |
| 3007 | llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv))); | |
| 3008 | }, | |
| 2884 | else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder), | |
| 3009 | 2885 | } |
| 3010 | 2886 | |
| 3011 | if (fn_info.alignment.toByteUnitsOptional()) |a| { | |
| 3012 | function.alignment = Builder.Alignment.fromByteUnits(a); | |
| 3013 | llvm_fn.setAlignment(@intCast(a)); | |
| 3014 | } | |
| 2887 | if (fn_info.alignment.toByteUnitsOptional()) |alignment| | |
| 2888 | function_index.setAlignment(Builder.Alignment.fromByteUnits(alignment), &o.builder); | |
| 3015 | 2889 | |
| 3016 | 2890 | // Function attributes that are independent of analysis results of the function body. |
| 3017 | try o.addCommonFnAttributes(&attributes, llvm_fn); | |
| 2891 | try o.addCommonFnAttributes(&attributes); | |
| 3018 | 2892 | |
| 3019 | if (fn_info.return_type == .noreturn_type) { | |
| 3020 | try attributes.addFnAttr(.noreturn, &o.builder); | |
| 3021 | o.addFnAttr(llvm_fn, "noreturn"); | |
| 3022 | } | |
| 2893 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); | |
| 3023 | 2894 | |
| 3024 | 2895 | // Add parameter attributes. We handle only the case of extern functions (no body) |
| 3025 | 2896 | // because functions with bodies are handled in `updateFunc`. |
| ... | ... | @@ -3031,7 +2902,7 @@ pub const Object = struct { |
| 3031 | 2902 | const param_index = it.zig_index - 1; |
| 3032 | 2903 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 3033 | 2904 | if (!isByRef(param_ty, mod)) { |
| 3034 | try o.addByValParamAttrsOld(&attributes, llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); | |
| 2905 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); | |
| 3035 | 2906 | } |
| 3036 | 2907 | }, |
| 3037 | 2908 | .byref => { |
| ... | ... | @@ -3039,12 +2910,9 @@ pub const Object = struct { |
| 3039 | 2910 | const param_llvm_ty = try o.lowerType(param_ty.toType()); |
| 3040 | 2911 | const alignment = |
| 3041 | 2912 | Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod)); |
| 3042 | try o.addByRefParamAttrsOld(&attributes, llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | |
| 3043 | }, | |
| 3044 | .byref_mut => { | |
| 3045 | try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder); | |
| 3046 | o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); | |
| 2913 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | |
| 3047 | 2914 | }, |
| 2915 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), | |
| 3048 | 2916 | // No attributes needed for these. |
| 3049 | 2917 | .no_bits, |
| 3050 | 2918 | .abi_sized_int, |
| ... | ... | @@ -3060,43 +2928,33 @@ pub const Object = struct { |
| 3060 | 2928 | }; |
| 3061 | 2929 | } |
| 3062 | 2930 | |
| 3063 | function.attributes = try attributes.finish(&o.builder); | |
| 3064 | ||
| 3065 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); | |
| 3066 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); | |
| 3067 | try o.builder.functions.append(o.gpa, function); | |
| 3068 | return global.kind.function; | |
| 2931 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 2932 | return function_index; | |
| 3069 | 2933 | } |
| 3070 | 2934 | |
| 3071 | 2935 | fn addCommonFnAttributes( |
| 3072 | 2936 | o: *Object, |
| 3073 | 2937 | attributes: *Builder.FunctionAttributes.Wip, |
| 3074 | llvm_fn: *llvm.Value, | |
| 3075 | 2938 | ) Allocator.Error!void { |
| 3076 | 2939 | const comp = o.module.comp; |
| 3077 | 2940 | |
| 3078 | 2941 | if (!comp.bin_file.options.red_zone) { |
| 3079 | 2942 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 3080 | o.addFnAttr(llvm_fn, "noredzone"); | |
| 3081 | 2943 | } |
| 3082 | 2944 | if (comp.bin_file.options.omit_frame_pointer) { |
| 3083 | 2945 | try attributes.addFnAttr(.{ .string = .{ |
| 3084 | 2946 | .kind = try o.builder.string("frame-pointer"), |
| 3085 | 2947 | .value = try o.builder.string("none"), |
| 3086 | 2948 | } }, &o.builder); |
| 3087 | o.addFnAttrString(llvm_fn, "frame-pointer", "none"); | |
| 3088 | 2949 | } else { |
| 3089 | 2950 | try attributes.addFnAttr(.{ .string = .{ |
| 3090 | 2951 | .kind = try o.builder.string("frame-pointer"), |
| 3091 | 2952 | .value = try o.builder.string("all"), |
| 3092 | 2953 | } }, &o.builder); |
| 3093 | o.addFnAttrString(llvm_fn, "frame-pointer", "all"); | |
| 3094 | 2954 | } |
| 3095 | 2955 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 3096 | o.addFnAttr(llvm_fn, "nounwind"); | |
| 3097 | 2956 | if (comp.unwind_tables) { |
| 3098 | 2957 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 3099 | o.addFnAttrInt(llvm_fn, "uwtable", 2); | |
| 3100 | 2958 | } |
| 3101 | 2959 | if (comp.bin_file.options.skip_linker_dependencies or |
| 3102 | 2960 | comp.bin_file.options.no_builtin) |
| ... | ... | @@ -3107,111 +2965,78 @@ pub const Object = struct { |
| 3107 | 2965 | // body of memcpy with a call to memcpy, which would then cause a stack |
| 3108 | 2966 | // overflow instead of performing memcpy. |
| 3109 | 2967 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 3110 | o.addFnAttr(llvm_fn, "nobuiltin"); | |
| 3111 | 2968 | } |
| 3112 | 2969 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { |
| 3113 | 2970 | try attributes.addFnAttr(.minsize, &o.builder); |
| 3114 | 2971 | try attributes.addFnAttr(.optsize, &o.builder); |
| 3115 | o.addFnAttr(llvm_fn, "minsize"); | |
| 3116 | o.addFnAttr(llvm_fn, "optsize"); | |
| 3117 | 2972 | } |
| 3118 | 2973 | if (comp.bin_file.options.tsan) { |
| 3119 | 2974 | try attributes.addFnAttr(.sanitize_thread, &o.builder); |
| 3120 | o.addFnAttr(llvm_fn, "sanitize_thread"); | |
| 3121 | 2975 | } |
| 3122 | 2976 | if (comp.getTarget().cpu.model.llvm_name) |s| { |
| 3123 | 2977 | try attributes.addFnAttr(.{ .string = .{ |
| 3124 | 2978 | .kind = try o.builder.string("target-cpu"), |
| 3125 | 2979 | .value = try o.builder.string(s), |
| 3126 | 2980 | } }, &o.builder); |
| 3127 | llvm_fn.addFunctionAttr("target-cpu", s); | |
| 3128 | 2981 | } |
| 3129 | 2982 | if (comp.bin_file.options.llvm_cpu_features) |s| { |
| 3130 | 2983 | try attributes.addFnAttr(.{ .string = .{ |
| 3131 | 2984 | .kind = try o.builder.string("target-features"), |
| 3132 | 2985 | .value = try o.builder.string(std.mem.span(s)), |
| 3133 | 2986 | } }, &o.builder); |
| 3134 | llvm_fn.addFunctionAttr("target-features", s); | |
| 3135 | 2987 | } |
| 3136 | 2988 | if (comp.getTarget().cpu.arch.isBpf()) { |
| 3137 | 2989 | try attributes.addFnAttr(.{ .string = .{ |
| 3138 | 2990 | .kind = try o.builder.string("no-builtins"), |
| 3139 | 2991 | .value = .empty, |
| 3140 | 2992 | } }, &o.builder); |
| 3141 | llvm_fn.addFunctionAttr("no-builtins", ""); | |
| 3142 | 2993 | } |
| 3143 | 2994 | } |
| 3144 | 2995 | |
| 3145 | fn resolveGlobalDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Variable.Index { | |
| 2996 | fn resolveGlobalDecl( | |
| 2997 | o: *Object, | |
| 2998 | decl_index: Module.Decl.Index, | |
| 2999 | ) Allocator.Error!Builder.Variable.Index { | |
| 3146 | 3000 | const gop = try o.decl_map.getOrPut(o.gpa, decl_index); |
| 3147 | 3001 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; |
| 3148 | 3002 | errdefer assert(o.decl_map.remove(decl_index)); |
| 3149 | 3003 | |
| 3150 | 3004 | const mod = o.module; |
| 3151 | 3005 | const decl = mod.declPtr(decl_index); |
| 3152 | const fqn = try o.builder.string(mod.intern_pool.stringToSlice( | |
| 3153 | try decl.getFullyQualifiedName(mod), | |
| 3154 | )); | |
| 3155 | ||
| 3156 | const target = mod.getTarget(); | |
| 3157 | ||
| 3158 | var global = Builder.Global{ | |
| 3159 | .addr_space = toLlvmGlobalAddressSpace(decl.@"addrspace", target), | |
| 3160 | .type = try o.lowerType(decl.ty), | |
| 3161 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 3162 | }; | |
| 3163 | var variable = Builder.Variable{ | |
| 3164 | .global = @enumFromInt(o.builder.globals.count()), | |
| 3165 | }; | |
| 3166 | ||
| 3167 | 3006 | const is_extern = decl.isExtern(mod); |
| 3168 | const name = if (is_extern) | |
| 3169 | try o.builder.string(mod.intern_pool.stringToSlice(decl.name)) | |
| 3170 | else | |
| 3171 | fqn; | |
| 3172 | const llvm_global = o.llvm_module.addGlobalInAddressSpace( | |
| 3173 | global.type.toLlvm(&o.builder), | |
| 3174 | fqn.slice(&o.builder).?, | |
| 3175 | @intFromEnum(global.addr_space), | |
| 3007 | ||
| 3008 | const variable_index = try o.builder.addVariable( | |
| 3009 | try o.builder.string(mod.intern_pool.stringToSlice( | |
| 3010 | if (is_extern) decl.name else try decl.getFullyQualifiedName(mod), | |
| 3011 | )), | |
| 3012 | try o.lowerType(decl.ty), | |
| 3013 | toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()), | |
| 3176 | 3014 | ); |
| 3015 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; | |
| 3177 | 3016 | |
| 3178 | 3017 | // This is needed for declarations created by `@extern`. |
| 3179 | 3018 | if (is_extern) { |
| 3180 | global.unnamed_addr = .default; | |
| 3181 | llvm_global.setUnnamedAddr(.False); | |
| 3182 | global.linkage = .external; | |
| 3183 | llvm_global.setLinkage(.External); | |
| 3019 | variable_index.setLinkage(.external, &o.builder); | |
| 3020 | variable_index.setUnnamedAddr(.default, &o.builder); | |
| 3184 | 3021 | if (decl.val.getVariable(mod)) |decl_var| { |
| 3185 | 3022 | const single_threaded = mod.comp.bin_file.options.single_threaded; |
| 3186 | if (decl_var.is_threadlocal and !single_threaded) { | |
| 3187 | variable.thread_local = .generaldynamic; | |
| 3188 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | |
| 3189 | } else { | |
| 3190 | variable.thread_local = .default; | |
| 3191 | llvm_global.setThreadLocalMode(.NotThreadLocal); | |
| 3192 | } | |
| 3193 | if (decl_var.is_weak_linkage) { | |
| 3194 | global.linkage = .extern_weak; | |
| 3195 | llvm_global.setLinkage(.ExternalWeak); | |
| 3196 | } | |
| 3023 | variable_index.setThreadLocal( | |
| 3024 | if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, | |
| 3025 | &o.builder, | |
| 3026 | ); | |
| 3027 | if (decl_var.is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); | |
| 3197 | 3028 | } |
| 3198 | 3029 | } else { |
| 3199 | global.linkage = .internal; | |
| 3200 | llvm_global.setLinkage(.Internal); | |
| 3201 | global.unnamed_addr = .unnamed_addr; | |
| 3202 | llvm_global.setUnnamedAddr(.True); | |
| 3030 | variable_index.setLinkage(.internal, &o.builder); | |
| 3031 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 3203 | 3032 | } |
| 3204 | ||
| 3205 | try o.builder.llvm.globals.append(o.gpa, llvm_global); | |
| 3206 | gop.value_ptr.* = try o.builder.addGlobal(name, global); | |
| 3207 | try o.builder.variables.append(o.gpa, variable); | |
| 3208 | return global.kind.variable; | |
| 3033 | return variable_index; | |
| 3209 | 3034 | } |
| 3210 | 3035 | |
| 3211 | 3036 | fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type { |
| 3212 | 3037 | const ty = try o.lowerTypeInner(t); |
| 3213 | 3038 | const mod = o.module; |
| 3214 | if (std.debug.runtime_safety and false) check: { | |
| 3039 | if (std.debug.runtime_safety and o.builder.useLibLlvm() and false) check: { | |
| 3215 | 3040 | const llvm_ty = ty.toLlvm(&o.builder); |
| 3216 | 3041 | if (t.zigTypeTag(mod) == .Opaque) break :check; |
| 3217 | 3042 | if (!t.hasRuntimeBits(mod)) break :check; |
| ... | ... | @@ -4483,69 +4308,6 @@ pub const Object = struct { |
| 4483 | 4308 | return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty); |
| 4484 | 4309 | } |
| 4485 | 4310 | |
| 4486 | fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { | |
| 4487 | return o.addAttrInt(val, index, name, 0); | |
| 4488 | } | |
| 4489 | ||
| 4490 | fn addArgAttr(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void { | |
| 4491 | return o.addAttr(fn_val, param_index + 1, attr_name); | |
| 4492 | } | |
| 4493 | ||
| 4494 | fn addArgAttrInt(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void { | |
| 4495 | return o.addAttrInt(fn_val, param_index + 1, attr_name, int); | |
| 4496 | } | |
| 4497 | ||
| 4498 | fn removeAttr(val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { | |
| 4499 | const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); | |
| 4500 | assert(kind_id != 0); | |
| 4501 | val.removeEnumAttributeAtIndex(index, kind_id); | |
| 4502 | } | |
| 4503 | ||
| 4504 | fn addAttrInt( | |
| 4505 | o: *Object, | |
| 4506 | val: *llvm.Value, | |
| 4507 | index: llvm.AttributeIndex, | |
| 4508 | name: []const u8, | |
| 4509 | int: u64, | |
| 4510 | ) void { | |
| 4511 | const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); | |
| 4512 | assert(kind_id != 0); | |
| 4513 | const llvm_attr = o.builder.llvm.context.createEnumAttribute(kind_id, int); | |
| 4514 | val.addAttributeAtIndex(index, llvm_attr); | |
| 4515 | } | |
| 4516 | ||
| 4517 | fn addAttrString( | |
| 4518 | o: *Object, | |
| 4519 | val: *llvm.Value, | |
| 4520 | index: llvm.AttributeIndex, | |
| 4521 | name: []const u8, | |
| 4522 | value: []const u8, | |
| 4523 | ) void { | |
| 4524 | const llvm_attr = o.builder.llvm.context.createStringAttribute( | |
| 4525 | name.ptr, | |
| 4526 | @intCast(name.len), | |
| 4527 | value.ptr, | |
| 4528 | @intCast(value.len), | |
| 4529 | ); | |
| 4530 | val.addAttributeAtIndex(index, llvm_attr); | |
| 4531 | } | |
| 4532 | ||
| 4533 | fn addFnAttr(o: *Object, val: *llvm.Value, name: []const u8) void { | |
| 4534 | o.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name); | |
| 4535 | } | |
| 4536 | ||
| 4537 | fn addFnAttrString(o: *Object, val: *llvm.Value, name: []const u8, value: []const u8) void { | |
| 4538 | o.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value); | |
| 4539 | } | |
| 4540 | ||
| 4541 | fn removeFnAttr(fn_val: *llvm.Value, name: []const u8) void { | |
| 4542 | removeAttr(fn_val, std.math.maxInt(llvm.AttributeIndex), name); | |
| 4543 | } | |
| 4544 | ||
| 4545 | fn addFnAttrInt(o: *Object, fn_val: *llvm.Value, name: []const u8, int: u64) void { | |
| 4546 | return o.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int); | |
| 4547 | } | |
| 4548 | ||
| 4549 | 4311 | /// If the operand type of an atomic operation is not byte sized we need to |
| 4550 | 4312 | /// widen it before using it and then truncate the result. |
| 4551 | 4313 | /// RMW exchange of floating-point values is bitcasted to same-sized integer |
| ... | ... | @@ -4608,80 +4370,13 @@ pub const Object = struct { |
| 4608 | 4370 | attributes: *Builder.FunctionAttributes.Wip, |
| 4609 | 4371 | llvm_arg_i: u32, |
| 4610 | 4372 | alignment: Builder.Alignment, |
| 4611 | byval_attr: bool, | |
| 4612 | param_llvm_ty: Builder.Type, | |
| 4613 | ) Allocator.Error!void { | |
| 4614 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | |
| 4615 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); | |
| 4616 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); | |
| 4617 | if (byval_attr) { | |
| 4618 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); | |
| 4619 | } | |
| 4620 | } | |
| 4621 | ||
| 4622 | fn addByValParamAttrsOld( | |
| 4623 | o: *Object, | |
| 4624 | attributes: *Builder.FunctionAttributes.Wip, | |
| 4625 | llvm_fn: *llvm.Value, | |
| 4626 | param_ty: Type, | |
| 4627 | param_index: u32, | |
| 4628 | fn_info: InternPool.Key.FuncType, | |
| 4629 | llvm_arg_i: u32, | |
| 4630 | ) Allocator.Error!void { | |
| 4631 | const mod = o.module; | |
| 4632 | if (param_ty.isPtrAtRuntime(mod)) { | |
| 4633 | const ptr_info = param_ty.ptrInfo(mod); | |
| 4634 | if (math.cast(u5, param_index)) |i| { | |
| 4635 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | |
| 4636 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); | |
| 4637 | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); | |
| 4638 | } | |
| 4639 | } | |
| 4640 | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { | |
| 4641 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | |
| 4642 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | |
| 4643 | } | |
| 4644 | if (ptr_info.flags.is_const) { | |
| 4645 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); | |
| 4646 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); | |
| 4647 | } | |
| 4648 | const elem_align = Builder.Alignment.fromByteUnits( | |
| 4649 | ptr_info.flags.alignment.toByteUnitsOptional() orelse | |
| 4650 | @max(ptr_info.child.toType().abiAlignment(mod), 1), | |
| 4651 | ); | |
| 4652 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); | |
| 4653 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); | |
| 4654 | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { | |
| 4655 | .signed => { | |
| 4656 | try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder); | |
| 4657 | o.addArgAttr(llvm_fn, llvm_arg_i, "signext"); | |
| 4658 | }, | |
| 4659 | .unsigned => { | |
| 4660 | try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder); | |
| 4661 | o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"); | |
| 4662 | }, | |
| 4663 | }; | |
| 4664 | } | |
| 4665 | ||
| 4666 | fn addByRefParamAttrsOld( | |
| 4667 | o: *Object, | |
| 4668 | attributes: *Builder.FunctionAttributes.Wip, | |
| 4669 | llvm_fn: *llvm.Value, | |
| 4670 | llvm_arg_i: u32, | |
| 4671 | alignment: Builder.Alignment, | |
| 4672 | byval_attr: bool, | |
| 4373 | byval: bool, | |
| 4673 | 4374 | param_llvm_ty: Builder.Type, |
| 4674 | 4375 | ) Allocator.Error!void { |
| 4675 | 4376 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4676 | 4377 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4677 | 4378 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| 4678 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | |
| 4679 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); | |
| 4680 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment.toByteUnits() orelse 0); | |
| 4681 | if (byval_attr) { | |
| 4682 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); | |
| 4683 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); | |
| 4684 | } | |
| 4379 | if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); | |
| 4685 | 4380 | } |
| 4686 | 4381 | }; |
| 4687 | 4382 | |
| ... | ... | @@ -4712,65 +4407,22 @@ pub const DeclGen = struct { |
| 4712 | 4407 | if (decl.val.getExternFunc(mod)) |extern_func| { |
| 4713 | 4408 | _ = try o.resolveLlvmFunction(extern_func.decl); |
| 4714 | 4409 | } else { |
| 4715 | const target = mod.getTarget(); | |
| 4716 | const variable = try o.resolveGlobalDecl(decl_index); | |
| 4717 | const global = variable.ptrConst(&o.builder).global; | |
| 4718 | var llvm_global = global.toLlvm(&o.builder); | |
| 4719 | variable.ptr(&o.builder).alignment = Builder.Alignment.fromByteUnits(decl.getAlignment(mod)); | |
| 4720 | llvm_global.setAlignment(decl.getAlignment(mod)); | |
| 4721 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| { | |
| 4722 | variable.ptr(&o.builder).section = try o.builder.string(section); | |
| 4723 | llvm_global.setSection(section); | |
| 4724 | } | |
| 4410 | const variable_index = try o.resolveGlobalDecl(decl_index); | |
| 4411 | variable_index.setAlignment( | |
| 4412 | Builder.Alignment.fromByteUnits(decl.getAlignment(mod)), | |
| 4413 | &o.builder, | |
| 4414 | ); | |
| 4415 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| | |
| 4416 | variable_index.setSection(try o.builder.string(section), &o.builder); | |
| 4725 | 4417 | assert(decl.has_tv); |
| 4726 | 4418 | const init_val = if (decl.val.getVariable(mod)) |decl_var| decl_var.init else init_val: { |
| 4727 | variable.ptr(&o.builder).mutability = .constant; | |
| 4728 | llvm_global.setGlobalConstant(.True); | |
| 4419 | variable_index.setMutability(.constant, &o.builder); | |
| 4729 | 4420 | break :init_val decl.val.toIntern(); |
| 4730 | 4421 | }; |
| 4731 | if (init_val != .none) { | |
| 4732 | const llvm_init = try o.lowerValue(init_val); | |
| 4733 | const llvm_init_ty = llvm_init.typeOf(&o.builder); | |
| 4734 | if (global.ptrConst(&o.builder).type == llvm_init_ty) { | |
| 4735 | llvm_global.setInitializer(llvm_init.toLlvm(&o.builder)); | |
| 4736 | } else { | |
| 4737 | // LLVM does not allow us to change the type of globals. So we must | |
| 4738 | // create a new global with the correct type, copy all its attributes, | |
| 4739 | // and then update all references to point to the new global, | |
| 4740 | // delete the original, and rename the new one to the old one's name. | |
| 4741 | // This is necessary because LLVM does not support const bitcasting | |
| 4742 | // a struct with padding bytes, which is needed to lower a const union value | |
| 4743 | // to LLVM, when a field other than the most-aligned is active. Instead, | |
| 4744 | // we must lower to an unnamed struct, and pointer cast at usage sites | |
| 4745 | // of the global. Such an unnamed struct is the cause of the global type | |
| 4746 | // mismatch, because we don't have the LLVM type until the *value* is created, | |
| 4747 | // whereas the global needs to be created based on the type alone, because | |
| 4748 | // lowering the value may reference the global as a pointer. | |
| 4749 | // Related: https://github.com/ziglang/zig/issues/13265 | |
| 4750 | const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); | |
| 4751 | const new_global = o.llvm_module.addGlobalInAddressSpace( | |
| 4752 | llvm_init_ty.toLlvm(&o.builder), | |
| 4753 | "", | |
| 4754 | @intFromEnum(llvm_global_addrspace), | |
| 4755 | ); | |
| 4756 | new_global.setLinkage(llvm_global.getLinkage()); | |
| 4757 | new_global.setUnnamedAddr(llvm_global.getUnnamedAddress()); | |
| 4758 | new_global.setAlignment(llvm_global.getAlignment()); | |
| 4759 | if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| | |
| 4760 | new_global.setSection(section); | |
| 4761 | new_global.setInitializer(llvm_init.toLlvm(&o.builder)); | |
| 4762 | // TODO: How should this work then the address space of a global changed? | |
| 4763 | llvm_global.replaceAllUsesWith(new_global); | |
| 4764 | new_global.takeName(llvm_global); | |
| 4765 | o.builder.llvm.globals.items[@intFromEnum(variable.ptrConst(&o.builder).global)] = | |
| 4766 | new_global; | |
| 4767 | llvm_global.deleteGlobal(); | |
| 4768 | llvm_global = new_global; | |
| 4769 | variable.ptr(&o.builder).mutability = .global; | |
| 4770 | global.ptr(&o.builder).type = llvm_init_ty; | |
| 4771 | } | |
| 4772 | variable.ptr(&o.builder).init = llvm_init; | |
| 4773 | } | |
| 4422 | try variable_index.setInitializer(switch (init_val) { | |
| 4423 | .none => .no_init, | |
| 4424 | else => try o.lowerValue(init_val), | |
| 4425 | }, &o.builder); | |
| 4774 | 4426 | |
| 4775 | 4427 | if (o.di_builder) |dib| { |
| 4776 | 4428 | const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| ... | ... | @@ -4780,7 +4432,7 @@ pub const DeclGen = struct { |
| 4780 | 4432 | const di_global = dib.createGlobalVariableExpression( |
| 4781 | 4433 | di_file.toScope(), |
| 4782 | 4434 | mod.intern_pool.stringToSlice(decl.name), |
| 4783 | llvm_global.getValueName(), | |
| 4435 | variable_index.name(&o.builder).slice(&o.builder).?, | |
| 4784 | 4436 | di_file, |
| 4785 | 4437 | line_number, |
| 4786 | 4438 | try o.lowerDebugType(decl.ty, .full), |
| ... | ... | @@ -4788,7 +4440,8 @@ pub const DeclGen = struct { |
| 4788 | 4440 | ); |
| 4789 | 4441 | |
| 4790 | 4442 | try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode()); |
| 4791 | if (!is_internal_linkage or decl.isExtern(mod)) llvm_global.attachMetaData(di_global); | |
| 4443 | if (!is_internal_linkage or decl.isExtern(mod)) | |
| 4444 | variable_index.toLlvm(&o.builder).attachMetaData(di_global); | |
| 4792 | 4445 | } |
| 4793 | 4446 | } |
| 4794 | 4447 | } |
| ... | ... | @@ -4800,7 +4453,6 @@ pub const FuncGen = struct { |
| 4800 | 4453 | air: Air, |
| 4801 | 4454 | liveness: Liveness, |
| 4802 | 4455 | wip: Builder.WipFunction, |
| 4803 | builder: *llvm.Builder, | |
| 4804 | 4456 | di_scope: ?*llvm.DIScope, |
| 4805 | 4457 | di_file: ?*llvm.DIFile, |
| 4806 | 4458 | base_line: u32, |
| ... | ... | @@ -4889,38 +4541,22 @@ pub const FuncGen = struct { |
| 4889 | 4541 | // We have an LLVM value but we need to create a global constant and |
| 4890 | 4542 | // set the value as its initializer, and then return a pointer to the global. |
| 4891 | 4543 | const target = mod.getTarget(); |
| 4892 | const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target); | |
| 4893 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target); | |
| 4894 | const llvm_ty = llvm_val.typeOf(&o.builder); | |
| 4895 | const llvm_alignment = tv.ty.abiAlignment(mod); | |
| 4896 | const llvm_global = o.llvm_module.addGlobalInAddressSpace(llvm_ty.toLlvm(&o.builder), "", @intFromEnum(llvm_actual_addrspace)); | |
| 4897 | llvm_global.setInitializer(llvm_val.toLlvm(&o.builder)); | |
| 4898 | llvm_global.setLinkage(.Private); | |
| 4899 | llvm_global.setGlobalConstant(.True); | |
| 4900 | llvm_global.setUnnamedAddr(.True); | |
| 4901 | llvm_global.setAlignment(llvm_alignment); | |
| 4902 | ||
| 4903 | var global = Builder.Global{ | |
| 4904 | .linkage = .private, | |
| 4905 | .unnamed_addr = .unnamed_addr, | |
| 4906 | .addr_space = llvm_actual_addrspace, | |
| 4907 | .type = llvm_ty, | |
| 4908 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 4909 | }; | |
| 4910 | var variable = Builder.Variable{ | |
| 4911 | .global = @enumFromInt(o.builder.globals.count()), | |
| 4912 | .mutability = .constant, | |
| 4913 | .init = llvm_val, | |
| 4914 | .alignment = Builder.Alignment.fromByteUnits(llvm_alignment), | |
| 4915 | }; | |
| 4916 | try o.builder.llvm.globals.append(o.gpa, llvm_global); | |
| 4917 | const global_index = try o.builder.addGlobal(.empty, global); | |
| 4918 | try o.builder.variables.append(o.gpa, variable); | |
| 4919 | ||
| 4544 | const variable_index = try o.builder.addVariable( | |
| 4545 | .empty, | |
| 4546 | llvm_val.typeOf(&o.builder), | |
| 4547 | toLlvmGlobalAddressSpace(.generic, target), | |
| 4548 | ); | |
| 4549 | try variable_index.setInitializer(llvm_val, &o.builder); | |
| 4550 | variable_index.setLinkage(.private, &o.builder); | |
| 4551 | variable_index.setMutability(.constant, &o.builder); | |
| 4552 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 4553 | variable_index.setAlignment(Builder.Alignment.fromByteUnits( | |
| 4554 | tv.ty.abiAlignment(mod), | |
| 4555 | ), &o.builder); | |
| 4920 | 4556 | return o.builder.convConst( |
| 4921 | 4557 | .unneeded, |
| 4922 | global_index.toConst(), | |
| 4923 | try o.builder.ptrType(llvm_wanted_addrspace), | |
| 4558 | variable_index.toConst(&o.builder), | |
| 4559 | try o.builder.ptrType(toLlvmAddressSpace(.generic, target)), | |
| 4924 | 4560 | ); |
| 4925 | 4561 | } |
| 4926 | 4562 | |
| ... | ... | @@ -4947,31 +4583,31 @@ pub const FuncGen = struct { |
| 4947 | 4583 | |
| 4948 | 4584 | const val: Builder.Value = switch (air_tags[inst]) { |
| 4949 | 4585 | // zig fmt: off |
| 4950 | .add => try self.airAdd(inst, false), | |
| 4951 | .add_optimized => try self.airAdd(inst, true), | |
| 4586 | .add => try self.airAdd(inst, .normal), | |
| 4587 | .add_optimized => try self.airAdd(inst, .fast), | |
| 4952 | 4588 | .add_wrap => try self.airAddWrap(inst), |
| 4953 | 4589 | .add_sat => try self.airAddSat(inst), |
| 4954 | 4590 | |
| 4955 | .sub => try self.airSub(inst, false), | |
| 4956 | .sub_optimized => try self.airSub(inst, true), | |
| 4591 | .sub => try self.airSub(inst, .normal), | |
| 4592 | .sub_optimized => try self.airSub(inst, .fast), | |
| 4957 | 4593 | .sub_wrap => try self.airSubWrap(inst), |
| 4958 | 4594 | .sub_sat => try self.airSubSat(inst), |
| 4959 | 4595 | |
| 4960 | .mul => try self.airMul(inst, false), | |
| 4961 | .mul_optimized => try self.airMul(inst, true), | |
| 4596 | .mul => try self.airMul(inst, .normal), | |
| 4597 | .mul_optimized => try self.airMul(inst, .fast), | |
| 4962 | 4598 | .mul_wrap => try self.airMulWrap(inst), |
| 4963 | 4599 | .mul_sat => try self.airMulSat(inst), |
| 4964 | 4600 | |
| 4965 | .add_safe => try self.airSafeArithmetic(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"), | |
| 4966 | .sub_safe => try self.airSafeArithmetic(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"), | |
| 4967 | .mul_safe => try self.airSafeArithmetic(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"), | |
| 4601 | .add_safe => try self.airSafeArithmetic(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"), | |
| 4602 | .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"), | |
| 4603 | .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"), | |
| 4968 | 4604 | |
| 4969 | .div_float => try self.airDivFloat(inst, false), | |
| 4970 | .div_trunc => try self.airDivTrunc(inst, false), | |
| 4971 | .div_floor => try self.airDivFloor(inst, false), | |
| 4972 | .div_exact => try self.airDivExact(inst, false), | |
| 4973 | .rem => try self.airRem(inst, false), | |
| 4974 | .mod => try self.airMod(inst, false), | |
| 4605 | .div_float => try self.airDivFloat(inst, .normal), | |
| 4606 | .div_trunc => try self.airDivTrunc(inst, .normal), | |
| 4607 | .div_floor => try self.airDivFloor(inst, .normal), | |
| 4608 | .div_exact => try self.airDivExact(inst, .normal), | |
| 4609 | .rem => try self.airRem(inst, .normal), | |
| 4610 | .mod => try self.airMod(inst, .normal), | |
| 4975 | 4611 | .ptr_add => try self.airPtrAdd(inst), |
| 4976 | 4612 | .ptr_sub => try self.airPtrSub(inst), |
| 4977 | 4613 | .shl => try self.airShl(inst), |
| ... | ... | @@ -4982,16 +4618,16 @@ pub const FuncGen = struct { |
| 4982 | 4618 | .slice => try self.airSlice(inst), |
| 4983 | 4619 | .mul_add => try self.airMulAdd(inst), |
| 4984 | 4620 | |
| 4985 | .div_float_optimized => try self.airDivFloat(inst, true), | |
| 4986 | .div_trunc_optimized => try self.airDivTrunc(inst, true), | |
| 4987 | .div_floor_optimized => try self.airDivFloor(inst, true), | |
| 4988 | .div_exact_optimized => try self.airDivExact(inst, true), | |
| 4989 | .rem_optimized => try self.airRem(inst, true), | |
| 4990 | .mod_optimized => try self.airMod(inst, true), | |
| 4621 | .div_float_optimized => try self.airDivFloat(inst, .fast), | |
| 4622 | .div_trunc_optimized => try self.airDivTrunc(inst, .fast), | |
| 4623 | .div_floor_optimized => try self.airDivFloor(inst, .fast), | |
| 4624 | .div_exact_optimized => try self.airDivExact(inst, .fast), | |
| 4625 | .rem_optimized => try self.airRem(inst, .fast), | |
| 4626 | .mod_optimized => try self.airMod(inst, .fast), | |
| 4991 | 4627 | |
| 4992 | .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"), | |
| 4993 | .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"), | |
| 4994 | .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"), | |
| 4628 | .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"), | |
| 4629 | .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"), | |
| 4630 | .mul_with_overflow => try self.airOverflow(inst, .@"smul.with.overflow", .@"umul.with.overflow"), | |
| 4995 | 4631 | .shl_with_overflow => try self.airShlWithOverflow(inst), |
| 4996 | 4632 | |
| 4997 | 4633 | .bit_and, .bool_and => try self.airAnd(inst), |
| ... | ... | @@ -5015,25 +4651,25 @@ pub const FuncGen = struct { |
| 5015 | 4651 | .round => try self.airUnaryOp(inst, .round), |
| 5016 | 4652 | .trunc_float => try self.airUnaryOp(inst, .trunc), |
| 5017 | 4653 | |
| 5018 | .neg => try self.airNeg(inst, false), | |
| 5019 | .neg_optimized => try self.airNeg(inst, true), | |
| 5020 | ||
| 5021 | .cmp_eq => try self.airCmp(inst, .eq, false), | |
| 5022 | .cmp_gt => try self.airCmp(inst, .gt, false), | |
| 5023 | .cmp_gte => try self.airCmp(inst, .gte, false), | |
| 5024 | .cmp_lt => try self.airCmp(inst, .lt, false), | |
| 5025 | .cmp_lte => try self.airCmp(inst, .lte, false), | |
| 5026 | .cmp_neq => try self.airCmp(inst, .neq, false), | |
| 5027 | ||
| 5028 | .cmp_eq_optimized => try self.airCmp(inst, .eq, true), | |
| 5029 | .cmp_gt_optimized => try self.airCmp(inst, .gt, true), | |
| 5030 | .cmp_gte_optimized => try self.airCmp(inst, .gte, true), | |
| 5031 | .cmp_lt_optimized => try self.airCmp(inst, .lt, true), | |
| 5032 | .cmp_lte_optimized => try self.airCmp(inst, .lte, true), | |
| 5033 | .cmp_neq_optimized => try self.airCmp(inst, .neq, true), | |
| 5034 | ||
| 5035 | .cmp_vector => try self.airCmpVector(inst, false), | |
| 5036 | .cmp_vector_optimized => try self.airCmpVector(inst, true), | |
| 4654 | .neg => try self.airNeg(inst, .normal), | |
| 4655 | .neg_optimized => try self.airNeg(inst, .fast), | |
| 4656 | ||
| 4657 | .cmp_eq => try self.airCmp(inst, .eq, .normal), | |
| 4658 | .cmp_gt => try self.airCmp(inst, .gt, .normal), | |
| 4659 | .cmp_gte => try self.airCmp(inst, .gte, .normal), | |
| 4660 | .cmp_lt => try self.airCmp(inst, .lt, .normal), | |
| 4661 | .cmp_lte => try self.airCmp(inst, .lte, .normal), | |
| 4662 | .cmp_neq => try self.airCmp(inst, .neq, .normal), | |
| 4663 | ||
| 4664 | .cmp_eq_optimized => try self.airCmp(inst, .eq, .fast), | |
| 4665 | .cmp_gt_optimized => try self.airCmp(inst, .gt, .fast), | |
| 4666 | .cmp_gte_optimized => try self.airCmp(inst, .gte, .fast), | |
| 4667 | .cmp_lt_optimized => try self.airCmp(inst, .lt, .fast), | |
| 4668 | .cmp_lte_optimized => try self.airCmp(inst, .lte, .fast), | |
| 4669 | .cmp_neq_optimized => try self.airCmp(inst, .neq, .fast), | |
| 4670 | ||
| 4671 | .cmp_vector => try self.airCmpVector(inst, .normal), | |
| 4672 | .cmp_vector_optimized => try self.airCmpVector(inst, .fast), | |
| 5037 | 4673 | .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst), |
| 5038 | 4674 | |
| 5039 | 4675 | .is_non_null => try self.airIsNonNull(inst, false, .ne), |
| ... | ... | @@ -5085,13 +4721,13 @@ pub const FuncGen = struct { |
| 5085 | 4721 | .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0), |
| 5086 | 4722 | .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1), |
| 5087 | 4723 | |
| 5088 | .int_from_float => try self.airIntFromFloat(inst, false), | |
| 5089 | .int_from_float_optimized => try self.airIntFromFloat(inst, true), | |
| 4724 | .int_from_float => try self.airIntFromFloat(inst, .normal), | |
| 4725 | .int_from_float_optimized => try self.airIntFromFloat(inst, .fast), | |
| 5090 | 4726 | |
| 5091 | 4727 | .array_to_slice => try self.airArrayToSlice(inst), |
| 5092 | 4728 | .float_from_int => try self.airFloatFromInt(inst), |
| 5093 | .cmpxchg_weak => try self.airCmpxchg(inst, true), | |
| 5094 | .cmpxchg_strong => try self.airCmpxchg(inst, false), | |
| 4729 | .cmpxchg_weak => try self.airCmpxchg(inst, .weak), | |
| 4730 | .cmpxchg_strong => try self.airCmpxchg(inst, .strong), | |
| 5095 | 4731 | .fence => try self.airFence(inst), |
| 5096 | 4732 | .atomic_rmw => try self.airAtomicRmw(inst), |
| 5097 | 4733 | .atomic_load => try self.airAtomicLoad(inst), |
| ... | ... | @@ -5100,11 +4736,11 @@ pub const FuncGen = struct { |
| 5100 | 4736 | .memcpy => try self.airMemcpy(inst), |
| 5101 | 4737 | .set_union_tag => try self.airSetUnionTag(inst), |
| 5102 | 4738 | .get_union_tag => try self.airGetUnionTag(inst), |
| 5103 | .clz => try self.airClzCtz(inst, .@"llvm.ctlz."), | |
| 5104 | .ctz => try self.airClzCtz(inst, .@"llvm.cttz."), | |
| 5105 | .popcount => try self.airBitOp(inst, .@"llvm.ctpop."), | |
| 4739 | .clz => try self.airClzCtz(inst, .ctlz), | |
| 4740 | .ctz => try self.airClzCtz(inst, .cttz), | |
| 4741 | .popcount => try self.airBitOp(inst, .ctpop), | |
| 5106 | 4742 | .byte_swap => try self.airByteSwap(inst), |
| 5107 | .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."), | |
| 4743 | .bit_reverse => try self.airBitOp(inst, .bitreverse), | |
| 5108 | 4744 | .tag_name => try self.airTagName(inst), |
| 5109 | 4745 | .error_name => try self.airErrorName(inst), |
| 5110 | 4746 | .splat => try self.airSplat(inst), |
| ... | ... | @@ -5118,8 +4754,8 @@ pub const FuncGen = struct { |
| 5118 | 4754 | .is_named_enum_value => try self.airIsNamedEnumValue(inst), |
| 5119 | 4755 | .error_set_has_value => try self.airErrorSetHasValue(inst), |
| 5120 | 4756 | |
| 5121 | .reduce => try self.airReduce(inst, false), | |
| 5122 | .reduce_optimized => try self.airReduce(inst, true), | |
| 4757 | .reduce => try self.airReduce(inst, .normal), | |
| 4758 | .reduce_optimized => try self.airReduce(inst, .fast), | |
| 5123 | 4759 | |
| 5124 | 4760 | .atomic_store_unordered => try self.airAtomicStore(inst, .unordered), |
| 5125 | 4761 | .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic), |
| ... | ... | @@ -5304,10 +4940,7 @@ pub const FuncGen = struct { |
| 5304 | 4940 | } else { |
| 5305 | 4941 | // LLVM does not allow bitcasting structs so we must allocate |
| 5306 | 4942 | // a local, store as one type, and then load as another type. |
| 5307 | const alignment = Builder.Alignment.fromByteUnits(@max( | |
| 5308 | param_ty.abiAlignment(mod), | |
| 5309 | o.target_data.abiAlignmentOfType(int_llvm_ty.toLlvm(&o.builder)), | |
| 5310 | )); | |
| 4943 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | |
| 5311 | 4944 | const int_ptr = try self.buildAlloca(int_llvm_ty, alignment); |
| 5312 | 4945 | _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment); |
| 5313 | 4946 | const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, ""); |
| ... | ... | @@ -5483,12 +5116,10 @@ pub const FuncGen = struct { |
| 5483 | 5116 | // In this case the function return type is honoring the calling convention by having |
| 5484 | 5117 | // a different LLVM type than the usual one. We solve this here at the callsite |
| 5485 | 5118 | // by using our canonical type, then loading it if necessary. |
| 5486 | const alignment = Builder.Alignment.fromByteUnits(@max( | |
| 5487 | o.target_data.abiAlignmentOfType(abi_ret_ty.toLlvm(&o.builder)), | |
| 5488 | return_type.abiAlignment(mod), | |
| 5489 | )); | |
| 5490 | assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >= | |
| 5491 | o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder))); | |
| 5119 | const alignment = Builder.Alignment.fromByteUnits(return_type.abiAlignment(mod)); | |
| 5120 | if (o.builder.useLibLlvm()) | |
| 5121 | assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >= | |
| 5122 | o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder))); | |
| 5492 | 5123 | const rp = try self.buildAlloca(abi_ret_ty, alignment); |
| 5493 | 5124 | _ = try self.wip.store(.normal, call, rp, alignment); |
| 5494 | 5125 | return if (isByRef(return_type, mod)) |
| ... | ... | @@ -5645,22 +5276,7 @@ pub const FuncGen = struct { |
| 5645 | 5276 | const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod)); |
| 5646 | 5277 | const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5647 | 5278 | |
| 5648 | const llvm_fn_name = "llvm.va_copy"; | |
| 5649 | const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal); | |
| 5650 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse | |
| 5651 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | |
| 5652 | ||
| 5653 | const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) }; | |
| 5654 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 5655 | llvm_fn_ty.toLlvm(&o.builder), | |
| 5656 | llvm_fn, | |
| 5657 | &args, | |
| 5658 | args.len, | |
| 5659 | .Fast, | |
| 5660 | .Auto, | |
| 5661 | "", | |
| 5662 | ), &self.wip); | |
| 5663 | ||
| 5279 | _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{}, &.{ dest_list, src_list }, ""); | |
| 5664 | 5280 | return if (isByRef(va_list_ty, mod)) |
| 5665 | 5281 | dest_list |
| 5666 | 5282 | else |
| ... | ... | @@ -5668,25 +5284,10 @@ pub const FuncGen = struct { |
| 5668 | 5284 | } |
| 5669 | 5285 | |
| 5670 | 5286 | fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 5671 | const o = self.dg.object; | |
| 5672 | 5287 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5673 | const list = try self.resolveInst(un_op); | |
| 5674 | ||
| 5675 | const llvm_fn_name = "llvm.va_end"; | |
| 5676 | const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal); | |
| 5677 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse | |
| 5678 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | |
| 5288 | const src_list = try self.resolveInst(un_op); | |
| 5679 | 5289 | |
| 5680 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; | |
| 5681 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 5682 | llvm_fn_ty.toLlvm(&o.builder), | |
| 5683 | llvm_fn, | |
| 5684 | &args, | |
| 5685 | args.len, | |
| 5686 | .Fast, | |
| 5687 | .Auto, | |
| 5688 | "", | |
| 5689 | ), &self.wip); | |
| 5290 | _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{}, &.{src_list}, ""); | |
| 5690 | 5291 | return .none; |
| 5691 | 5292 | } |
| 5692 | 5293 | |
| ... | ... | @@ -5697,44 +5298,30 @@ pub const FuncGen = struct { |
| 5697 | 5298 | const llvm_va_list_ty = try o.lowerType(va_list_ty); |
| 5698 | 5299 | |
| 5699 | 5300 | const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod)); |
| 5700 | const list = try self.buildAlloca(llvm_va_list_ty, result_alignment); | |
| 5701 | ||
| 5702 | const llvm_fn_name = "llvm.va_start"; | |
| 5703 | const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal); | |
| 5704 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse | |
| 5705 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | |
| 5706 | ||
| 5707 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; | |
| 5708 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 5709 | llvm_fn_ty.toLlvm(&o.builder), | |
| 5710 | llvm_fn, | |
| 5711 | &args, | |
| 5712 | args.len, | |
| 5713 | .Fast, | |
| 5714 | .Auto, | |
| 5715 | "", | |
| 5716 | ), &self.wip); | |
| 5301 | const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); | |
| 5717 | 5302 | |
| 5303 | _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{}, &.{dest_list}, ""); | |
| 5718 | 5304 | return if (isByRef(va_list_ty, mod)) |
| 5719 | list | |
| 5305 | dest_list | |
| 5720 | 5306 | else |
| 5721 | try self.wip.load(.normal, llvm_va_list_ty, list, result_alignment, ""); | |
| 5307 | try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, ""); | |
| 5722 | 5308 | } |
| 5723 | 5309 | |
| 5724 | fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value { | |
| 5725 | self.builder.setFastMath(want_fast_math); | |
| 5726 | ||
| 5310 | fn airCmp( | |
| 5311 | self: *FuncGen, | |
| 5312 | inst: Air.Inst.Index, | |
| 5313 | op: math.CompareOperator, | |
| 5314 | fast: Builder.FastMathKind, | |
| 5315 | ) !Builder.Value { | |
| 5727 | 5316 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 5728 | 5317 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5729 | 5318 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5730 | 5319 | const operand_ty = self.typeOf(bin_op.lhs); |
| 5731 | 5320 | |
| 5732 | return self.cmp(lhs, rhs, operand_ty, op); | |
| 5321 | return self.cmp(fast, op, operand_ty, lhs, rhs); | |
| 5733 | 5322 | } |
| 5734 | 5323 | |
| 5735 | fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 5736 | self.builder.setFastMath(want_fast_math); | |
| 5737 | ||
| 5324 | fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 5738 | 5325 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5739 | 5326 | const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| 5740 | 5327 | |
| ... | ... | @@ -5743,7 +5330,7 @@ pub const FuncGen = struct { |
| 5743 | 5330 | const vec_ty = self.typeOf(extra.lhs); |
| 5744 | 5331 | const cmp_op = extra.compareOperator(); |
| 5745 | 5332 | |
| 5746 | return self.cmp(lhs, rhs, vec_ty, cmp_op); | |
| 5333 | return self.cmp(fast, cmp_op, vec_ty, lhs, rhs); | |
| 5747 | 5334 | } |
| 5748 | 5335 | |
| 5749 | 5336 | fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -5764,10 +5351,11 @@ pub const FuncGen = struct { |
| 5764 | 5351 | |
| 5765 | 5352 | fn cmp( |
| 5766 | 5353 | self: *FuncGen, |
| 5354 | fast: Builder.FastMathKind, | |
| 5355 | op: math.CompareOperator, | |
| 5356 | operand_ty: Type, | |
| 5767 | 5357 | lhs: Builder.Value, |
| 5768 | 5358 | rhs: Builder.Value, |
| 5769 | operand_ty: Type, | |
| 5770 | op: math.CompareOperator, | |
| 5771 | 5359 | ) Allocator.Error!Builder.Value { |
| 5772 | 5360 | const o = self.dg.object; |
| 5773 | 5361 | const mod = o.module; |
| ... | ... | @@ -5819,13 +5407,13 @@ pub const FuncGen = struct { |
| 5819 | 5407 | self.wip.cursor = .{ .block = both_pl_block }; |
| 5820 | 5408 | const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty, true); |
| 5821 | 5409 | const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty, true); |
| 5822 | const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); | |
| 5410 | const payload_cmp = try self.cmp(fast, op, payload_ty, lhs_payload, rhs_payload); | |
| 5823 | 5411 | _ = try self.wip.br(end_block); |
| 5824 | 5412 | const both_pl_block_end = self.wip.cursor.block; |
| 5825 | 5413 | |
| 5826 | 5414 | self.wip.cursor = .{ .block = end_block }; |
| 5827 | const llvm_i1_0 = try o.builder.intValue(.i1, 0); | |
| 5828 | const llvm_i1_1 = try o.builder.intValue(.i1, 1); | |
| 5415 | const llvm_i1_0 = Builder.Value.false; | |
| 5416 | const llvm_i1_1 = Builder.Value.true; | |
| 5829 | 5417 | const incoming_values: [3]Builder.Value = .{ |
| 5830 | 5418 | switch (op) { |
| 5831 | 5419 | .eq => llvm_i1_1, |
| ... | ... | @@ -5848,7 +5436,7 @@ pub const FuncGen = struct { |
| 5848 | 5436 | ); |
| 5849 | 5437 | return phi.toValue(); |
| 5850 | 5438 | }, |
| 5851 | .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }), | |
| 5439 | .Float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }), | |
| 5852 | 5440 | else => unreachable, |
| 5853 | 5441 | }; |
| 5854 | 5442 | const is_signed = int_ty.isSignedInt(mod); |
| ... | ... | @@ -6046,7 +5634,7 @@ pub const FuncGen = struct { |
| 6046 | 5634 | if (can_elide_load) |
| 6047 | 5635 | return payload_ptr; |
| 6048 | 5636 | |
| 6049 | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false); | |
| 5637 | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); | |
| 6050 | 5638 | } |
| 6051 | 5639 | const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset]; |
| 6052 | 5640 | return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, ""); |
| ... | ... | @@ -6219,8 +5807,12 @@ pub const FuncGen = struct { |
| 6219 | 5807 | ); |
| 6220 | 5808 | } |
| 6221 | 5809 | |
| 6222 | fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 6223 | self.builder.setFastMath(want_fast_math); | |
| 5810 | fn airIntFromFloat( | |
| 5811 | self: *FuncGen, | |
| 5812 | inst: Air.Inst.Index, | |
| 5813 | fast: Builder.FastMathKind, | |
| 5814 | ) !Builder.Value { | |
| 5815 | _ = fast; | |
| 6224 | 5816 | |
| 6225 | 5817 | const o = self.dg.object; |
| 6226 | 5818 | const mod = o.module; |
| ... | ... | @@ -6345,7 +5937,7 @@ pub const FuncGen = struct { |
| 6345 | 5937 | return ptr; |
| 6346 | 5938 | |
| 6347 | 5939 | const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)); |
| 6348 | return self.loadByRef(ptr, elem_ty, elem_alignment, false); | |
| 5940 | return self.loadByRef(ptr, elem_ty, elem_alignment, .normal); | |
| 6349 | 5941 | } |
| 6350 | 5942 | |
| 6351 | 5943 | return self.load(ptr, slice_ty); |
| ... | ... | @@ -6385,7 +5977,7 @@ pub const FuncGen = struct { |
| 6385 | 5977 | try self.wip.gep(.inbounds, array_llvm_ty, array_llvm_val, &indices, ""); |
| 6386 | 5978 | if (canElideLoad(self, body_tail)) return elem_ptr; |
| 6387 | 5979 | const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)); |
| 6388 | return self.loadByRef(elem_ptr, elem_ty, elem_alignment, false); | |
| 5980 | return self.loadByRef(elem_ptr, elem_ty, elem_alignment, .normal); | |
| 6389 | 5981 | } else { |
| 6390 | 5982 | const elem_llvm_ty = try o.lowerType(elem_ty); |
| 6391 | 5983 | if (Air.refToIndex(bin_op.lhs)) |lhs_index| { |
| ... | ... | @@ -6445,7 +6037,7 @@ pub const FuncGen = struct { |
| 6445 | 6037 | if (isByRef(elem_ty, mod)) { |
| 6446 | 6038 | if (self.canElideLoad(body_tail)) return ptr; |
| 6447 | 6039 | const elem_alignment = Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)); |
| 6448 | return self.loadByRef(ptr, elem_ty, elem_alignment, false); | |
| 6040 | return self.loadByRef(ptr, elem_ty, elem_alignment, .normal); | |
| 6449 | 6041 | } |
| 6450 | 6042 | |
| 6451 | 6043 | return self.load(ptr, ptr_ty); |
| ... | ... | @@ -6467,7 +6059,7 @@ pub const FuncGen = struct { |
| 6467 | 6059 | if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr; |
| 6468 | 6060 | |
| 6469 | 6061 | const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty); |
| 6470 | return try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(mod)) | |
| 6062 | return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(mod)) | |
| 6471 | 6063 | // If this is a single-item pointer to an array, we need another index in the GEP. |
| 6472 | 6064 | &.{ try o.builder.intValue(try o.lowerType(Type.usize), 0), rhs } |
| 6473 | 6065 | else |
| ... | ... | @@ -6575,7 +6167,7 @@ pub const FuncGen = struct { |
| 6575 | 6167 | |
| 6576 | 6168 | assert(llvm_field.alignment != 0); |
| 6577 | 6169 | const field_alignment = Builder.Alignment.fromByteUnits(llvm_field.alignment); |
| 6578 | return self.loadByRef(field_ptr, field_ty, field_alignment, false); | |
| 6170 | return self.loadByRef(field_ptr, field_ty, field_alignment, .normal); | |
| 6579 | 6171 | } else { |
| 6580 | 6172 | return self.load(field_ptr, field_ptr_ty); |
| 6581 | 6173 | } |
| ... | ... | @@ -6590,7 +6182,7 @@ pub const FuncGen = struct { |
| 6590 | 6182 | const payload_alignment = Builder.Alignment.fromByteUnits(layout.payload_align); |
| 6591 | 6183 | if (isByRef(field_ty, mod)) { |
| 6592 | 6184 | if (canElideLoad(self, body_tail)) return field_ptr; |
| 6593 | return self.loadByRef(field_ptr, field_ty, payload_alignment, false); | |
| 6185 | return self.loadByRef(field_ptr, field_ty, payload_alignment, .normal); | |
| 6594 | 6186 | } else { |
| 6595 | 6187 | return self.wip.load(.normal, llvm_field_ty, field_ptr, payload_alignment, ""); |
| 6596 | 6188 | } |
| ... | ... | @@ -6638,6 +6230,8 @@ pub const FuncGen = struct { |
| 6638 | 6230 | } |
| 6639 | 6231 | |
| 6640 | 6232 | fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6233 | if (!self.dg.object.builder.useLibLlvm()) return .none; | |
| 6234 | ||
| 6641 | 6235 | const di_scope = self.di_scope orelse return .none; |
| 6642 | 6236 | const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; |
| 6643 | 6237 | self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1); |
| ... | ... | @@ -6646,12 +6240,19 @@ pub const FuncGen = struct { |
| 6646 | 6240 | self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc |
| 6647 | 6241 | else |
| 6648 | 6242 | null; |
| 6649 | self.builder.setCurrentDebugLocation(self.prev_dbg_line, self.prev_dbg_column, di_scope, inlined_at); | |
| 6243 | self.wip.llvm.builder.setCurrentDebugLocation( | |
| 6244 | self.prev_dbg_line, | |
| 6245 | self.prev_dbg_column, | |
| 6246 | di_scope, | |
| 6247 | inlined_at, | |
| 6248 | ); | |
| 6650 | 6249 | return .none; |
| 6651 | 6250 | } |
| 6652 | 6251 | |
| 6653 | 6252 | fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6654 | 6253 | const o = self.dg.object; |
| 6254 | if (!o.builder.useLibLlvm()) return .none; | |
| 6255 | ||
| 6655 | 6256 | const dib = o.di_builder orelse return .none; |
| 6656 | 6257 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 6657 | 6258 | |
| ... | ... | @@ -6662,7 +6263,7 @@ pub const FuncGen = struct { |
| 6662 | 6263 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| 6663 | 6264 | self.di_file = di_file; |
| 6664 | 6265 | const line_number = decl.src_line + 1; |
| 6665 | const cur_debug_location = self.builder.getCurrentDebugLocation2(); | |
| 6266 | const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2(); | |
| 6666 | 6267 | |
| 6667 | 6268 | try self.dbg_inlined.append(self.gpa, .{ |
| 6668 | 6269 | .loc = @ptrCast(cur_debug_location), |
| ... | ... | @@ -6710,6 +6311,8 @@ pub const FuncGen = struct { |
| 6710 | 6311 | |
| 6711 | 6312 | fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6712 | 6313 | const o = self.dg.object; |
| 6314 | if (!o.builder.useLibLlvm()) return .none; | |
| 6315 | ||
| 6713 | 6316 | if (o.di_builder == null) return .none; |
| 6714 | 6317 | const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; |
| 6715 | 6318 | |
| ... | ... | @@ -6725,6 +6328,8 @@ pub const FuncGen = struct { |
| 6725 | 6328 | |
| 6726 | 6329 | fn airDbgBlockBegin(self: *FuncGen) !Builder.Value { |
| 6727 | 6330 | const o = self.dg.object; |
| 6331 | if (!o.builder.useLibLlvm()) return .none; | |
| 6332 | ||
| 6728 | 6333 | const dib = o.di_builder orelse return .none; |
| 6729 | 6334 | const old_scope = self.di_scope.?; |
| 6730 | 6335 | try self.dbg_block_stack.append(self.gpa, old_scope); |
| ... | ... | @@ -6735,6 +6340,8 @@ pub const FuncGen = struct { |
| 6735 | 6340 | |
| 6736 | 6341 | fn airDbgBlockEnd(self: *FuncGen) !Builder.Value { |
| 6737 | 6342 | const o = self.dg.object; |
| 6343 | if (!o.builder.useLibLlvm()) return .none; | |
| 6344 | ||
| 6738 | 6345 | if (o.di_builder == null) return .none; |
| 6739 | 6346 | self.di_scope = self.dbg_block_stack.pop(); |
| 6740 | 6347 | return .none; |
| ... | ... | @@ -6742,6 +6349,8 @@ pub const FuncGen = struct { |
| 6742 | 6349 | |
| 6743 | 6350 | fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6744 | 6351 | const o = self.dg.object; |
| 6352 | if (!o.builder.useLibLlvm()) return .none; | |
| 6353 | ||
| 6745 | 6354 | const mod = o.module; |
| 6746 | 6355 | const dib = o.di_builder orelse return .none; |
| 6747 | 6356 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| ... | ... | @@ -6770,6 +6379,8 @@ pub const FuncGen = struct { |
| 6770 | 6379 | |
| 6771 | 6380 | fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6772 | 6381 | const o = self.dg.object; |
| 6382 | if (!o.builder.useLibLlvm()) return .none; | |
| 6383 | ||
| 6773 | 6384 | const dib = o.di_builder orelse return .none; |
| 6774 | 6385 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 6775 | 6386 | const operand = try self.resolveInst(pl_op.operand); |
| ... | ... | @@ -7374,7 +6985,7 @@ pub const FuncGen = struct { |
| 7374 | 6985 | const payload_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, ""); |
| 7375 | 6986 | if (isByRef(payload_ty, mod)) { |
| 7376 | 6987 | if (self.canElideLoad(body_tail)) return payload_ptr; |
| 7377 | return self.loadByRef(payload_ptr, payload_ty, payload_alignment, false); | |
| 6988 | return self.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); | |
| 7378 | 6989 | } |
| 7379 | 6990 | const payload_llvm_ty = err_union_llvm_ty.structFields(&o.builder)[offset]; |
| 7380 | 6991 | return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, ""); |
| ... | ... | @@ -7570,40 +7181,18 @@ pub const FuncGen = struct { |
| 7570 | 7181 | const o = self.dg.object; |
| 7571 | 7182 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7572 | 7183 | const index = pl_op.payload; |
| 7573 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32}); | |
| 7574 | const args: [1]*llvm.Value = .{ | |
| 7575 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), | |
| 7576 | }; | |
| 7577 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( | |
| 7578 | (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder), | |
| 7579 | llvm_fn, | |
| 7580 | &args, | |
| 7581 | args.len, | |
| 7582 | .Fast, | |
| 7583 | .Auto, | |
| 7584 | "", | |
| 7585 | ), &self.wip); | |
| 7184 | return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{.i32}, &.{ | |
| 7185 | try o.builder.intValue(.i32, index), | |
| 7186 | }, ""); | |
| 7586 | 7187 | } |
| 7587 | 7188 | |
| 7588 | 7189 | fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 7589 | 7190 | const o = self.dg.object; |
| 7590 | 7191 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7591 | 7192 | const index = pl_op.payload; |
| 7592 | const operand = try self.resolveInst(pl_op.operand); | |
| 7593 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32}); | |
| 7594 | const args: [2]*llvm.Value = .{ | |
| 7595 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), | |
| 7596 | operand.toLlvm(&self.wip), | |
| 7597 | }; | |
| 7598 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( | |
| 7599 | (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder), | |
| 7600 | llvm_fn, | |
| 7601 | &args, | |
| 7602 | args.len, | |
| 7603 | .Fast, | |
| 7604 | .Auto, | |
| 7605 | "", | |
| 7606 | ), &self.wip); | |
| 7193 | return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{.i32}, &.{ | |
| 7194 | try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), | |
| 7195 | }, ""); | |
| 7607 | 7196 | } |
| 7608 | 7197 | |
| 7609 | 7198 | fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7617,13 +7206,11 @@ pub const FuncGen = struct { |
| 7617 | 7206 | const index = try self.resolveInst(extra.lhs); |
| 7618 | 7207 | const operand = try self.resolveInst(extra.rhs); |
| 7619 | 7208 | |
| 7620 | const kind: Builder.MemoryAccessKind = switch (vector_ptr_ty.isVolatilePtr(mod)) { | |
| 7621 | false => .normal, | |
| 7622 | true => .@"volatile", | |
| 7623 | }; | |
| 7209 | const access_kind: Builder.MemoryAccessKind = | |
| 7210 | if (vector_ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal; | |
| 7624 | 7211 | const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(mod)); |
| 7625 | 7212 | const alignment = Builder.Alignment.fromByteUnits(vector_ptr_ty.ptrAlignment(mod)); |
| 7626 | const loaded = try self.wip.load(kind, elem_llvm_ty, vector_ptr, alignment, ""); | |
| 7213 | const loaded = try self.wip.load(access_kind, elem_llvm_ty, vector_ptr, alignment, ""); | |
| 7627 | 7214 | |
| 7628 | 7215 | const new_vector = try self.wip.insertElement(loaded, operand, index, ""); |
| 7629 | 7216 | _ = try self.store(vector_ptr, vector_ptr_ty, new_vector, .none); |
| ... | ... | @@ -7636,13 +7223,18 @@ pub const FuncGen = struct { |
| 7636 | 7223 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7637 | 7224 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7638 | 7225 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7639 | const scalar_ty = self.typeOfIndex(inst).scalarType(mod); | |
| 7226 | const inst_ty = self.typeOfIndex(inst); | |
| 7227 | const scalar_ty = inst_ty.scalarType(mod); | |
| 7640 | 7228 | |
| 7641 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs }); | |
| 7642 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7643 | .@"llvm.smin." | |
| 7644 | else | |
| 7645 | .@"llvm.umin.", lhs, rhs, ""); | |
| 7229 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, .normal, inst_ty, 2, .{ lhs, rhs }); | |
| 7230 | return self.wip.callIntrinsic( | |
| 7231 | .normal, | |
| 7232 | .none, | |
| 7233 | if (scalar_ty.isSignedInt(mod)) .smin else .umin, | |
| 7234 | &.{try o.lowerType(inst_ty)}, | |
| 7235 | &.{ lhs, rhs }, | |
| 7236 | "", | |
| 7237 | ); | |
| 7646 | 7238 | } |
| 7647 | 7239 | |
| 7648 | 7240 | fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7651,13 +7243,18 @@ pub const FuncGen = struct { |
| 7651 | 7243 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7652 | 7244 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7653 | 7245 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7654 | const scalar_ty = self.typeOfIndex(inst).scalarType(mod); | |
| 7246 | const inst_ty = self.typeOfIndex(inst); | |
| 7247 | const scalar_ty = inst_ty.scalarType(mod); | |
| 7655 | 7248 | |
| 7656 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs }); | |
| 7657 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7658 | .@"llvm.smax." | |
| 7659 | else | |
| 7660 | .@"llvm.umax.", lhs, rhs, ""); | |
| 7249 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, .normal, inst_ty, 2, .{ lhs, rhs }); | |
| 7250 | return self.wip.callIntrinsic( | |
| 7251 | .normal, | |
| 7252 | .none, | |
| 7253 | if (scalar_ty.isSignedInt(mod)) .smax else .umax, | |
| 7254 | &.{try o.lowerType(inst_ty)}, | |
| 7255 | &.{ lhs, rhs }, | |
| 7256 | "", | |
| 7257 | ); | |
| 7661 | 7258 | } |
| 7662 | 7259 | |
| 7663 | 7260 | fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7670,9 +7267,7 @@ pub const FuncGen = struct { |
| 7670 | 7267 | return self.wip.buildAggregate(try o.lowerType(inst_ty), &.{ ptr, len }, ""); |
| 7671 | 7268 | } |
| 7672 | 7269 | |
| 7673 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7674 | self.builder.setFastMath(want_fast_math); | |
| 7675 | ||
| 7270 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7676 | 7271 | const o = self.dg.object; |
| 7677 | 7272 | const mod = o.module; |
| 7678 | 7273 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7681,15 +7276,15 @@ pub const FuncGen = struct { |
| 7681 | 7276 | const inst_ty = self.typeOfIndex(inst); |
| 7682 | 7277 | const scalar_ty = inst_ty.scalarType(mod); |
| 7683 | 7278 | |
| 7684 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs }); | |
| 7279 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7685 | 7280 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"add nsw" else .@"add nuw", lhs, rhs, ""); |
| 7686 | 7281 | } |
| 7687 | 7282 | |
| 7688 | 7283 | fn airSafeArithmetic( |
| 7689 | 7284 | fg: *FuncGen, |
| 7690 | 7285 | inst: Air.Inst.Index, |
| 7691 | signed_intrinsic: []const u8, | |
| 7692 | unsigned_intrinsic: []const u8, | |
| 7286 | signed_intrinsic: Builder.Intrinsic, | |
| 7287 | unsigned_intrinsic: Builder.Intrinsic, | |
| 7693 | 7288 | ) !Builder.Value { |
| 7694 | 7289 | const o = fg.dg.object; |
| 7695 | 7290 | const mod = o.module; |
| ... | ... | @@ -7699,46 +7294,35 @@ pub const FuncGen = struct { |
| 7699 | 7294 | const rhs = try fg.resolveInst(bin_op.rhs); |
| 7700 | 7295 | const inst_ty = fg.typeOfIndex(inst); |
| 7701 | 7296 | const scalar_ty = inst_ty.scalarType(mod); |
| 7702 | const is_scalar = scalar_ty.ip_index == inst_ty.ip_index; | |
| 7703 | 7297 | |
| 7704 | const intrinsic_name = switch (scalar_ty.isSignedInt(mod)) { | |
| 7705 | true => signed_intrinsic, | |
| 7706 | false => unsigned_intrinsic, | |
| 7707 | }; | |
| 7298 | const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; | |
| 7708 | 7299 | const llvm_inst_ty = try o.lowerType(inst_ty); |
| 7709 | const llvm_ret_ty = try o.builder.structType(.normal, &.{ | |
| 7710 | llvm_inst_ty, | |
| 7711 | try llvm_inst_ty.changeScalar(.i1, &o.builder), | |
| 7712 | }); | |
| 7713 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal); | |
| 7714 | const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); | |
| 7715 | const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld( | |
| 7716 | llvm_fn_ty.toLlvm(&o.builder), | |
| 7717 | llvm_fn, | |
| 7718 | &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) }, | |
| 7719 | 2, | |
| 7720 | .Fast, | |
| 7721 | .Auto, | |
| 7722 | "", | |
| 7723 | ), &fg.wip); | |
| 7724 | const overflow_bit = try fg.wip.extractValue(result_struct, &.{1}, ""); | |
| 7725 | const scalar_overflow_bit = switch (is_scalar) { | |
| 7726 | true => overflow_bit, | |
| 7727 | false => (try fg.wip.unimplemented(.i1, "")).finish( | |
| 7728 | fg.builder.buildOrReduce(overflow_bit.toLlvm(&fg.wip)), | |
| 7729 | &fg.wip, | |
| 7730 | ), | |
| 7731 | }; | |
| 7300 | const results = | |
| 7301 | try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); | |
| 7302 | ||
| 7303 | const overflow_bits = try fg.wip.extractValue(results, &.{1}, ""); | |
| 7304 | const overflow_bits_ty = overflow_bits.typeOfWip(&fg.wip); | |
| 7305 | const overflow_bit = if (overflow_bits_ty.isVector(&o.builder)) | |
| 7306 | try fg.wip.callIntrinsic( | |
| 7307 | .normal, | |
| 7308 | .none, | |
| 7309 | .@"vector.reduce.or", | |
| 7310 | &.{overflow_bits_ty}, | |
| 7311 | &.{overflow_bits}, | |
| 7312 | "", | |
| 7313 | ) | |
| 7314 | else | |
| 7315 | overflow_bits; | |
| 7732 | 7316 | |
| 7733 | 7317 | const fail_block = try fg.wip.block(1, "OverflowFail"); |
| 7734 | 7318 | const ok_block = try fg.wip.block(1, "OverflowOk"); |
| 7735 | _ = try fg.wip.brCond(scalar_overflow_bit, fail_block, ok_block); | |
| 7319 | _ = try fg.wip.brCond(overflow_bit, fail_block, ok_block); | |
| 7736 | 7320 | |
| 7737 | 7321 | fg.wip.cursor = .{ .block = fail_block }; |
| 7738 | 7322 | try fg.buildSimplePanic(.integer_overflow); |
| 7739 | 7323 | |
| 7740 | 7324 | fg.wip.cursor = .{ .block = ok_block }; |
| 7741 | return fg.wip.extractValue(result_struct, &.{0}, ""); | |
| 7325 | return fg.wip.extractValue(results, &.{0}, ""); | |
| 7742 | 7326 | } |
| 7743 | 7327 | |
| 7744 | 7328 | fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7759,15 +7343,17 @@ pub const FuncGen = struct { |
| 7759 | 7343 | const scalar_ty = inst_ty.scalarType(mod); |
| 7760 | 7344 | |
| 7761 | 7345 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{}); |
| 7762 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7763 | .@"llvm.sadd.sat." | |
| 7764 | else | |
| 7765 | .@"llvm.uadd.sat.", lhs, rhs, ""); | |
| 7346 | return self.wip.callIntrinsic( | |
| 7347 | .normal, | |
| 7348 | .none, | |
| 7349 | if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat", | |
| 7350 | &.{try o.lowerType(inst_ty)}, | |
| 7351 | &.{ lhs, rhs }, | |
| 7352 | "", | |
| 7353 | ); | |
| 7766 | 7354 | } |
| 7767 | 7355 | |
| 7768 | fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7769 | self.builder.setFastMath(want_fast_math); | |
| 7770 | ||
| 7356 | fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7771 | 7357 | const o = self.dg.object; |
| 7772 | 7358 | const mod = o.module; |
| 7773 | 7359 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7776,7 +7362,7 @@ pub const FuncGen = struct { |
| 7776 | 7362 | const inst_ty = self.typeOfIndex(inst); |
| 7777 | 7363 | const scalar_ty = inst_ty.scalarType(mod); |
| 7778 | 7364 | |
| 7779 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs }); | |
| 7365 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7780 | 7366 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"sub nsw" else .@"sub nuw", lhs, rhs, ""); |
| 7781 | 7367 | } |
| 7782 | 7368 | |
| ... | ... | @@ -7798,15 +7384,17 @@ pub const FuncGen = struct { |
| 7798 | 7384 | const scalar_ty = inst_ty.scalarType(mod); |
| 7799 | 7385 | |
| 7800 | 7386 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); |
| 7801 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7802 | .@"llvm.ssub.sat." | |
| 7803 | else | |
| 7804 | .@"llvm.usub.sat.", lhs, rhs, ""); | |
| 7387 | return self.wip.callIntrinsic( | |
| 7388 | .normal, | |
| 7389 | .none, | |
| 7390 | if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat", | |
| 7391 | &.{try o.lowerType(inst_ty)}, | |
| 7392 | &.{ lhs, rhs }, | |
| 7393 | "", | |
| 7394 | ); | |
| 7805 | 7395 | } |
| 7806 | 7396 | |
| 7807 | fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7808 | self.builder.setFastMath(want_fast_math); | |
| 7809 | ||
| 7397 | fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7810 | 7398 | const o = self.dg.object; |
| 7811 | 7399 | const mod = o.module; |
| 7812 | 7400 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7815,7 +7403,7 @@ pub const FuncGen = struct { |
| 7815 | 7403 | const inst_ty = self.typeOfIndex(inst); |
| 7816 | 7404 | const scalar_ty = inst_ty.scalarType(mod); |
| 7817 | 7405 | |
| 7818 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs }); | |
| 7406 | if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7819 | 7407 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .@"mul nsw" else .@"mul nuw", lhs, rhs, ""); |
| 7820 | 7408 | } |
| 7821 | 7409 | |
| ... | ... | @@ -7837,26 +7425,26 @@ pub const FuncGen = struct { |
| 7837 | 7425 | const scalar_ty = inst_ty.scalarType(mod); |
| 7838 | 7426 | |
| 7839 | 7427 | if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); |
| 7840 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7841 | .@"llvm.smul.fix.sat." | |
| 7842 | else | |
| 7843 | .@"llvm.umul.fix.sat.", lhs, rhs, ""); | |
| 7428 | return self.wip.callIntrinsic( | |
| 7429 | .normal, | |
| 7430 | .none, | |
| 7431 | if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat", | |
| 7432 | &.{try o.lowerType(inst_ty)}, | |
| 7433 | &.{ lhs, rhs, try o.builder.intValue(.i32, 0) }, | |
| 7434 | "", | |
| 7435 | ); | |
| 7844 | 7436 | } |
| 7845 | 7437 | |
| 7846 | fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7847 | self.builder.setFastMath(want_fast_math); | |
| 7848 | ||
| 7438 | fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7849 | 7439 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7850 | 7440 | const lhs = try self.resolveInst(bin_op.lhs); |
| 7851 | 7441 | const rhs = try self.resolveInst(bin_op.rhs); |
| 7852 | 7442 | const inst_ty = self.typeOfIndex(inst); |
| 7853 | 7443 | |
| 7854 | return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | |
| 7444 | return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7855 | 7445 | } |
| 7856 | 7446 | |
| 7857 | fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7858 | self.builder.setFastMath(want_fast_math); | |
| 7859 | ||
| 7447 | fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7860 | 7448 | const o = self.dg.object; |
| 7861 | 7449 | const mod = o.module; |
| 7862 | 7450 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7866,15 +7454,13 @@ pub const FuncGen = struct { |
| 7866 | 7454 | const scalar_ty = inst_ty.scalarType(mod); |
| 7867 | 7455 | |
| 7868 | 7456 | if (scalar_ty.isRuntimeFloat()) { |
| 7869 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | |
| 7870 | return self.buildFloatOp(.trunc, inst_ty, 1, .{result}); | |
| 7457 | const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7458 | return self.buildFloatOp(.trunc, fast, inst_ty, 1, .{result}); | |
| 7871 | 7459 | } |
| 7872 | 7460 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) .sdiv else .udiv, lhs, rhs, ""); |
| 7873 | 7461 | } |
| 7874 | 7462 | |
| 7875 | fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7876 | self.builder.setFastMath(want_fast_math); | |
| 7877 | ||
| 7463 | fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7878 | 7464 | const o = self.dg.object; |
| 7879 | 7465 | const mod = o.module; |
| 7880 | 7466 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7884,8 +7470,8 @@ pub const FuncGen = struct { |
| 7884 | 7470 | const scalar_ty = inst_ty.scalarType(mod); |
| 7885 | 7471 | |
| 7886 | 7472 | if (scalar_ty.isRuntimeFloat()) { |
| 7887 | const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | |
| 7888 | return self.buildFloatOp(.floor, inst_ty, 1, .{result}); | |
| 7473 | const result = try self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7474 | return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); | |
| 7889 | 7475 | } |
| 7890 | 7476 | if (scalar_ty.isSignedInt(mod)) { |
| 7891 | 7477 | const inst_llvm_ty = try o.lowerType(inst_ty); |
| ... | ... | @@ -7900,15 +7486,13 @@ pub const FuncGen = struct { |
| 7900 | 7486 | const div_sign_mask = try self.wip.bin(.ashr, div_sign, bit_size_minus_one, ""); |
| 7901 | 7487 | const zero = try o.builder.zeroInitValue(inst_llvm_ty); |
| 7902 | 7488 | const rem_nonzero = try self.wip.icmp(.ne, rem, zero, ""); |
| 7903 | const correction = try self.wip.select(rem_nonzero, div_sign_mask, zero, ""); | |
| 7489 | const correction = try self.wip.select(.normal, rem_nonzero, div_sign_mask, zero, ""); | |
| 7904 | 7490 | return self.wip.bin(.@"add nsw", div, correction, ""); |
| 7905 | 7491 | } |
| 7906 | 7492 | return self.wip.bin(.udiv, lhs, rhs, ""); |
| 7907 | 7493 | } |
| 7908 | 7494 | |
| 7909 | fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7910 | self.builder.setFastMath(want_fast_math); | |
| 7911 | ||
| 7495 | fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7912 | 7496 | const o = self.dg.object; |
| 7913 | 7497 | const mod = o.module; |
| 7914 | 7498 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7917,16 +7501,16 @@ pub const FuncGen = struct { |
| 7917 | 7501 | const inst_ty = self.typeOfIndex(inst); |
| 7918 | 7502 | const scalar_ty = inst_ty.scalarType(mod); |
| 7919 | 7503 | |
| 7920 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs }); | |
| 7921 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) | |
| 7922 | .@"sdiv exact" | |
| 7923 | else | |
| 7924 | .@"udiv exact", lhs, rhs, ""); | |
| 7504 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7505 | return self.wip.bin( | |
| 7506 | if (scalar_ty.isSignedInt(mod)) .@"sdiv exact" else .@"udiv exact", | |
| 7507 | lhs, | |
| 7508 | rhs, | |
| 7509 | "", | |
| 7510 | ); | |
| 7925 | 7511 | } |
| 7926 | 7512 | |
| 7927 | fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7928 | self.builder.setFastMath(want_fast_math); | |
| 7929 | ||
| 7513 | fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7930 | 7514 | const o = self.dg.object; |
| 7931 | 7515 | const mod = o.module; |
| 7932 | 7516 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7935,16 +7519,15 @@ pub const FuncGen = struct { |
| 7935 | 7519 | const inst_ty = self.typeOfIndex(inst); |
| 7936 | 7520 | const scalar_ty = inst_ty.scalarType(mod); |
| 7937 | 7521 | |
| 7938 | if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); | |
| 7522 | if (scalar_ty.isRuntimeFloat()) | |
| 7523 | return self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7939 | 7524 | return self.wip.bin(if (scalar_ty.isSignedInt(mod)) |
| 7940 | 7525 | .srem |
| 7941 | 7526 | else |
| 7942 | 7527 | .urem, lhs, rhs, ""); |
| 7943 | 7528 | } |
| 7944 | 7529 | |
| 7945 | fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 7946 | self.builder.setFastMath(want_fast_math); | |
| 7947 | ||
| 7530 | fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 7948 | 7531 | const o = self.dg.object; |
| 7949 | 7532 | const mod = o.module; |
| 7950 | 7533 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | ... | @@ -7955,12 +7538,12 @@ pub const FuncGen = struct { |
| 7955 | 7538 | const scalar_ty = inst_ty.scalarType(mod); |
| 7956 | 7539 | |
| 7957 | 7540 | if (scalar_ty.isRuntimeFloat()) { |
| 7958 | const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs }); | |
| 7959 | const b = try self.buildFloatOp(.add, inst_ty, 2, .{ a, rhs }); | |
| 7960 | const c = try self.buildFloatOp(.fmod, inst_ty, 2, .{ b, rhs }); | |
| 7541 | const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs }); | |
| 7542 | const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs }); | |
| 7543 | const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs }); | |
| 7961 | 7544 | const zero = try o.builder.zeroInitValue(inst_llvm_ty); |
| 7962 | const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero }); | |
| 7963 | return self.wip.select(ltz, c, a, ""); | |
| 7545 | const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero }); | |
| 7546 | return self.wip.select(fast, ltz, c, a, ""); | |
| 7964 | 7547 | } |
| 7965 | 7548 | if (scalar_ty.isSignedInt(mod)) { |
| 7966 | 7549 | const bit_size_minus_one = try o.builder.splatValue(inst_llvm_ty, try o.builder.intConst( |
| ... | ... | @@ -7974,7 +7557,7 @@ pub const FuncGen = struct { |
| 7974 | 7557 | const rhs_masked = try self.wip.bin(.@"and", rhs, div_sign_mask, ""); |
| 7975 | 7558 | const zero = try o.builder.zeroInitValue(inst_llvm_ty); |
| 7976 | 7559 | const rem_nonzero = try self.wip.icmp(.ne, rem, zero, ""); |
| 7977 | const correction = try self.wip.select(rem_nonzero, rhs_masked, zero, ""); | |
| 7560 | const correction = try self.wip.select(.normal, rem_nonzero, rhs_masked, zero, ""); | |
| 7978 | 7561 | return self.wip.bin(.@"add nsw", rem, correction, ""); |
| 7979 | 7562 | } |
| 7980 | 7563 | return self.wip.bin(.urem, lhs, rhs, ""); |
| ... | ... | @@ -8028,8 +7611,8 @@ pub const FuncGen = struct { |
| 8028 | 7611 | fn airOverflow( |
| 8029 | 7612 | self: *FuncGen, |
| 8030 | 7613 | inst: Air.Inst.Index, |
| 8031 | signed_intrinsic: []const u8, | |
| 8032 | unsigned_intrinsic: []const u8, | |
| 7614 | signed_intrinsic: Builder.Intrinsic, | |
| 7615 | unsigned_intrinsic: Builder.Intrinsic, | |
| 8033 | 7616 | ) !Builder.Value { |
| 8034 | 7617 | const o = self.dg.object; |
| 8035 | 7618 | const mod = o.module; |
| ... | ... | @@ -8041,48 +7624,30 @@ pub const FuncGen = struct { |
| 8041 | 7624 | |
| 8042 | 7625 | const lhs_ty = self.typeOf(extra.lhs); |
| 8043 | 7626 | const scalar_ty = lhs_ty.scalarType(mod); |
| 8044 | const dest_ty = self.typeOfIndex(inst); | |
| 8045 | ||
| 8046 | const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; | |
| 7627 | const inst_ty = self.typeOfIndex(inst); | |
| 8047 | 7628 | |
| 8048 | const llvm_dest_ty = try o.lowerType(dest_ty); | |
| 7629 | const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; | |
| 7630 | const llvm_inst_ty = try o.lowerType(inst_ty); | |
| 8049 | 7631 | const llvm_lhs_ty = try o.lowerType(lhs_ty); |
| 7632 | const results = | |
| 7633 | try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); | |
| 8050 | 7634 | |
| 8051 | const llvm_fn = try self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); | |
| 8052 | const llvm_ret_ty = try o.builder.structType( | |
| 8053 | .normal, | |
| 8054 | &.{ llvm_lhs_ty, try llvm_lhs_ty.changeScalar(.i1, &o.builder) }, | |
| 8055 | ); | |
| 8056 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal); | |
| 8057 | const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish( | |
| 8058 | self.builder.buildCallOld( | |
| 8059 | llvm_fn_ty.toLlvm(&o.builder), | |
| 8060 | llvm_fn, | |
| 8061 | &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) }, | |
| 8062 | 2, | |
| 8063 | .Fast, | |
| 8064 | .Auto, | |
| 8065 | "", | |
| 8066 | ), | |
| 8067 | &self.wip, | |
| 8068 | ); | |
| 7635 | const result_val = try self.wip.extractValue(results, &.{0}, ""); | |
| 7636 | const overflow_bit = try self.wip.extractValue(results, &.{1}, ""); | |
| 8069 | 7637 | |
| 8070 | const result = try self.wip.extractValue(result_struct, &.{0}, ""); | |
| 8071 | const overflow_bit = try self.wip.extractValue(result_struct, &.{1}, ""); | |
| 7638 | const result_index = llvmField(inst_ty, 0, mod).?.index; | |
| 7639 | const overflow_index = llvmField(inst_ty, 1, mod).?.index; | |
| 8072 | 7640 | |
| 8073 | const result_index = llvmField(dest_ty, 0, mod).?.index; | |
| 8074 | const overflow_index = llvmField(dest_ty, 1, mod).?.index; | |
| 8075 | ||
| 8076 | if (isByRef(dest_ty, mod)) { | |
| 8077 | const result_alignment = Builder.Alignment.fromByteUnits(dest_ty.abiAlignment(mod)); | |
| 8078 | const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment); | |
| 7641 | if (isByRef(inst_ty, mod)) { | |
| 7642 | const result_alignment = Builder.Alignment.fromByteUnits(inst_ty.abiAlignment(mod)); | |
| 7643 | const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment); | |
| 8079 | 7644 | { |
| 8080 | const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, result_index, ""); | |
| 8081 | _ = try self.wip.store(.normal, result, field_ptr, result_alignment); | |
| 7645 | const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, result_index, ""); | |
| 7646 | _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment); | |
| 8082 | 7647 | } |
| 8083 | 7648 | { |
| 8084 | 7649 | const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1); |
| 8085 | const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, ""); | |
| 7650 | const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, ""); | |
| 8086 | 7651 | _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment); |
| 8087 | 7652 | } |
| 8088 | 7653 | |
| ... | ... | @@ -8090,9 +7655,9 @@ pub const FuncGen = struct { |
| 8090 | 7655 | } |
| 8091 | 7656 | |
| 8092 | 7657 | var fields: [2]Builder.Value = undefined; |
| 8093 | fields[result_index] = result; | |
| 7658 | fields[result_index] = result_val; | |
| 8094 | 7659 | fields[overflow_index] = overflow_bit; |
| 8095 | return self.wip.buildAggregate(llvm_dest_ty, &fields, ""); | |
| 7660 | return self.wip.buildAggregate(llvm_inst_ty, &fields, ""); | |
| 8096 | 7661 | } |
| 8097 | 7662 | |
| 8098 | 7663 | fn buildElementwiseCall( |
| ... | ... | @@ -8138,30 +7703,20 @@ pub const FuncGen = struct { |
| 8138 | 7703 | if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { |
| 8139 | 7704 | .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, |
| 8140 | 7705 | .function => |function| function, |
| 8141 | else => unreachable, | |
| 8142 | }; | |
| 8143 | ||
| 8144 | const fn_type = try o.builder.fnType(return_type, param_types, .normal); | |
| 8145 | const f = o.llvm_module.addFunction(fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); | |
| 8146 | ||
| 8147 | var global = Builder.Global{ | |
| 8148 | .type = fn_type, | |
| 8149 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | |
| 8150 | }; | |
| 8151 | var function = Builder.Function{ | |
| 8152 | .global = @enumFromInt(o.builder.globals.count()), | |
| 7706 | .variable, .replaced => unreachable, | |
| 8153 | 7707 | }; |
| 8154 | ||
| 8155 | try o.builder.llvm.globals.append(self.gpa, f); | |
| 8156 | _ = try o.builder.addGlobal(fn_name, global); | |
| 8157 | try o.builder.functions.append(self.gpa, function); | |
| 8158 | return global.kind.function; | |
| 7708 | return o.builder.addFunction( | |
| 7709 | try o.builder.fnType(return_type, param_types, .normal), | |
| 7710 | fn_name, | |
| 7711 | toLlvmAddressSpace(.generic, o.module.getTarget()), | |
| 7712 | ); | |
| 8159 | 7713 | } |
| 8160 | 7714 | |
| 8161 | 7715 | /// Creates a floating point comparison by lowering to the appropriate |
| 8162 | 7716 | /// hardware instruction or softfloat routine for the target |
| 8163 | 7717 | fn buildFloatCmp( |
| 8164 | 7718 | self: *FuncGen, |
| 7719 | fast: Builder.FastMathKind, | |
| 8165 | 7720 | pred: math.CompareOperator, |
| 8166 | 7721 | ty: Type, |
| 8167 | 7722 | params: [2]Builder.Value, |
| ... | ... | @@ -8181,7 +7736,7 @@ pub const FuncGen = struct { |
| 8181 | 7736 | .gt => .ogt, |
| 8182 | 7737 | .gte => .oge, |
| 8183 | 7738 | }; |
| 8184 | return self.wip.fcmp(cond, params[0], params[1], ""); | |
| 7739 | return self.wip.fcmp(fast, cond, params[0], params[1], ""); | |
| 8185 | 7740 | } |
| 8186 | 7741 | |
| 8187 | 7742 | const float_bits = scalar_ty.floatBits(target); |
| ... | ... | @@ -8196,11 +7751,7 @@ pub const FuncGen = struct { |
| 8196 | 7751 | }; |
| 8197 | 7752 | const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); |
| 8198 | 7753 | |
| 8199 | const libc_fn = try self.getLibcFunction( | |
| 8200 | fn_name, | |
| 8201 | ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..], | |
| 8202 | .i32, | |
| 8203 | ); | |
| 7754 | const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); | |
| 8204 | 7755 | |
| 8205 | 7756 | const zero = try o.builder.intConst(.i32, 0); |
| 8206 | 7757 | const int_cond: Builder.IntegerCondition = switch (pred) { |
| ... | ... | @@ -8272,6 +7823,7 @@ pub const FuncGen = struct { |
| 8272 | 7823 | fn buildFloatOp( |
| 8273 | 7824 | self: *FuncGen, |
| 8274 | 7825 | comptime op: FloatOp, |
| 7826 | fast: Builder.FastMathKind, | |
| 8275 | 7827 | ty: Type, |
| 8276 | 7828 | comptime params_len: usize, |
| 8277 | 7829 | params: [params_len]Builder.Value, |
| ... | ... | @@ -8285,27 +7837,59 @@ pub const FuncGen = struct { |
| 8285 | 7837 | if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { |
| 8286 | 7838 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| 8287 | 7839 | .neg => return self.wip.un(.fneg, params[0], ""), |
| 8288 | .add => return self.wip.bin(.fadd, params[0], params[1], ""), | |
| 8289 | .sub => return self.wip.bin(.fsub, params[0], params[1], ""), | |
| 8290 | .mul => return self.wip.bin(.fmul, params[0], params[1], ""), | |
| 8291 | .div => return self.wip.bin(.fdiv, params[0], params[1], ""), | |
| 8292 | .fmod => return self.wip.bin(.frem, params[0], params[1], ""), | |
| 8293 | .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""), | |
| 8294 | .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""), | |
| 8295 | .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""), | |
| 8296 | .cos => return self.wip.un(.@"llvm.cos.", params[0], ""), | |
| 8297 | .exp => return self.wip.un(.@"llvm.exp.", params[0], ""), | |
| 8298 | .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""), | |
| 8299 | .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""), | |
| 8300 | .floor => return self.wip.un(.@"llvm.floor.", params[0], ""), | |
| 8301 | .log => return self.wip.un(.@"llvm.log.", params[0], ""), | |
| 8302 | .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""), | |
| 8303 | .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""), | |
| 8304 | .round => return self.wip.un(.@"llvm.round.", params[0], ""), | |
| 8305 | .sin => return self.wip.un(.@"llvm.sin.", params[0], ""), | |
| 8306 | .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""), | |
| 8307 | .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""), | |
| 8308 | .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]), | |
| 7840 | .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) { | |
| 7841 | .normal => switch (op) { | |
| 7842 | .add => .fadd, | |
| 7843 | .sub => .fsub, | |
| 7844 | .mul => .fmul, | |
| 7845 | .div => .fdiv, | |
| 7846 | .fmod => .frem, | |
| 7847 | else => unreachable, | |
| 7848 | }, | |
| 7849 | .fast => switch (op) { | |
| 7850 | .add => .@"fadd fast", | |
| 7851 | .sub => .@"fsub fast", | |
| 7852 | .mul => .@"fmul fast", | |
| 7853 | .div => .@"fdiv fast", | |
| 7854 | .fmod => .@"frem fast", | |
| 7855 | else => unreachable, | |
| 7856 | }, | |
| 7857 | }, params[0], params[1], ""), | |
| 7858 | .fmax, | |
| 7859 | .fmin, | |
| 7860 | .ceil, | |
| 7861 | .cos, | |
| 7862 | .exp, | |
| 7863 | .exp2, | |
| 7864 | .fabs, | |
| 7865 | .floor, | |
| 7866 | .log, | |
| 7867 | .log10, | |
| 7868 | .log2, | |
| 7869 | .round, | |
| 7870 | .sin, | |
| 7871 | .sqrt, | |
| 7872 | .trunc, | |
| 7873 | .fma, | |
| 7874 | => return self.wip.callIntrinsic(fast, .none, switch (op) { | |
| 7875 | .fmax => .maxnum, | |
| 7876 | .fmin => .minnum, | |
| 7877 | .ceil => .ceil, | |
| 7878 | .cos => .cos, | |
| 7879 | .exp => .exp, | |
| 7880 | .exp2 => .exp2, | |
| 7881 | .fabs => .fabs, | |
| 7882 | .floor => .floor, | |
| 7883 | .log => .log, | |
| 7884 | .log10 => .log10, | |
| 7885 | .log2 => .log2, | |
| 7886 | .round => .round, | |
| 7887 | .sin => .sin, | |
| 7888 | .sqrt => .sqrt, | |
| 7889 | .trunc => .trunc, | |
| 7890 | .fma => .fma, | |
| 7891 | else => unreachable, | |
| 7892 | }, &.{llvm_ty}, &params, ""), | |
| 8309 | 7893 | .tan => unreachable, |
| 8310 | 7894 | }; |
| 8311 | 7895 | |
| ... | ... | @@ -8362,7 +7946,7 @@ pub const FuncGen = struct { |
| 8362 | 7946 | } |
| 8363 | 7947 | |
| 8364 | 7948 | return self.wip.call( |
| 8365 | .normal, | |
| 7949 | fast.toCallKind(), | |
| 8366 | 7950 | .ccc, |
| 8367 | 7951 | .none, |
| 8368 | 7952 | libc_fn.typeOf(&o.builder), |
| ... | ... | @@ -8381,7 +7965,7 @@ pub const FuncGen = struct { |
| 8381 | 7965 | const addend = try self.resolveInst(pl_op.operand); |
| 8382 | 7966 | |
| 8383 | 7967 | const ty = self.typeOfIndex(inst); |
| 8384 | return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend }); | |
| 7968 | return self.buildFloatOp(.fma, .normal, ty, 3, .{ mulend1, mulend2, addend }); | |
| 8385 | 7969 | } |
| 8386 | 7970 | |
| 8387 | 7971 | fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -8499,28 +8083,32 @@ pub const FuncGen = struct { |
| 8499 | 8083 | |
| 8500 | 8084 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| 8501 | 8085 | |
| 8502 | const result = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(mod)) | |
| 8503 | .@"llvm.sshl.sat." | |
| 8504 | else | |
| 8505 | .@"llvm.ushl.sat.", lhs, casted_rhs, ""); | |
| 8086 | const llvm_lhs_ty = try o.lowerType(lhs_ty); | |
| 8087 | const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); | |
| 8088 | const result = try self.wip.callIntrinsic( | |
| 8089 | .normal, | |
| 8090 | .none, | |
| 8091 | if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat", | |
| 8092 | &.{llvm_lhs_ty}, | |
| 8093 | &.{ lhs, casted_rhs }, | |
| 8094 | "", | |
| 8095 | ); | |
| 8506 | 8096 | |
| 8507 | 8097 | // LLVM langref says "If b is (statically or dynamically) equal to or |
| 8508 | 8098 | // larger than the integer bit width of the arguments, the result is a |
| 8509 | 8099 | // poison value." |
| 8510 | 8100 | // However Zig semantics says that saturating shift left can never produce |
| 8511 | 8101 | // undefined; instead it saturates. |
| 8512 | const lhs_llvm_ty = try o.lowerType(lhs_ty); | |
| 8513 | const lhs_scalar_llvm_ty = lhs_llvm_ty.scalarType(&o.builder); | |
| 8514 | 8102 | const bits = try o.builder.splatValue( |
| 8515 | lhs_llvm_ty, | |
| 8516 | try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits), | |
| 8103 | llvm_lhs_ty, | |
| 8104 | try o.builder.intConst(llvm_lhs_scalar_ty, lhs_bits), | |
| 8517 | 8105 | ); |
| 8518 | 8106 | const lhs_max = try o.builder.splatValue( |
| 8519 | lhs_llvm_ty, | |
| 8520 | try o.builder.intConst(lhs_scalar_llvm_ty, -1), | |
| 8107 | llvm_lhs_ty, | |
| 8108 | try o.builder.intConst(llvm_lhs_scalar_ty, -1), | |
| 8521 | 8109 | ); |
| 8522 | 8110 | const in_range = try self.wip.icmp(.ult, rhs, bits, ""); |
| 8523 | return self.wip.select(in_range, result, lhs_max, ""); | |
| 8111 | return self.wip.select(.normal, in_range, result, lhs_max, ""); | |
| 8524 | 8112 | } |
| 8525 | 8113 | |
| 8526 | 8114 | fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value { |
| ... | ... | @@ -8873,21 +8461,14 @@ pub const FuncGen = struct { |
| 8873 | 8461 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8874 | 8462 | // extra information to LLVM. However, safety makes the difference between using |
| 8875 | 8463 | // 0xaa or actual undefined for the fill byte. |
| 8876 | const fill_byte = if (safety) | |
| 8877 | try o.builder.intConst(.i8, 0xaa) | |
| 8878 | else | |
| 8879 | try o.builder.undefConst(.i8); | |
| 8880 | const operand_size = operand_ty.abiSize(mod); | |
| 8881 | const usize_ty = try o.lowerType(Type.usize); | |
| 8882 | const len = try o.builder.intValue(usize_ty, operand_size); | |
| 8883 | const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)); | |
| 8884 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet( | |
| 8885 | dest_ptr.toLlvm(&self.wip), | |
| 8886 | fill_byte.toLlvm(&o.builder), | |
| 8887 | len.toLlvm(&self.wip), | |
| 8888 | @intCast(dest_ptr_align.toByteUnits() orelse 0), | |
| 8889 | ptr_ty.isVolatilePtr(mod), | |
| 8890 | ), &self.wip); | |
| 8464 | const len = try o.builder.intValue(try o.lowerType(Type.usize), operand_ty.abiSize(mod)); | |
| 8465 | _ = try self.wip.callMemSet( | |
| 8466 | dest_ptr, | |
| 8467 | Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)), | |
| 8468 | if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8), | |
| 8469 | len, | |
| 8470 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, | |
| 8471 | ); | |
| 8891 | 8472 | if (safety and mod.comp.bin_file.options.valgrind) { |
| 8892 | 8473 | try self.valgrindMarkUndef(dest_ptr, len); |
| 8893 | 8474 | } |
| ... | ... | @@ -8940,90 +8521,38 @@ pub const FuncGen = struct { |
| 8940 | 8521 | |
| 8941 | 8522 | fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8942 | 8523 | _ = inst; |
| 8943 | const o = self.dg.object; | |
| 8944 | const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); | |
| 8945 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 8946 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), | |
| 8947 | llvm_fn, | |
| 8948 | undefined, | |
| 8949 | 0, | |
| 8950 | .Cold, | |
| 8951 | .Auto, | |
| 8952 | "", | |
| 8953 | ), &self.wip); | |
| 8524 | _ = try self.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, ""); | |
| 8954 | 8525 | _ = try self.wip.@"unreachable"(); |
| 8955 | 8526 | return .none; |
| 8956 | 8527 | } |
| 8957 | 8528 | |
| 8958 | 8529 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8959 | 8530 | _ = inst; |
| 8960 | const o = self.dg.object; | |
| 8961 | const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); | |
| 8962 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 8963 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), | |
| 8964 | llvm_fn, | |
| 8965 | undefined, | |
| 8966 | 0, | |
| 8967 | .C, | |
| 8968 | .Auto, | |
| 8969 | "", | |
| 8970 | ), &self.wip); | |
| 8531 | _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, ""); | |
| 8971 | 8532 | return .none; |
| 8972 | 8533 | } |
| 8973 | 8534 | |
| 8974 | 8535 | fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8975 | 8536 | _ = inst; |
| 8976 | 8537 | const o = self.dg.object; |
| 8977 | const mod = o.module; | |
| 8978 | 8538 | const llvm_usize = try o.lowerType(Type.usize); |
| 8979 | const target = mod.getTarget(); | |
| 8980 | if (!target_util.supportsReturnAddress(target)) { | |
| 8539 | if (!target_util.supportsReturnAddress(o.module.getTarget())) { | |
| 8981 | 8540 | // https://github.com/ziglang/zig/issues/11946 |
| 8982 | 8541 | return o.builder.intValue(llvm_usize, 0); |
| 8983 | 8542 | } |
| 8984 | ||
| 8985 | const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{}); | |
| 8986 | const params = [_]*llvm.Value{ | |
| 8987 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), | |
| 8988 | }; | |
| 8989 | const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCallOld( | |
| 8990 | (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder), | |
| 8991 | llvm_fn, | |
| 8992 | &params, | |
| 8993 | params.len, | |
| 8994 | .Fast, | |
| 8995 | .Auto, | |
| 8996 | "", | |
| 8997 | ), &self.wip); | |
| 8998 | return self.wip.cast(.ptrtoint, ptr_val, llvm_usize, ""); | |
| 8543 | const result = try self.wip.callIntrinsic(.normal, .none, .returnaddress, &.{}, &.{ | |
| 8544 | try o.builder.intValue(.i32, 0), | |
| 8545 | }, ""); | |
| 8546 | return self.wip.cast(.ptrtoint, result, llvm_usize, ""); | |
| 8999 | 8547 | } |
| 9000 | 8548 | |
| 9001 | 8549 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9002 | 8550 | _ = inst; |
| 9003 | 8551 | const o = self.dg.object; |
| 9004 | const llvm_fn_name = "llvm.frameaddress.p0"; | |
| 9005 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | |
| 9006 | const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal); | |
| 9007 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); | |
| 9008 | }; | |
| 9009 | const llvm_fn_ty = try o.builder.fnType(.ptr, &.{.i32}, .normal); | |
| 9010 | ||
| 9011 | const params = [_]*llvm.Value{ | |
| 9012 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), | |
| 9013 | }; | |
| 9014 | const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( | |
| 9015 | self.builder.buildCallOld( | |
| 9016 | llvm_fn_ty.toLlvm(&o.builder), | |
| 9017 | llvm_fn, | |
| 9018 | &params, | |
| 9019 | params.len, | |
| 9020 | .Fast, | |
| 9021 | .Auto, | |
| 9022 | "", | |
| 9023 | ), | |
| 9024 | &self.wip, | |
| 9025 | ); | |
| 9026 | return self.wip.cast(.ptrtoint, ptr_val, try o.lowerType(Type.usize), ""); | |
| 8552 | const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{ | |
| 8553 | try o.builder.intValue(.i32, 0), | |
| 8554 | }, ""); | |
| 8555 | return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), ""); | |
| 9027 | 8556 | } |
| 9028 | 8557 | |
| 9029 | 8558 | fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9033,15 +8562,20 @@ pub const FuncGen = struct { |
| 9033 | 8562 | return .none; |
| 9034 | 8563 | } |
| 9035 | 8564 | |
| 9036 | fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !Builder.Value { | |
| 8565 | fn airCmpxchg( | |
| 8566 | self: *FuncGen, | |
| 8567 | inst: Air.Inst.Index, | |
| 8568 | kind: Builder.Function.Instruction.CmpXchg.Kind, | |
| 8569 | ) !Builder.Value { | |
| 9037 | 8570 | const o = self.dg.object; |
| 9038 | 8571 | const mod = o.module; |
| 9039 | 8572 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9040 | 8573 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| 9041 | 8574 | const ptr = try self.resolveInst(extra.ptr); |
| 8575 | const ptr_ty = self.typeOf(extra.ptr); | |
| 9042 | 8576 | var expected_value = try self.resolveInst(extra.expected_value); |
| 9043 | 8577 | var new_value = try self.resolveInst(extra.new_value); |
| 9044 | const operand_ty = self.typeOf(extra.ptr).childType(mod); | |
| 8578 | const operand_ty = ptr_ty.childType(mod); | |
| 9045 | 8579 | const llvm_operand_ty = try o.lowerType(operand_ty); |
| 9046 | 8580 | const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, false); |
| 9047 | 8581 | if (llvm_abi_ty != .none) { |
| ... | ... | @@ -9052,22 +8586,18 @@ pub const FuncGen = struct { |
| 9052 | 8586 | new_value = try self.wip.conv(signedness, new_value, llvm_abi_ty, ""); |
| 9053 | 8587 | } |
| 9054 | 8588 | |
| 9055 | const llvm_result_ty = try o.builder.structType(.normal, &.{ | |
| 9056 | if (llvm_abi_ty != .none) llvm_abi_ty else llvm_operand_ty, | |
| 9057 | .i1, | |
| 9058 | }); | |
| 9059 | const result = (try self.wip.unimplemented(llvm_result_ty, "")).finish( | |
| 9060 | self.builder.buildAtomicCmpXchg( | |
| 9061 | ptr.toLlvm(&self.wip), | |
| 9062 | expected_value.toLlvm(&self.wip), | |
| 9063 | new_value.toLlvm(&self.wip), | |
| 9064 | @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.successOrder()))), | |
| 9065 | @enumFromInt(@intFromEnum(toLlvmAtomicOrdering(extra.failureOrder()))), | |
| 9066 | llvm.Bool.fromBool(self.sync_scope == .singlethread), | |
| 9067 | ), | |
| 9068 | &self.wip, | |
| 8589 | const result = try self.wip.cmpxchg( | |
| 8590 | kind, | |
| 8591 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, | |
| 8592 | ptr, | |
| 8593 | expected_value, | |
| 8594 | new_value, | |
| 8595 | self.sync_scope, | |
| 8596 | toLlvmAtomicOrdering(extra.successOrder()), | |
| 8597 | toLlvmAtomicOrdering(extra.failureOrder()), | |
| 8598 | Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)), | |
| 8599 | "", | |
| 9069 | 8600 | ); |
| 9070 | result.toLlvm(&self.wip).setWeak(llvm.Bool.fromBool(is_weak)); | |
| 9071 | 8601 | |
| 9072 | 8602 | const optional_ty = self.typeOfIndex(inst); |
| 9073 | 8603 | |
| ... | ... | @@ -9077,7 +8607,7 @@ pub const FuncGen = struct { |
| 9077 | 8607 | |
| 9078 | 8608 | if (optional_ty.optionalReprIsPayload(mod)) { |
| 9079 | 8609 | const zero = try o.builder.zeroInitValue(payload.typeOfWip(&self.wip)); |
| 9080 | return self.wip.select(success_bit, zero, payload, ""); | |
| 8610 | return self.wip.select(.normal, success_bit, zero, payload, ""); | |
| 9081 | 8611 | } |
| 9082 | 8612 | |
| 9083 | 8613 | comptime assert(optional_layout_version == 3); |
| ... | ... | @@ -9099,63 +8629,54 @@ pub const FuncGen = struct { |
| 9099 | 8629 | const is_float = operand_ty.isRuntimeFloat(); |
| 9100 | 8630 | const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); |
| 9101 | 8631 | const ordering = toLlvmAtomicOrdering(extra.ordering()); |
| 9102 | const single_threaded = llvm.Bool.fromBool(self.sync_scope == .singlethread); | |
| 9103 | const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .Xchg); | |
| 8632 | const llvm_abi_ty = try o.getAtomicAbiType(operand_ty, op == .xchg); | |
| 9104 | 8633 | const llvm_operand_ty = try o.lowerType(operand_ty); |
| 8634 | ||
| 8635 | const access_kind: Builder.MemoryAccessKind = | |
| 8636 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal; | |
| 8637 | const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)); | |
| 8638 | ||
| 9105 | 8639 | if (llvm_abi_ty != .none) { |
| 9106 | 8640 | // operand needs widening and truncating or bitcasting. |
| 9107 | const casted_operand = try self.wip.cast( | |
| 9108 | if (is_float) .bitcast else if (is_signed_int) .sext else .zext, | |
| 9109 | @enumFromInt(@intFromEnum(operand)), | |
| 9110 | llvm_abi_ty, | |
| 9111 | "", | |
| 9112 | ); | |
| 9113 | ||
| 9114 | const uncasted_result = (try self.wip.unimplemented(llvm_abi_ty, "")).finish( | |
| 9115 | self.builder.buildAtomicRmw( | |
| 9116 | op, | |
| 9117 | ptr.toLlvm(&self.wip), | |
| 9118 | casted_operand.toLlvm(&self.wip), | |
| 9119 | @enumFromInt(@intFromEnum(ordering)), | |
| 9120 | single_threaded, | |
| 8641 | return self.wip.cast(if (is_float) .bitcast else .trunc, try self.wip.atomicrmw( | |
| 8642 | access_kind, | |
| 8643 | op, | |
| 8644 | ptr, | |
| 8645 | try self.wip.cast( | |
| 8646 | if (is_float) .bitcast else if (is_signed_int) .sext else .zext, | |
| 8647 | operand, | |
| 8648 | llvm_abi_ty, | |
| 8649 | "", | |
| 9121 | 8650 | ), |
| 9122 | &self.wip, | |
| 9123 | ); | |
| 9124 | ||
| 9125 | if (is_float) { | |
| 9126 | return self.wip.cast(.bitcast, uncasted_result, llvm_operand_ty, ""); | |
| 9127 | } else { | |
| 9128 | return self.wip.cast(.trunc, uncasted_result, llvm_operand_ty, ""); | |
| 9129 | } | |
| 8651 | self.sync_scope, | |
| 8652 | ordering, | |
| 8653 | ptr_alignment, | |
| 8654 | "", | |
| 8655 | ), llvm_operand_ty, ""); | |
| 9130 | 8656 | } |
| 9131 | 8657 | |
| 9132 | if (!llvm_operand_ty.isPointer(&o.builder)) { | |
| 9133 | return (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | |
| 9134 | self.builder.buildAtomicRmw( | |
| 9135 | op, | |
| 9136 | ptr.toLlvm(&self.wip), | |
| 9137 | operand.toLlvm(&self.wip), | |
| 9138 | @enumFromInt(@intFromEnum(ordering)), | |
| 9139 | single_threaded, | |
| 9140 | ), | |
| 9141 | &self.wip, | |
| 9142 | ); | |
| 9143 | } | |
| 8658 | if (!llvm_operand_ty.isPointer(&o.builder)) return self.wip.atomicrmw( | |
| 8659 | access_kind, | |
| 8660 | op, | |
| 8661 | ptr, | |
| 8662 | operand, | |
| 8663 | self.sync_scope, | |
| 8664 | ordering, | |
| 8665 | ptr_alignment, | |
| 8666 | "", | |
| 8667 | ); | |
| 9144 | 8668 | |
| 9145 | 8669 | // It's a pointer but we need to treat it as an int. |
| 9146 | const llvm_usize = try o.lowerType(Type.usize); | |
| 9147 | const casted_operand = try self.wip.cast(.ptrtoint, operand, llvm_usize, ""); | |
| 9148 | const uncasted_result = (try self.wip.unimplemented(llvm_usize, "")).finish( | |
| 9149 | self.builder.buildAtomicRmw( | |
| 9150 | op, | |
| 9151 | ptr.toLlvm(&self.wip), | |
| 9152 | casted_operand.toLlvm(&self.wip), | |
| 9153 | @enumFromInt(@intFromEnum(ordering)), | |
| 9154 | single_threaded, | |
| 9155 | ), | |
| 9156 | &self.wip, | |
| 9157 | ); | |
| 9158 | return self.wip.cast(.inttoptr, uncasted_result, llvm_operand_ty, ""); | |
| 8670 | return self.wip.cast(.inttoptr, try self.wip.atomicrmw( | |
| 8671 | access_kind, | |
| 8672 | op, | |
| 8673 | ptr, | |
| 8674 | try self.wip.cast(.ptrtoint, operand, try o.lowerType(Type.usize), ""), | |
| 8675 | self.sync_scope, | |
| 8676 | ordering, | |
| 8677 | ptr_alignment, | |
| 8678 | "", | |
| 8679 | ), llvm_operand_ty, ""); | |
| 9159 | 8680 | } |
| 9160 | 8681 | |
| 9161 | 8682 | fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9172,16 +8693,14 @@ pub const FuncGen = struct { |
| 9172 | 8693 | const ptr_alignment = Builder.Alignment.fromByteUnits( |
| 9173 | 8694 | info.flags.alignment.toByteUnitsOptional() orelse info.child.toType().abiAlignment(mod), |
| 9174 | 8695 | ); |
| 9175 | const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) { | |
| 9176 | false => .normal, | |
| 9177 | true => .@"volatile", | |
| 9178 | }; | |
| 8696 | const access_kind: Builder.MemoryAccessKind = | |
| 8697 | if (info.flags.is_volatile) .@"volatile" else .normal; | |
| 9179 | 8698 | const elem_llvm_ty = try o.lowerType(elem_ty); |
| 9180 | 8699 | |
| 9181 | 8700 | if (llvm_abi_ty != .none) { |
| 9182 | 8701 | // operand needs widening and truncating |
| 9183 | 8702 | const loaded = try self.wip.loadAtomic( |
| 9184 | ptr_kind, | |
| 8703 | access_kind, | |
| 9185 | 8704 | llvm_abi_ty, |
| 9186 | 8705 | ptr, |
| 9187 | 8706 | self.sync_scope, |
| ... | ... | @@ -9192,7 +8711,7 @@ pub const FuncGen = struct { |
| 9192 | 8711 | return self.wip.cast(.trunc, loaded, elem_llvm_ty, ""); |
| 9193 | 8712 | } |
| 9194 | 8713 | return self.wip.loadAtomic( |
| 9195 | ptr_kind, | |
| 8714 | access_kind, | |
| 9196 | 8715 | elem_llvm_ty, |
| 9197 | 8716 | ptr, |
| 9198 | 8717 | self.sync_scope, |
| ... | ... | @@ -9239,7 +8758,8 @@ pub const FuncGen = struct { |
| 9239 | 8758 | const elem_ty = self.typeOf(bin_op.rhs); |
| 9240 | 8759 | const dest_ptr_align = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)); |
| 9241 | 8760 | const dest_ptr = try self.sliceOrArrayPtr(dest_slice, ptr_ty); |
| 9242 | const is_volatile = ptr_ty.isVolatilePtr(mod); | |
| 8761 | const access_kind: Builder.MemoryAccessKind = | |
| 8762 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal; | |
| 9243 | 8763 | |
| 9244 | 8764 | // Any WebAssembly runtime will trap when the destination pointer is out-of-bounds, regardless |
| 9245 | 8765 | // of the length. This means we need to emit a check where we skip the memset when the length |
| ... | ... | @@ -9260,17 +8780,10 @@ pub const FuncGen = struct { |
| 9260 | 8780 | try o.builder.undefValue(.i8); |
| 9261 | 8781 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 9262 | 8782 | if (intrinsic_len0_traps) { |
| 9263 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | |
| 8783 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); | |
| 9264 | 8784 | } else { |
| 9265 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet( | |
| 9266 | dest_ptr.toLlvm(&self.wip), | |
| 9267 | fill_byte.toLlvm(&self.wip), | |
| 9268 | len.toLlvm(&self.wip), | |
| 9269 | @intCast(dest_ptr_align.toByteUnits() orelse 0), | |
| 9270 | is_volatile, | |
| 9271 | ), &self.wip); | |
| 8785 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); | |
| 9272 | 8786 | } |
| 9273 | ||
| 9274 | 8787 | if (safety and mod.comp.bin_file.options.valgrind) { |
| 9275 | 8788 | try self.valgrindMarkUndef(dest_ptr, len); |
| 9276 | 8789 | } |
| ... | ... | @@ -9282,19 +8795,12 @@ pub const FuncGen = struct { |
| 9282 | 8795 | // repeating byte pattern of 0 bytes. In such case, the memset |
| 9283 | 8796 | // intrinsic can be used. |
| 9284 | 8797 | if (try elem_val.hasRepeatedByteRepr(elem_ty, mod)) |byte_val| { |
| 9285 | const fill_byte = try self.resolveValue(.{ .ty = Type.u8, .val = byte_val }); | |
| 8798 | const fill_byte = try o.builder.intValue(.i8, byte_val); | |
| 9286 | 8799 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 9287 | ||
| 9288 | 8800 | if (intrinsic_len0_traps) { |
| 9289 | try self.safeWasmMemset(dest_ptr, fill_byte.toValue(), len, dest_ptr_align, is_volatile); | |
| 8801 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); | |
| 9290 | 8802 | } else { |
| 9291 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet( | |
| 9292 | dest_ptr.toLlvm(&self.wip), | |
| 9293 | fill_byte.toLlvm(&o.builder), | |
| 9294 | len.toLlvm(&self.wip), | |
| 9295 | @intCast(dest_ptr_align.toByteUnits() orelse 0), | |
| 9296 | is_volatile, | |
| 9297 | ), &self.wip); | |
| 8803 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); | |
| 9298 | 8804 | } |
| 9299 | 8805 | return .none; |
| 9300 | 8806 | } |
| ... | ... | @@ -9309,15 +8815,9 @@ pub const FuncGen = struct { |
| 9309 | 8815 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 9310 | 8816 | |
| 9311 | 8817 | if (intrinsic_len0_traps) { |
| 9312 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | |
| 8818 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); | |
| 9313 | 8819 | } else { |
| 9314 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet( | |
| 9315 | dest_ptr.toLlvm(&self.wip), | |
| 9316 | fill_byte.toLlvm(&self.wip), | |
| 9317 | len.toLlvm(&self.wip), | |
| 9318 | @intCast(dest_ptr_align.toByteUnits() orelse 0), | |
| 9319 | is_volatile, | |
| 9320 | ), &self.wip); | |
| 8820 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); | |
| 9321 | 8821 | } |
| 9322 | 8822 | return .none; |
| 9323 | 8823 | } |
| ... | ... | @@ -9343,10 +8843,10 @@ pub const FuncGen = struct { |
| 9343 | 8843 | const body_block = try self.wip.block(1, "InlineMemsetBody"); |
| 9344 | 8844 | const end_block = try self.wip.block(1, "InlineMemsetEnd"); |
| 9345 | 8845 | |
| 9346 | const usize_ty = try o.lowerType(Type.usize); | |
| 8846 | const llvm_usize_ty = try o.lowerType(Type.usize); | |
| 9347 | 8847 | const len = switch (ptr_ty.ptrSize(mod)) { |
| 9348 | 8848 | .Slice => try self.wip.extractValue(dest_slice, &.{1}, ""), |
| 9349 | .One => try o.builder.intValue(usize_ty, ptr_ty.childType(mod).arrayLen(mod)), | |
| 8849 | .One => try o.builder.intValue(llvm_usize_ty, ptr_ty.childType(mod).arrayLen(mod)), | |
| 9350 | 8850 | .Many, .C => unreachable, |
| 9351 | 8851 | }; |
| 9352 | 8852 | const elem_llvm_ty = try o.lowerType(elem_ty); |
| ... | ... | @@ -9359,25 +8859,22 @@ pub const FuncGen = struct { |
| 9359 | 8859 | _ = try self.wip.brCond(end, body_block, end_block); |
| 9360 | 8860 | |
| 9361 | 8861 | self.wip.cursor = .{ .block = body_block }; |
| 9362 | const elem_abi_alignment = elem_ty.abiAlignment(mod); | |
| 9363 | const it_ptr_alignment = Builder.Alignment.fromByteUnits( | |
| 9364 | @min(elem_abi_alignment, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)), | |
| 8862 | const elem_abi_align = elem_ty.abiAlignment(mod); | |
| 8863 | const it_ptr_align = Builder.Alignment.fromByteUnits( | |
| 8864 | @min(elem_abi_align, dest_ptr_align.toByteUnits() orelse std.math.maxInt(u64)), | |
| 9365 | 8865 | ); |
| 9366 | 8866 | if (isByRef(elem_ty, mod)) { |
| 9367 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy( | |
| 9368 | it_ptr.toValue().toLlvm(&self.wip), | |
| 9369 | @intCast(it_ptr_alignment.toByteUnits() orelse 0), | |
| 9370 | value.toLlvm(&self.wip), | |
| 9371 | elem_abi_alignment, | |
| 9372 | (try o.builder.intConst(usize_ty, elem_abi_size)).toLlvm(&o.builder), | |
| 9373 | is_volatile, | |
| 9374 | ), &self.wip); | |
| 9375 | } else _ = try self.wip.store(switch (is_volatile) { | |
| 9376 | false => .normal, | |
| 9377 | true => .@"volatile", | |
| 9378 | }, value, it_ptr.toValue(), it_ptr_alignment); | |
| 8867 | _ = try self.wip.callMemCpy( | |
| 8868 | it_ptr.toValue(), | |
| 8869 | it_ptr_align, | |
| 8870 | value, | |
| 8871 | Builder.Alignment.fromByteUnits(elem_abi_align), | |
| 8872 | try o.builder.intValue(llvm_usize_ty, elem_abi_size), | |
| 8873 | access_kind, | |
| 8874 | ); | |
| 8875 | } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align); | |
| 9379 | 8876 | const next_ptr = try self.wip.gep(.inbounds, elem_llvm_ty, it_ptr.toValue(), &.{ |
| 9380 | try o.builder.intValue(usize_ty, 1), | |
| 8877 | try o.builder.intValue(llvm_usize_ty, 1), | |
| 9381 | 8878 | }, ""); |
| 9382 | 8879 | _ = try self.wip.br(loop_block); |
| 9383 | 8880 | |
| ... | ... | @@ -9392,22 +8889,16 @@ pub const FuncGen = struct { |
| 9392 | 8889 | fill_byte: Builder.Value, |
| 9393 | 8890 | len: Builder.Value, |
| 9394 | 8891 | dest_ptr_align: Builder.Alignment, |
| 9395 | is_volatile: bool, | |
| 8892 | access_kind: Builder.MemoryAccessKind, | |
| 9396 | 8893 | ) !void { |
| 9397 | 8894 | const o = self.dg.object; |
| 9398 | const llvm_usize_ty = try o.lowerType(Type.usize); | |
| 9399 | const cond = try self.cmp(len, try o.builder.intValue(llvm_usize_ty, 0), Type.usize, .neq); | |
| 8895 | const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0); | |
| 8896 | const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero); | |
| 9400 | 8897 | const memset_block = try self.wip.block(1, "MemsetTrapSkip"); |
| 9401 | 8898 | const end_block = try self.wip.block(2, "MemsetTrapEnd"); |
| 9402 | 8899 | _ = try self.wip.brCond(cond, memset_block, end_block); |
| 9403 | 8900 | self.wip.cursor = .{ .block = memset_block }; |
| 9404 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemSet( | |
| 9405 | dest_ptr.toLlvm(&self.wip), | |
| 9406 | fill_byte.toLlvm(&self.wip), | |
| 9407 | len.toLlvm(&self.wip), | |
| 9408 | @intCast(dest_ptr_align.toByteUnits() orelse 0), | |
| 9409 | is_volatile, | |
| 9410 | ), &self.wip); | |
| 8901 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); | |
| 9411 | 8902 | _ = try self.wip.br(end_block); |
| 9412 | 8903 | self.wip.cursor = .{ .block = end_block }; |
| 9413 | 8904 | } |
| ... | ... | @@ -9423,7 +8914,8 @@ pub const FuncGen = struct { |
| 9423 | 8914 | const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ptr_ty); |
| 9424 | 8915 | const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); |
| 9425 | 8916 | const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); |
| 9426 | const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); | |
| 8917 | const access_kind: Builder.MemoryAccessKind = if (src_ptr_ty.isVolatilePtr(mod) or | |
| 8918 | dest_ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal; | |
| 9427 | 8919 | |
| 9428 | 8920 | // When bulk-memory is enabled, this will be lowered to WebAssembly's memory.copy instruction. |
| 9429 | 8921 | // This instruction will trap on an invalid address, regardless of the length. |
| ... | ... | @@ -9434,33 +8926,33 @@ pub const FuncGen = struct { |
| 9434 | 8926 | std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and |
| 9435 | 8927 | dest_ptr_ty.isSlice(mod)) |
| 9436 | 8928 | { |
| 9437 | const zero_usize = try o.builder.intValue(try o.lowerType(Type.usize), 0); | |
| 9438 | const cond = try self.cmp(len, zero_usize, Type.usize, .neq); | |
| 8929 | const usize_zero = try o.builder.intValue(try o.lowerType(Type.usize), 0); | |
| 8930 | const cond = try self.cmp(.normal, .neq, Type.usize, len, usize_zero); | |
| 9439 | 8931 | const memcpy_block = try self.wip.block(1, "MemcpyTrapSkip"); |
| 9440 | 8932 | const end_block = try self.wip.block(2, "MemcpyTrapEnd"); |
| 9441 | 8933 | _ = try self.wip.brCond(cond, memcpy_block, end_block); |
| 9442 | 8934 | self.wip.cursor = .{ .block = memcpy_block }; |
| 9443 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy( | |
| 9444 | dest_ptr.toLlvm(&self.wip), | |
| 9445 | dest_ptr_ty.ptrAlignment(mod), | |
| 9446 | src_ptr.toLlvm(&self.wip), | |
| 9447 | src_ptr_ty.ptrAlignment(mod), | |
| 9448 | len.toLlvm(&self.wip), | |
| 9449 | is_volatile, | |
| 9450 | ), &self.wip); | |
| 8935 | _ = try self.wip.callMemCpy( | |
| 8936 | dest_ptr, | |
| 8937 | Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)), | |
| 8938 | src_ptr, | |
| 8939 | Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)), | |
| 8940 | len, | |
| 8941 | access_kind, | |
| 8942 | ); | |
| 9451 | 8943 | _ = try self.wip.br(end_block); |
| 9452 | 8944 | self.wip.cursor = .{ .block = end_block }; |
| 9453 | 8945 | return .none; |
| 9454 | 8946 | } |
| 9455 | 8947 | |
| 9456 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy( | |
| 9457 | dest_ptr.toLlvm(&self.wip), | |
| 9458 | dest_ptr_ty.ptrAlignment(mod), | |
| 9459 | src_ptr.toLlvm(&self.wip), | |
| 9460 | src_ptr_ty.ptrAlignment(mod), | |
| 9461 | len.toLlvm(&self.wip), | |
| 9462 | is_volatile, | |
| 9463 | ), &self.wip); | |
| 8948 | _ = try self.wip.callMemCpy( | |
| 8949 | dest_ptr, | |
| 8950 | Builder.Alignment.fromByteUnits(dest_ptr_ty.ptrAlignment(mod)), | |
| 8951 | src_ptr, | |
| 8952 | Builder.Alignment.fromByteUnits(src_ptr_ty.ptrAlignment(mod)), | |
| 8953 | len, | |
| 8954 | access_kind, | |
| 8955 | ); | |
| 9464 | 8956 | return .none; |
| 9465 | 8957 | } |
| 9466 | 8958 | |
| ... | ... | @@ -9513,39 +9005,51 @@ pub const FuncGen = struct { |
| 9513 | 9005 | const operand = try self.resolveInst(un_op); |
| 9514 | 9006 | const operand_ty = self.typeOf(un_op); |
| 9515 | 9007 | |
| 9516 | return self.buildFloatOp(op, operand_ty, 1, .{operand}); | |
| 9008 | return self.buildFloatOp(op, .normal, operand_ty, 1, .{operand}); | |
| 9517 | 9009 | } |
| 9518 | 9010 | |
| 9519 | fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 9520 | self.builder.setFastMath(want_fast_math); | |
| 9521 | ||
| 9011 | fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 9522 | 9012 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 9523 | 9013 | const operand = try self.resolveInst(un_op); |
| 9524 | 9014 | const operand_ty = self.typeOf(un_op); |
| 9525 | 9015 | |
| 9526 | return self.buildFloatOp(.neg, operand_ty, 1, .{operand}); | |
| 9016 | return self.buildFloatOp(.neg, fast, operand_ty, 1, .{operand}); | |
| 9527 | 9017 | } |
| 9528 | 9018 | |
| 9529 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { | |
| 9019 | fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { | |
| 9530 | 9020 | const o = self.dg.object; |
| 9531 | 9021 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 9022 | const inst_ty = self.typeOfIndex(inst); | |
| 9023 | const operand_ty = self.typeOf(ty_op.operand); | |
| 9532 | 9024 | const operand = try self.resolveInst(ty_op.operand); |
| 9533 | 9025 | |
| 9534 | const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), ""); | |
| 9535 | ||
| 9536 | const result_ty = self.typeOfIndex(inst); | |
| 9537 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); | |
| 9026 | const result = try self.wip.callIntrinsic( | |
| 9027 | .normal, | |
| 9028 | .none, | |
| 9029 | intrinsic, | |
| 9030 | &.{try o.lowerType(operand_ty)}, | |
| 9031 | &.{ operand, .false }, | |
| 9032 | "", | |
| 9033 | ); | |
| 9034 | return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); | |
| 9538 | 9035 | } |
| 9539 | 9036 | |
| 9540 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { | |
| 9037 | fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { | |
| 9541 | 9038 | const o = self.dg.object; |
| 9542 | 9039 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 9040 | const inst_ty = self.typeOfIndex(inst); | |
| 9041 | const operand_ty = self.typeOf(ty_op.operand); | |
| 9543 | 9042 | const operand = try self.resolveInst(ty_op.operand); |
| 9544 | 9043 | |
| 9545 | const wrong_size_result = try self.wip.un(intrinsic, operand, ""); | |
| 9546 | ||
| 9547 | const result_ty = self.typeOfIndex(inst); | |
| 9548 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); | |
| 9044 | const result = try self.wip.callIntrinsic( | |
| 9045 | .normal, | |
| 9046 | .none, | |
| 9047 | intrinsic, | |
| 9048 | &.{try o.lowerType(operand_ty)}, | |
| 9049 | &.{operand}, | |
| 9050 | "", | |
| 9051 | ); | |
| 9052 | return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); | |
| 9549 | 9053 | } |
| 9550 | 9054 | |
| 9551 | 9055 | fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9556,6 +9060,7 @@ pub const FuncGen = struct { |
| 9556 | 9060 | var bits = operand_ty.intInfo(mod).bits; |
| 9557 | 9061 | assert(bits % 8 == 0); |
| 9558 | 9062 | |
| 9063 | const inst_ty = self.typeOfIndex(inst); | |
| 9559 | 9064 | var operand = try self.resolveInst(ty_op.operand); |
| 9560 | 9065 | var llvm_operand_ty = try o.lowerType(operand_ty); |
| 9561 | 9066 | |
| ... | ... | @@ -9576,10 +9081,9 @@ pub const FuncGen = struct { |
| 9576 | 9081 | bits = bits + 8; |
| 9577 | 9082 | } |
| 9578 | 9083 | |
| 9579 | const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, ""); | |
| 9580 | ||
| 9581 | const result_ty = self.typeOfIndex(inst); | |
| 9582 | return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); | |
| 9084 | const result = | |
| 9085 | try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, ""); | |
| 9086 | return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); | |
| 9583 | 9087 | } |
| 9584 | 9088 | |
| 9585 | 9089 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9609,11 +9113,7 @@ pub const FuncGen = struct { |
| 9609 | 9113 | |
| 9610 | 9114 | self.wip.cursor = .{ .block = end_block }; |
| 9611 | 9115 | const phi = try self.wip.phi(.i1, ""); |
| 9612 | try phi.finish( | |
| 9613 | &.{ Builder.Constant.true.toValue(), Builder.Constant.false.toValue() }, | |
| 9614 | &.{ valid_block, invalid_block }, | |
| 9615 | &self.wip, | |
| 9616 | ); | |
| 9116 | try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip); | |
| 9617 | 9117 | return phi.toValue(); |
| 9618 | 9118 | } |
| 9619 | 9119 | |
| ... | ... | @@ -9646,37 +9146,22 @@ pub const FuncGen = struct { |
| 9646 | 9146 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); |
| 9647 | 9147 | |
| 9648 | 9148 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9649 | const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{ | |
| 9650 | fqn.fmt(&mod.intern_pool), | |
| 9651 | }); | |
| 9149 | const function_index = try o.builder.addFunction( | |
| 9150 | try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal), | |
| 9151 | try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}), | |
| 9152 | toLlvmAddressSpace(.generic, mod.getTarget()), | |
| 9153 | ); | |
| 9652 | 9154 | |
| 9653 | 9155 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9654 | 9156 | defer attributes.deinit(&o.builder); |
| 9157 | try o.addCommonFnAttributes(&attributes); | |
| 9655 | 9158 | |
| 9656 | const fn_type = try o.builder.fnType(.i1, &.{ | |
| 9657 | try o.lowerType(enum_type.tag_ty.toType()), | |
| 9658 | }, .normal); | |
| 9659 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); | |
| 9660 | fn_val.setLinkage(.Internal); | |
| 9661 | fn_val.setFunctionCallConv(.Fast); | |
| 9662 | try o.addCommonFnAttributes(&attributes, fn_val); | |
| 9663 | ||
| 9664 | var global = Builder.Global{ | |
| 9665 | .linkage = .internal, | |
| 9666 | .type = fn_type, | |
| 9667 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | |
| 9668 | }; | |
| 9669 | var function = Builder.Function{ | |
| 9670 | .global = @enumFromInt(o.builder.globals.count()), | |
| 9671 | .call_conv = .fastcc, | |
| 9672 | .attributes = try attributes.finish(&o.builder), | |
| 9673 | }; | |
| 9674 | try o.builder.llvm.globals.append(self.gpa, fn_val); | |
| 9675 | _ = try o.builder.addGlobal(llvm_fn_name, global); | |
| 9676 | try o.builder.functions.append(self.gpa, function); | |
| 9677 | gop.value_ptr.* = global.kind.function; | |
| 9159 | function_index.setLinkage(.internal, &o.builder); | |
| 9160 | function_index.setCallConv(.fastcc, &o.builder); | |
| 9161 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 9162 | gop.value_ptr.* = function_index; | |
| 9678 | 9163 | |
| 9679 | var wip = try Builder.WipFunction.init(&o.builder, global.kind.function); | |
| 9164 | var wip = try Builder.WipFunction.init(&o.builder, function_index); | |
| 9680 | 9165 | defer wip.deinit(); |
| 9681 | 9166 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 9682 | 9167 | |
| ... | ... | @@ -9693,13 +9178,13 @@ pub const FuncGen = struct { |
| 9693 | 9178 | try wip_switch.addCase(this_tag_int_value, named_block, &wip); |
| 9694 | 9179 | } |
| 9695 | 9180 | wip.cursor = .{ .block = named_block }; |
| 9696 | _ = try wip.ret(Builder.Constant.true.toValue()); | |
| 9181 | _ = try wip.ret(.true); | |
| 9697 | 9182 | |
| 9698 | 9183 | wip.cursor = .{ .block = unnamed_block }; |
| 9699 | _ = try wip.ret(Builder.Constant.false.toValue()); | |
| 9184 | _ = try wip.ret(.false); | |
| 9700 | 9185 | |
| 9701 | 9186 | try wip.finish(); |
| 9702 | return global.kind.function; | |
| 9187 | return function_index; | |
| 9703 | 9188 | } |
| 9704 | 9189 | |
| 9705 | 9190 | fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9730,38 +9215,25 @@ pub const FuncGen = struct { |
| 9730 | 9215 | if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; |
| 9731 | 9216 | errdefer assert(o.decl_map.remove(enum_type.decl)); |
| 9732 | 9217 | |
| 9218 | const usize_ty = try o.lowerType(Type.usize); | |
| 9219 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); | |
| 9733 | 9220 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9734 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); | |
| 9221 | const function_index = try o.builder.addFunction( | |
| 9222 | try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal), | |
| 9223 | try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}), | |
| 9224 | toLlvmAddressSpace(.generic, mod.getTarget()), | |
| 9225 | ); | |
| 9735 | 9226 | |
| 9736 | 9227 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9737 | 9228 | defer attributes.deinit(&o.builder); |
| 9229 | try o.addCommonFnAttributes(&attributes); | |
| 9738 | 9230 | |
| 9739 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); | |
| 9740 | const usize_ty = try o.lowerType(Type.usize); | |
| 9231 | function_index.setLinkage(.internal, &o.builder); | |
| 9232 | function_index.setCallConv(.fastcc, &o.builder); | |
| 9233 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 9234 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; | |
| 9741 | 9235 | |
| 9742 | const fn_type = try o.builder.fnType(ret_ty, &.{ | |
| 9743 | try o.lowerType(enum_type.tag_ty.toType()), | |
| 9744 | }, .normal); | |
| 9745 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); | |
| 9746 | fn_val.setLinkage(.Internal); | |
| 9747 | fn_val.setFunctionCallConv(.Fast); | |
| 9748 | try o.addCommonFnAttributes(&attributes, fn_val); | |
| 9749 | ||
| 9750 | var global = Builder.Global{ | |
| 9751 | .linkage = .internal, | |
| 9752 | .type = fn_type, | |
| 9753 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | |
| 9754 | }; | |
| 9755 | var function = Builder.Function{ | |
| 9756 | .global = @enumFromInt(o.builder.globals.count()), | |
| 9757 | .call_conv = .fastcc, | |
| 9758 | .attributes = try attributes.finish(&o.builder), | |
| 9759 | }; | |
| 9760 | try o.builder.llvm.globals.append(self.gpa, fn_val); | |
| 9761 | gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); | |
| 9762 | try o.builder.functions.append(self.gpa, function); | |
| 9763 | ||
| 9764 | var wip = try Builder.WipFunction.init(&o.builder, global.kind.function); | |
| 9236 | var wip = try Builder.WipFunction.init(&o.builder, function_index); | |
| 9765 | 9237 | defer wip.deinit(); |
| 9766 | 9238 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 9767 | 9239 | |
| ... | ... | @@ -9771,36 +9243,20 @@ pub const FuncGen = struct { |
| 9771 | 9243 | try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len)); |
| 9772 | 9244 | defer wip_switch.finish(&wip); |
| 9773 | 9245 | |
| 9774 | for (enum_type.names, 0..) |name_ip, field_index| { | |
| 9775 | const name = try o.builder.string(mod.intern_pool.stringToSlice(name_ip)); | |
| 9776 | const str_init = try o.builder.stringNullConst(name); | |
| 9777 | const str_ty = str_init.typeOf(&o.builder); | |
| 9778 | const str_llvm_global = o.llvm_module.addGlobal(str_ty.toLlvm(&o.builder), ""); | |
| 9779 | str_llvm_global.setInitializer(str_init.toLlvm(&o.builder)); | |
| 9780 | str_llvm_global.setLinkage(.Private); | |
| 9781 | str_llvm_global.setGlobalConstant(.True); | |
| 9782 | str_llvm_global.setUnnamedAddr(.True); | |
| 9783 | str_llvm_global.setAlignment(1); | |
| 9784 | ||
| 9785 | var str_global = Builder.Global{ | |
| 9786 | .linkage = .private, | |
| 9787 | .unnamed_addr = .unnamed_addr, | |
| 9788 | .type = str_ty, | |
| 9789 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 9790 | }; | |
| 9791 | var str_variable = Builder.Variable{ | |
| 9792 | .global = @enumFromInt(o.builder.globals.count()), | |
| 9793 | .mutability = .constant, | |
| 9794 | .init = str_init, | |
| 9795 | .alignment = comptime Builder.Alignment.fromByteUnits(1), | |
| 9796 | }; | |
| 9797 | try o.builder.llvm.globals.append(o.gpa, str_llvm_global); | |
| 9798 | const global_index = try o.builder.addGlobal(.empty, str_global); | |
| 9799 | try o.builder.variables.append(o.gpa, str_variable); | |
| 9800 | ||
| 9801 | const slice_val = try o.builder.structValue(ret_ty, &.{ | |
| 9802 | global_index.toConst(), | |
| 9803 | try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), | |
| 9246 | for (enum_type.names, 0..) |name, field_index| { | |
| 9247 | const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name)); | |
| 9248 | const name_init = try o.builder.stringNullConst(name_string); | |
| 9249 | const name_variable_index = | |
| 9250 | try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); | |
| 9251 | try name_variable_index.setInitializer(name_init, &o.builder); | |
| 9252 | name_variable_index.setLinkage(.private, &o.builder); | |
| 9253 | name_variable_index.setMutability(.constant, &o.builder); | |
| 9254 | name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 9255 | name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); | |
| 9256 | ||
| 9257 | const name_val = try o.builder.structValue(ret_ty, &.{ | |
| 9258 | name_variable_index.toConst(&o.builder), | |
| 9259 | try o.builder.intConst(usize_ty, name_string.slice(&o.builder).?.len), | |
| 9804 | 9260 | }); |
| 9805 | 9261 | |
| 9806 | 9262 | const return_block = try wip.block(1, "Name"); |
| ... | ... | @@ -9810,14 +9266,14 @@ pub const FuncGen = struct { |
| 9810 | 9266 | try wip_switch.addCase(this_tag_int_value, return_block, &wip); |
| 9811 | 9267 | |
| 9812 | 9268 | wip.cursor = .{ .block = return_block }; |
| 9813 | _ = try wip.ret(slice_val); | |
| 9269 | _ = try wip.ret(name_val); | |
| 9814 | 9270 | } |
| 9815 | 9271 | |
| 9816 | 9272 | wip.cursor = .{ .block = bad_value_block }; |
| 9817 | 9273 | _ = try wip.@"unreachable"(); |
| 9818 | 9274 | |
| 9819 | 9275 | try wip.finish(); |
| 9820 | return global.kind.function; | |
| 9276 | return function_index; | |
| 9821 | 9277 | } |
| 9822 | 9278 | |
| 9823 | 9279 | fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index { |
| ... | ... | @@ -9826,33 +9282,20 @@ pub const FuncGen = struct { |
| 9826 | 9282 | const name = try o.builder.string(lt_errors_fn_name); |
| 9827 | 9283 | if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; |
| 9828 | 9284 | |
| 9829 | // Function signature: fn (anyerror) bool | |
| 9830 | ||
| 9831 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); | |
| 9832 | const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); | |
| 9285 | const function_index = try o.builder.addFunction( | |
| 9286 | try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal), | |
| 9287 | name, | |
| 9288 | toLlvmAddressSpace(.generic, o.module.getTarget()), | |
| 9289 | ); | |
| 9833 | 9290 | |
| 9834 | 9291 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9835 | 9292 | defer attributes.deinit(&o.builder); |
| 9293 | try o.addCommonFnAttributes(&attributes); | |
| 9836 | 9294 | |
| 9837 | llvm_fn.setLinkage(.Internal); | |
| 9838 | llvm_fn.setFunctionCallConv(.Fast); | |
| 9839 | try o.addCommonFnAttributes(&attributes, llvm_fn); | |
| 9840 | ||
| 9841 | var global = Builder.Global{ | |
| 9842 | .linkage = .internal, | |
| 9843 | .type = fn_type, | |
| 9844 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | |
| 9845 | }; | |
| 9846 | var function = Builder.Function{ | |
| 9847 | .global = @enumFromInt(o.builder.globals.count()), | |
| 9848 | .call_conv = .fastcc, | |
| 9849 | .attributes = try attributes.finish(&o.builder), | |
| 9850 | }; | |
| 9851 | ||
| 9852 | try o.builder.llvm.globals.append(self.gpa, llvm_fn); | |
| 9853 | _ = try o.builder.addGlobal(name, global); | |
| 9854 | try o.builder.functions.append(self.gpa, function); | |
| 9855 | return global.kind.function; | |
| 9295 | function_index.setLinkage(.internal, &o.builder); | |
| 9296 | function_index.setCallConv(.fastcc, &o.builder); | |
| 9297 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 9298 | return function_index; | |
| 9856 | 9299 | } |
| 9857 | 9300 | |
| 9858 | 9301 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9885,7 +9328,7 @@ pub const FuncGen = struct { |
| 9885 | 9328 | const a = try self.resolveInst(extra.lhs); |
| 9886 | 9329 | const b = try self.resolveInst(extra.rhs); |
| 9887 | 9330 | |
| 9888 | return self.wip.select(pred, a, b, ""); | |
| 9331 | return self.wip.select(.normal, pred, a, b, ""); | |
| 9889 | 9332 | } |
| 9890 | 9333 | |
| 9891 | 9334 | fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -9997,8 +9440,7 @@ pub const FuncGen = struct { |
| 9997 | 9440 | return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, ""); |
| 9998 | 9441 | } |
| 9999 | 9442 | |
| 10000 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | |
| 10001 | self.builder.setFastMath(want_fast_math); | |
| 9443 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { | |
| 10002 | 9444 | const o = self.dg.object; |
| 10003 | 9445 | const mod = o.module; |
| 10004 | 9446 | const target = mod.getTarget(); |
| ... | ... | @@ -10006,72 +9448,53 @@ pub const FuncGen = struct { |
| 10006 | 9448 | const reduce = self.air.instructions.items(.data)[inst].reduce; |
| 10007 | 9449 | const operand = try self.resolveInst(reduce.operand); |
| 10008 | 9450 | const operand_ty = self.typeOf(reduce.operand); |
| 9451 | const llvm_operand_ty = try o.lowerType(operand_ty); | |
| 10009 | 9452 | const scalar_ty = self.typeOfIndex(inst); |
| 10010 | 9453 | const llvm_scalar_ty = try o.lowerType(scalar_ty); |
| 10011 | 9454 | |
| 10012 | 9455 | switch (reduce.operation) { |
| 10013 | .And => return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10014 | .finish(self.builder.buildAndReduce(operand.toLlvm(&self.wip)), &self.wip), | |
| 10015 | .Or => return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10016 | .finish(self.builder.buildOrReduce(operand.toLlvm(&self.wip)), &self.wip), | |
| 10017 | .Xor => return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10018 | .finish(self.builder.buildXorReduce(operand.toLlvm(&self.wip)), &self.wip), | |
| 10019 | .Min => switch (scalar_ty.zigTypeTag(mod)) { | |
| 10020 | .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish( | |
| 10021 | self.builder.buildIntMinReduce( | |
| 10022 | operand.toLlvm(&self.wip), | |
| 10023 | scalar_ty.isSignedInt(mod), | |
| 10024 | ), | |
| 10025 | &self.wip, | |
| 10026 | ), | |
| 10027 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | |
| 10028 | return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10029 | .finish(self.builder.buildFPMinReduce(operand.toLlvm(&self.wip)), &self.wip); | |
| 10030 | }, | |
| 10031 | else => unreachable, | |
| 10032 | }, | |
| 10033 | .Max => switch (scalar_ty.zigTypeTag(mod)) { | |
| 10034 | .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish( | |
| 10035 | self.builder.buildIntMaxReduce( | |
| 10036 | operand.toLlvm(&self.wip), | |
| 10037 | scalar_ty.isSignedInt(mod), | |
| 10038 | ), | |
| 10039 | &self.wip, | |
| 10040 | ), | |
| 10041 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | |
| 10042 | return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10043 | .finish(self.builder.buildFPMaxReduce(operand.toLlvm(&self.wip)), &self.wip); | |
| 10044 | }, | |
| 9456 | .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { | |
| 9457 | .And => .@"vector.reduce.and", | |
| 9458 | .Or => .@"vector.reduce.or", | |
| 9459 | .Xor => .@"vector.reduce.xor", | |
| 10045 | 9460 | else => unreachable, |
| 10046 | }, | |
| 10047 | .Add => switch (scalar_ty.zigTypeTag(mod)) { | |
| 10048 | .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10049 | .finish(self.builder.buildAddReduce(operand.toLlvm(&self.wip)), &self.wip), | |
| 10050 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | |
| 10051 | const neutral_value = try o.builder.fpConst(llvm_scalar_ty, -0.0); | |
| 10052 | return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish( | |
| 10053 | self.builder.buildFPAddReduce( | |
| 10054 | neutral_value.toLlvm(&o.builder), | |
| 10055 | operand.toLlvm(&self.wip), | |
| 10056 | ), | |
| 10057 | &self.wip, | |
| 10058 | ); | |
| 10059 | }, | |
| 9461 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 9462 | .Min, .Max => switch (scalar_ty.zigTypeTag(mod)) { | |
| 9463 | .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { | |
| 9464 | .Min => if (scalar_ty.isSignedInt(mod)) | |
| 9465 | .@"vector.reduce.smin" | |
| 9466 | else | |
| 9467 | .@"vector.reduce.umin", | |
| 9468 | .Max => if (scalar_ty.isSignedInt(mod)) | |
| 9469 | .@"vector.reduce.smax" | |
| 9470 | else | |
| 9471 | .@"vector.reduce.umax", | |
| 9472 | else => unreachable, | |
| 9473 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 9474 | .Float => if (intrinsicsAllowed(scalar_ty, target)) | |
| 9475 | return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 9476 | .Min => .@"vector.reduce.fmin", | |
| 9477 | .Max => .@"vector.reduce.fmax", | |
| 9478 | else => unreachable, | |
| 9479 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 10060 | 9480 | else => unreachable, |
| 10061 | 9481 | }, |
| 10062 | .Mul => switch (scalar_ty.zigTypeTag(mod)) { | |
| 10063 | .Int => return (try self.wip.unimplemented(llvm_scalar_ty, "")) | |
| 10064 | .finish(self.builder.buildMulReduce(operand.toLlvm(&self.wip)), &self.wip), | |
| 10065 | .Float => if (intrinsicsAllowed(scalar_ty, target)) { | |
| 10066 | const neutral_value = try o.builder.fpConst(llvm_scalar_ty, 1.0); | |
| 10067 | return (try self.wip.unimplemented(llvm_scalar_ty, "")).finish( | |
| 10068 | self.builder.buildFPMulReduce( | |
| 10069 | neutral_value.toLlvm(&o.builder), | |
| 10070 | operand.toLlvm(&self.wip), | |
| 10071 | ), | |
| 10072 | &self.wip, | |
| 10073 | ); | |
| 10074 | }, | |
| 9482 | .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) { | |
| 9483 | .Int => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { | |
| 9484 | .Add => .@"vector.reduce.add", | |
| 9485 | .Mul => .@"vector.reduce.mul", | |
| 9486 | else => unreachable, | |
| 9487 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 9488 | .Float => if (intrinsicsAllowed(scalar_ty, target)) | |
| 9489 | return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 9490 | .Add => .@"vector.reduce.fadd", | |
| 9491 | .Mul => .@"vector.reduce.fmul", | |
| 9492 | else => unreachable, | |
| 9493 | }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) { | |
| 9494 | .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0), | |
| 9495 | .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0), | |
| 9496 | else => unreachable, | |
| 9497 | }, operand }, ""), | |
| 10075 | 9498 | else => unreachable, |
| 10076 | 9499 | }, |
| 10077 | 9500 | } |
| ... | ... | @@ -10168,10 +9591,8 @@ pub const FuncGen = struct { |
| 10168 | 9591 | else |
| 10169 | 9592 | try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); |
| 10170 | 9593 | const shift_rhs = try o.builder.intValue(int_ty, running_bits); |
| 10171 | // If the field is as large as the entire packed struct, this | |
| 10172 | // zext would go from, e.g. i16 to i16. This is legal with | |
| 10173 | // constZExtOrBitCast but not legal with constZExt. | |
| 10174 | const extended_int_val = try self.wip.conv(.unsigned, small_int_val, int_ty, ""); | |
| 9594 | const extended_int_val = | |
| 9595 | try self.wip.conv(.unsigned, small_int_val, int_ty, ""); | |
| 10175 | 9596 | const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, ""); |
| 10176 | 9597 | running_int = try self.wip.bin(.@"or", running_int, shifted, ""); |
| 10177 | 9598 | running_bits += ty_bit_size; |
| ... | ... | @@ -10416,29 +9837,12 @@ pub const FuncGen = struct { |
| 10416 | 9837 | .data => {}, |
| 10417 | 9838 | } |
| 10418 | 9839 | |
| 10419 | const llvm_fn_name = "llvm.prefetch.p0"; | |
| 10420 | // declare void @llvm.prefetch(i8*, i32, i32, i32) | |
| 10421 | const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal); | |
| 10422 | const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse | |
| 10423 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | |
| 10424 | ||
| 10425 | const ptr = try self.resolveInst(prefetch.ptr); | |
| 10426 | ||
| 10427 | const params = [_]*llvm.Value{ | |
| 10428 | ptr.toLlvm(&self.wip), | |
| 10429 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.rw))).toLlvm(&o.builder), | |
| 10430 | (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder), | |
| 10431 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder), | |
| 10432 | }; | |
| 10433 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( | |
| 10434 | llvm_fn_ty.toLlvm(&o.builder), | |
| 10435 | fn_val, | |
| 10436 | &params, | |
| 10437 | params.len, | |
| 10438 | .C, | |
| 10439 | .Auto, | |
| 10440 | "", | |
| 10441 | ), &self.wip); | |
| 9840 | _ = try self.wip.callIntrinsic(.normal, .none, .prefetch, &.{.ptr}, &.{ | |
| 9841 | try self.resolveInst(prefetch.ptr), | |
| 9842 | try o.builder.intValue(.i32, prefetch.rw), | |
| 9843 | try o.builder.intValue(.i32, prefetch.locality), | |
| 9844 | try o.builder.intValue(.i32, prefetch.cache), | |
| 9845 | }, ""); | |
| 10442 | 9846 | return .none; |
| 10443 | 9847 | } |
| 10444 | 9848 | |
| ... | ... | @@ -10451,26 +9855,18 @@ pub const FuncGen = struct { |
| 10451 | 9855 | return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), ""); |
| 10452 | 9856 | } |
| 10453 | 9857 | |
| 10454 | fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !Builder.Value { | |
| 10455 | const o = self.dg.object; | |
| 10456 | const llvm_fn_name = switch (dimension) { | |
| 10457 | 0 => basename ++ ".x", | |
| 10458 | 1 => basename ++ ".y", | |
| 10459 | 2 => basename ++ ".z", | |
| 10460 | else => return o.builder.intValue(.i32, default), | |
| 10461 | }; | |
| 10462 | ||
| 10463 | const args: [0]*llvm.Value = .{}; | |
| 10464 | const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{}); | |
| 10465 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( | |
| 10466 | (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder), | |
| 10467 | llvm_fn, | |
| 10468 | &args, | |
| 10469 | args.len, | |
| 10470 | .Fast, | |
| 10471 | .Auto, | |
| 10472 | "", | |
| 10473 | ), &self.wip); | |
| 9858 | fn amdgcnWorkIntrinsic( | |
| 9859 | self: *FuncGen, | |
| 9860 | dimension: u32, | |
| 9861 | default: u32, | |
| 9862 | comptime basename: []const u8, | |
| 9863 | ) !Builder.Value { | |
| 9864 | return self.wip.callIntrinsic(.normal, .none, switch (dimension) { | |
| 9865 | 0 => @field(Builder.Intrinsic, basename ++ ".x"), | |
| 9866 | 1 => @field(Builder.Intrinsic, basename ++ ".y"), | |
| 9867 | 2 => @field(Builder.Intrinsic, basename ++ ".z"), | |
| 9868 | else => return self.dg.object.builder.intValue(.i32, default), | |
| 9869 | }, &.{}, &.{}, ""); | |
| 10474 | 9870 | } |
| 10475 | 9871 | |
| 10476 | 9872 | fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -10480,7 +9876,7 @@ pub const FuncGen = struct { |
| 10480 | 9876 | |
| 10481 | 9877 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10482 | 9878 | const dimension = pl_op.payload; |
| 10483 | return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workitem.id"); | |
| 9879 | return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workitem.id"); | |
| 10484 | 9880 | } |
| 10485 | 9881 | |
| 10486 | 9882 | fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -10492,27 +9888,10 @@ pub const FuncGen = struct { |
| 10492 | 9888 | const dimension = pl_op.payload; |
| 10493 | 9889 | if (dimension >= 3) return o.builder.intValue(.i32, 1); |
| 10494 | 9890 | |
| 10495 | var attributes: Builder.FunctionAttributes.Wip = .{}; | |
| 10496 | defer attributes.deinit(&o.builder); | |
| 10497 | ||
| 10498 | 9891 | // Fetch the dispatch pointer, which points to this structure: |
| 10499 | 9892 | // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 |
| 10500 | const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); | |
| 10501 | const args: [0]*llvm.Value = .{}; | |
| 10502 | const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant); | |
| 10503 | const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCallOld( | |
| 10504 | (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder), | |
| 10505 | llvm_fn, | |
| 10506 | &args, | |
| 10507 | args.len, | |
| 10508 | .Fast, | |
| 10509 | .Auto, | |
| 10510 | "", | |
| 10511 | ), &self.wip); | |
| 10512 | try attributes.addRetAttr(.{ | |
| 10513 | .@"align" = comptime Builder.Alignment.fromByteUnits(4), | |
| 10514 | }, &o.builder); | |
| 10515 | o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4); | |
| 9893 | const dispatch_ptr = | |
| 9894 | try self.wip.callIntrinsic(.normal, .none, .@"amdgcn.dispatch.ptr", &.{}, &.{}, ""); | |
| 10516 | 9895 | |
| 10517 | 9896 | // Load the work_group_* member from the struct as u16. |
| 10518 | 9897 | // Just treat the dispatch pointer as an array of u16 to keep things simple. |
| ... | ... | @@ -10530,45 +9909,29 @@ pub const FuncGen = struct { |
| 10530 | 9909 | |
| 10531 | 9910 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10532 | 9911 | const dimension = pl_op.payload; |
| 10533 | return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workgroup.id"); | |
| 9912 | return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workgroup.id"); | |
| 10534 | 9913 | } |
| 10535 | 9914 | |
| 10536 | 9915 | fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index { |
| 10537 | 9916 | const o = self.dg.object; |
| 9917 | const mod = o.module; | |
| 9918 | ||
| 10538 | 9919 | const table = o.error_name_table; |
| 10539 | 9920 | if (table != .none) return table; |
| 10540 | 9921 | |
| 10541 | const mod = o.module; | |
| 10542 | const slice_ty = Type.slice_const_u8_sentinel_0; | |
| 10543 | const slice_alignment = slice_ty.abiAlignment(mod); | |
| 10544 | const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space | |
| 10545 | ||
| 10546 | const name = try o.builder.string("__zig_err_name_table"); | |
| 10547 | const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?); | |
| 10548 | error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder)); | |
| 10549 | error_name_table_global.setLinkage(.Private); | |
| 10550 | error_name_table_global.setGlobalConstant(.True); | |
| 10551 | error_name_table_global.setUnnamedAddr(.True); | |
| 10552 | error_name_table_global.setAlignment(slice_alignment); | |
| 10553 | ||
| 10554 | var global = Builder.Global{ | |
| 10555 | .linkage = .private, | |
| 10556 | .unnamed_addr = .unnamed_addr, | |
| 10557 | .type = .ptr, | |
| 10558 | .kind = .{ .variable = @enumFromInt(o.builder.variables.items.len) }, | |
| 10559 | }; | |
| 10560 | var variable = Builder.Variable{ | |
| 10561 | .global = @enumFromInt(o.builder.globals.count()), | |
| 10562 | .mutability = .constant, | |
| 10563 | .init = undef_init, | |
| 10564 | .alignment = Builder.Alignment.fromByteUnits(slice_alignment), | |
| 10565 | }; | |
| 10566 | try o.builder.llvm.globals.append(o.gpa, error_name_table_global); | |
| 10567 | _ = try o.builder.addGlobal(name, global); | |
| 10568 | try o.builder.variables.append(o.gpa, variable); | |
| 9922 | // TODO: Address space | |
| 9923 | const variable_index = | |
| 9924 | try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default); | |
| 9925 | variable_index.setLinkage(.private, &o.builder); | |
| 9926 | variable_index.setMutability(.constant, &o.builder); | |
| 9927 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 9928 | variable_index.setAlignment( | |
| 9929 | Builder.Alignment.fromByteUnits(Type.slice_const_u8_sentinel_0.abiAlignment(mod)), | |
| 9930 | &o.builder, | |
| 9931 | ); | |
| 10569 | 9932 | |
| 10570 | o.error_name_table = global.kind.variable; | |
| 10571 | return global.kind.variable; | |
| 9933 | o.error_name_table = variable_index; | |
| 9934 | return variable_index; | |
| 10572 | 9935 | } |
| 10573 | 9936 | |
| 10574 | 9937 | /// Assumes the optional is not pointer-like and payload has bits. |
| ... | ... | @@ -10613,7 +9976,7 @@ pub const FuncGen = struct { |
| 10613 | 9976 | if (can_elide_load) |
| 10614 | 9977 | return payload_ptr; |
| 10615 | 9978 | |
| 10616 | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false); | |
| 9979 | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); | |
| 10617 | 9980 | } |
| 10618 | 9981 | const payload_llvm_ty = try o.lowerType(payload_ty); |
| 10619 | 9982 | return fg.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, ""); |
| ... | ... | @@ -10716,27 +10079,13 @@ pub const FuncGen = struct { |
| 10716 | 10079 | } |
| 10717 | 10080 | } |
| 10718 | 10081 | |
| 10719 | fn getIntrinsic( | |
| 10720 | fg: *FuncGen, | |
| 10721 | name: []const u8, | |
| 10722 | types: []const Builder.Type, | |
| 10723 | ) Allocator.Error!*llvm.Value { | |
| 10724 | const o = fg.dg.object; | |
| 10725 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); | |
| 10726 | assert(id != 0); | |
| 10727 | const llvm_types = try o.gpa.alloc(*llvm.Type, types.len); | |
| 10728 | defer o.gpa.free(llvm_types); | |
| 10729 | for (llvm_types, types) |*llvm_type, ty| llvm_type.* = ty.toLlvm(&o.builder); | |
| 10730 | return o.llvm_module.getIntrinsicDeclaration(id, llvm_types.ptr, llvm_types.len); | |
| 10731 | } | |
| 10732 | ||
| 10733 | 10082 | /// Load a by-ref type by constructing a new alloca and performing a memcpy. |
| 10734 | 10083 | fn loadByRef( |
| 10735 | 10084 | fg: *FuncGen, |
| 10736 | 10085 | ptr: Builder.Value, |
| 10737 | 10086 | pointee_type: Type, |
| 10738 | 10087 | ptr_alignment: Builder.Alignment, |
| 10739 | is_volatile: bool, | |
| 10088 | access_kind: Builder.MemoryAccessKind, | |
| 10740 | 10089 | ) !Builder.Value { |
| 10741 | 10090 | const o = fg.dg.object; |
| 10742 | 10091 | const mod = o.module; |
| ... | ... | @@ -10745,16 +10094,15 @@ pub const FuncGen = struct { |
| 10745 | 10094 | @max(ptr_alignment.toByteUnits() orelse 0, pointee_type.abiAlignment(mod)), |
| 10746 | 10095 | ); |
| 10747 | 10096 | const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); |
| 10748 | const usize_ty = try o.lowerType(Type.usize); | |
| 10749 | 10097 | const size_bytes = pointee_type.abiSize(mod); |
| 10750 | _ = (try fg.wip.unimplemented(.void, "")).finish(fg.builder.buildMemCpy( | |
| 10751 | result_ptr.toLlvm(&fg.wip), | |
| 10752 | @intCast(result_align.toByteUnits() orelse 0), | |
| 10753 | ptr.toLlvm(&fg.wip), | |
| 10754 | @intCast(ptr_alignment.toByteUnits() orelse 0), | |
| 10755 | (try o.builder.intConst(usize_ty, size_bytes)).toLlvm(&o.builder), | |
| 10756 | is_volatile, | |
| 10757 | ), &fg.wip); | |
| 10098 | _ = try fg.wip.callMemCpy( | |
| 10099 | result_ptr, | |
| 10100 | result_align, | |
| 10101 | ptr, | |
| 10102 | ptr_alignment, | |
| 10103 | try o.builder.intValue(try o.lowerType(Type.usize), size_bytes), | |
| 10104 | access_kind, | |
| 10105 | ); | |
| 10758 | 10106 | return result_ptr; |
| 10759 | 10107 | } |
| 10760 | 10108 | |
| ... | ... | @@ -10771,30 +10119,29 @@ pub const FuncGen = struct { |
| 10771 | 10119 | const ptr_alignment = Builder.Alignment.fromByteUnits( |
| 10772 | 10120 | info.flags.alignment.toByteUnitsOptional() orelse elem_ty.abiAlignment(mod), |
| 10773 | 10121 | ); |
| 10774 | const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) { | |
| 10775 | false => .normal, | |
| 10776 | true => .@"volatile", | |
| 10777 | }; | |
| 10122 | const access_kind: Builder.MemoryAccessKind = | |
| 10123 | if (info.flags.is_volatile) .@"volatile" else .normal; | |
| 10778 | 10124 | |
| 10779 | 10125 | assert(info.flags.vector_index != .runtime); |
| 10780 | 10126 | if (info.flags.vector_index != .none) { |
| 10781 | const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index)); | |
| 10127 | const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); | |
| 10782 | 10128 | const vec_elem_ty = try o.lowerType(elem_ty); |
| 10783 | 10129 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); |
| 10784 | 10130 | |
| 10785 | const loaded_vector = try self.wip.load(ptr_kind, vec_ty, ptr, ptr_alignment, ""); | |
| 10131 | const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, ""); | |
| 10786 | 10132 | return self.wip.extractElement(loaded_vector, index_u32, ""); |
| 10787 | 10133 | } |
| 10788 | 10134 | |
| 10789 | 10135 | if (info.packed_offset.host_size == 0) { |
| 10790 | 10136 | if (isByRef(elem_ty, mod)) { |
| 10791 | return self.loadByRef(ptr, elem_ty, ptr_alignment, info.flags.is_volatile); | |
| 10137 | return self.loadByRef(ptr, elem_ty, ptr_alignment, access_kind); | |
| 10792 | 10138 | } |
| 10793 | return self.wip.load(ptr_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, ""); | |
| 10139 | return self.wip.load(access_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, ""); | |
| 10794 | 10140 | } |
| 10795 | 10141 | |
| 10796 | 10142 | const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); |
| 10797 | const containing_int = try self.wip.load(ptr_kind, containing_int_ty, ptr, ptr_alignment, ""); | |
| 10143 | const containing_int = | |
| 10144 | try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, ""); | |
| 10798 | 10145 | |
| 10799 | 10146 | const elem_bits = ptr_ty.childType(mod).bitSize(mod); |
| 10800 | 10147 | const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset); |
| ... | ... | @@ -10841,23 +10188,21 @@ pub const FuncGen = struct { |
| 10841 | 10188 | return; |
| 10842 | 10189 | } |
| 10843 | 10190 | const ptr_alignment = Builder.Alignment.fromByteUnits(ptr_ty.ptrAlignment(mod)); |
| 10844 | const ptr_kind: Builder.MemoryAccessKind = switch (info.flags.is_volatile) { | |
| 10845 | false => .normal, | |
| 10846 | true => .@"volatile", | |
| 10847 | }; | |
| 10191 | const access_kind: Builder.MemoryAccessKind = | |
| 10192 | if (info.flags.is_volatile) .@"volatile" else .normal; | |
| 10848 | 10193 | |
| 10849 | 10194 | assert(info.flags.vector_index != .runtime); |
| 10850 | 10195 | if (info.flags.vector_index != .none) { |
| 10851 | const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index)); | |
| 10196 | const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); | |
| 10852 | 10197 | const vec_elem_ty = try o.lowerType(elem_ty); |
| 10853 | 10198 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); |
| 10854 | 10199 | |
| 10855 | const loaded_vector = try self.wip.load(ptr_kind, vec_ty, ptr, ptr_alignment, ""); | |
| 10200 | const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, ""); | |
| 10856 | 10201 | |
| 10857 | 10202 | const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, ""); |
| 10858 | 10203 | |
| 10859 | 10204 | assert(ordering == .none); |
| 10860 | _ = try self.wip.store(ptr_kind, modified_vector, ptr, ptr_alignment); | |
| 10205 | _ = try self.wip.store(access_kind, modified_vector, ptr, ptr_alignment); | |
| 10861 | 10206 | return; |
| 10862 | 10207 | } |
| 10863 | 10208 | |
| ... | ... | @@ -10865,7 +10210,7 @@ pub const FuncGen = struct { |
| 10865 | 10210 | const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); |
| 10866 | 10211 | assert(ordering == .none); |
| 10867 | 10212 | const containing_int = |
| 10868 | try self.wip.load(ptr_kind, containing_int_ty, ptr, ptr_alignment, ""); | |
| 10213 | try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, ""); | |
| 10869 | 10214 | const elem_bits = ptr_ty.childType(mod).bitSize(mod); |
| 10870 | 10215 | const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset); |
| 10871 | 10216 | // Convert to equally-sized integer type in order to perform the bit |
| ... | ... | @@ -10889,23 +10234,29 @@ pub const FuncGen = struct { |
| 10889 | 10234 | const ored_value = try self.wip.bin(.@"or", shifted_value, anded_containing_int, ""); |
| 10890 | 10235 | |
| 10891 | 10236 | assert(ordering == .none); |
| 10892 | _ = try self.wip.store(ptr_kind, ored_value, ptr, ptr_alignment); | |
| 10237 | _ = try self.wip.store(access_kind, ored_value, ptr, ptr_alignment); | |
| 10893 | 10238 | return; |
| 10894 | 10239 | } |
| 10895 | 10240 | if (!isByRef(elem_ty, mod)) { |
| 10896 | _ = try self.wip.storeAtomic(ptr_kind, elem, ptr, self.sync_scope, ordering, ptr_alignment); | |
| 10241 | _ = try self.wip.storeAtomic( | |
| 10242 | access_kind, | |
| 10243 | elem, | |
| 10244 | ptr, | |
| 10245 | self.sync_scope, | |
| 10246 | ordering, | |
| 10247 | ptr_alignment, | |
| 10248 | ); | |
| 10897 | 10249 | return; |
| 10898 | 10250 | } |
| 10899 | 10251 | assert(ordering == .none); |
| 10900 | const size_bytes = elem_ty.abiSize(mod); | |
| 10901 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildMemCpy( | |
| 10902 | ptr.toLlvm(&self.wip), | |
| 10903 | @intCast(ptr_alignment.toByteUnits() orelse 0), | |
| 10904 | elem.toLlvm(&self.wip), | |
| 10905 | elem_ty.abiAlignment(mod), | |
| 10906 | (try o.builder.intConst(try o.lowerType(Type.usize), size_bytes)).toLlvm(&o.builder), | |
| 10907 | info.flags.is_volatile, | |
| 10908 | ), &self.wip); | |
| 10252 | _ = try self.wip.callMemCpy( | |
| 10253 | ptr, | |
| 10254 | ptr_alignment, | |
| 10255 | elem, | |
| 10256 | Builder.Alignment.fromByteUnits(elem_ty.abiAlignment(mod)), | |
| 10257 | try o.builder.intValue(try o.lowerType(Type.usize), elem_ty.abiSize(mod)), | |
| 10258 | access_kind, | |
| 10259 | ); | |
| 10909 | 10260 | } |
| 10910 | 10261 | |
| 10911 | 10262 | fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { |
| ... | ... | @@ -10982,26 +10333,15 @@ pub const FuncGen = struct { |
| 10982 | 10333 | else => unreachable, |
| 10983 | 10334 | }; |
| 10984 | 10335 | |
| 10985 | const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder); | |
| 10986 | const array_ptr_as_usize = try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""); | |
| 10987 | const args = [_]*llvm.Value{ array_ptr_as_usize.toLlvm(&fg.wip), default_value.toLlvm(&fg.wip) }; | |
| 10988 | const asm_fn = llvm.getInlineAsm( | |
| 10989 | fn_llvm_ty, | |
| 10990 | arch_specific.template.ptr, | |
| 10991 | arch_specific.template.len, | |
| 10992 | arch_specific.constraints.ptr, | |
| 10993 | arch_specific.constraints.len, | |
| 10994 | .True, // has side effects | |
| 10995 | .False, // alignstack | |
| 10996 | .ATT, | |
| 10997 | .False, // can throw | |
| 10998 | ); | |
| 10999 | ||
| 11000 | const call = (try fg.wip.unimplemented(llvm_usize, "")).finish( | |
| 11001 | fg.builder.buildCallOld(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""), | |
| 11002 | &fg.wip, | |
| 10336 | return fg.wip.callAsm( | |
| 10337 | .none, | |
| 10338 | try o.builder.fnType(llvm_usize, &.{ llvm_usize, llvm_usize }, .normal), | |
| 10339 | .{ .sideeffect = true }, | |
| 10340 | try o.builder.string(arch_specific.template), | |
| 10341 | try o.builder.string(arch_specific.constraints), | |
| 10342 | &.{ try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""), default_value }, | |
| 10343 | "", | |
| 11003 | 10344 | ); |
| 11004 | return call; | |
| 11005 | 10345 | } |
| 11006 | 10346 | |
| 11007 | 10347 | fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type { |
| ... | ... | @@ -11032,17 +10372,17 @@ fn toLlvmAtomicRmwBinOp( |
| 11032 | 10372 | op: std.builtin.AtomicRmwOp, |
| 11033 | 10373 | is_signed: bool, |
| 11034 | 10374 | is_float: bool, |
| 11035 | ) llvm.AtomicRMWBinOp { | |
| 10375 | ) Builder.Function.Instruction.AtomicRmw.Operation { | |
| 11036 | 10376 | return switch (op) { |
| 11037 | .Xchg => .Xchg, | |
| 11038 | .Add => if (is_float) .FAdd else return .Add, | |
| 11039 | .Sub => if (is_float) .FSub else return .Sub, | |
| 11040 | .And => .And, | |
| 11041 | .Nand => .Nand, | |
| 11042 | .Or => .Or, | |
| 11043 | .Xor => .Xor, | |
| 11044 | .Max => if (is_float) .FMax else if (is_signed) .Max else return .UMax, | |
| 11045 | .Min => if (is_float) .FMin else if (is_signed) .Min else return .UMin, | |
| 10377 | .Xchg => .xchg, | |
| 10378 | .Add => if (is_float) .fadd else return .add, | |
| 10379 | .Sub => if (is_float) .fsub else return .sub, | |
| 10380 | .And => .@"and", | |
| 10381 | .Nand => .nand, | |
| 10382 | .Or => .@"or", | |
| 10383 | .Xor => .xor, | |
| 10384 | .Max => if (is_float) .fmax else if (is_signed) .max else return .umax, | |
| 10385 | .Min => if (is_float) .fmin else if (is_signed) .min else return .umin, | |
| 11046 | 10386 | }; |
| 11047 | 10387 | } |
| 11048 | 10388 | |
| ... | ... | @@ -12008,15 +11348,19 @@ fn buildAllocaInner( |
| 12008 | 11348 | |
| 12009 | 11349 | const alloca = blk: { |
| 12010 | 11350 | const prev_cursor = wip.cursor; |
| 12011 | const prev_debug_location = wip.llvm.builder.getCurrentDebugLocation2(); | |
| 11351 | const prev_debug_location = if (wip.builder.useLibLlvm()) | |
| 11352 | wip.llvm.builder.getCurrentDebugLocation2() | |
| 11353 | else | |
| 11354 | undefined; | |
| 12012 | 11355 | defer { |
| 12013 | 11356 | wip.cursor = prev_cursor; |
| 12014 | 11357 | if (wip.cursor.block == .entry) wip.cursor.instruction += 1; |
| 12015 | if (di_scope_non_null) wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location); | |
| 11358 | if (wip.builder.useLibLlvm() and di_scope_non_null) | |
| 11359 | wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location); | |
| 12016 | 11360 | } |
| 12017 | 11361 | |
| 12018 | 11362 | wip.cursor = .{ .block = .entry }; |
| 12019 | wip.llvm.builder.clearCurrentDebugLocation(); | |
| 11363 | if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation(); | |
| 12020 | 11364 | break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, ""); |
| 12021 | 11365 | }; |
| 12022 | 11366 |
src/codegen/llvm/Builder.zig+3028-1057| ... | ... | @@ -13,6 +13,7 @@ llvm: if (build_options.have_llvm) struct { |
| 13 | 13 | types: std.ArrayListUnmanaged(*llvm.Type), |
| 14 | 14 | globals: std.ArrayListUnmanaged(*llvm.Value), |
| 15 | 15 | constants: std.ArrayListUnmanaged(*llvm.Value), |
| 16 | replacements: std.AutoHashMapUnmanaged(*llvm.Value, Global.Index), | |
| 16 | 17 | } else void, |
| 17 | 18 | |
| 18 | 19 | source_filename: String, |
| ... | ... | @@ -50,10 +51,12 @@ constant_extra: std.ArrayListUnmanaged(u32), |
| 50 | 51 | constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), |
| 51 | 52 | |
| 52 | 53 | pub const expected_args_len = 16; |
| 54 | pub const expected_attrs_len = 16; | |
| 53 | 55 | pub const expected_fields_len = 32; |
| 54 | 56 | pub const expected_gep_indices_len = 8; |
| 55 | 57 | pub const expected_cases_len = 8; |
| 56 | 58 | pub const expected_incoming_len = 8; |
| 59 | pub const expected_intrinsic_name_len = 64; | |
| 57 | 60 | |
| 58 | 61 | pub const Options = struct { |
| 59 | 62 | allocator: Allocator, |
| ... | ... | @@ -151,11 +154,14 @@ pub const Type = enum(u32) { |
| 151 | 154 | i80, |
| 152 | 155 | i128, |
| 153 | 156 | ptr, |
| 157 | @"ptr addrspace(4)", | |
| 154 | 158 | |
| 155 | 159 | none = std.math.maxInt(u32), |
| 156 | 160 | _, |
| 157 | 161 | |
| 158 | 162 | pub const err_int = Type.i16; |
| 163 | pub const ptr_amdgpu_constant = | |
| 164 | @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant})); | |
| 159 | 165 | |
| 160 | 166 | pub const Tag = enum(u4) { |
| 161 | 167 | simple, |
| ... | ... | @@ -391,7 +397,7 @@ pub const Type = enum(u32) { |
| 391 | 397 | .double, .i64, .x86_mmx => 64, |
| 392 | 398 | .x86_fp80, .i80 => 80, |
| 393 | 399 | .fp128, .ppc_fp128, .i128 => 128, |
| 394 | .ptr => @panic("TODO: query data layout"), | |
| 400 | .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"), | |
| 395 | 401 | _ => { |
| 396 | 402 | const item = builder.type_items.items[@intFromEnum(self)]; |
| 397 | 403 | return switch (item.tag) { |
| ... | ... | @@ -690,7 +696,7 @@ pub const Type = enum(u32) { |
| 690 | 696 | } |
| 691 | 697 | }, |
| 692 | 698 | .integer => try writer.print("i{d}", .{item.data}), |
| 693 | .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(item.data))}), | |
| 699 | .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}), | |
| 694 | 700 | .target => { |
| 695 | 701 | var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); |
| 696 | 702 | const types = extra.trail.next(extra.data.types_len, Type, data.builder); |
| ... | ... | @@ -795,6 +801,7 @@ pub const Type = enum(u32) { |
| 795 | 801 | .i80, |
| 796 | 802 | .i128, |
| 797 | 803 | .ptr, |
| 804 | .@"ptr addrspace(4)", | |
| 798 | 805 | => true, |
| 799 | 806 | .none => unreachable, |
| 800 | 807 | _ => { |
| ... | ... | @@ -1151,13 +1158,13 @@ pub const Attribute = union(Kind) { |
| 1151 | 1158 | .sret, |
| 1152 | 1159 | .elementtype, |
| 1153 | 1160 | => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }), |
| 1154 | .@"align" => |alignment| try writer.print("{}", .{alignment}), | |
| 1161 | .@"align" => |alignment| try writer.print("{ }", .{alignment}), | |
| 1155 | 1162 | .dereferenceable, |
| 1156 | 1163 | .dereferenceable_or_null, |
| 1157 | 1164 | => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }), |
| 1158 | 1165 | .nofpclass => |fpclass| { |
| 1159 | 1166 | const Int = @typeInfo(FpClass).Struct.backing_integer.?; |
| 1160 | try writer.print("{s}(", .{@tagName(attribute)}); | |
| 1167 | try writer.print(" {s}(", .{@tagName(attribute)}); | |
| 1161 | 1168 | var any = false; |
| 1162 | 1169 | var remaining: Int = @bitCast(fpclass); |
| 1163 | 1170 | inline for (@typeInfo(FpClass).Struct.decls) |decl| { |
| ... | ... | @@ -1175,13 +1182,13 @@ pub const Attribute = union(Kind) { |
| 1175 | 1182 | }, |
| 1176 | 1183 | .alignstack => |alignment| try writer.print( |
| 1177 | 1184 | if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null) |
| 1178 | "{s}={d}" | |
| 1185 | " {s}={d}" | |
| 1179 | 1186 | else |
| 1180 | "{s}({d})", | |
| 1187 | " {s}({d})", | |
| 1181 | 1188 | .{ @tagName(attribute), alignment.toByteUnits() orelse return }, |
| 1182 | 1189 | ), |
| 1183 | 1190 | .allockind => |allockind| { |
| 1184 | try writer.print("{s}(\"", .{@tagName(attribute)}); | |
| 1191 | try writer.print(" {s}(\"", .{@tagName(attribute)}); | |
| 1185 | 1192 | var any = false; |
| 1186 | 1193 | inline for (@typeInfo(AllocKind).Struct.fields) |field| { |
| 1187 | 1194 | if (comptime std.mem.eql(u8, field.name, "_")) continue; |
| ... | ... | @@ -1196,22 +1203,30 @@ pub const Attribute = union(Kind) { |
| 1196 | 1203 | try writer.writeAll("\")"); |
| 1197 | 1204 | }, |
| 1198 | 1205 | .allocsize => |allocsize| { |
| 1199 | try writer.print("{s}({d}", .{ @tagName(attribute), allocsize.elem_size }); | |
| 1206 | try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size }); | |
| 1200 | 1207 | if (allocsize.num_elems != AllocSize.none) |
| 1201 | 1208 | try writer.print(",{d}", .{allocsize.num_elems}); |
| 1202 | 1209 | try writer.writeByte(')'); |
| 1203 | 1210 | }, |
| 1204 | .memory => |memory| try writer.print("{s}({s}, argmem: {s}, inaccessiblemem: {s})", .{ | |
| 1205 | @tagName(attribute), | |
| 1206 | @tagName(memory.other), | |
| 1207 | @tagName(memory.argmem), | |
| 1208 | @tagName(memory.inaccessiblemem), | |
| 1209 | }), | |
| 1211 | .memory => |memory| { | |
| 1212 | try writer.print(" {s}(", .{@tagName(attribute)}); | |
| 1213 | var any = memory.other != .none or | |
| 1214 | (memory.argmem == .none and memory.inaccessiblemem == .none); | |
| 1215 | if (any) try writer.writeAll(@tagName(memory.other)); | |
| 1216 | inline for (.{ "argmem", "inaccessiblemem" }) |kind| { | |
| 1217 | if (@field(memory, kind) != memory.other) { | |
| 1218 | if (any) try writer.writeAll(", "); | |
| 1219 | try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) }); | |
| 1220 | any = true; | |
| 1221 | } | |
| 1222 | } | |
| 1223 | try writer.writeByte(')'); | |
| 1224 | }, | |
| 1210 | 1225 | .uwtable => |uwtable| if (uwtable != .none) { |
| 1211 | try writer.writeAll(@tagName(attribute)); | |
| 1226 | try writer.print(" {s}", .{@tagName(attribute)}); | |
| 1212 | 1227 | if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)}); |
| 1213 | 1228 | }, |
| 1214 | .vscale_range => |vscale_range| try writer.print("{s}({d},{d})", .{ | |
| 1229 | .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{ | |
| 1215 | 1230 | @tagName(attribute), |
| 1216 | 1231 | vscale_range.min.toByteUnits().?, |
| 1217 | 1232 | vscale_range.max.toByteUnits() orelse 0, |
| ... | ... | @@ -1335,21 +1350,29 @@ pub const Attribute = union(Kind) { |
| 1335 | 1350 | //sanitize_memtag, |
| 1336 | 1351 | sanitize_address_dyninit, |
| 1337 | 1352 | |
| 1338 | string = std.math.maxInt(u31) - 1, | |
| 1339 | none = std.math.maxInt(u31), | |
| 1353 | string = std.math.maxInt(u31), | |
| 1354 | none = std.math.maxInt(u32), | |
| 1340 | 1355 | _, |
| 1341 | 1356 | |
| 1342 | 1357 | pub const len = @typeInfo(Kind).Enum.fields.len - 2; |
| 1343 | 1358 | |
| 1344 | 1359 | pub fn fromString(str: String) Kind { |
| 1345 | 1360 | assert(!str.isAnon()); |
| 1346 | return @enumFromInt(@intFromEnum(str)); | |
| 1361 | const kind: Kind = @enumFromInt(@intFromEnum(str)); | |
| 1362 | assert(kind != .none); | |
| 1363 | return kind; | |
| 1347 | 1364 | } |
| 1348 | 1365 | |
| 1349 | 1366 | fn toString(self: Kind) ?String { |
| 1367 | assert(self != .none); | |
| 1350 | 1368 | const str: String = @enumFromInt(@intFromEnum(self)); |
| 1351 | 1369 | return if (str.isAnon()) null else str; |
| 1352 | 1370 | } |
| 1371 | ||
| 1372 | fn toLlvm(self: Kind, builder: *const Builder) *c_uint { | |
| 1373 | assert(builder.useLibLlvm()); | |
| 1374 | return &builder.llvm.attribute_kind_ids.?[@intFromEnum(self)]; | |
| 1375 | } | |
| 1353 | 1376 | }; |
| 1354 | 1377 | |
| 1355 | 1378 | pub const FpClass = packed struct(u32) { |
| ... | ... | @@ -1424,12 +1447,16 @@ pub const Attribute = union(Kind) { |
| 1424 | 1447 | }; |
| 1425 | 1448 | |
| 1426 | 1449 | pub const Memory = packed struct(u32) { |
| 1427 | argmem: Effect, | |
| 1428 | inaccessiblemem: Effect, | |
| 1429 | other: Effect, | |
| 1450 | argmem: Effect = .none, | |
| 1451 | inaccessiblemem: Effect = .none, | |
| 1452 | other: Effect = .none, | |
| 1430 | 1453 | _: u26 = 0, |
| 1431 | 1454 | |
| 1432 | 1455 | pub const Effect = enum(u2) { none, read, write, readwrite }; |
| 1456 | ||
| 1457 | fn all(effect: Effect) Memory { | |
| 1458 | return .{ .argmem = effect, .inaccessiblemem = effect, .other = effect }; | |
| 1459 | } | |
| 1433 | 1460 | }; |
| 1434 | 1461 | |
| 1435 | 1462 | pub const UwTable = enum(u32) { |
| ... | ... | @@ -1683,17 +1710,17 @@ pub const FunctionAttributes = enum(u32) { |
| 1683 | 1710 | }; |
| 1684 | 1711 | |
| 1685 | 1712 | pub const Linkage = enum { |
| 1686 | external, | |
| 1687 | 1713 | private, |
| 1688 | 1714 | internal, |
| 1689 | available_externally, | |
| 1690 | linkonce, | |
| 1691 | 1715 | weak, |
| 1692 | common, | |
| 1716 | weak_odr, | |
| 1717 | linkonce, | |
| 1718 | linkonce_odr, | |
| 1719 | available_externally, | |
| 1693 | 1720 | appending, |
| 1721 | common, | |
| 1694 | 1722 | extern_weak, |
| 1695 | linkonce_odr, | |
| 1696 | weak_odr, | |
| 1723 | external, | |
| 1697 | 1724 | |
| 1698 | 1725 | pub fn format( |
| 1699 | 1726 | self: Linkage, |
| ... | ... | @@ -1703,6 +1730,22 @@ pub const Linkage = enum { |
| 1703 | 1730 | ) @TypeOf(writer).Error!void { |
| 1704 | 1731 | if (self != .external) try writer.print(" {s}", .{@tagName(self)}); |
| 1705 | 1732 | } |
| 1733 | ||
| 1734 | fn toLlvm(self: Linkage) llvm.Linkage { | |
| 1735 | return switch (self) { | |
| 1736 | .private => .Private, | |
| 1737 | .internal => .Internal, | |
| 1738 | .weak => .WeakAny, | |
| 1739 | .weak_odr => .WeakODR, | |
| 1740 | .linkonce => .LinkOnceAny, | |
| 1741 | .linkonce_odr => .LinkOnceODR, | |
| 1742 | .available_externally => .AvailableExternally, | |
| 1743 | .appending => .Appending, | |
| 1744 | .common => .Common, | |
| 1745 | .extern_weak => .ExternalWeak, | |
| 1746 | .external => .External, | |
| 1747 | }; | |
| 1748 | } | |
| 1706 | 1749 | }; |
| 1707 | 1750 | |
| 1708 | 1751 | pub const Preemption = enum { |
| ... | ... | @@ -1733,6 +1776,14 @@ pub const Visibility = enum { |
| 1733 | 1776 | ) @TypeOf(writer).Error!void { |
| 1734 | 1777 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); |
| 1735 | 1778 | } |
| 1779 | ||
| 1780 | fn toLlvm(self: Visibility) llvm.Visibility { | |
| 1781 | return switch (self) { | |
| 1782 | .default => .Default, | |
| 1783 | .hidden => .Hidden, | |
| 1784 | .protected => .Protected, | |
| 1785 | }; | |
| 1786 | } | |
| 1736 | 1787 | }; |
| 1737 | 1788 | |
| 1738 | 1789 | pub const DllStorageClass = enum { |
| ... | ... | @@ -1748,6 +1799,14 @@ pub const DllStorageClass = enum { |
| 1748 | 1799 | ) @TypeOf(writer).Error!void { |
| 1749 | 1800 | if (self != .default) try writer.print(" {s}", .{@tagName(self)}); |
| 1750 | 1801 | } |
| 1802 | ||
| 1803 | fn toLlvm(self: DllStorageClass) llvm.DLLStorageClass { | |
| 1804 | return switch (self) { | |
| 1805 | .default => .Default, | |
| 1806 | .dllimport => .DLLImport, | |
| 1807 | .dllexport => .DLLExport, | |
| 1808 | }; | |
| 1809 | } | |
| 1751 | 1810 | }; |
| 1752 | 1811 | |
| 1753 | 1812 | pub const ThreadLocal = enum { |
| ... | ... | @@ -1759,20 +1818,28 @@ pub const ThreadLocal = enum { |
| 1759 | 1818 | |
| 1760 | 1819 | pub fn format( |
| 1761 | 1820 | self: ThreadLocal, |
| 1762 | comptime _: []const u8, | |
| 1821 | comptime prefix: []const u8, | |
| 1763 | 1822 | _: std.fmt.FormatOptions, |
| 1764 | 1823 | writer: anytype, |
| 1765 | 1824 | ) @TypeOf(writer).Error!void { |
| 1766 | 1825 | if (self == .default) return; |
| 1767 | try writer.writeAll(" thread_local"); | |
| 1768 | if (self != .generaldynamic) { | |
| 1769 | try writer.writeByte('('); | |
| 1770 | try writer.writeAll(@tagName(self)); | |
| 1771 | try writer.writeByte(')'); | |
| 1772 | } | |
| 1826 | try writer.print("{s}thread_local", .{prefix}); | |
| 1827 | if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)}); | |
| 1828 | } | |
| 1829 | ||
| 1830 | fn toLlvm(self: ThreadLocal) llvm.ThreadLocalMode { | |
| 1831 | return switch (self) { | |
| 1832 | .default => .NotThreadLocal, | |
| 1833 | .generaldynamic => .GeneralDynamicTLSModel, | |
| 1834 | .localdynamic => .LocalDynamicTLSModel, | |
| 1835 | .initialexec => .InitialExecTLSModel, | |
| 1836 | .localexec => .LocalExecTLSModel, | |
| 1837 | }; | |
| 1773 | 1838 | } |
| 1774 | 1839 | }; |
| 1775 | 1840 | |
| 1841 | pub const Mutability = enum { global, constant }; | |
| 1842 | ||
| 1776 | 1843 | pub const UnnamedAddr = enum { |
| 1777 | 1844 | default, |
| 1778 | 1845 | unnamed_addr, |
| ... | ... | @@ -1867,7 +1934,7 @@ pub const AddrSpace = enum(u24) { |
| 1867 | 1934 | _: std.fmt.FormatOptions, |
| 1868 | 1935 | writer: anytype, |
| 1869 | 1936 | ) @TypeOf(writer).Error!void { |
| 1870 | if (self != .default) try writer.print("{s} addrspace({d})", .{ prefix, @intFromEnum(self) }); | |
| 1937 | if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) }); | |
| 1871 | 1938 | } |
| 1872 | 1939 | }; |
| 1873 | 1940 | |
| ... | ... | @@ -1908,7 +1975,7 @@ pub const Alignment = enum(u6) { |
| 1908 | 1975 | _: std.fmt.FormatOptions, |
| 1909 | 1976 | writer: anytype, |
| 1910 | 1977 | ) @TypeOf(writer).Error!void { |
| 1911 | try writer.print("{s} align {d}", .{ prefix, self.toByteUnits() orelse return }); | |
| 1978 | try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return }); | |
| 1912 | 1979 | } |
| 1913 | 1980 | }; |
| 1914 | 1981 | |
| ... | ... | @@ -2031,6 +2098,11 @@ pub const CallConv = enum(u10) { |
| 2031 | 2098 | _ => try writer.print(" cc{d}", .{@intFromEnum(self)}), |
| 2032 | 2099 | } |
| 2033 | 2100 | } |
| 2101 | ||
| 2102 | fn toLlvm(self: CallConv) llvm.CallConv { | |
| 2103 | // These enum values appear in LLVM IR, and so are guaranteed to be stable. | |
| 2104 | return @enumFromInt(@intFromEnum(self)); | |
| 2105 | } | |
| 2034 | 2106 | }; |
| 2035 | 2107 | |
| 2036 | 2108 | pub const Global = struct { |
| ... | ... | @@ -2067,10 +2139,6 @@ pub const Global = struct { |
| 2067 | 2139 | return self.unwrap(builder) == other.unwrap(builder); |
| 2068 | 2140 | } |
| 2069 | 2141 | |
| 2070 | pub fn name(self: Index, builder: *const Builder) String { | |
| 2071 | return builder.globals.keys()[@intFromEnum(self.unwrap(builder))]; | |
| 2072 | } | |
| 2073 | ||
| 2074 | 2142 | pub fn ptr(self: Index, builder: *Builder) *Global { |
| 2075 | 2143 | return &builder.globals.values()[@intFromEnum(self.unwrap(builder))]; |
| 2076 | 2144 | } |
| ... | ... | @@ -2079,6 +2147,10 @@ pub const Global = struct { |
| 2079 | 2147 | return &builder.globals.values()[@intFromEnum(self.unwrap(builder))]; |
| 2080 | 2148 | } |
| 2081 | 2149 | |
| 2150 | pub fn name(self: Index, builder: *const Builder) String { | |
| 2151 | return builder.globals.keys()[@intFromEnum(self.unwrap(builder))]; | |
| 2152 | } | |
| 2153 | ||
| 2082 | 2154 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2083 | 2155 | return self.ptrConst(builder).type; |
| 2084 | 2156 | } |
| ... | ... | @@ -2087,6 +2159,30 @@ pub const Global = struct { |
| 2087 | 2159 | return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self)); |
| 2088 | 2160 | } |
| 2089 | 2161 | |
| 2162 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { | |
| 2163 | if (builder.useLibLlvm()) self.toLlvm(builder).setLinkage(linkage.toLlvm()); | |
| 2164 | self.ptr(builder).linkage = linkage; | |
| 2165 | self.updateDsoLocal(builder); | |
| 2166 | } | |
| 2167 | ||
| 2168 | pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { | |
| 2169 | if (builder.useLibLlvm()) self.toLlvm(builder).setVisibility(visibility.toLlvm()); | |
| 2170 | self.ptr(builder).visibility = visibility; | |
| 2171 | self.updateDsoLocal(builder); | |
| 2172 | } | |
| 2173 | ||
| 2174 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { | |
| 2175 | if (builder.useLibLlvm()) self.toLlvm(builder).setDLLStorageClass(class.toLlvm()); | |
| 2176 | self.ptr(builder).dll_storage_class = class; | |
| 2177 | } | |
| 2178 | ||
| 2179 | pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { | |
| 2180 | if (builder.useLibLlvm()) self.toLlvm(builder).setUnnamedAddr( | |
| 2181 | llvm.Bool.fromBool(unnamed_addr != .default), | |
| 2182 | ); | |
| 2183 | self.ptr(builder).unnamed_addr = unnamed_addr; | |
| 2184 | } | |
| 2185 | ||
| 2090 | 2186 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2091 | 2187 | assert(builder.useLibLlvm()); |
| 2092 | 2188 | return builder.llvm.globals.items[@intFromEnum(self.unwrap(builder))]; |
| ... | ... | @@ -2122,9 +2218,36 @@ pub const Global = struct { |
| 2122 | 2218 | |
| 2123 | 2219 | pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void { |
| 2124 | 2220 | try builder.ensureUnusedGlobalCapacity(.empty); |
| 2221 | if (builder.useLibLlvm()) | |
| 2222 | try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1); | |
| 2125 | 2223 | self.replaceAssumeCapacity(other, builder); |
| 2126 | 2224 | } |
| 2127 | 2225 | |
| 2226 | pub fn delete(self: Index, builder: *Builder) void { | |
| 2227 | if (builder.useLibLlvm()) self.toLlvm(builder).eraseGlobalValue(); | |
| 2228 | self.ptr(builder).kind = .{ .replaced = .none }; | |
| 2229 | } | |
| 2230 | ||
| 2231 | fn updateDsoLocal(self: Index, builder: *Builder) void { | |
| 2232 | const self_ptr = self.ptr(builder); | |
| 2233 | switch (self_ptr.linkage) { | |
| 2234 | .private, .internal => { | |
| 2235 | self_ptr.visibility = .default; | |
| 2236 | self_ptr.dll_storage_class = .default; | |
| 2237 | self_ptr.preemption = .implicit_dso_local; | |
| 2238 | }, | |
| 2239 | .extern_weak => if (self_ptr.preemption == .implicit_dso_local) { | |
| 2240 | self_ptr.preemption = .dso_local; | |
| 2241 | }, | |
| 2242 | else => switch (self_ptr.visibility) { | |
| 2243 | .default => if (self_ptr.preemption == .implicit_dso_local) { | |
| 2244 | self_ptr.preemption = .dso_local; | |
| 2245 | }, | |
| 2246 | else => self_ptr.preemption = .implicit_dso_local, | |
| 2247 | }, | |
| 2248 | } | |
| 2249 | } | |
| 2250 | ||
| 2128 | 2251 | fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void { |
| 2129 | 2252 | const old_name = self.name(builder); |
| 2130 | 2253 | if (new_name == old_name) return; |
| ... | ... | @@ -2151,7 +2274,7 @@ pub const Global = struct { |
| 2151 | 2274 | if (!builder.useLibLlvm()) return; |
| 2152 | 2275 | const index = @intFromEnum(self.unwrap(builder)); |
| 2153 | 2276 | const name_slice = self.name(builder).slice(builder) orelse ""; |
| 2154 | builder.llvm.globals.items[index].setValueName2(name_slice.ptr, name_slice.len); | |
| 2277 | builder.llvm.globals.items[index].setValueName(name_slice.ptr, name_slice.len); | |
| 2155 | 2278 | } |
| 2156 | 2279 | |
| 2157 | 2280 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { |
| ... | ... | @@ -2161,13 +2284,8 @@ pub const Global = struct { |
| 2161 | 2284 | if (builder.useLibLlvm()) { |
| 2162 | 2285 | const self_llvm = self.toLlvm(builder); |
| 2163 | 2286 | self_llvm.replaceAllUsesWith(other.toLlvm(builder)); |
| 2164 | switch (self.ptr(builder).kind) { | |
| 2165 | .alias, | |
| 2166 | .variable, | |
| 2167 | => self_llvm.deleteGlobal(), | |
| 2168 | .function => self_llvm.deleteFunction(), | |
| 2169 | .replaced => unreachable, | |
| 2170 | } | |
| 2287 | self_llvm.removeGlobalValue(); | |
| 2288 | builder.llvm.replacements.putAssumeCapacityNoClobber(self_llvm, other); | |
| 2171 | 2289 | } |
| 2172 | 2290 | self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; |
| 2173 | 2291 | } |
| ... | ... | @@ -2179,42 +2297,17 @@ pub const Global = struct { |
| 2179 | 2297 | }; |
| 2180 | 2298 | } |
| 2181 | 2299 | }; |
| 2182 | ||
| 2183 | pub fn updateAttributes(self: *Global) void { | |
| 2184 | switch (self.linkage) { | |
| 2185 | .private, .internal => { | |
| 2186 | self.visibility = .default; | |
| 2187 | self.dll_storage_class = .default; | |
| 2188 | self.preemption = .implicit_dso_local; | |
| 2189 | }, | |
| 2190 | .extern_weak => if (self.preemption == .implicit_dso_local) { | |
| 2191 | self.preemption = .dso_local; | |
| 2192 | }, | |
| 2193 | else => switch (self.visibility) { | |
| 2194 | .default => if (self.preemption == .implicit_dso_local) { | |
| 2195 | self.preemption = .dso_local; | |
| 2196 | }, | |
| 2197 | else => self.preemption = .implicit_dso_local, | |
| 2198 | }, | |
| 2199 | } | |
| 2200 | } | |
| 2201 | 2300 | }; |
| 2202 | 2301 | |
| 2203 | 2302 | pub const Alias = struct { |
| 2204 | 2303 | global: Global.Index, |
| 2205 | 2304 | thread_local: ThreadLocal = .default, |
| 2206 | init: Constant = .no_init, | |
| 2305 | aliasee: Constant = .no_init, | |
| 2207 | 2306 | |
| 2208 | 2307 | pub const Index = enum(u32) { |
| 2209 | 2308 | none = std.math.maxInt(u32), |
| 2210 | 2309 | _, |
| 2211 | 2310 | |
| 2212 | pub fn getAliasee(self: Index, builder: *const Builder) Global.Index { | |
| 2213 | const aliasee = self.ptrConst(builder).init.getBase(builder); | |
| 2214 | assert(aliasee != .none); | |
| 2215 | return aliasee; | |
| 2216 | } | |
| 2217 | ||
| 2218 | 2311 | pub fn ptr(self: Index, builder: *Builder) *Alias { |
| 2219 | 2312 | return &builder.aliases.items[@intFromEnum(self)]; |
| 2220 | 2313 | } |
| ... | ... | @@ -2223,6 +2316,14 @@ pub const Alias = struct { |
| 2223 | 2316 | return &builder.aliases.items[@intFromEnum(self)]; |
| 2224 | 2317 | } |
| 2225 | 2318 | |
| 2319 | pub fn name(self: Index, builder: *const Builder) String { | |
| 2320 | return self.ptrConst(builder).global.name(builder); | |
| 2321 | } | |
| 2322 | ||
| 2323 | pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { | |
| 2324 | return self.ptrConst(builder).global.rename(new_name, builder); | |
| 2325 | } | |
| 2326 | ||
| 2226 | 2327 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2227 | 2328 | return self.ptrConst(builder).global.typeOf(builder); |
| 2228 | 2329 | } |
| ... | ... | @@ -2235,7 +2336,18 @@ pub const Alias = struct { |
| 2235 | 2336 | return self.toConst(builder).toValue(); |
| 2236 | 2337 | } |
| 2237 | 2338 | |
| 2238 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | |
| 2339 | pub fn getAliasee(self: Index, builder: *const Builder) Global.Index { | |
| 2340 | const aliasee = self.ptrConst(builder).aliasee.getBase(builder); | |
| 2341 | assert(aliasee != .none); | |
| 2342 | return aliasee; | |
| 2343 | } | |
| 2344 | ||
| 2345 | pub fn setAliasee(self: Index, aliasee: Constant, builder: *Builder) void { | |
| 2346 | if (builder.useLibLlvm()) self.toLlvm(builder).setAliasee(aliasee.toLlvm(builder)); | |
| 2347 | self.ptr(builder).aliasee = aliasee; | |
| 2348 | } | |
| 2349 | ||
| 2350 | fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | |
| 2239 | 2351 | return self.ptrConst(builder).global.toLlvm(builder); |
| 2240 | 2352 | } |
| 2241 | 2353 | }; |
| ... | ... | @@ -2244,7 +2356,7 @@ pub const Alias = struct { |
| 2244 | 2356 | pub const Variable = struct { |
| 2245 | 2357 | global: Global.Index, |
| 2246 | 2358 | thread_local: ThreadLocal = .default, |
| 2247 | mutability: enum { global, constant } = .global, | |
| 2359 | mutability: Mutability = .global, | |
| 2248 | 2360 | init: Constant = .no_init, |
| 2249 | 2361 | section: String = .none, |
| 2250 | 2362 | alignment: Alignment = .default, |
| ... | ... | @@ -2261,6 +2373,14 @@ pub const Variable = struct { |
| 2261 | 2373 | return &builder.variables.items[@intFromEnum(self)]; |
| 2262 | 2374 | } |
| 2263 | 2375 | |
| 2376 | pub fn name(self: Index, builder: *const Builder) String { | |
| 2377 | return self.ptrConst(builder).global.name(builder); | |
| 2378 | } | |
| 2379 | ||
| 2380 | pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { | |
| 2381 | return self.ptrConst(builder).global.rename(new_name, builder); | |
| 2382 | } | |
| 2383 | ||
| 2264 | 2384 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2265 | 2385 | return self.ptrConst(builder).global.typeOf(builder); |
| 2266 | 2386 | } |
| ... | ... | @@ -2269,14 +2389,1407 @@ pub const Variable = struct { |
| 2269 | 2389 | return self.ptrConst(builder).global.toConst(); |
| 2270 | 2390 | } |
| 2271 | 2391 | |
| 2272 | pub fn toValue(self: Index, builder: *const Builder) Value { | |
| 2273 | return self.toConst(builder).toValue(); | |
| 2274 | } | |
| 2392 | pub fn toValue(self: Index, builder: *const Builder) Value { | |
| 2393 | return self.toConst(builder).toValue(); | |
| 2394 | } | |
| 2395 | ||
| 2396 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { | |
| 2397 | return self.ptrConst(builder).global.setLinkage(linkage, builder); | |
| 2398 | } | |
| 2399 | ||
| 2400 | pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { | |
| 2401 | return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder); | |
| 2402 | } | |
| 2403 | ||
| 2404 | pub fn setThreadLocal(self: Index, thread_local: ThreadLocal, builder: *Builder) void { | |
| 2405 | if (builder.useLibLlvm()) self.toLlvm(builder).setThreadLocalMode(thread_local.toLlvm()); | |
| 2406 | self.ptr(builder).thread_local = thread_local; | |
| 2407 | } | |
| 2408 | ||
| 2409 | pub fn setMutability(self: Index, mutability: Mutability, builder: *Builder) void { | |
| 2410 | if (builder.useLibLlvm()) self.toLlvm(builder).setGlobalConstant( | |
| 2411 | llvm.Bool.fromBool(mutability == .constant), | |
| 2412 | ); | |
| 2413 | self.ptr(builder).mutability = mutability; | |
| 2414 | } | |
| 2415 | ||
| 2416 | pub fn setInitializer( | |
| 2417 | self: Index, | |
| 2418 | initializer: Constant, | |
| 2419 | builder: *Builder, | |
| 2420 | ) Allocator.Error!void { | |
| 2421 | if (initializer != .no_init) { | |
| 2422 | const variable = self.ptrConst(builder); | |
| 2423 | const global = variable.global.ptr(builder); | |
| 2424 | const initializer_type = initializer.typeOf(builder); | |
| 2425 | if (builder.useLibLlvm() and global.type != initializer_type) { | |
| 2426 | try builder.llvm.replacements.ensureUnusedCapacity(builder.gpa, 1); | |
| 2427 | // LLVM does not allow us to change the type of globals. So we must | |
| 2428 | // create a new global with the correct type, copy all its attributes, | |
| 2429 | // and then update all references to point to the new global, | |
| 2430 | // delete the original, and rename the new one to the old one's name. | |
| 2431 | // This is necessary because LLVM does not support const bitcasting | |
| 2432 | // a struct with padding bytes, which is needed to lower a const union value | |
| 2433 | // to LLVM, when a field other than the most-aligned is active. Instead, | |
| 2434 | // we must lower to an unnamed struct, and pointer cast at usage sites | |
| 2435 | // of the global. Such an unnamed struct is the cause of the global type | |
| 2436 | // mismatch, because we don't have the LLVM type until the *value* is created, | |
| 2437 | // whereas the global needs to be created based on the type alone, because | |
| 2438 | // lowering the value may reference the global as a pointer. | |
| 2439 | // Related: https://github.com/ziglang/zig/issues/13265 | |
| 2440 | const old_global = &builder.llvm.globals.items[@intFromEnum(variable.global)]; | |
| 2441 | const new_global = builder.llvm.module.?.addGlobalInAddressSpace( | |
| 2442 | initializer_type.toLlvm(builder), | |
| 2443 | "", | |
| 2444 | @intFromEnum(global.addr_space), | |
| 2445 | ); | |
| 2446 | new_global.setLinkage(global.linkage.toLlvm()); | |
| 2447 | new_global.setUnnamedAddr(llvm.Bool.fromBool(global.unnamed_addr != .default)); | |
| 2448 | new_global.setAlignment(@intCast(variable.alignment.toByteUnits() orelse 0)); | |
| 2449 | if (variable.section != .none) | |
| 2450 | new_global.setSection(variable.section.slice(builder).?); | |
| 2451 | old_global.*.replaceAllUsesWith(new_global); | |
| 2452 | builder.llvm.replacements.putAssumeCapacityNoClobber(old_global.*, variable.global); | |
| 2453 | new_global.takeName(old_global.*); | |
| 2454 | old_global.*.removeGlobalValue(); | |
| 2455 | old_global.* = new_global; | |
| 2456 | self.ptr(builder).mutability = .global; | |
| 2457 | } | |
| 2458 | global.type = initializer_type; | |
| 2459 | } | |
| 2460 | if (builder.useLibLlvm()) self.toLlvm(builder).setInitializer(switch (initializer) { | |
| 2461 | .no_init => null, | |
| 2462 | else => initializer.toLlvm(builder), | |
| 2463 | }); | |
| 2464 | self.ptr(builder).init = initializer; | |
| 2465 | } | |
| 2466 | ||
| 2467 | pub fn setSection(self: Index, section: String, builder: *Builder) void { | |
| 2468 | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); | |
| 2469 | self.ptr(builder).section = section; | |
| 2470 | } | |
| 2471 | ||
| 2472 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { | |
| 2473 | if (builder.useLibLlvm()) | |
| 2474 | self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0)); | |
| 2475 | self.ptr(builder).alignment = alignment; | |
| 2476 | } | |
| 2477 | ||
| 2478 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | |
| 2479 | return self.ptrConst(builder).global.toLlvm(builder); | |
| 2480 | } | |
| 2481 | }; | |
| 2482 | }; | |
| 2483 | ||
| 2484 | pub const Intrinsic = enum { | |
| 2485 | // Variable Argument Handling | |
| 2486 | va_start, | |
| 2487 | va_end, | |
| 2488 | va_copy, | |
| 2489 | ||
| 2490 | // Code Generator | |
| 2491 | returnaddress, | |
| 2492 | addressofreturnaddress, | |
| 2493 | sponentry, | |
| 2494 | frameaddress, | |
| 2495 | prefetch, | |
| 2496 | @"thread.pointer", | |
| 2497 | ||
| 2498 | // Standard C/C++ Library | |
| 2499 | abs, | |
| 2500 | smax, | |
| 2501 | smin, | |
| 2502 | umax, | |
| 2503 | umin, | |
| 2504 | memcpy, | |
| 2505 | @"memcpy.inline", | |
| 2506 | memmove, | |
| 2507 | memset, | |
| 2508 | @"memset.inline", | |
| 2509 | sqrt, | |
| 2510 | powi, | |
| 2511 | sin, | |
| 2512 | cos, | |
| 2513 | pow, | |
| 2514 | exp, | |
| 2515 | exp2, | |
| 2516 | ldexp, | |
| 2517 | frexp, | |
| 2518 | log, | |
| 2519 | log10, | |
| 2520 | log2, | |
| 2521 | fma, | |
| 2522 | fabs, | |
| 2523 | minnum, | |
| 2524 | maxnum, | |
| 2525 | minimum, | |
| 2526 | maximum, | |
| 2527 | copysign, | |
| 2528 | floor, | |
| 2529 | ceil, | |
| 2530 | trunc, | |
| 2531 | rint, | |
| 2532 | nearbyint, | |
| 2533 | round, | |
| 2534 | roundeven, | |
| 2535 | lround, | |
| 2536 | llround, | |
| 2537 | lrint, | |
| 2538 | llrint, | |
| 2539 | ||
| 2540 | // Bit Manipulation | |
| 2541 | bitreverse, | |
| 2542 | bswap, | |
| 2543 | ctpop, | |
| 2544 | ctlz, | |
| 2545 | cttz, | |
| 2546 | fshl, | |
| 2547 | fshr, | |
| 2548 | ||
| 2549 | // Arithmetic with Overflow | |
| 2550 | @"sadd.with.overflow", | |
| 2551 | @"uadd.with.overflow", | |
| 2552 | @"ssub.with.overflow", | |
| 2553 | @"usub.with.overflow", | |
| 2554 | @"smul.with.overflow", | |
| 2555 | @"umul.with.overflow", | |
| 2556 | ||
| 2557 | // Saturation Arithmetic | |
| 2558 | @"sadd.sat", | |
| 2559 | @"uadd.sat", | |
| 2560 | @"ssub.sat", | |
| 2561 | @"usub.sat", | |
| 2562 | @"sshl.sat", | |
| 2563 | @"ushl.sat", | |
| 2564 | ||
| 2565 | // Fixed Point Arithmetic | |
| 2566 | @"smul.fix", | |
| 2567 | @"umul.fix", | |
| 2568 | @"smul.fix.sat", | |
| 2569 | @"umul.fix.sat", | |
| 2570 | @"sdiv.fix", | |
| 2571 | @"udiv.fix", | |
| 2572 | @"sdiv.fix.sat", | |
| 2573 | @"udiv.fix.sat", | |
| 2574 | ||
| 2575 | // Specialised Arithmetic | |
| 2576 | canonicalize, | |
| 2577 | fmuladd, | |
| 2578 | ||
| 2579 | // Vector Reduction | |
| 2580 | @"vector.reduce.add", | |
| 2581 | @"vector.reduce.fadd", | |
| 2582 | @"vector.reduce.mul", | |
| 2583 | @"vector.reduce.fmul", | |
| 2584 | @"vector.reduce.and", | |
| 2585 | @"vector.reduce.or", | |
| 2586 | @"vector.reduce.xor", | |
| 2587 | @"vector.reduce.smax", | |
| 2588 | @"vector.reduce.smin", | |
| 2589 | @"vector.reduce.umax", | |
| 2590 | @"vector.reduce.umin", | |
| 2591 | @"vector.reduce.fmax", | |
| 2592 | @"vector.reduce.fmin", | |
| 2593 | @"vector.reduce.fmaximum", | |
| 2594 | @"vector.reduce.fminimum", | |
| 2595 | @"vector.insert", | |
| 2596 | @"vector.extract", | |
| 2597 | ||
| 2598 | // Floating-Point Test | |
| 2599 | @"is.fpclass", | |
| 2600 | ||
| 2601 | // General | |
| 2602 | @"var.annotation", | |
| 2603 | @"ptr.annotation", | |
| 2604 | annotation, | |
| 2605 | @"codeview.annotation", | |
| 2606 | trap, | |
| 2607 | debugtrap, | |
| 2608 | ubsantrap, | |
| 2609 | stackprotector, | |
| 2610 | stackguard, | |
| 2611 | objectsize, | |
| 2612 | expect, | |
| 2613 | @"expect.with.probability", | |
| 2614 | assume, | |
| 2615 | @"ssa.copy", | |
| 2616 | @"type.test", | |
| 2617 | @"type.checked.load", | |
| 2618 | @"type.checked.load.relative", | |
| 2619 | @"arithmetic.fence", | |
| 2620 | donothing, | |
| 2621 | @"load.relative", | |
| 2622 | sideeffect, | |
| 2623 | @"is.constant", | |
| 2624 | ptrmask, | |
| 2625 | @"threadlocal.address", | |
| 2626 | vscale, | |
| 2627 | ||
| 2628 | // AMDGPU | |
| 2629 | @"amdgcn.workitem.id.x", | |
| 2630 | @"amdgcn.workitem.id.y", | |
| 2631 | @"amdgcn.workitem.id.z", | |
| 2632 | @"amdgcn.workgroup.id.x", | |
| 2633 | @"amdgcn.workgroup.id.y", | |
| 2634 | @"amdgcn.workgroup.id.z", | |
| 2635 | @"amdgcn.dispatch.ptr", | |
| 2636 | ||
| 2637 | // WebAssembly | |
| 2638 | @"wasm.memory.size", | |
| 2639 | @"wasm.memory.grow", | |
| 2640 | ||
| 2641 | const Signature = struct { | |
| 2642 | ret_len: u8, | |
| 2643 | params: []const Parameter, | |
| 2644 | attrs: []const Attribute = &.{}, | |
| 2645 | ||
| 2646 | const Parameter = struct { | |
| 2647 | kind: Kind, | |
| 2648 | attrs: []const Attribute = &.{}, | |
| 2649 | ||
| 2650 | const Kind = union(enum) { | |
| 2651 | type: Type, | |
| 2652 | overloaded, | |
| 2653 | matches: u8, | |
| 2654 | matches_scalar: u8, | |
| 2655 | matches_changed_scalar: struct { | |
| 2656 | index: u8, | |
| 2657 | scalar: Type, | |
| 2658 | }, | |
| 2659 | }; | |
| 2660 | }; | |
| 2661 | }; | |
| 2662 | ||
| 2663 | const signatures = std.enums.EnumArray(Intrinsic, Signature).init(.{ | |
| 2664 | .va_start = .{ | |
| 2665 | .ret_len = 0, | |
| 2666 | .params = &.{ | |
| 2667 | .{ .kind = .{ .type = .ptr } }, | |
| 2668 | }, | |
| 2669 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 2670 | }, | |
| 2671 | .va_end = .{ | |
| 2672 | .ret_len = 0, | |
| 2673 | .params = &.{ | |
| 2674 | .{ .kind = .{ .type = .ptr } }, | |
| 2675 | }, | |
| 2676 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 2677 | }, | |
| 2678 | .va_copy = .{ | |
| 2679 | .ret_len = 0, | |
| 2680 | .params = &.{ | |
| 2681 | .{ .kind = .{ .type = .ptr } }, | |
| 2682 | .{ .kind = .{ .type = .ptr } }, | |
| 2683 | }, | |
| 2684 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 2685 | }, | |
| 2686 | ||
| 2687 | .returnaddress = .{ | |
| 2688 | .ret_len = 1, | |
| 2689 | .params = &.{ | |
| 2690 | .{ .kind = .{ .type = .ptr } }, | |
| 2691 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 2692 | }, | |
| 2693 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2694 | }, | |
| 2695 | .addressofreturnaddress = .{ | |
| 2696 | .ret_len = 1, | |
| 2697 | .params = &.{ | |
| 2698 | .{ .kind = .overloaded }, | |
| 2699 | }, | |
| 2700 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2701 | }, | |
| 2702 | .sponentry = .{ | |
| 2703 | .ret_len = 1, | |
| 2704 | .params = &.{ | |
| 2705 | .{ .kind = .overloaded }, | |
| 2706 | }, | |
| 2707 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2708 | }, | |
| 2709 | .frameaddress = .{ | |
| 2710 | .ret_len = 1, | |
| 2711 | .params = &.{ | |
| 2712 | .{ .kind = .overloaded }, | |
| 2713 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 2714 | }, | |
| 2715 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2716 | }, | |
| 2717 | .prefetch = .{ | |
| 2718 | .ret_len = 0, | |
| 2719 | .params = &.{ | |
| 2720 | .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } }, | |
| 2721 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 2722 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 2723 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 2724 | }, | |
| 2725 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } }, | |
| 2726 | }, | |
| 2727 | .@"thread.pointer" = .{ | |
| 2728 | .ret_len = 1, | |
| 2729 | .params = &.{ | |
| 2730 | .{ .kind = .{ .type = .ptr } }, | |
| 2731 | }, | |
| 2732 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2733 | }, | |
| 2734 | ||
| 2735 | .abs = .{ | |
| 2736 | .ret_len = 1, | |
| 2737 | .params = &.{ | |
| 2738 | .{ .kind = .overloaded }, | |
| 2739 | .{ .kind = .{ .matches = 0 } }, | |
| 2740 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2741 | }, | |
| 2742 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2743 | }, | |
| 2744 | .smax = .{ | |
| 2745 | .ret_len = 1, | |
| 2746 | .params = &.{ | |
| 2747 | .{ .kind = .overloaded }, | |
| 2748 | .{ .kind = .{ .matches = 0 } }, | |
| 2749 | .{ .kind = .{ .matches = 0 } }, | |
| 2750 | }, | |
| 2751 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2752 | }, | |
| 2753 | .smin = .{ | |
| 2754 | .ret_len = 1, | |
| 2755 | .params = &.{ | |
| 2756 | .{ .kind = .overloaded }, | |
| 2757 | .{ .kind = .{ .matches = 0 } }, | |
| 2758 | .{ .kind = .{ .matches = 0 } }, | |
| 2759 | }, | |
| 2760 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2761 | }, | |
| 2762 | .umax = .{ | |
| 2763 | .ret_len = 1, | |
| 2764 | .params = &.{ | |
| 2765 | .{ .kind = .overloaded }, | |
| 2766 | .{ .kind = .{ .matches = 0 } }, | |
| 2767 | .{ .kind = .{ .matches = 0 } }, | |
| 2768 | }, | |
| 2769 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2770 | }, | |
| 2771 | .umin = .{ | |
| 2772 | .ret_len = 1, | |
| 2773 | .params = &.{ | |
| 2774 | .{ .kind = .overloaded }, | |
| 2775 | .{ .kind = .{ .matches = 0 } }, | |
| 2776 | .{ .kind = .{ .matches = 0 } }, | |
| 2777 | }, | |
| 2778 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2779 | }, | |
| 2780 | .memcpy = .{ | |
| 2781 | .ret_len = 0, | |
| 2782 | .params = &.{ | |
| 2783 | .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .writeonly } }, | |
| 2784 | .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .readonly } }, | |
| 2785 | .{ .kind = .overloaded }, | |
| 2786 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2787 | }, | |
| 2788 | .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } }, | |
| 2789 | }, | |
| 2790 | .@"memcpy.inline" = .{ | |
| 2791 | .ret_len = 0, | |
| 2792 | .params = &.{ | |
| 2793 | .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .writeonly } }, | |
| 2794 | .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .readonly } }, | |
| 2795 | .{ .kind = .overloaded, .attrs = &.{.immarg} }, | |
| 2796 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2797 | }, | |
| 2798 | .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } }, | |
| 2799 | }, | |
| 2800 | .memmove = .{ | |
| 2801 | .ret_len = 0, | |
| 2802 | .params = &.{ | |
| 2803 | .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } }, | |
| 2804 | .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } }, | |
| 2805 | .{ .kind = .overloaded }, | |
| 2806 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2807 | }, | |
| 2808 | .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } }, | |
| 2809 | }, | |
| 2810 | .memset = .{ | |
| 2811 | .ret_len = 0, | |
| 2812 | .params = &.{ | |
| 2813 | .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } }, | |
| 2814 | .{ .kind = .{ .type = .i8 } }, | |
| 2815 | .{ .kind = .overloaded }, | |
| 2816 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2817 | }, | |
| 2818 | .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .write } } }, | |
| 2819 | }, | |
| 2820 | .@"memset.inline" = .{ | |
| 2821 | .ret_len = 0, | |
| 2822 | .params = &.{ | |
| 2823 | .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } }, | |
| 2824 | .{ .kind = .{ .type = .i8 } }, | |
| 2825 | .{ .kind = .overloaded, .attrs = &.{.immarg} }, | |
| 2826 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 2827 | }, | |
| 2828 | .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .write } } }, | |
| 2829 | }, | |
| 2830 | .sqrt = .{ | |
| 2831 | .ret_len = 1, | |
| 2832 | .params = &.{ | |
| 2833 | .{ .kind = .overloaded }, | |
| 2834 | .{ .kind = .{ .matches = 0 } }, | |
| 2835 | }, | |
| 2836 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2837 | }, | |
| 2838 | .powi = .{ | |
| 2839 | .ret_len = 1, | |
| 2840 | .params = &.{ | |
| 2841 | .{ .kind = .overloaded }, | |
| 2842 | .{ .kind = .{ .matches = 0 } }, | |
| 2843 | .{ .kind = .overloaded }, | |
| 2844 | }, | |
| 2845 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2846 | }, | |
| 2847 | .sin = .{ | |
| 2848 | .ret_len = 1, | |
| 2849 | .params = &.{ | |
| 2850 | .{ .kind = .overloaded }, | |
| 2851 | .{ .kind = .{ .matches = 0 } }, | |
| 2852 | }, | |
| 2853 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2854 | }, | |
| 2855 | .cos = .{ | |
| 2856 | .ret_len = 1, | |
| 2857 | .params = &.{ | |
| 2858 | .{ .kind = .overloaded }, | |
| 2859 | .{ .kind = .{ .matches = 0 } }, | |
| 2860 | }, | |
| 2861 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2862 | }, | |
| 2863 | .pow = .{ | |
| 2864 | .ret_len = 1, | |
| 2865 | .params = &.{ | |
| 2866 | .{ .kind = .overloaded }, | |
| 2867 | .{ .kind = .{ .matches = 0 } }, | |
| 2868 | .{ .kind = .{ .matches = 0 } }, | |
| 2869 | }, | |
| 2870 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2871 | }, | |
| 2872 | .exp = .{ | |
| 2873 | .ret_len = 1, | |
| 2874 | .params = &.{ | |
| 2875 | .{ .kind = .overloaded }, | |
| 2876 | .{ .kind = .{ .matches = 0 } }, | |
| 2877 | }, | |
| 2878 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2879 | }, | |
| 2880 | .exp2 = .{ | |
| 2881 | .ret_len = 1, | |
| 2882 | .params = &.{ | |
| 2883 | .{ .kind = .overloaded }, | |
| 2884 | .{ .kind = .{ .matches = 0 } }, | |
| 2885 | }, | |
| 2886 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2887 | }, | |
| 2888 | .ldexp = .{ | |
| 2889 | .ret_len = 1, | |
| 2890 | .params = &.{ | |
| 2891 | .{ .kind = .overloaded }, | |
| 2892 | .{ .kind = .{ .matches = 0 } }, | |
| 2893 | .{ .kind = .overloaded }, | |
| 2894 | }, | |
| 2895 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2896 | }, | |
| 2897 | .frexp = .{ | |
| 2898 | .ret_len = 2, | |
| 2899 | .params = &.{ | |
| 2900 | .{ .kind = .overloaded }, | |
| 2901 | .{ .kind = .overloaded }, | |
| 2902 | .{ .kind = .{ .matches = 0 } }, | |
| 2903 | }, | |
| 2904 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2905 | }, | |
| 2906 | .log = .{ | |
| 2907 | .ret_len = 1, | |
| 2908 | .params = &.{ | |
| 2909 | .{ .kind = .overloaded }, | |
| 2910 | .{ .kind = .{ .matches = 0 } }, | |
| 2911 | }, | |
| 2912 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2913 | }, | |
| 2914 | .log10 = .{ | |
| 2915 | .ret_len = 1, | |
| 2916 | .params = &.{ | |
| 2917 | .{ .kind = .overloaded }, | |
| 2918 | .{ .kind = .{ .matches = 0 } }, | |
| 2919 | }, | |
| 2920 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2921 | }, | |
| 2922 | .log2 = .{ | |
| 2923 | .ret_len = 1, | |
| 2924 | .params = &.{ | |
| 2925 | .{ .kind = .overloaded }, | |
| 2926 | .{ .kind = .{ .matches = 0 } }, | |
| 2927 | }, | |
| 2928 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2929 | }, | |
| 2930 | .fma = .{ | |
| 2931 | .ret_len = 1, | |
| 2932 | .params = &.{ | |
| 2933 | .{ .kind = .overloaded }, | |
| 2934 | .{ .kind = .{ .matches = 0 } }, | |
| 2935 | .{ .kind = .{ .matches = 0 } }, | |
| 2936 | .{ .kind = .{ .matches = 0 } }, | |
| 2937 | }, | |
| 2938 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2939 | }, | |
| 2940 | .fabs = .{ | |
| 2941 | .ret_len = 1, | |
| 2942 | .params = &.{ | |
| 2943 | .{ .kind = .overloaded }, | |
| 2944 | .{ .kind = .{ .matches = 0 } }, | |
| 2945 | }, | |
| 2946 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2947 | }, | |
| 2948 | .minnum = .{ | |
| 2949 | .ret_len = 1, | |
| 2950 | .params = &.{ | |
| 2951 | .{ .kind = .overloaded }, | |
| 2952 | .{ .kind = .{ .matches = 0 } }, | |
| 2953 | .{ .kind = .{ .matches = 0 } }, | |
| 2954 | }, | |
| 2955 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2956 | }, | |
| 2957 | .maxnum = .{ | |
| 2958 | .ret_len = 1, | |
| 2959 | .params = &.{ | |
| 2960 | .{ .kind = .overloaded }, | |
| 2961 | .{ .kind = .{ .matches = 0 } }, | |
| 2962 | .{ .kind = .{ .matches = 0 } }, | |
| 2963 | }, | |
| 2964 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2965 | }, | |
| 2966 | .minimum = .{ | |
| 2967 | .ret_len = 1, | |
| 2968 | .params = &.{ | |
| 2969 | .{ .kind = .overloaded }, | |
| 2970 | .{ .kind = .{ .matches = 0 } }, | |
| 2971 | .{ .kind = .{ .matches = 0 } }, | |
| 2972 | }, | |
| 2973 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2974 | }, | |
| 2975 | .maximum = .{ | |
| 2976 | .ret_len = 1, | |
| 2977 | .params = &.{ | |
| 2978 | .{ .kind = .overloaded }, | |
| 2979 | .{ .kind = .{ .matches = 0 } }, | |
| 2980 | .{ .kind = .{ .matches = 0 } }, | |
| 2981 | }, | |
| 2982 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2983 | }, | |
| 2984 | .copysign = .{ | |
| 2985 | .ret_len = 1, | |
| 2986 | .params = &.{ | |
| 2987 | .{ .kind = .overloaded }, | |
| 2988 | .{ .kind = .{ .matches = 0 } }, | |
| 2989 | .{ .kind = .{ .matches = 0 } }, | |
| 2990 | }, | |
| 2991 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 2992 | }, | |
| 2993 | .floor = .{ | |
| 2994 | .ret_len = 1, | |
| 2995 | .params = &.{ | |
| 2996 | .{ .kind = .overloaded }, | |
| 2997 | .{ .kind = .{ .matches = 0 } }, | |
| 2998 | }, | |
| 2999 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3000 | }, | |
| 3001 | .ceil = .{ | |
| 3002 | .ret_len = 1, | |
| 3003 | .params = &.{ | |
| 3004 | .{ .kind = .overloaded }, | |
| 3005 | .{ .kind = .{ .matches = 0 } }, | |
| 3006 | }, | |
| 3007 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3008 | }, | |
| 3009 | .trunc = .{ | |
| 3010 | .ret_len = 1, | |
| 3011 | .params = &.{ | |
| 3012 | .{ .kind = .overloaded }, | |
| 3013 | .{ .kind = .{ .matches = 0 } }, | |
| 3014 | }, | |
| 3015 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3016 | }, | |
| 3017 | .rint = .{ | |
| 3018 | .ret_len = 1, | |
| 3019 | .params = &.{ | |
| 3020 | .{ .kind = .overloaded }, | |
| 3021 | .{ .kind = .{ .matches = 0 } }, | |
| 3022 | }, | |
| 3023 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3024 | }, | |
| 3025 | .nearbyint = .{ | |
| 3026 | .ret_len = 1, | |
| 3027 | .params = &.{ | |
| 3028 | .{ .kind = .overloaded }, | |
| 3029 | .{ .kind = .{ .matches = 0 } }, | |
| 3030 | }, | |
| 3031 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3032 | }, | |
| 3033 | .round = .{ | |
| 3034 | .ret_len = 1, | |
| 3035 | .params = &.{ | |
| 3036 | .{ .kind = .overloaded }, | |
| 3037 | .{ .kind = .{ .matches = 0 } }, | |
| 3038 | }, | |
| 3039 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3040 | }, | |
| 3041 | .roundeven = .{ | |
| 3042 | .ret_len = 1, | |
| 3043 | .params = &.{ | |
| 3044 | .{ .kind = .overloaded }, | |
| 3045 | .{ .kind = .{ .matches = 0 } }, | |
| 3046 | }, | |
| 3047 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3048 | }, | |
| 3049 | .lround = .{ | |
| 3050 | .ret_len = 1, | |
| 3051 | .params = &.{ | |
| 3052 | .{ .kind = .overloaded }, | |
| 3053 | .{ .kind = .overloaded }, | |
| 3054 | }, | |
| 3055 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3056 | }, | |
| 3057 | .llround = .{ | |
| 3058 | .ret_len = 1, | |
| 3059 | .params = &.{ | |
| 3060 | .{ .kind = .overloaded }, | |
| 3061 | .{ .kind = .overloaded }, | |
| 3062 | }, | |
| 3063 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3064 | }, | |
| 3065 | .lrint = .{ | |
| 3066 | .ret_len = 1, | |
| 3067 | .params = &.{ | |
| 3068 | .{ .kind = .overloaded }, | |
| 3069 | .{ .kind = .overloaded }, | |
| 3070 | }, | |
| 3071 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3072 | }, | |
| 3073 | .llrint = .{ | |
| 3074 | .ret_len = 1, | |
| 3075 | .params = &.{ | |
| 3076 | .{ .kind = .overloaded }, | |
| 3077 | .{ .kind = .overloaded }, | |
| 3078 | }, | |
| 3079 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3080 | }, | |
| 3081 | ||
| 3082 | .bitreverse = .{ | |
| 3083 | .ret_len = 1, | |
| 3084 | .params = &.{ | |
| 3085 | .{ .kind = .overloaded }, | |
| 3086 | .{ .kind = .{ .matches = 0 } }, | |
| 3087 | }, | |
| 3088 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3089 | }, | |
| 3090 | .bswap = .{ | |
| 3091 | .ret_len = 1, | |
| 3092 | .params = &.{ | |
| 3093 | .{ .kind = .overloaded }, | |
| 3094 | .{ .kind = .{ .matches = 0 } }, | |
| 3095 | }, | |
| 3096 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3097 | }, | |
| 3098 | .ctpop = .{ | |
| 3099 | .ret_len = 1, | |
| 3100 | .params = &.{ | |
| 3101 | .{ .kind = .overloaded }, | |
| 3102 | .{ .kind = .{ .matches = 0 } }, | |
| 3103 | }, | |
| 3104 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3105 | }, | |
| 3106 | .ctlz = .{ | |
| 3107 | .ret_len = 1, | |
| 3108 | .params = &.{ | |
| 3109 | .{ .kind = .overloaded }, | |
| 3110 | .{ .kind = .{ .matches = 0 } }, | |
| 3111 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 3112 | }, | |
| 3113 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3114 | }, | |
| 3115 | .cttz = .{ | |
| 3116 | .ret_len = 1, | |
| 3117 | .params = &.{ | |
| 3118 | .{ .kind = .overloaded }, | |
| 3119 | .{ .kind = .{ .matches = 0 } }, | |
| 3120 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 3121 | }, | |
| 3122 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3123 | }, | |
| 3124 | .fshl = .{ | |
| 3125 | .ret_len = 1, | |
| 3126 | .params = &.{ | |
| 3127 | .{ .kind = .overloaded }, | |
| 3128 | .{ .kind = .{ .matches = 0 } }, | |
| 3129 | .{ .kind = .{ .matches = 0 } }, | |
| 3130 | .{ .kind = .{ .matches = 0 } }, | |
| 3131 | }, | |
| 3132 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3133 | }, | |
| 3134 | .fshr = .{ | |
| 3135 | .ret_len = 1, | |
| 3136 | .params = &.{ | |
| 3137 | .{ .kind = .overloaded }, | |
| 3138 | .{ .kind = .{ .matches = 0 } }, | |
| 3139 | .{ .kind = .{ .matches = 0 } }, | |
| 3140 | .{ .kind = .{ .matches = 0 } }, | |
| 3141 | }, | |
| 3142 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3143 | }, | |
| 3144 | ||
| 3145 | .@"sadd.with.overflow" = .{ | |
| 3146 | .ret_len = 2, | |
| 3147 | .params = &.{ | |
| 3148 | .{ .kind = .overloaded }, | |
| 3149 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3150 | .{ .kind = .{ .matches = 0 } }, | |
| 3151 | .{ .kind = .{ .matches = 0 } }, | |
| 3152 | }, | |
| 3153 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3154 | }, | |
| 3155 | .@"uadd.with.overflow" = .{ | |
| 3156 | .ret_len = 2, | |
| 3157 | .params = &.{ | |
| 3158 | .{ .kind = .overloaded }, | |
| 3159 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3160 | .{ .kind = .{ .matches = 0 } }, | |
| 3161 | .{ .kind = .{ .matches = 0 } }, | |
| 3162 | }, | |
| 3163 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3164 | }, | |
| 3165 | .@"ssub.with.overflow" = .{ | |
| 3166 | .ret_len = 2, | |
| 3167 | .params = &.{ | |
| 3168 | .{ .kind = .overloaded }, | |
| 3169 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3170 | .{ .kind = .{ .matches = 0 } }, | |
| 3171 | .{ .kind = .{ .matches = 0 } }, | |
| 3172 | }, | |
| 3173 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3174 | }, | |
| 3175 | .@"usub.with.overflow" = .{ | |
| 3176 | .ret_len = 2, | |
| 3177 | .params = &.{ | |
| 3178 | .{ .kind = .overloaded }, | |
| 3179 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3180 | .{ .kind = .{ .matches = 0 } }, | |
| 3181 | .{ .kind = .{ .matches = 0 } }, | |
| 3182 | }, | |
| 3183 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3184 | }, | |
| 3185 | .@"smul.with.overflow" = .{ | |
| 3186 | .ret_len = 2, | |
| 3187 | .params = &.{ | |
| 3188 | .{ .kind = .overloaded }, | |
| 3189 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3190 | .{ .kind = .{ .matches = 0 } }, | |
| 3191 | .{ .kind = .{ .matches = 0 } }, | |
| 3192 | }, | |
| 3193 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3194 | }, | |
| 3195 | .@"umul.with.overflow" = .{ | |
| 3196 | .ret_len = 2, | |
| 3197 | .params = &.{ | |
| 3198 | .{ .kind = .overloaded }, | |
| 3199 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 0, .scalar = .i1 } } }, | |
| 3200 | .{ .kind = .{ .matches = 0 } }, | |
| 3201 | .{ .kind = .{ .matches = 0 } }, | |
| 3202 | }, | |
| 3203 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3204 | }, | |
| 3205 | ||
| 3206 | .@"sadd.sat" = .{ | |
| 3207 | .ret_len = 1, | |
| 3208 | .params = &.{ | |
| 3209 | .{ .kind = .overloaded }, | |
| 3210 | .{ .kind = .{ .matches = 0 } }, | |
| 3211 | .{ .kind = .{ .matches = 0 } }, | |
| 3212 | }, | |
| 3213 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3214 | }, | |
| 3215 | .@"uadd.sat" = .{ | |
| 3216 | .ret_len = 1, | |
| 3217 | .params = &.{ | |
| 3218 | .{ .kind = .overloaded }, | |
| 3219 | .{ .kind = .{ .matches = 0 } }, | |
| 3220 | .{ .kind = .{ .matches = 0 } }, | |
| 3221 | }, | |
| 3222 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3223 | }, | |
| 3224 | .@"ssub.sat" = .{ | |
| 3225 | .ret_len = 1, | |
| 3226 | .params = &.{ | |
| 3227 | .{ .kind = .overloaded }, | |
| 3228 | .{ .kind = .{ .matches = 0 } }, | |
| 3229 | .{ .kind = .{ .matches = 0 } }, | |
| 3230 | }, | |
| 3231 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3232 | }, | |
| 3233 | .@"usub.sat" = .{ | |
| 3234 | .ret_len = 1, | |
| 3235 | .params = &.{ | |
| 3236 | .{ .kind = .overloaded }, | |
| 3237 | .{ .kind = .{ .matches = 0 } }, | |
| 3238 | .{ .kind = .{ .matches = 0 } }, | |
| 3239 | }, | |
| 3240 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3241 | }, | |
| 3242 | .@"sshl.sat" = .{ | |
| 3243 | .ret_len = 1, | |
| 3244 | .params = &.{ | |
| 3245 | .{ .kind = .overloaded }, | |
| 3246 | .{ .kind = .{ .matches = 0 } }, | |
| 3247 | .{ .kind = .{ .matches = 0 } }, | |
| 3248 | }, | |
| 3249 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3250 | }, | |
| 3251 | .@"ushl.sat" = .{ | |
| 3252 | .ret_len = 1, | |
| 3253 | .params = &.{ | |
| 3254 | .{ .kind = .overloaded }, | |
| 3255 | .{ .kind = .{ .matches = 0 } }, | |
| 3256 | .{ .kind = .{ .matches = 0 } }, | |
| 3257 | }, | |
| 3258 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3259 | }, | |
| 3260 | ||
| 3261 | .@"smul.fix" = .{ | |
| 3262 | .ret_len = 1, | |
| 3263 | .params = &.{ | |
| 3264 | .{ .kind = .overloaded }, | |
| 3265 | .{ .kind = .{ .matches = 0 } }, | |
| 3266 | .{ .kind = .{ .matches = 0 } }, | |
| 3267 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3268 | }, | |
| 3269 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3270 | }, | |
| 3271 | .@"umul.fix" = .{ | |
| 3272 | .ret_len = 1, | |
| 3273 | .params = &.{ | |
| 3274 | .{ .kind = .overloaded }, | |
| 3275 | .{ .kind = .{ .matches = 0 } }, | |
| 3276 | .{ .kind = .{ .matches = 0 } }, | |
| 3277 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3278 | }, | |
| 3279 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3280 | }, | |
| 3281 | .@"smul.fix.sat" = .{ | |
| 3282 | .ret_len = 1, | |
| 3283 | .params = &.{ | |
| 3284 | .{ .kind = .overloaded }, | |
| 3285 | .{ .kind = .{ .matches = 0 } }, | |
| 3286 | .{ .kind = .{ .matches = 0 } }, | |
| 3287 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3288 | }, | |
| 3289 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3290 | }, | |
| 3291 | .@"umul.fix.sat" = .{ | |
| 3292 | .ret_len = 1, | |
| 3293 | .params = &.{ | |
| 3294 | .{ .kind = .overloaded }, | |
| 3295 | .{ .kind = .{ .matches = 0 } }, | |
| 3296 | .{ .kind = .{ .matches = 0 } }, | |
| 3297 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3298 | }, | |
| 3299 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3300 | }, | |
| 3301 | .@"sdiv.fix" = .{ | |
| 3302 | .ret_len = 1, | |
| 3303 | .params = &.{ | |
| 3304 | .{ .kind = .overloaded }, | |
| 3305 | .{ .kind = .{ .matches = 0 } }, | |
| 3306 | .{ .kind = .{ .matches = 0 } }, | |
| 3307 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3308 | }, | |
| 3309 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3310 | }, | |
| 3311 | .@"udiv.fix" = .{ | |
| 3312 | .ret_len = 1, | |
| 3313 | .params = &.{ | |
| 3314 | .{ .kind = .overloaded }, | |
| 3315 | .{ .kind = .{ .matches = 0 } }, | |
| 3316 | .{ .kind = .{ .matches = 0 } }, | |
| 3317 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3318 | }, | |
| 3319 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3320 | }, | |
| 3321 | .@"sdiv.fix.sat" = .{ | |
| 3322 | .ret_len = 1, | |
| 3323 | .params = &.{ | |
| 3324 | .{ .kind = .overloaded }, | |
| 3325 | .{ .kind = .{ .matches = 0 } }, | |
| 3326 | .{ .kind = .{ .matches = 0 } }, | |
| 3327 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3328 | }, | |
| 3329 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3330 | }, | |
| 3331 | .@"udiv.fix.sat" = .{ | |
| 3332 | .ret_len = 1, | |
| 3333 | .params = &.{ | |
| 3334 | .{ .kind = .overloaded }, | |
| 3335 | .{ .kind = .{ .matches = 0 } }, | |
| 3336 | .{ .kind = .{ .matches = 0 } }, | |
| 3337 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3338 | }, | |
| 3339 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3340 | }, | |
| 3341 | ||
| 3342 | .canonicalize = .{ | |
| 3343 | .ret_len = 1, | |
| 3344 | .params = &.{ | |
| 3345 | .{ .kind = .overloaded }, | |
| 3346 | .{ .kind = .{ .matches = 0 } }, | |
| 3347 | }, | |
| 3348 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3349 | }, | |
| 3350 | .fmuladd = .{ | |
| 3351 | .ret_len = 1, | |
| 3352 | .params = &.{ | |
| 3353 | .{ .kind = .overloaded }, | |
| 3354 | .{ .kind = .{ .matches = 0 } }, | |
| 3355 | .{ .kind = .{ .matches = 0 } }, | |
| 3356 | .{ .kind = .{ .matches = 0 } }, | |
| 3357 | }, | |
| 3358 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3359 | }, | |
| 3360 | ||
| 3361 | .@"vector.reduce.add" = .{ | |
| 3362 | .ret_len = 1, | |
| 3363 | .params = &.{ | |
| 3364 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3365 | .{ .kind = .overloaded }, | |
| 3366 | }, | |
| 3367 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3368 | }, | |
| 3369 | .@"vector.reduce.fadd" = .{ | |
| 3370 | .ret_len = 1, | |
| 3371 | .params = &.{ | |
| 3372 | .{ .kind = .{ .matches_scalar = 2 } }, | |
| 3373 | .{ .kind = .{ .matches_scalar = 2 } }, | |
| 3374 | .{ .kind = .overloaded }, | |
| 3375 | }, | |
| 3376 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3377 | }, | |
| 3378 | .@"vector.reduce.mul" = .{ | |
| 3379 | .ret_len = 1, | |
| 3380 | .params = &.{ | |
| 3381 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3382 | .{ .kind = .overloaded }, | |
| 3383 | }, | |
| 3384 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3385 | }, | |
| 3386 | .@"vector.reduce.fmul" = .{ | |
| 3387 | .ret_len = 1, | |
| 3388 | .params = &.{ | |
| 3389 | .{ .kind = .{ .matches_scalar = 2 } }, | |
| 3390 | .{ .kind = .{ .matches_scalar = 2 } }, | |
| 3391 | .{ .kind = .overloaded }, | |
| 3392 | }, | |
| 3393 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3394 | }, | |
| 3395 | .@"vector.reduce.and" = .{ | |
| 3396 | .ret_len = 1, | |
| 3397 | .params = &.{ | |
| 3398 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3399 | .{ .kind = .overloaded }, | |
| 3400 | }, | |
| 3401 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3402 | }, | |
| 3403 | .@"vector.reduce.or" = .{ | |
| 3404 | .ret_len = 1, | |
| 3405 | .params = &.{ | |
| 3406 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3407 | .{ .kind = .overloaded }, | |
| 3408 | }, | |
| 3409 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3410 | }, | |
| 3411 | .@"vector.reduce.xor" = .{ | |
| 3412 | .ret_len = 1, | |
| 3413 | .params = &.{ | |
| 3414 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3415 | .{ .kind = .overloaded }, | |
| 3416 | }, | |
| 3417 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3418 | }, | |
| 3419 | .@"vector.reduce.smax" = .{ | |
| 3420 | .ret_len = 1, | |
| 3421 | .params = &.{ | |
| 3422 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3423 | .{ .kind = .overloaded }, | |
| 3424 | }, | |
| 3425 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3426 | }, | |
| 3427 | .@"vector.reduce.smin" = .{ | |
| 3428 | .ret_len = 1, | |
| 3429 | .params = &.{ | |
| 3430 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3431 | .{ .kind = .overloaded }, | |
| 3432 | }, | |
| 3433 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3434 | }, | |
| 3435 | .@"vector.reduce.umax" = .{ | |
| 3436 | .ret_len = 1, | |
| 3437 | .params = &.{ | |
| 3438 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3439 | .{ .kind = .overloaded }, | |
| 3440 | }, | |
| 3441 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3442 | }, | |
| 3443 | .@"vector.reduce.umin" = .{ | |
| 3444 | .ret_len = 1, | |
| 3445 | .params = &.{ | |
| 3446 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3447 | .{ .kind = .overloaded }, | |
| 3448 | }, | |
| 3449 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3450 | }, | |
| 3451 | .@"vector.reduce.fmax" = .{ | |
| 3452 | .ret_len = 1, | |
| 3453 | .params = &.{ | |
| 3454 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3455 | .{ .kind = .overloaded }, | |
| 3456 | }, | |
| 3457 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3458 | }, | |
| 3459 | .@"vector.reduce.fmin" = .{ | |
| 3460 | .ret_len = 1, | |
| 3461 | .params = &.{ | |
| 3462 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3463 | .{ .kind = .overloaded }, | |
| 3464 | }, | |
| 3465 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3466 | }, | |
| 3467 | .@"vector.reduce.fmaximum" = .{ | |
| 3468 | .ret_len = 1, | |
| 3469 | .params = &.{ | |
| 3470 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3471 | .{ .kind = .overloaded }, | |
| 3472 | }, | |
| 3473 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3474 | }, | |
| 3475 | .@"vector.reduce.fminimum" = .{ | |
| 3476 | .ret_len = 1, | |
| 3477 | .params = &.{ | |
| 3478 | .{ .kind = .{ .matches_scalar = 1 } }, | |
| 3479 | .{ .kind = .overloaded }, | |
| 3480 | }, | |
| 3481 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3482 | }, | |
| 3483 | .@"vector.insert" = .{ | |
| 3484 | .ret_len = 1, | |
| 3485 | .params = &.{ | |
| 3486 | .{ .kind = .overloaded }, | |
| 3487 | .{ .kind = .{ .matches = 0 } }, | |
| 3488 | .{ .kind = .overloaded }, | |
| 3489 | .{ .kind = .{ .type = .i64 } }, | |
| 3490 | }, | |
| 3491 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3492 | }, | |
| 3493 | .@"vector.extract" = .{ | |
| 3494 | .ret_len = 1, | |
| 3495 | .params = &.{ | |
| 3496 | .{ .kind = .overloaded }, | |
| 3497 | .{ .kind = .overloaded }, | |
| 3498 | .{ .kind = .{ .type = .i64 } }, | |
| 3499 | }, | |
| 3500 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3501 | }, | |
| 3502 | ||
| 3503 | .@"is.fpclass" = .{ | |
| 3504 | .ret_len = 1, | |
| 3505 | .params = &.{ | |
| 3506 | .{ .kind = .{ .matches_changed_scalar = .{ .index = 1, .scalar = .i1 } } }, | |
| 3507 | .{ .kind = .overloaded }, | |
| 3508 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, | |
| 3509 | }, | |
| 3510 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3511 | }, | |
| 3512 | ||
| 3513 | .@"var.annotation" = .{ | |
| 3514 | .ret_len = 0, | |
| 3515 | .params = &.{ | |
| 3516 | .{ .kind = .overloaded }, | |
| 3517 | .{ .kind = .overloaded }, | |
| 3518 | .{ .kind = .{ .matches = 1 } }, | |
| 3519 | .{ .kind = .{ .type = .i32 } }, | |
| 3520 | .{ .kind = .{ .matches = 1 } }, | |
| 3521 | }, | |
| 3522 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } }, | |
| 3523 | }, | |
| 3524 | .@"ptr.annotation" = .{ | |
| 3525 | .ret_len = 1, | |
| 3526 | .params = &.{ | |
| 3527 | .{ .kind = .overloaded }, | |
| 3528 | .{ .kind = .{ .matches = 0 } }, | |
| 3529 | .{ .kind = .overloaded }, | |
| 3530 | .{ .kind = .{ .matches = 2 } }, | |
| 3531 | .{ .kind = .{ .type = .i32 } }, | |
| 3532 | .{ .kind = .{ .matches = 2 } }, | |
| 3533 | }, | |
| 3534 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } }, | |
| 3535 | }, | |
| 3536 | .annotation = .{ | |
| 3537 | .ret_len = 1, | |
| 3538 | .params = &.{ | |
| 3539 | .{ .kind = .overloaded }, | |
| 3540 | .{ .kind = .{ .matches = 0 } }, | |
| 3541 | .{ .kind = .overloaded }, | |
| 3542 | .{ .kind = .{ .matches = 2 } }, | |
| 3543 | .{ .kind = .{ .type = .i32 } }, | |
| 3544 | }, | |
| 3545 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } }, | |
| 3546 | }, | |
| 3547 | .@"codeview.annotation" = .{ | |
| 3548 | .ret_len = 0, | |
| 3549 | .params = &.{ | |
| 3550 | .{ .kind = .{ .type = .metadata } }, | |
| 3551 | }, | |
| 3552 | .attrs = &.{ .nocallback, .noduplicate, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } }, | |
| 3553 | }, | |
| 3554 | .trap = .{ | |
| 3555 | .ret_len = 0, | |
| 3556 | .params = &.{}, | |
| 3557 | .attrs = &.{ .cold, .noreturn, .nounwind, .{ .memory = .{ .inaccessiblemem = .write } } }, | |
| 3558 | }, | |
| 3559 | .debugtrap = .{ | |
| 3560 | .ret_len = 0, | |
| 3561 | .params = &.{}, | |
| 3562 | .attrs = &.{.nounwind}, | |
| 3563 | }, | |
| 3564 | .ubsantrap = .{ | |
| 3565 | .ret_len = 0, | |
| 3566 | .params = &.{ | |
| 3567 | .{ .kind = .{ .type = .i8 }, .attrs = &.{.immarg} }, | |
| 3568 | }, | |
| 3569 | .attrs = &.{ .cold, .noreturn, .nounwind }, | |
| 3570 | }, | |
| 3571 | .stackprotector = .{ | |
| 3572 | .ret_len = 0, | |
| 3573 | .params = &.{ | |
| 3574 | .{ .kind = .{ .type = .ptr } }, | |
| 3575 | .{ .kind = .{ .type = .ptr } }, | |
| 3576 | }, | |
| 3577 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 3578 | }, | |
| 3579 | .stackguard = .{ | |
| 3580 | .ret_len = 1, | |
| 3581 | .params = &.{ | |
| 3582 | .{ .kind = .{ .type = .ptr } }, | |
| 3583 | }, | |
| 3584 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 3585 | }, | |
| 3586 | .objectsize = .{ | |
| 3587 | .ret_len = 1, | |
| 3588 | .params = &.{ | |
| 3589 | .{ .kind = .overloaded }, | |
| 3590 | .{ .kind = .overloaded }, | |
| 3591 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 3592 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 3593 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, | |
| 3594 | }, | |
| 3595 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3596 | }, | |
| 3597 | .expect = .{ | |
| 3598 | .ret_len = 1, | |
| 3599 | .params = &.{ | |
| 3600 | .{ .kind = .overloaded }, | |
| 3601 | .{ .kind = .{ .matches = 0 } }, | |
| 3602 | .{ .kind = .{ .matches = 0 } }, | |
| 3603 | }, | |
| 3604 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3605 | }, | |
| 3606 | .@"expect.with.probability" = .{ | |
| 3607 | .ret_len = 1, | |
| 3608 | .params = &.{ | |
| 3609 | .{ .kind = .overloaded }, | |
| 3610 | .{ .kind = .{ .matches = 0 } }, | |
| 3611 | .{ .kind = .{ .matches = 0 } }, | |
| 3612 | .{ .kind = .{ .type = .double }, .attrs = &.{.immarg} }, | |
| 3613 | }, | |
| 3614 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3615 | }, | |
| 3616 | .assume = .{ | |
| 3617 | .ret_len = 0, | |
| 3618 | .params = &.{ | |
| 3619 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.noundef} }, | |
| 3620 | }, | |
| 3621 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .write } } }, | |
| 3622 | }, | |
| 3623 | .@"ssa.copy" = .{ | |
| 3624 | .ret_len = 1, | |
| 3625 | .params = &.{ | |
| 3626 | .{ .kind = .overloaded }, | |
| 3627 | .{ .kind = .{ .matches = 0 }, .attrs = &.{.returned} }, | |
| 3628 | }, | |
| 3629 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3630 | }, | |
| 3631 | .@"type.test" = .{ | |
| 3632 | .ret_len = 1, | |
| 3633 | .params = &.{ | |
| 3634 | .{ .kind = .{ .type = .i1 } }, | |
| 3635 | .{ .kind = .{ .type = .ptr } }, | |
| 3636 | .{ .kind = .{ .type = .metadata } }, | |
| 3637 | }, | |
| 3638 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3639 | }, | |
| 3640 | .@"type.checked.load" = .{ | |
| 3641 | .ret_len = 2, | |
| 3642 | .params = &.{ | |
| 3643 | .{ .kind = .{ .type = .ptr } }, | |
| 3644 | .{ .kind = .{ .type = .i1 } }, | |
| 3645 | .{ .kind = .{ .type = .ptr } }, | |
| 3646 | .{ .kind = .{ .type = .i32 } }, | |
| 3647 | .{ .kind = .{ .type = .metadata } }, | |
| 3648 | }, | |
| 3649 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3650 | }, | |
| 3651 | .@"type.checked.load.relative" = .{ | |
| 3652 | .ret_len = 2, | |
| 3653 | .params = &.{ | |
| 3654 | .{ .kind = .{ .type = .ptr } }, | |
| 3655 | .{ .kind = .{ .type = .i1 } }, | |
| 3656 | .{ .kind = .{ .type = .ptr } }, | |
| 3657 | .{ .kind = .{ .type = .i32 } }, | |
| 3658 | .{ .kind = .{ .type = .metadata } }, | |
| 3659 | }, | |
| 3660 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3661 | }, | |
| 3662 | .@"arithmetic.fence" = .{ | |
| 3663 | .ret_len = 1, | |
| 3664 | .params = &.{ | |
| 3665 | .{ .kind = .overloaded }, | |
| 3666 | .{ .kind = .{ .matches = 0 } }, | |
| 3667 | }, | |
| 3668 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3669 | }, | |
| 3670 | .donothing = .{ | |
| 3671 | .ret_len = 0, | |
| 3672 | .params = &.{}, | |
| 3673 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3674 | }, | |
| 3675 | .@"load.relative" = .{ | |
| 3676 | .ret_len = 1, | |
| 3677 | .params = &.{ | |
| 3678 | .{ .kind = .{ .type = .ptr } }, | |
| 3679 | .{ .kind = .{ .type = .ptr } }, | |
| 3680 | .{ .kind = .overloaded }, | |
| 3681 | }, | |
| 3682 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .argmem = .read } } }, | |
| 3683 | }, | |
| 3684 | .sideeffect = .{ | |
| 3685 | .ret_len = 0, | |
| 3686 | .params = &.{}, | |
| 3687 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = .{ .inaccessiblemem = .readwrite } } }, | |
| 3688 | }, | |
| 3689 | .@"is.constant" = .{ | |
| 3690 | .ret_len = 1, | |
| 3691 | .params = &.{ | |
| 3692 | .{ .kind = .{ .type = .i1 } }, | |
| 3693 | .{ .kind = .overloaded }, | |
| 3694 | }, | |
| 3695 | .attrs = &.{ .convergent, .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3696 | }, | |
| 3697 | .ptrmask = .{ | |
| 3698 | .ret_len = 1, | |
| 3699 | .params = &.{ | |
| 3700 | .{ .kind = .overloaded }, | |
| 3701 | .{ .kind = .{ .matches = 0 } }, | |
| 3702 | .{ .kind = .overloaded }, | |
| 3703 | }, | |
| 3704 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3705 | }, | |
| 3706 | .@"threadlocal.address" = .{ | |
| 3707 | .ret_len = 1, | |
| 3708 | .params = &.{ | |
| 3709 | .{ .kind = .overloaded, .attrs = &.{.nonnull} }, | |
| 3710 | .{ .kind = .{ .matches = 0 }, .attrs = &.{.nonnull} }, | |
| 3711 | }, | |
| 3712 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3713 | }, | |
| 3714 | .vscale = .{ | |
| 3715 | .ret_len = 1, | |
| 3716 | .params = &.{ | |
| 3717 | .{ .kind = .overloaded }, | |
| 3718 | }, | |
| 3719 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3720 | }, | |
| 3721 | ||
| 3722 | .@"amdgcn.workitem.id.x" = .{ | |
| 3723 | .ret_len = 1, | |
| 3724 | .params = &.{ | |
| 3725 | .{ .kind = .{ .type = .i32 } }, | |
| 3726 | }, | |
| 3727 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3728 | }, | |
| 3729 | .@"amdgcn.workitem.id.y" = .{ | |
| 3730 | .ret_len = 1, | |
| 3731 | .params = &.{ | |
| 3732 | .{ .kind = .{ .type = .i32 } }, | |
| 3733 | }, | |
| 3734 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3735 | }, | |
| 3736 | .@"amdgcn.workitem.id.z" = .{ | |
| 3737 | .ret_len = 1, | |
| 3738 | .params = &.{ | |
| 3739 | .{ .kind = .{ .type = .i32 } }, | |
| 3740 | }, | |
| 3741 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3742 | }, | |
| 3743 | .@"amdgcn.workgroup.id.x" = .{ | |
| 3744 | .ret_len = 1, | |
| 3745 | .params = &.{ | |
| 3746 | .{ .kind = .{ .type = .i32 } }, | |
| 3747 | }, | |
| 3748 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3749 | }, | |
| 3750 | .@"amdgcn.workgroup.id.y" = .{ | |
| 3751 | .ret_len = 1, | |
| 3752 | .params = &.{ | |
| 3753 | .{ .kind = .{ .type = .i32 } }, | |
| 3754 | }, | |
| 3755 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3756 | }, | |
| 3757 | .@"amdgcn.workgroup.id.z" = .{ | |
| 3758 | .ret_len = 1, | |
| 3759 | .params = &.{ | |
| 3760 | .{ .kind = .{ .type = .i32 } }, | |
| 3761 | }, | |
| 3762 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3763 | }, | |
| 3764 | .@"amdgcn.dispatch.ptr" = .{ | |
| 3765 | .ret_len = 1, | |
| 3766 | .params = &.{ | |
| 3767 | .{ | |
| 3768 | .kind = .{ .type = Type.ptr_amdgpu_constant }, | |
| 3769 | .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }}, | |
| 3770 | }, | |
| 3771 | }, | |
| 3772 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3773 | }, | |
| 2275 | 3774 | |
| 2276 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | |
| 2277 | return self.ptrConst(builder).global.toLlvm(builder); | |
| 2278 | } | |
| 2279 | }; | |
| 3775 | .@"wasm.memory.size" = .{ | |
| 3776 | .ret_len = 1, | |
| 3777 | .params = &.{ | |
| 3778 | .{ .kind = .overloaded }, | |
| 3779 | .{ .kind = .{ .type = .i32 } }, | |
| 3780 | }, | |
| 3781 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, | |
| 3782 | }, | |
| 3783 | .@"wasm.memory.grow" = .{ | |
| 3784 | .ret_len = 1, | |
| 3785 | .params = &.{ | |
| 3786 | .{ .kind = .overloaded }, | |
| 3787 | .{ .kind = .{ .type = .i32 } }, | |
| 3788 | .{ .kind = .{ .matches = 0 } }, | |
| 3789 | }, | |
| 3790 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, | |
| 3791 | }, | |
| 3792 | }); | |
| 2280 | 3793 | }; |
| 2281 | 3794 | |
| 2282 | 3795 | pub const Function = struct { |
| ... | ... | @@ -2303,6 +3816,14 @@ pub const Function = struct { |
| 2303 | 3816 | return &builder.functions.items[@intFromEnum(self)]; |
| 2304 | 3817 | } |
| 2305 | 3818 | |
| 3819 | pub fn name(self: Index, builder: *const Builder) String { | |
| 3820 | return self.ptrConst(builder).global.name(builder); | |
| 3821 | } | |
| 3822 | ||
| 3823 | pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { | |
| 3824 | return self.ptrConst(builder).global.rename(new_name, builder); | |
| 3825 | } | |
| 3826 | ||
| 2306 | 3827 | pub fn typeOf(self: Index, builder: *const Builder) Type { |
| 2307 | 3828 | return self.ptrConst(builder).global.typeOf(builder); |
| 2308 | 3829 | } |
| ... | ... | @@ -2315,6 +3836,110 @@ pub const Function = struct { |
| 2315 | 3836 | return self.toConst(builder).toValue(); |
| 2316 | 3837 | } |
| 2317 | 3838 | |
| 3839 | pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void { | |
| 3840 | return self.ptrConst(builder).global.setLinkage(linkage, builder); | |
| 3841 | } | |
| 3842 | ||
| 3843 | pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { | |
| 3844 | return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder); | |
| 3845 | } | |
| 3846 | ||
| 3847 | pub fn setCallConv(self: Index, call_conv: CallConv, builder: *Builder) void { | |
| 3848 | if (builder.useLibLlvm()) self.toLlvm(builder).setFunctionCallConv(call_conv.toLlvm()); | |
| 3849 | self.ptr(builder).call_conv = call_conv; | |
| 3850 | } | |
| 3851 | ||
| 3852 | pub fn setAttributes( | |
| 3853 | self: Index, | |
| 3854 | new_function_attributes: FunctionAttributes, | |
| 3855 | builder: *Builder, | |
| 3856 | ) void { | |
| 3857 | if (builder.useLibLlvm()) { | |
| 3858 | const llvm_function = self.toLlvm(builder); | |
| 3859 | const old_function_attributes = self.ptrConst(builder).attributes; | |
| 3860 | for (0..@max( | |
| 3861 | old_function_attributes.slice(builder).len, | |
| 3862 | new_function_attributes.slice(builder).len, | |
| 3863 | )) |function_attribute_index| { | |
| 3864 | const llvm_attribute_index = | |
| 3865 | @as(llvm.AttributeIndex, @intCast(function_attribute_index)) -% 1; | |
| 3866 | const old_attributes_slice = | |
| 3867 | old_function_attributes.get(function_attribute_index, builder).slice(builder); | |
| 3868 | const new_attributes_slice = | |
| 3869 | new_function_attributes.get(function_attribute_index, builder).slice(builder); | |
| 3870 | var old_attribute_index: usize = 0; | |
| 3871 | var new_attribute_index: usize = 0; | |
| 3872 | while (true) { | |
| 3873 | const old_attribute_kind = if (old_attribute_index < old_attributes_slice.len) | |
| 3874 | old_attributes_slice[old_attribute_index].getKind(builder) | |
| 3875 | else | |
| 3876 | .none; | |
| 3877 | const new_attribute_kind = if (new_attribute_index < new_attributes_slice.len) | |
| 3878 | new_attributes_slice[new_attribute_index].getKind(builder) | |
| 3879 | else | |
| 3880 | .none; | |
| 3881 | switch (std.math.order( | |
| 3882 | @intFromEnum(old_attribute_kind), | |
| 3883 | @intFromEnum(new_attribute_kind), | |
| 3884 | )) { | |
| 3885 | .lt => { | |
| 3886 | // Removed | |
| 3887 | if (old_attribute_kind.toString()) |attribute_name| { | |
| 3888 | const attribute_name_slice = attribute_name.slice(builder).?; | |
| 3889 | llvm_function.removeStringAttributeAtIndex( | |
| 3890 | llvm_attribute_index, | |
| 3891 | attribute_name_slice.ptr, | |
| 3892 | @intCast(attribute_name_slice.len), | |
| 3893 | ); | |
| 3894 | } else { | |
| 3895 | const llvm_kind_id = old_attribute_kind.toLlvm(builder).*; | |
| 3896 | assert(llvm_kind_id != 0); | |
| 3897 | llvm_function.removeEnumAttributeAtIndex( | |
| 3898 | llvm_attribute_index, | |
| 3899 | llvm_kind_id, | |
| 3900 | ); | |
| 3901 | } | |
| 3902 | old_attribute_index += 1; | |
| 3903 | continue; | |
| 3904 | }, | |
| 3905 | .eq => { | |
| 3906 | // Iteration finished | |
| 3907 | if (old_attribute_kind == .none) break; | |
| 3908 | // No change | |
| 3909 | if (old_attributes_slice[old_attribute_index] == | |
| 3910 | new_attributes_slice[new_attribute_index]) | |
| 3911 | { | |
| 3912 | old_attribute_index += 1; | |
| 3913 | new_attribute_index += 1; | |
| 3914 | continue; | |
| 3915 | } | |
| 3916 | old_attribute_index += 1; | |
| 3917 | }, | |
| 3918 | .gt => {}, | |
| 3919 | } | |
| 3920 | // New or changed | |
| 3921 | llvm_function.addAttributeAtIndex( | |
| 3922 | llvm_attribute_index, | |
| 3923 | new_attributes_slice[new_attribute_index].toLlvm(builder), | |
| 3924 | ); | |
| 3925 | new_attribute_index += 1; | |
| 3926 | } | |
| 3927 | } | |
| 3928 | } | |
| 3929 | self.ptr(builder).attributes = new_function_attributes; | |
| 3930 | } | |
| 3931 | ||
| 3932 | pub fn setSection(self: Index, section: String, builder: *Builder) void { | |
| 3933 | if (builder.useLibLlvm()) self.toLlvm(builder).setSection(section.slice(builder).?); | |
| 3934 | self.ptr(builder).section = section; | |
| 3935 | } | |
| 3936 | ||
| 3937 | pub fn setAlignment(self: Index, alignment: Alignment, builder: *Builder) void { | |
| 3938 | if (builder.useLibLlvm()) | |
| 3939 | self.toLlvm(builder).setAlignment(@intCast(alignment.toByteUnits() orelse 0)); | |
| 3940 | self.ptr(builder).alignment = alignment; | |
| 3941 | } | |
| 3942 | ||
| 2318 | 3943 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2319 | 3944 | return self.ptrConst(builder).global.toLlvm(builder); |
| 2320 | 3945 | } |
| ... | ... | @@ -2342,12 +3967,15 @@ pub const Function = struct { |
| 2342 | 3967 | arg, |
| 2343 | 3968 | ashr, |
| 2344 | 3969 | @"ashr exact", |
| 3970 | atomicrmw, | |
| 2345 | 3971 | bitcast, |
| 2346 | 3972 | block, |
| 2347 | 3973 | br, |
| 2348 | 3974 | br_cond, |
| 2349 | 3975 | call, |
| 2350 | 3976 | @"call fast", |
| 3977 | cmpxchg, | |
| 3978 | @"cmpxchg weak", | |
| 2351 | 3979 | extractelement, |
| 2352 | 3980 | extractvalue, |
| 2353 | 3981 | fadd, |
| ... | ... | @@ -2414,43 +4042,8 @@ pub const Function = struct { |
| 2414 | 4042 | insertelement, |
| 2415 | 4043 | insertvalue, |
| 2416 | 4044 | inttoptr, |
| 2417 | @"llvm.maxnum.", | |
| 2418 | @"llvm.minnum.", | |
| 2419 | @"llvm.ceil.", | |
| 2420 | @"llvm.cos.", | |
| 2421 | @"llvm.exp.", | |
| 2422 | @"llvm.exp2.", | |
| 2423 | @"llvm.fabs.", | |
| 2424 | @"llvm.floor.", | |
| 2425 | @"llvm.log.", | |
| 2426 | @"llvm.log10.", | |
| 2427 | @"llvm.log2.", | |
| 2428 | @"llvm.round.", | |
| 2429 | @"llvm.sin.", | |
| 2430 | @"llvm.sqrt.", | |
| 2431 | @"llvm.trunc.", | |
| 2432 | @"llvm.fma.", | |
| 2433 | @"llvm.bitreverse.", | |
| 2434 | @"llvm.bswap.", | |
| 2435 | @"llvm.ctpop.", | |
| 2436 | @"llvm.ctlz.", | |
| 2437 | @"llvm.cttz.", | |
| 2438 | @"llvm.sadd.sat.", | |
| 2439 | @"llvm.smax.", | |
| 2440 | @"llvm.smin.", | |
| 2441 | @"llvm.smul.fix.sat.", | |
| 2442 | @"llvm.sshl.sat.", | |
| 2443 | @"llvm.ssub.sat.", | |
| 2444 | @"llvm.uadd.sat.", | |
| 2445 | @"llvm.umax.", | |
| 2446 | @"llvm.umin.", | |
| 2447 | @"llvm.umul.fix.sat.", | |
| 2448 | @"llvm.ushl.sat.", | |
| 2449 | @"llvm.usub.sat.", | |
| 2450 | 4045 | load, |
| 2451 | 4046 | @"load atomic", |
| 2452 | @"load atomic volatile", | |
| 2453 | @"load volatile", | |
| 2454 | 4047 | lshr, |
| 2455 | 4048 | @"lshr exact", |
| 2456 | 4049 | mul, |
| ... | ... | @@ -2481,8 +4074,6 @@ pub const Function = struct { |
| 2481 | 4074 | srem, |
| 2482 | 4075 | store, |
| 2483 | 4076 | @"store atomic", |
| 2484 | @"store atomic volatile", | |
| 2485 | @"store volatile", | |
| 2486 | 4077 | sub, |
| 2487 | 4078 | @"sub nsw", |
| 2488 | 4079 | @"sub nuw", |
| ... | ... | @@ -2495,7 +4086,6 @@ pub const Function = struct { |
| 2495 | 4086 | @"udiv exact", |
| 2496 | 4087 | urem, |
| 2497 | 4088 | uitofp, |
| 2498 | unimplemented, | |
| 2499 | 4089 | @"unreachable", |
| 2500 | 4090 | va_arg, |
| 2501 | 4091 | xor, |
| ... | ... | @@ -2536,8 +4126,6 @@ pub const Function = struct { |
| 2536 | 4126 | .@"ret void", |
| 2537 | 4127 | .store, |
| 2538 | 4128 | .@"store atomic", |
| 2539 | .@"store atomic volatile", | |
| 2540 | .@"store volatile", | |
| 2541 | 4129 | .@"switch", |
| 2542 | 4130 | .@"unreachable", |
| 2543 | 4131 | => false, |
| ... | ... | @@ -2549,7 +4137,6 @@ pub const Function = struct { |
| 2549 | 4137 | .@"notail call fast", |
| 2550 | 4138 | .@"tail call", |
| 2551 | 4139 | .@"tail call fast", |
| 2552 | .unimplemented, | |
| 2553 | 4140 | => self.typeOfWip(wip) != .void, |
| 2554 | 4141 | else => true, |
| 2555 | 4142 | }; |
| ... | ... | @@ -2575,22 +4162,6 @@ pub const Function = struct { |
| 2575 | 4162 | .@"frem fast", |
| 2576 | 4163 | .fsub, |
| 2577 | 4164 | .@"fsub fast", |
| 2578 | .@"llvm.maxnum.", | |
| 2579 | .@"llvm.minnum.", | |
| 2580 | .@"llvm.ctlz.", | |
| 2581 | .@"llvm.cttz.", | |
| 2582 | .@"llvm.sadd.sat.", | |
| 2583 | .@"llvm.smax.", | |
| 2584 | .@"llvm.smin.", | |
| 2585 | .@"llvm.smul.fix.sat.", | |
| 2586 | .@"llvm.sshl.sat.", | |
| 2587 | .@"llvm.ssub.sat.", | |
| 2588 | .@"llvm.uadd.sat.", | |
| 2589 | .@"llvm.umax.", | |
| 2590 | .@"llvm.umin.", | |
| 2591 | .@"llvm.umul.fix.sat.", | |
| 2592 | .@"llvm.ushl.sat.", | |
| 2593 | .@"llvm.usub.sat.", | |
| 2594 | 4165 | .lshr, |
| 2595 | 4166 | .@"lshr exact", |
| 2596 | 4167 | .mul, |
| ... | ... | @@ -2635,6 +4206,7 @@ pub const Function = struct { |
| 2635 | 4206 | ), |
| 2636 | 4207 | .arg => wip.function.typeOf(wip.builder) |
| 2637 | 4208 | .functionParameters(wip.builder)[instruction.data], |
| 4209 | .atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip), | |
| 2638 | 4210 | .block => .label, |
| 2639 | 4211 | .br, |
| 2640 | 4212 | .br_cond, |
| ... | ... | @@ -2643,8 +4215,6 @@ pub const Function = struct { |
| 2643 | 4215 | .@"ret void", |
| 2644 | 4216 | .store, |
| 2645 | 4217 | .@"store atomic", |
| 2646 | .@"store atomic volatile", | |
| 2647 | .@"store volatile", | |
| 2648 | 4218 | .@"switch", |
| 2649 | 4219 | .@"unreachable", |
| 2650 | 4220 | => .none, |
| ... | ... | @@ -2657,6 +4227,12 @@ pub const Function = struct { |
| 2657 | 4227 | .@"tail call", |
| 2658 | 4228 | .@"tail call fast", |
| 2659 | 4229 | => wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder), |
| 4230 | .cmpxchg, | |
| 4231 | .@"cmpxchg weak", | |
| 4232 | => wip.builder.structTypeAssumeCapacity(.normal, &.{ | |
| 4233 | wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip), | |
| 4234 | .i1, | |
| 4235 | }) catch unreachable, | |
| 2660 | 4236 | .extractelement => wip.extraData(ExtractElement, instruction.data) |
| 2661 | 4237 | .val.typeOfWip(wip).childType(wip.builder), |
| 2662 | 4238 | .extractvalue => { |
| ... | ... | @@ -2710,22 +4286,6 @@ pub const Function = struct { |
| 2710 | 4286 | .changeScalarAssumeCapacity(.i1, wip.builder), |
| 2711 | 4287 | .fneg, |
| 2712 | 4288 | .@"fneg fast", |
| 2713 | .@"llvm.ceil.", | |
| 2714 | .@"llvm.cos.", | |
| 2715 | .@"llvm.exp.", | |
| 2716 | .@"llvm.exp2.", | |
| 2717 | .@"llvm.fabs.", | |
| 2718 | .@"llvm.floor.", | |
| 2719 | .@"llvm.log.", | |
| 2720 | .@"llvm.log10.", | |
| 2721 | .@"llvm.log2.", | |
| 2722 | .@"llvm.round.", | |
| 2723 | .@"llvm.sin.", | |
| 2724 | .@"llvm.sqrt.", | |
| 2725 | .@"llvm.trunc.", | |
| 2726 | .@"llvm.bitreverse.", | |
| 2727 | .@"llvm.bswap.", | |
| 2728 | .@"llvm.ctpop.", | |
| 2729 | 4289 | => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), |
| 2730 | 4290 | .getelementptr, |
| 2731 | 4291 | .@"getelementptr inbounds", |
| ... | ... | @@ -2744,8 +4304,6 @@ pub const Function = struct { |
| 2744 | 4304 | .insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip), |
| 2745 | 4305 | .load, |
| 2746 | 4306 | .@"load atomic", |
| 2747 | .@"load atomic volatile", | |
| 2748 | .@"load volatile", | |
| 2749 | 4307 | => wip.extraData(Load, instruction.data).type, |
| 2750 | 4308 | .phi, |
| 2751 | 4309 | .@"phi fast", |
| ... | ... | @@ -2760,9 +4318,7 @@ pub const Function = struct { |
| 2760 | 4318 | wip.builder, |
| 2761 | 4319 | ); |
| 2762 | 4320 | }, |
| 2763 | .unimplemented => @enumFromInt(instruction.data), | |
| 2764 | 4321 | .va_arg => wip.extraData(VaArg, instruction.data).type, |
| 2765 | .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip), | |
| 2766 | 4322 | }; |
| 2767 | 4323 | } |
| 2768 | 4324 | |
| ... | ... | @@ -2791,22 +4347,6 @@ pub const Function = struct { |
| 2791 | 4347 | .@"frem fast", |
| 2792 | 4348 | .fsub, |
| 2793 | 4349 | .@"fsub fast", |
| 2794 | .@"llvm.maxnum.", | |
| 2795 | .@"llvm.minnum.", | |
| 2796 | .@"llvm.ctlz.", | |
| 2797 | .@"llvm.cttz.", | |
| 2798 | .@"llvm.sadd.sat.", | |
| 2799 | .@"llvm.smax.", | |
| 2800 | .@"llvm.smin.", | |
| 2801 | .@"llvm.smul.fix.sat.", | |
| 2802 | .@"llvm.sshl.sat.", | |
| 2803 | .@"llvm.ssub.sat.", | |
| 2804 | .@"llvm.uadd.sat.", | |
| 2805 | .@"llvm.umax.", | |
| 2806 | .@"llvm.umin.", | |
| 2807 | .@"llvm.umul.fix.sat.", | |
| 2808 | .@"llvm.ushl.sat.", | |
| 2809 | .@"llvm.usub.sat.", | |
| 2810 | 4350 | .lshr, |
| 2811 | 4351 | .@"lshr exact", |
| 2812 | 4352 | .mul, |
| ... | ... | @@ -2851,6 +4391,8 @@ pub const Function = struct { |
| 2851 | 4391 | ), |
| 2852 | 4392 | .arg => function.global.typeOf(builder) |
| 2853 | 4393 | .functionParameters(builder)[instruction.data], |
| 4394 | .atomicrmw => function.extraData(AtomicRmw, instruction.data) | |
| 4395 | .val.typeOf(function_index, builder), | |
| 2854 | 4396 | .block => .label, |
| 2855 | 4397 | .br, |
| 2856 | 4398 | .br_cond, |
| ... | ... | @@ -2859,8 +4401,6 @@ pub const Function = struct { |
| 2859 | 4401 | .@"ret void", |
| 2860 | 4402 | .store, |
| 2861 | 4403 | .@"store atomic", |
| 2862 | .@"store atomic volatile", | |
| 2863 | .@"store volatile", | |
| 2864 | 4404 | .@"switch", |
| 2865 | 4405 | .@"unreachable", |
| 2866 | 4406 | => .none, |
| ... | ... | @@ -2873,6 +4413,13 @@ pub const Function = struct { |
| 2873 | 4413 | .@"tail call", |
| 2874 | 4414 | .@"tail call fast", |
| 2875 | 4415 | => function.extraData(Call, instruction.data).ty.functionReturn(builder), |
| 4416 | .cmpxchg, | |
| 4417 | .@"cmpxchg weak", | |
| 4418 | => builder.structTypeAssumeCapacity(.normal, &.{ | |
| 4419 | function.extraData(CmpXchg, instruction.data) | |
| 4420 | .cmp.typeOf(function_index, builder), | |
| 4421 | .i1, | |
| 4422 | }) catch unreachable, | |
| 2876 | 4423 | .extractelement => function.extraData(ExtractElement, instruction.data) |
| 2877 | 4424 | .val.typeOf(function_index, builder).childType(builder), |
| 2878 | 4425 | .extractvalue => { |
| ... | ... | @@ -2927,22 +4474,6 @@ pub const Function = struct { |
| 2927 | 4474 | .changeScalarAssumeCapacity(.i1, builder), |
| 2928 | 4475 | .fneg, |
| 2929 | 4476 | .@"fneg fast", |
| 2930 | .@"llvm.ceil.", | |
| 2931 | .@"llvm.cos.", | |
| 2932 | .@"llvm.exp.", | |
| 2933 | .@"llvm.exp2.", | |
| 2934 | .@"llvm.fabs.", | |
| 2935 | .@"llvm.floor.", | |
| 2936 | .@"llvm.log.", | |
| 2937 | .@"llvm.log10.", | |
| 2938 | .@"llvm.log2.", | |
| 2939 | .@"llvm.round.", | |
| 2940 | .@"llvm.sin.", | |
| 2941 | .@"llvm.sqrt.", | |
| 2942 | .@"llvm.trunc.", | |
| 2943 | .@"llvm.bitreverse.", | |
| 2944 | .@"llvm.bswap.", | |
| 2945 | .@"llvm.ctpop.", | |
| 2946 | 4477 | => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), |
| 2947 | 4478 | .getelementptr, |
| 2948 | 4479 | .@"getelementptr inbounds", |
| ... | ... | @@ -2963,8 +4494,6 @@ pub const Function = struct { |
| 2963 | 4494 | .val.typeOf(function_index, builder), |
| 2964 | 4495 | .load, |
| 2965 | 4496 | .@"load atomic", |
| 2966 | .@"load atomic volatile", | |
| 2967 | .@"load volatile", | |
| 2968 | 4497 | => function.extraData(Load, instruction.data).type, |
| 2969 | 4498 | .phi, |
| 2970 | 4499 | .@"phi fast", |
| ... | ... | @@ -2979,9 +4508,7 @@ pub const Function = struct { |
| 2979 | 4508 | builder, |
| 2980 | 4509 | ); |
| 2981 | 4510 | }, |
| 2982 | .unimplemented => @enumFromInt(instruction.data), | |
| 2983 | 4511 | .va_arg => function.extraData(VaArg, instruction.data).type, |
| 2984 | .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder), | |
| 2985 | 4512 | }; |
| 2986 | 4513 | } |
| 2987 | 4514 | |
| ... | ... | @@ -3023,12 +4550,14 @@ pub const Function = struct { |
| 3023 | 4550 | return .{ .data = .{ .instruction = self, .function = function, .builder = builder } }; |
| 3024 | 4551 | } |
| 3025 | 4552 | |
| 3026 | pub fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value { | |
| 4553 | fn toLlvm(self: Instruction.Index, wip: *const WipFunction) *llvm.Value { | |
| 3027 | 4554 | assert(wip.builder.useLibLlvm()); |
| 3028 | return wip.llvm.instructions.items[@intFromEnum(self)]; | |
| 4555 | const llvm_value = wip.llvm.instructions.items[@intFromEnum(self)]; | |
| 4556 | const global = wip.builder.llvm.replacements.get(llvm_value) orelse return llvm_value; | |
| 4557 | return global.toLlvm(wip.builder); | |
| 3029 | 4558 | } |
| 3030 | 4559 | |
| 3031 | fn llvmName(self: Instruction.Index, wip: *const WipFunction) [*:0]const u8 { | |
| 4560 | fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 { | |
| 3032 | 4561 | return if (wip.builder.strip) |
| 3033 | 4562 | "" |
| 3034 | 4563 | else |
| ... | ... | @@ -3074,12 +4603,6 @@ pub const Function = struct { |
| 3074 | 4603 | mask: Value, |
| 3075 | 4604 | }; |
| 3076 | 4605 | |
| 3077 | pub const FusedMultiplyAdd = struct { | |
| 3078 | a: Value, | |
| 3079 | b: Value, | |
| 3080 | c: Value, | |
| 3081 | }; | |
| 3082 | ||
| 3083 | 4606 | pub const ExtractValue = struct { |
| 3084 | 4607 | val: Value, |
| 3085 | 4608 | indices_len: u32, |
| ... | ... | @@ -3107,15 +4630,70 @@ pub const Function = struct { |
| 3107 | 4630 | }; |
| 3108 | 4631 | |
| 3109 | 4632 | pub const Load = struct { |
| 4633 | info: MemoryAccessInfo, | |
| 3110 | 4634 | type: Type, |
| 3111 | 4635 | ptr: Value, |
| 3112 | info: MemoryAccessInfo, | |
| 3113 | 4636 | }; |
| 3114 | 4637 | |
| 3115 | 4638 | pub const Store = struct { |
| 4639 | info: MemoryAccessInfo, | |
| 3116 | 4640 | val: Value, |
| 3117 | 4641 | ptr: Value, |
| 4642 | }; | |
| 4643 | ||
| 4644 | pub const CmpXchg = struct { | |
| 4645 | info: MemoryAccessInfo, | |
| 4646 | ptr: Value, | |
| 4647 | cmp: Value, | |
| 4648 | new: Value, | |
| 4649 | ||
| 4650 | pub const Kind = enum { strong, weak }; | |
| 4651 | }; | |
| 4652 | ||
| 4653 | pub const AtomicRmw = struct { | |
| 3118 | 4654 | info: MemoryAccessInfo, |
| 4655 | ptr: Value, | |
| 4656 | val: Value, | |
| 4657 | ||
| 4658 | pub const Operation = enum(u5) { | |
| 4659 | xchg, | |
| 4660 | add, | |
| 4661 | sub, | |
| 4662 | @"and", | |
| 4663 | nand, | |
| 4664 | @"or", | |
| 4665 | xor, | |
| 4666 | max, | |
| 4667 | min, | |
| 4668 | umax, | |
| 4669 | umin, | |
| 4670 | fadd, | |
| 4671 | fsub, | |
| 4672 | fmax, | |
| 4673 | fmin, | |
| 4674 | none = std.math.maxInt(u5), | |
| 4675 | ||
| 4676 | fn toLlvm(self: Operation) llvm.AtomicRMWBinOp { | |
| 4677 | return switch (self) { | |
| 4678 | .xchg => .Xchg, | |
| 4679 | .add => .Add, | |
| 4680 | .sub => .Sub, | |
| 4681 | .@"and" => .And, | |
| 4682 | .nand => .Nand, | |
| 4683 | .@"or" => .Or, | |
| 4684 | .xor => .Xor, | |
| 4685 | .max => .Max, | |
| 4686 | .min => .Min, | |
| 4687 | .umax => .UMax, | |
| 4688 | .umin => .UMin, | |
| 4689 | .fadd => .FAdd, | |
| 4690 | .fsub => .FSub, | |
| 4691 | .fmax => .FMax, | |
| 4692 | .fmin => .FMin, | |
| 4693 | .none => unreachable, | |
| 4694 | }; | |
| 4695 | } | |
| 4696 | }; | |
| 3119 | 4697 | }; |
| 3120 | 4698 | |
| 3121 | 4699 | pub const GetElementPtr = struct { |
| ... | ... | @@ -3487,24 +5065,7 @@ pub const WipFunction = struct { |
| 3487 | 5065 | switch (tag) { |
| 3488 | 5066 | .fneg, |
| 3489 | 5067 | .@"fneg fast", |
| 3490 | .@"llvm.ceil.", | |
| 3491 | .@"llvm.cos.", | |
| 3492 | .@"llvm.exp.", | |
| 3493 | .@"llvm.exp2.", | |
| 3494 | .@"llvm.fabs.", | |
| 3495 | .@"llvm.floor.", | |
| 3496 | .@"llvm.log.", | |
| 3497 | .@"llvm.log10.", | |
| 3498 | .@"llvm.log2.", | |
| 3499 | .@"llvm.round.", | |
| 3500 | .@"llvm.sin.", | |
| 3501 | .@"llvm.sqrt.", | |
| 3502 | .@"llvm.trunc.", | |
| 3503 | 5068 | => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), |
| 3504 | .@"llvm.bitreverse.", | |
| 3505 | .@"llvm.bswap.", | |
| 3506 | .@"llvm.ctpop.", | |
| 3507 | => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)), | |
| 3508 | 5069 | else => unreachable, |
| 3509 | 5070 | } |
| 3510 | 5071 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); |
| ... | ... | @@ -3513,43 +5074,10 @@ pub const WipFunction = struct { |
| 3513 | 5074 | switch (tag) { |
| 3514 | 5075 | .fneg => self.llvm.builder.setFastMath(false), |
| 3515 | 5076 | .@"fneg fast" => self.llvm.builder.setFastMath(true), |
| 3516 | .@"llvm.ceil.", | |
| 3517 | .@"llvm.cos.", | |
| 3518 | .@"llvm.exp.", | |
| 3519 | .@"llvm.exp2.", | |
| 3520 | .@"llvm.fabs.", | |
| 3521 | .@"llvm.floor.", | |
| 3522 | .@"llvm.log.", | |
| 3523 | .@"llvm.log10.", | |
| 3524 | .@"llvm.log2.", | |
| 3525 | .@"llvm.round.", | |
| 3526 | .@"llvm.sin.", | |
| 3527 | .@"llvm.sqrt.", | |
| 3528 | .@"llvm.trunc.", | |
| 3529 | .@"llvm.bitreverse.", | |
| 3530 | .@"llvm.bswap.", | |
| 3531 | .@"llvm.ctpop.", | |
| 3532 | => {}, | |
| 3533 | 5077 | else => unreachable, |
| 3534 | 5078 | } |
| 3535 | 5079 | self.llvm.instructions.appendAssumeCapacity(switch (tag) { |
| 3536 | 5080 | .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, |
| 3537 | .@"llvm.ceil." => &llvm.Builder.buildCeil, | |
| 3538 | .@"llvm.cos." => &llvm.Builder.buildCos, | |
| 3539 | .@"llvm.exp." => &llvm.Builder.buildExp, | |
| 3540 | .@"llvm.exp2." => &llvm.Builder.buildExp2, | |
| 3541 | .@"llvm.fabs." => &llvm.Builder.buildFAbs, | |
| 3542 | .@"llvm.floor." => &llvm.Builder.buildFloor, | |
| 3543 | .@"llvm.log." => &llvm.Builder.buildLog, | |
| 3544 | .@"llvm.log10." => &llvm.Builder.buildLog10, | |
| 3545 | .@"llvm.log2." => &llvm.Builder.buildLog2, | |
| 3546 | .@"llvm.round." => &llvm.Builder.buildRound, | |
| 3547 | .@"llvm.sin." => &llvm.Builder.buildSin, | |
| 3548 | .@"llvm.sqrt." => &llvm.Builder.buildSqrt, | |
| 3549 | .@"llvm.trunc." => &llvm.Builder.buildFTrunc, | |
| 3550 | .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse, | |
| 3551 | .@"llvm.bswap." => &llvm.Builder.buildBSwap, | |
| 3552 | .@"llvm.ctpop." => &llvm.Builder.buildCTPop, | |
| 3553 | 5081 | else => unreachable, |
| 3554 | 5082 | }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); |
| 3555 | 5083 | } |
| ... | ... | @@ -3593,20 +5121,6 @@ pub const WipFunction = struct { |
| 3593 | 5121 | .@"frem fast", |
| 3594 | 5122 | .fsub, |
| 3595 | 5123 | .@"fsub fast", |
| 3596 | .@"llvm.maxnum.", | |
| 3597 | .@"llvm.minnum.", | |
| 3598 | .@"llvm.sadd.sat.", | |
| 3599 | .@"llvm.smax.", | |
| 3600 | .@"llvm.smin.", | |
| 3601 | .@"llvm.smul.fix.sat.", | |
| 3602 | .@"llvm.sshl.sat.", | |
| 3603 | .@"llvm.ssub.sat.", | |
| 3604 | .@"llvm.uadd.sat.", | |
| 3605 | .@"llvm.umax.", | |
| 3606 | .@"llvm.umin.", | |
| 3607 | .@"llvm.umul.fix.sat.", | |
| 3608 | .@"llvm.ushl.sat.", | |
| 3609 | .@"llvm.usub.sat.", | |
| 3610 | 5124 | .lshr, |
| 3611 | 5125 | .@"lshr exact", |
| 3612 | 5126 | .mul, |
| ... | ... | @@ -3627,9 +5141,6 @@ pub const WipFunction = struct { |
| 3627 | 5141 | .urem, |
| 3628 | 5142 | .xor, |
| 3629 | 5143 | => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)), |
| 3630 | .@"llvm.ctlz.", | |
| 3631 | .@"llvm.cttz.", | |
| 3632 | => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1), | |
| 3633 | 5144 | else => unreachable, |
| 3634 | 5145 | } |
| 3635 | 5146 | try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0); |
| ... | ... | @@ -3665,22 +5176,6 @@ pub const WipFunction = struct { |
| 3665 | 5176 | .fmul, .@"fmul fast" => &llvm.Builder.buildFMul, |
| 3666 | 5177 | .frem, .@"frem fast" => &llvm.Builder.buildFRem, |
| 3667 | 5178 | .fsub, .@"fsub fast" => &llvm.Builder.buildFSub, |
| 3668 | .@"llvm.maxnum." => &llvm.Builder.buildMaxNum, | |
| 3669 | .@"llvm.minnum." => &llvm.Builder.buildMinNum, | |
| 3670 | .@"llvm.ctlz." => &llvm.Builder.buildCTLZ, | |
| 3671 | .@"llvm.cttz." => &llvm.Builder.buildCTTZ, | |
| 3672 | .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat, | |
| 3673 | .@"llvm.smax." => &llvm.Builder.buildSMax, | |
| 3674 | .@"llvm.smin." => &llvm.Builder.buildSMin, | |
| 3675 | .@"llvm.smul.fix.sat." => &llvm.Builder.buildSMulFixSat, | |
| 3676 | .@"llvm.sshl.sat." => &llvm.Builder.buildSShlSat, | |
| 3677 | .@"llvm.ssub.sat." => &llvm.Builder.buildSSubSat, | |
| 3678 | .@"llvm.uadd.sat." => &llvm.Builder.buildUAddSat, | |
| 3679 | .@"llvm.umax." => &llvm.Builder.buildUMax, | |
| 3680 | .@"llvm.umin." => &llvm.Builder.buildUMin, | |
| 3681 | .@"llvm.umul.fix.sat." => &llvm.Builder.buildUMulFixSat, | |
| 3682 | .@"llvm.ushl.sat." => &llvm.Builder.buildUShlSat, | |
| 3683 | .@"llvm.usub.sat." => &llvm.Builder.buildUSubSat, | |
| 3684 | 5179 | .lshr => &llvm.Builder.buildLShr, |
| 3685 | 5180 | .@"lshr exact" => &llvm.Builder.buildLShrExact, |
| 3686 | 5181 | .mul => &llvm.Builder.buildMul, |
| ... | ... | @@ -3934,21 +5429,21 @@ pub const WipFunction = struct { |
| 3934 | 5429 | |
| 3935 | 5430 | pub fn load( |
| 3936 | 5431 | self: *WipFunction, |
| 3937 | kind: MemoryAccessKind, | |
| 5432 | access_kind: MemoryAccessKind, | |
| 3938 | 5433 | ty: Type, |
| 3939 | 5434 | ptr: Value, |
| 3940 | 5435 | alignment: Alignment, |
| 3941 | 5436 | name: []const u8, |
| 3942 | 5437 | ) Allocator.Error!Value { |
| 3943 | return self.loadAtomic(kind, ty, ptr, .system, .none, alignment, name); | |
| 5438 | return self.loadAtomic(access_kind, ty, ptr, .system, .none, alignment, name); | |
| 3944 | 5439 | } |
| 3945 | 5440 | |
| 3946 | 5441 | pub fn loadAtomic( |
| 3947 | 5442 | self: *WipFunction, |
| 3948 | kind: MemoryAccessKind, | |
| 5443 | access_kind: MemoryAccessKind, | |
| 3949 | 5444 | ty: Type, |
| 3950 | 5445 | ptr: Value, |
| 3951 | scope: SyncScope, | |
| 5446 | sync_scope: SyncScope, | |
| 3952 | 5447 | ordering: AtomicOrdering, |
| 3953 | 5448 | alignment: Alignment, |
| 3954 | 5449 | name: []const u8, |
| ... | ... | @@ -3957,22 +5452,21 @@ pub const WipFunction = struct { |
| 3957 | 5452 | try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0); |
| 3958 | 5453 | const instruction = try self.addInst(name, .{ |
| 3959 | 5454 | .tag = switch (ordering) { |
| 3960 | .none => switch (kind) { | |
| 3961 | .normal => .load, | |
| 3962 | .@"volatile" => .@"load volatile", | |
| 3963 | }, | |
| 3964 | else => switch (kind) { | |
| 3965 | .normal => .@"load atomic", | |
| 3966 | .@"volatile" => .@"load atomic volatile", | |
| 3967 | }, | |
| 5455 | .none => .load, | |
| 5456 | else => .@"load atomic", | |
| 3968 | 5457 | }, |
| 3969 | 5458 | .data = self.addExtraAssumeCapacity(Instruction.Load{ |
| 5459 | .info = .{ | |
| 5460 | .access_kind = access_kind, | |
| 5461 | .sync_scope = switch (ordering) { | |
| 5462 | .none => .system, | |
| 5463 | else => sync_scope, | |
| 5464 | }, | |
| 5465 | .success_ordering = ordering, | |
| 5466 | .alignment = alignment, | |
| 5467 | }, | |
| 3970 | 5468 | .type = ty, |
| 3971 | 5469 | .ptr = ptr, |
| 3972 | .info = .{ .scope = switch (ordering) { | |
| 3973 | .none => .system, | |
| 3974 | else => scope, | |
| 3975 | }, .ordering = ordering, .alignment = alignment }, | |
| 3976 | 5470 | }), |
| 3977 | 5471 | }); |
| 3978 | 5472 | if (self.builder.useLibLlvm()) { |
| ... | ... | @@ -3981,7 +5475,8 @@ pub const WipFunction = struct { |
| 3981 | 5475 | ptr.toLlvm(self), |
| 3982 | 5476 | instruction.llvmName(self), |
| 3983 | 5477 | ); |
| 3984 | if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering))); | |
| 5478 | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); | |
| 5479 | if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm()); | |
| 3985 | 5480 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 3986 | 5481 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 3987 | 5482 | } |
| ... | ... | @@ -4000,10 +5495,10 @@ pub const WipFunction = struct { |
| 4000 | 5495 | |
| 4001 | 5496 | pub fn storeAtomic( |
| 4002 | 5497 | self: *WipFunction, |
| 4003 | kind: MemoryAccessKind, | |
| 5498 | access_kind: MemoryAccessKind, | |
| 4004 | 5499 | val: Value, |
| 4005 | 5500 | ptr: Value, |
| 4006 | scope: SyncScope, | |
| 5501 | sync_scope: SyncScope, | |
| 4007 | 5502 | ordering: AtomicOrdering, |
| 4008 | 5503 | alignment: Alignment, |
| 4009 | 5504 | ) Allocator.Error!Instruction.Index { |
| ... | ... | @@ -4011,31 +5506,27 @@ pub const WipFunction = struct { |
| 4011 | 5506 | try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0); |
| 4012 | 5507 | const instruction = try self.addInst(null, .{ |
| 4013 | 5508 | .tag = switch (ordering) { |
| 4014 | .none => switch (kind) { | |
| 4015 | .normal => .store, | |
| 4016 | .@"volatile" => .@"store volatile", | |
| 4017 | }, | |
| 4018 | else => switch (kind) { | |
| 4019 | .normal => .@"store atomic", | |
| 4020 | .@"volatile" => .@"store atomic volatile", | |
| 4021 | }, | |
| 5509 | .none => .store, | |
| 5510 | else => .@"store atomic", | |
| 4022 | 5511 | }, |
| 4023 | 5512 | .data = self.addExtraAssumeCapacity(Instruction.Store{ |
| 5513 | .info = .{ | |
| 5514 | .access_kind = access_kind, | |
| 5515 | .sync_scope = switch (ordering) { | |
| 5516 | .none => .system, | |
| 5517 | else => sync_scope, | |
| 5518 | }, | |
| 5519 | .success_ordering = ordering, | |
| 5520 | .alignment = alignment, | |
| 5521 | }, | |
| 4024 | 5522 | .val = val, |
| 4025 | 5523 | .ptr = ptr, |
| 4026 | .info = .{ .scope = switch (ordering) { | |
| 4027 | .none => .system, | |
| 4028 | else => scope, | |
| 4029 | }, .ordering = ordering, .alignment = alignment }, | |
| 4030 | 5524 | }), |
| 4031 | 5525 | }); |
| 4032 | 5526 | if (self.builder.useLibLlvm()) { |
| 4033 | 5527 | const llvm_instruction = self.llvm.builder.buildStore(val.toLlvm(self), ptr.toLlvm(self)); |
| 4034 | switch (kind) { | |
| 4035 | .normal => {}, | |
| 4036 | .@"volatile" => llvm_instruction.setVolatile(.True), | |
| 4037 | } | |
| 4038 | if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering))); | |
| 5528 | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); | |
| 5529 | if (ordering != .none) llvm_instruction.setOrdering(ordering.toLlvm()); | |
| 4039 | 5530 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); |
| 4040 | 5531 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 4041 | 5532 | } |
| ... | ... | @@ -4044,7 +5535,7 @@ pub const WipFunction = struct { |
| 4044 | 5535 | |
| 4045 | 5536 | pub fn fence( |
| 4046 | 5537 | self: *WipFunction, |
| 4047 | scope: SyncScope, | |
| 5538 | sync_scope: SyncScope, | |
| 4048 | 5539 | ordering: AtomicOrdering, |
| 4049 | 5540 | ) Allocator.Error!Instruction.Index { |
| 4050 | 5541 | assert(ordering != .none); |
| ... | ... | @@ -4052,21 +5543,130 @@ pub const WipFunction = struct { |
| 4052 | 5543 | const instruction = try self.addInst(null, .{ |
| 4053 | 5544 | .tag = .fence, |
| 4054 | 5545 | .data = @bitCast(MemoryAccessInfo{ |
| 4055 | .scope = scope, | |
| 4056 | .ordering = ordering, | |
| 4057 | .alignment = undefined, | |
| 5546 | .sync_scope = sync_scope, | |
| 5547 | .success_ordering = ordering, | |
| 4058 | 5548 | }), |
| 4059 | 5549 | }); |
| 4060 | 5550 | if (self.builder.useLibLlvm()) self.llvm.instructions.appendAssumeCapacity( |
| 4061 | 5551 | self.llvm.builder.buildFence( |
| 4062 | @enumFromInt(@intFromEnum(ordering)), | |
| 4063 | llvm.Bool.fromBool(scope == .singlethread), | |
| 5552 | ordering.toLlvm(), | |
| 5553 | llvm.Bool.fromBool(sync_scope == .singlethread), | |
| 4064 | 5554 | "", |
| 4065 | 5555 | ), |
| 4066 | 5556 | ); |
| 4067 | 5557 | return instruction; |
| 4068 | 5558 | } |
| 4069 | 5559 | |
| 5560 | pub fn cmpxchg( | |
| 5561 | self: *WipFunction, | |
| 5562 | kind: Instruction.CmpXchg.Kind, | |
| 5563 | access_kind: MemoryAccessKind, | |
| 5564 | ptr: Value, | |
| 5565 | cmp: Value, | |
| 5566 | new: Value, | |
| 5567 | sync_scope: SyncScope, | |
| 5568 | success_ordering: AtomicOrdering, | |
| 5569 | failure_ordering: AtomicOrdering, | |
| 5570 | alignment: Alignment, | |
| 5571 | name: []const u8, | |
| 5572 | ) Allocator.Error!Value { | |
| 5573 | assert(ptr.typeOfWip(self).isPointer(self.builder)); | |
| 5574 | const ty = cmp.typeOfWip(self); | |
| 5575 | assert(ty == new.typeOfWip(self)); | |
| 5576 | assert(success_ordering != .none); | |
| 5577 | assert(failure_ordering != .none); | |
| 5578 | ||
| 5579 | _ = try self.builder.structType(.normal, &.{ ty, .i1 }); | |
| 5580 | try self.ensureUnusedExtraCapacity(1, Instruction.CmpXchg, 0); | |
| 5581 | const instruction = try self.addInst(name, .{ | |
| 5582 | .tag = switch (kind) { | |
| 5583 | .strong => .cmpxchg, | |
| 5584 | .weak => .@"cmpxchg weak", | |
| 5585 | }, | |
| 5586 | .data = self.addExtraAssumeCapacity(Instruction.CmpXchg{ | |
| 5587 | .info = .{ | |
| 5588 | .access_kind = access_kind, | |
| 5589 | .sync_scope = sync_scope, | |
| 5590 | .success_ordering = success_ordering, | |
| 5591 | .failure_ordering = failure_ordering, | |
| 5592 | .alignment = alignment, | |
| 5593 | }, | |
| 5594 | .ptr = ptr, | |
| 5595 | .cmp = cmp, | |
| 5596 | .new = new, | |
| 5597 | }), | |
| 5598 | }); | |
| 5599 | if (self.builder.useLibLlvm()) { | |
| 5600 | const llvm_instruction = self.llvm.builder.buildAtomicCmpXchg( | |
| 5601 | ptr.toLlvm(self), | |
| 5602 | cmp.toLlvm(self), | |
| 5603 | new.toLlvm(self), | |
| 5604 | success_ordering.toLlvm(), | |
| 5605 | failure_ordering.toLlvm(), | |
| 5606 | llvm.Bool.fromBool(sync_scope == .singlethread), | |
| 5607 | ); | |
| 5608 | if (kind == .weak) llvm_instruction.setWeak(.True); | |
| 5609 | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); | |
| 5610 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); | |
| 5611 | const llvm_name = instruction.llvmName(self); | |
| 5612 | if (llvm_name.len > 0) llvm_instruction.setValueName( | |
| 5613 | llvm_name.ptr, | |
| 5614 | @intCast(llvm_name.len), | |
| 5615 | ); | |
| 5616 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); | |
| 5617 | } | |
| 5618 | return instruction.toValue(); | |
| 5619 | } | |
| 5620 | ||
| 5621 | pub fn atomicrmw( | |
| 5622 | self: *WipFunction, | |
| 5623 | access_kind: MemoryAccessKind, | |
| 5624 | operation: Instruction.AtomicRmw.Operation, | |
| 5625 | ptr: Value, | |
| 5626 | val: Value, | |
| 5627 | sync_scope: SyncScope, | |
| 5628 | ordering: AtomicOrdering, | |
| 5629 | alignment: Alignment, | |
| 5630 | name: []const u8, | |
| 5631 | ) Allocator.Error!Value { | |
| 5632 | assert(ptr.typeOfWip(self).isPointer(self.builder)); | |
| 5633 | assert(ordering != .none); | |
| 5634 | ||
| 5635 | try self.ensureUnusedExtraCapacity(1, Instruction.AtomicRmw, 0); | |
| 5636 | const instruction = try self.addInst(name, .{ | |
| 5637 | .tag = .atomicrmw, | |
| 5638 | .data = self.addExtraAssumeCapacity(Instruction.AtomicRmw{ | |
| 5639 | .info = .{ | |
| 5640 | .access_kind = access_kind, | |
| 5641 | .atomic_rmw_operation = operation, | |
| 5642 | .sync_scope = sync_scope, | |
| 5643 | .success_ordering = ordering, | |
| 5644 | .alignment = alignment, | |
| 5645 | }, | |
| 5646 | .ptr = ptr, | |
| 5647 | .val = val, | |
| 5648 | }), | |
| 5649 | }); | |
| 5650 | if (self.builder.useLibLlvm()) { | |
| 5651 | const llvm_instruction = self.llvm.builder.buildAtomicRmw( | |
| 5652 | operation.toLlvm(), | |
| 5653 | ptr.toLlvm(self), | |
| 5654 | val.toLlvm(self), | |
| 5655 | ordering.toLlvm(), | |
| 5656 | llvm.Bool.fromBool(sync_scope == .singlethread), | |
| 5657 | ); | |
| 5658 | if (access_kind == .@"volatile") llvm_instruction.setVolatile(.True); | |
| 5659 | if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes)); | |
| 5660 | const llvm_name = instruction.llvmName(self); | |
| 5661 | if (llvm_name.len > 0) llvm_instruction.setValueName( | |
| 5662 | llvm_name.ptr, | |
| 5663 | @intCast(llvm_name.len), | |
| 5664 | ); | |
| 5665 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); | |
| 5666 | } | |
| 5667 | return instruction.toValue(); | |
| 5668 | } | |
| 5669 | ||
| 4070 | 5670 | pub fn gep( |
| 4071 | 5671 | self: *WipFunction, |
| 4072 | 5672 | kind: Instruction.GetElementPtr.Kind, |
| ... | ... | @@ -4239,25 +5839,19 @@ pub const WipFunction = struct { |
| 4239 | 5839 | |
| 4240 | 5840 | pub fn fcmp( |
| 4241 | 5841 | self: *WipFunction, |
| 5842 | fast: FastMathKind, | |
| 4242 | 5843 | cond: FloatCondition, |
| 4243 | 5844 | lhs: Value, |
| 4244 | 5845 | rhs: Value, |
| 4245 | 5846 | name: []const u8, |
| 4246 | 5847 | ) Allocator.Error!Value { |
| 4247 | return self.cmpTag(switch (cond) { | |
| 4248 | inline else => |tag| @field(Instruction.Tag, "fcmp " ++ @tagName(tag)), | |
| 4249 | }, @intFromEnum(cond), lhs, rhs, name); | |
| 4250 | } | |
| 4251 | ||
| 4252 | pub fn fcmpFast( | |
| 4253 | self: *WipFunction, | |
| 4254 | cond: FloatCondition, | |
| 4255 | lhs: Value, | |
| 4256 | rhs: Value, | |
| 4257 | name: []const u8, | |
| 4258 | ) Allocator.Error!Value { | |
| 4259 | return self.cmpTag(switch (cond) { | |
| 4260 | inline else => |tag| @field(Instruction.Tag, "fcmp fast " ++ @tagName(tag)), | |
| 5848 | return self.cmpTag(switch (fast) { | |
| 5849 | inline else => |fast_tag| switch (cond) { | |
| 5850 | inline else => |cond_tag| @field(Instruction.Tag, "fcmp " ++ switch (fast_tag) { | |
| 5851 | .normal => "", | |
| 5852 | .fast => "fast ", | |
| 5853 | } ++ @tagName(cond_tag)), | |
| 5854 | }, | |
| 4261 | 5855 | }, @intFromEnum(cond), lhs, rhs, name); |
| 4262 | 5856 | } |
| 4263 | 5857 | |
| ... | ... | @@ -4315,22 +5909,16 @@ pub const WipFunction = struct { |
| 4315 | 5909 | |
| 4316 | 5910 | pub fn select( |
| 4317 | 5911 | self: *WipFunction, |
| 5912 | fast: FastMathKind, | |
| 4318 | 5913 | cond: Value, |
| 4319 | 5914 | lhs: Value, |
| 4320 | 5915 | rhs: Value, |
| 4321 | 5916 | name: []const u8, |
| 4322 | 5917 | ) Allocator.Error!Value { |
| 4323 | return self.selectTag(.select, cond, lhs, rhs, name); | |
| 4324 | } | |
| 4325 | ||
| 4326 | pub fn selectFast( | |
| 4327 | self: *WipFunction, | |
| 4328 | cond: Value, | |
| 4329 | lhs: Value, | |
| 4330 | rhs: Value, | |
| 4331 | name: []const u8, | |
| 4332 | ) Allocator.Error!Value { | |
| 4333 | return self.selectTag(.@"select fast", cond, lhs, rhs, name); | |
| 5918 | return self.selectTag(switch (fast) { | |
| 5919 | .normal => .select, | |
| 5920 | .fast => .@"select fast", | |
| 5921 | }, cond, lhs, rhs, name); | |
| 4334 | 5922 | } |
| 4335 | 5923 | |
| 4336 | 5924 | pub fn call( |
| ... | ... | @@ -4354,7 +5942,16 @@ pub const WipFunction = struct { |
| 4354 | 5942 | .void => null, |
| 4355 | 5943 | else => name, |
| 4356 | 5944 | }, .{ |
| 4357 | .tag = .call, | |
| 5945 | .tag = switch (kind) { | |
| 5946 | .normal => .call, | |
| 5947 | .fast => .@"call fast", | |
| 5948 | .musttail => .@"musttail call", | |
| 5949 | .musttail_fast => .@"musttail call fast", | |
| 5950 | .notail => .@"notail call", | |
| 5951 | .notail_fast => .@"notail call fast", | |
| 5952 | .tail => .@"tail call", | |
| 5953 | .tail_fast => .@"tail call fast", | |
| 5954 | }, | |
| 4358 | 5955 | .data = self.addExtraAssumeCapacity(Instruction.Call{ |
| 4359 | 5956 | .info = .{ .call_conv = call_conv }, |
| 4360 | 5957 | .attributes = function_attributes, |
| ... | ... | @@ -4396,7 +5993,7 @@ pub const WipFunction = struct { |
| 4396 | 5993 | else => instruction.llvmName(self), |
| 4397 | 5994 | }, |
| 4398 | 5995 | ); |
| 4399 | llvm_instruction.setInstructionCallConv(@enumFromInt(@intFromEnum(call_conv))); | |
| 5996 | llvm_instruction.setInstructionCallConv(call_conv.toLlvm()); | |
| 4400 | 5997 | llvm_instruction.setTailCallKind(switch (kind) { |
| 4401 | 5998 | .normal, .fast => .None, |
| 4402 | 5999 | .musttail, .musttail_fast => .MustTail, |
| ... | ... | @@ -4404,9 +6001,8 @@ pub const WipFunction = struct { |
| 4404 | 6001 | .tail, .tail_fast => .Tail, |
| 4405 | 6002 | }); |
| 4406 | 6003 | for (0.., function_attributes.slice(self.builder)) |index, attributes| { |
| 4407 | const attribute_index = @as(llvm.AttributeIndex, @intCast(index)) -% 1; | |
| 4408 | 6004 | for (attributes.slice(self.builder)) |attribute| llvm_instruction.addCallSiteAttribute( |
| 4409 | attribute_index, | |
| 6005 | @as(llvm.AttributeIndex, @intCast(index)) -% 1, | |
| 4410 | 6006 | attribute.toLlvm(self.builder), |
| 4411 | 6007 | ); |
| 4412 | 6008 | } |
| ... | ... | @@ -4419,7 +6015,7 @@ pub const WipFunction = struct { |
| 4419 | 6015 | self: *WipFunction, |
| 4420 | 6016 | function_attributes: FunctionAttributes, |
| 4421 | 6017 | ty: Type, |
| 4422 | kind: Constant.Asm.Info, | |
| 6018 | kind: Constant.Assembly.Info, | |
| 4423 | 6019 | assembly: String, |
| 4424 | 6020 | constraints: String, |
| 4425 | 6021 | args: []const Value, |
| ... | ... | @@ -4429,6 +6025,80 @@ pub const WipFunction = struct { |
| 4429 | 6025 | return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name); |
| 4430 | 6026 | } |
| 4431 | 6027 | |
| 6028 | pub fn callIntrinsic( | |
| 6029 | self: *WipFunction, | |
| 6030 | fast: FastMathKind, | |
| 6031 | function_attributes: FunctionAttributes, | |
| 6032 | id: Intrinsic, | |
| 6033 | overload: []const Type, | |
| 6034 | args: []const Value, | |
| 6035 | name: []const u8, | |
| 6036 | ) Allocator.Error!Value { | |
| 6037 | const intrinsic = try self.builder.getIntrinsic(id, overload); | |
| 6038 | return self.call( | |
| 6039 | fast.toCallKind(), | |
| 6040 | CallConv.default, | |
| 6041 | function_attributes, | |
| 6042 | intrinsic.typeOf(self.builder), | |
| 6043 | intrinsic.toValue(self.builder), | |
| 6044 | args, | |
| 6045 | name, | |
| 6046 | ); | |
| 6047 | } | |
| 6048 | ||
| 6049 | pub fn callMemCpy( | |
| 6050 | self: *WipFunction, | |
| 6051 | dst: Value, | |
| 6052 | dst_align: Alignment, | |
| 6053 | src: Value, | |
| 6054 | src_align: Alignment, | |
| 6055 | len: Value, | |
| 6056 | kind: MemoryAccessKind, | |
| 6057 | ) Allocator.Error!Instruction.Index { | |
| 6058 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; | |
| 6059 | var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; | |
| 6060 | const value = try self.callIntrinsic( | |
| 6061 | .normal, | |
| 6062 | try self.builder.fnAttrs(&.{ | |
| 6063 | .none, | |
| 6064 | .none, | |
| 6065 | try self.builder.attrs(&dst_attrs), | |
| 6066 | try self.builder.attrs(&src_attrs), | |
| 6067 | }), | |
| 6068 | .memcpy, | |
| 6069 | &.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) }, | |
| 6070 | &.{ dst, src, len, switch (kind) { | |
| 6071 | .normal => Value.false, | |
| 6072 | .@"volatile" => Value.true, | |
| 6073 | } }, | |
| 6074 | undefined, | |
| 6075 | ); | |
| 6076 | return value.unwrap().instruction; | |
| 6077 | } | |
| 6078 | ||
| 6079 | pub fn callMemSet( | |
| 6080 | self: *WipFunction, | |
| 6081 | dst: Value, | |
| 6082 | dst_align: Alignment, | |
| 6083 | val: Value, | |
| 6084 | len: Value, | |
| 6085 | kind: MemoryAccessKind, | |
| 6086 | ) Allocator.Error!Instruction.Index { | |
| 6087 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; | |
| 6088 | const value = try self.callIntrinsic( | |
| 6089 | .normal, | |
| 6090 | try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }), | |
| 6091 | .memset, | |
| 6092 | &.{ dst.typeOfWip(self), len.typeOfWip(self) }, | |
| 6093 | &.{ dst, val, len, switch (kind) { | |
| 6094 | .normal => Value.false, | |
| 6095 | .@"volatile" => Value.true, | |
| 6096 | } }, | |
| 6097 | undefined, | |
| 6098 | ); | |
| 6099 | return value.unwrap().instruction; | |
| 6100 | } | |
| 6101 | ||
| 4432 | 6102 | pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value { |
| 4433 | 6103 | try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0); |
| 4434 | 6104 | const instruction = try self.addInst(name, .{ |
| ... | ... | @@ -4448,53 +6118,6 @@ pub const WipFunction = struct { |
| 4448 | 6118 | return instruction.toValue(); |
| 4449 | 6119 | } |
| 4450 | 6120 | |
| 4451 | pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value { | |
| 4452 | assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self)); | |
| 4453 | try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0); | |
| 4454 | const instruction = try self.addInst("", .{ | |
| 4455 | .tag = .@"llvm.fma.", | |
| 4456 | .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{ | |
| 4457 | .a = a, | |
| 4458 | .b = b, | |
| 4459 | .c = c, | |
| 4460 | }), | |
| 4461 | }); | |
| 4462 | if (self.builder.useLibLlvm()) { | |
| 4463 | self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA( | |
| 4464 | self.llvm.builder, | |
| 4465 | a.toLlvm(self), | |
| 4466 | b.toLlvm(self), | |
| 4467 | c.toLlvm(self), | |
| 4468 | instruction.llvmName(self), | |
| 4469 | )); | |
| 4470 | } | |
| 4471 | return instruction.toValue(); | |
| 4472 | } | |
| 4473 | ||
| 4474 | pub const WipUnimplemented = struct { | |
| 4475 | instruction: Instruction.Index, | |
| 4476 | ||
| 4477 | pub fn finish(self: WipUnimplemented, val: *llvm.Value, wip: *WipFunction) Value { | |
| 4478 | assert(wip.builder.useLibLlvm()); | |
| 4479 | wip.llvm.instructions.items[@intFromEnum(self.instruction)] = val; | |
| 4480 | return self.instruction.toValue(); | |
| 4481 | } | |
| 4482 | }; | |
| 4483 | ||
| 4484 | pub fn unimplemented( | |
| 4485 | self: *WipFunction, | |
| 4486 | ty: Type, | |
| 4487 | name: []const u8, | |
| 4488 | ) Allocator.Error!WipUnimplemented { | |
| 4489 | try self.ensureUnusedExtraCapacity(1, NoExtra, 0); | |
| 4490 | const instruction = try self.addInst(name, .{ | |
| 4491 | .tag = .unimplemented, | |
| 4492 | .data = @intFromEnum(ty), | |
| 4493 | }); | |
| 4494 | if (self.builder.useLibLlvm()) _ = self.llvm.instructions.addOneAssumeCapacity(); | |
| 4495 | return .{ .instruction = instruction }; | |
| 4496 | } | |
| 4497 | ||
| 4498 | 6121 | pub fn finish(self: *WipFunction) Allocator.Error!void { |
| 4499 | 6122 | const gpa = self.builder.gpa; |
| 4500 | 6123 | const function = self.function.ptr(self.builder); |
| ... | ... | @@ -4697,22 +6320,6 @@ pub const WipFunction = struct { |
| 4697 | 6320 | .@"icmp ugt", |
| 4698 | 6321 | .@"icmp ule", |
| 4699 | 6322 | .@"icmp ult", |
| 4700 | .@"llvm.maxnum.", | |
| 4701 | .@"llvm.minnum.", | |
| 4702 | .@"llvm.ctlz.", | |
| 4703 | .@"llvm.cttz.", | |
| 4704 | .@"llvm.sadd.sat.", | |
| 4705 | .@"llvm.smax.", | |
| 4706 | .@"llvm.smin.", | |
| 4707 | .@"llvm.smul.fix.sat.", | |
| 4708 | .@"llvm.sshl.sat.", | |
| 4709 | .@"llvm.ssub.sat.", | |
| 4710 | .@"llvm.uadd.sat.", | |
| 4711 | .@"llvm.umax.", | |
| 4712 | .@"llvm.umin.", | |
| 4713 | .@"llvm.umul.fix.sat.", | |
| 4714 | .@"llvm.ushl.sat.", | |
| 4715 | .@"llvm.usub.sat.", | |
| 4716 | 6323 | .lshr, |
| 4717 | 6324 | .@"lshr exact", |
| 4718 | 6325 | .mul, |
| ... | ... | @@ -4775,19 +6382,19 @@ pub const WipFunction = struct { |
| 4775 | 6382 | .arg, |
| 4776 | 6383 | .block, |
| 4777 | 6384 | => unreachable, |
| 6385 | .atomicrmw => { | |
| 6386 | const extra = self.extraData(Instruction.AtomicRmw, instruction.data); | |
| 6387 | instruction.data = wip_extra.addExtra(Instruction.AtomicRmw{ | |
| 6388 | .info = extra.info, | |
| 6389 | .ptr = instructions.map(extra.ptr), | |
| 6390 | .val = instructions.map(extra.val), | |
| 6391 | }); | |
| 6392 | }, | |
| 4778 | 6393 | .br, |
| 4779 | 6394 | .fence, |
| 4780 | 6395 | .@"ret void", |
| 4781 | .unimplemented, | |
| 4782 | 6396 | .@"unreachable", |
| 4783 | 6397 | => {}, |
| 4784 | .extractelement => { | |
| 4785 | const extra = self.extraData(Instruction.ExtractElement, instruction.data); | |
| 4786 | instruction.data = wip_extra.addExtra(Instruction.ExtractElement{ | |
| 4787 | .val = instructions.map(extra.val), | |
| 4788 | .index = instructions.map(extra.index), | |
| 4789 | }); | |
| 4790 | }, | |
| 4791 | 6398 | .br_cond => { |
| 4792 | 6399 | const extra = self.extraData(Instruction.BrCond, instruction.data); |
| 4793 | 6400 | instruction.data = wip_extra.addExtra(Instruction.BrCond{ |
| ... | ... | @@ -4816,6 +6423,24 @@ pub const WipFunction = struct { |
| 4816 | 6423 | }); |
| 4817 | 6424 | wip_extra.appendMappedValues(args, instructions); |
| 4818 | 6425 | }, |
| 6426 | .cmpxchg, | |
| 6427 | .@"cmpxchg weak", | |
| 6428 | => { | |
| 6429 | const extra = self.extraData(Instruction.CmpXchg, instruction.data); | |
| 6430 | instruction.data = wip_extra.addExtra(Instruction.CmpXchg{ | |
| 6431 | .info = extra.info, | |
| 6432 | .ptr = instructions.map(extra.ptr), | |
| 6433 | .cmp = instructions.map(extra.cmp), | |
| 6434 | .new = instructions.map(extra.new), | |
| 6435 | }); | |
| 6436 | }, | |
| 6437 | .extractelement => { | |
| 6438 | const extra = self.extraData(Instruction.ExtractElement, instruction.data); | |
| 6439 | instruction.data = wip_extra.addExtra(Instruction.ExtractElement{ | |
| 6440 | .val = instructions.map(extra.val), | |
| 6441 | .index = instructions.map(extra.index), | |
| 6442 | }); | |
| 6443 | }, | |
| 4819 | 6444 | .extractvalue => { |
| 4820 | 6445 | var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data); |
| 4821 | 6446 | const indices = extra.trail.next(extra.data.indices_len, u32, self); |
| ... | ... | @@ -4828,22 +6453,6 @@ pub const WipFunction = struct { |
| 4828 | 6453 | .fneg, |
| 4829 | 6454 | .@"fneg fast", |
| 4830 | 6455 | .ret, |
| 4831 | .@"llvm.ceil.", | |
| 4832 | .@"llvm.cos.", | |
| 4833 | .@"llvm.exp.", | |
| 4834 | .@"llvm.exp2.", | |
| 4835 | .@"llvm.fabs.", | |
| 4836 | .@"llvm.floor.", | |
| 4837 | .@"llvm.log.", | |
| 4838 | .@"llvm.log10.", | |
| 4839 | .@"llvm.log2.", | |
| 4840 | .@"llvm.round.", | |
| 4841 | .@"llvm.sin.", | |
| 4842 | .@"llvm.sqrt.", | |
| 4843 | .@"llvm.trunc.", | |
| 4844 | .@"llvm.bitreverse.", | |
| 4845 | .@"llvm.bswap.", | |
| 4846 | .@"llvm.ctpop.", | |
| 4847 | 6456 | => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), |
| 4848 | 6457 | .getelementptr, |
| 4849 | 6458 | .@"getelementptr inbounds", |
| ... | ... | @@ -4877,8 +6486,6 @@ pub const WipFunction = struct { |
| 4877 | 6486 | }, |
| 4878 | 6487 | .load, |
| 4879 | 6488 | .@"load atomic", |
| 4880 | .@"load atomic volatile", | |
| 4881 | .@"load volatile", | |
| 4882 | 6489 | => { |
| 4883 | 6490 | const extra = self.extraData(Instruction.Load, instruction.data); |
| 4884 | 6491 | instruction.data = wip_extra.addExtra(Instruction.Load{ |
| ... | ... | @@ -4920,8 +6527,6 @@ pub const WipFunction = struct { |
| 4920 | 6527 | }, |
| 4921 | 6528 | .store, |
| 4922 | 6529 | .@"store atomic", |
| 4923 | .@"store atomic volatile", | |
| 4924 | .@"store volatile", | |
| 4925 | 6530 | => { |
| 4926 | 6531 | const extra = self.extraData(Instruction.Store, instruction.data); |
| 4927 | 6532 | instruction.data = wip_extra.addExtra(Instruction.Store{ |
| ... | ... | @@ -4949,14 +6554,6 @@ pub const WipFunction = struct { |
| 4949 | 6554 | .type = extra.type, |
| 4950 | 6555 | }); |
| 4951 | 6556 | }, |
| 4952 | .@"llvm.fma." => { | |
| 4953 | const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data); | |
| 4954 | instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{ | |
| 4955 | .a = instructions.map(extra.a), | |
| 4956 | .b = instructions.map(extra.b), | |
| 4957 | .c = instructions.map(extra.c), | |
| 4958 | }); | |
| 4959 | }, | |
| 4960 | 6557 | } |
| 4961 | 6558 | function.instructions.appendAssumeCapacity(instruction); |
| 4962 | 6559 | names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) |
| ... | ... | @@ -5365,6 +6962,24 @@ pub const FloatCondition = enum(u4) { |
| 5365 | 6962 | ult = 12, |
| 5366 | 6963 | ule = 13, |
| 5367 | 6964 | une = 14, |
| 6965 | ||
| 6966 | fn toLlvm(self: FloatCondition) llvm.RealPredicate { | |
| 6967 | return switch (self) { | |
| 6968 | .oeq => .OEQ, | |
| 6969 | .ogt => .OGT, | |
| 6970 | .oge => .OGE, | |
| 6971 | .olt => .OLT, | |
| 6972 | .ole => .OLE, | |
| 6973 | .one => .ONE, | |
| 6974 | .ord => .ORD, | |
| 6975 | .uno => .UNO, | |
| 6976 | .ueq => .UEQ, | |
| 6977 | .ugt => .UGT, | |
| 6978 | .uge => .UGE, | |
| 6979 | .ult => .ULT, | |
| 6980 | .uno => .UNE, | |
| 6981 | }; | |
| 6982 | } | |
| 5368 | 6983 | }; |
| 5369 | 6984 | |
| 5370 | 6985 | pub const IntegerCondition = enum(u6) { |
| ... | ... | @@ -5378,11 +6993,34 @@ pub const IntegerCondition = enum(u6) { |
| 5378 | 6993 | sge = 39, |
| 5379 | 6994 | slt = 40, |
| 5380 | 6995 | sle = 41, |
| 6996 | ||
| 6997 | fn toLlvm(self: IntegerCondition) llvm.IntPredicate { | |
| 6998 | return switch (self) { | |
| 6999 | .eq => .EQ, | |
| 7000 | .ne => .NE, | |
| 7001 | .ugt => .UGT, | |
| 7002 | .uge => .UGE, | |
| 7003 | .ult => .ULT, | |
| 7004 | .sgt => .SGT, | |
| 7005 | .sge => .SGE, | |
| 7006 | .slt => .SLT, | |
| 7007 | .sle => .SLE, | |
| 7008 | }; | |
| 7009 | } | |
| 5381 | 7010 | }; |
| 5382 | 7011 | |
| 5383 | 7012 | pub const MemoryAccessKind = enum(u1) { |
| 5384 | 7013 | normal, |
| 5385 | 7014 | @"volatile", |
| 7015 | ||
| 7016 | pub fn format( | |
| 7017 | self: MemoryAccessKind, | |
| 7018 | comptime prefix: []const u8, | |
| 7019 | _: std.fmt.FormatOptions, | |
| 7020 | writer: anytype, | |
| 7021 | ) @TypeOf(writer).Error!void { | |
| 7022 | if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); | |
| 7023 | } | |
| 5386 | 7024 | }; |
| 5387 | 7025 | |
| 5388 | 7026 | pub const SyncScope = enum(u1) { |
| ... | ... | @@ -5396,7 +7034,7 @@ pub const SyncScope = enum(u1) { |
| 5396 | 7034 | writer: anytype, |
| 5397 | 7035 | ) @TypeOf(writer).Error!void { |
| 5398 | 7036 | if (self != .system) try writer.print( |
| 5399 | \\{s} syncscope("{s}") | |
| 7037 | \\{s}syncscope("{s}") | |
| 5400 | 7038 | , .{ prefix, @tagName(self) }); |
| 5401 | 7039 | } |
| 5402 | 7040 | }; |
| ... | ... | @@ -5416,15 +7054,30 @@ pub const AtomicOrdering = enum(u3) { |
| 5416 | 7054 | _: std.fmt.FormatOptions, |
| 5417 | 7055 | writer: anytype, |
| 5418 | 7056 | ) @TypeOf(writer).Error!void { |
| 5419 | if (self != .none) try writer.print("{s} {s}", .{ prefix, @tagName(self) }); | |
| 7057 | if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) }); | |
| 7058 | } | |
| 7059 | ||
| 7060 | fn toLlvm(self: AtomicOrdering) llvm.AtomicOrdering { | |
| 7061 | return switch (self) { | |
| 7062 | .none => .NotAtomic, | |
| 7063 | .unordered => .Unordered, | |
| 7064 | .monotonic => .Monotonic, | |
| 7065 | .acquire => .Acquire, | |
| 7066 | .release => .Release, | |
| 7067 | .acq_rel => .AcquireRelease, | |
| 7068 | .seq_cst => .SequentiallyConsistent, | |
| 7069 | }; | |
| 5420 | 7070 | } |
| 5421 | 7071 | }; |
| 5422 | 7072 | |
| 5423 | 7073 | const MemoryAccessInfo = packed struct(u32) { |
| 5424 | scope: SyncScope, | |
| 5425 | ordering: AtomicOrdering, | |
| 5426 | alignment: Alignment, | |
| 5427 | _: u22 = undefined, | |
| 7074 | access_kind: MemoryAccessKind = .normal, | |
| 7075 | atomic_rmw_operation: Function.Instruction.AtomicRmw.Operation = .none, | |
| 7076 | sync_scope: SyncScope, | |
| 7077 | success_ordering: AtomicOrdering, | |
| 7078 | failure_ordering: AtomicOrdering = .none, | |
| 7079 | alignment: Alignment = .default, | |
| 7080 | _: u13 = undefined, | |
| 5428 | 7081 | }; |
| 5429 | 7082 | |
| 5430 | 7083 | pub const FastMath = packed struct(u32) { |
| ... | ... | @@ -5447,6 +7100,18 @@ pub const FastMath = packed struct(u32) { |
| 5447 | 7100 | }; |
| 5448 | 7101 | }; |
| 5449 | 7102 | |
| 7103 | pub const FastMathKind = enum { | |
| 7104 | normal, | |
| 7105 | fast, | |
| 7106 | ||
| 7107 | pub fn toCallKind(self: FastMathKind) Function.Instruction.Call.Kind { | |
| 7108 | return switch (self) { | |
| 7109 | .normal => .normal, | |
| 7110 | .fast => .fast, | |
| 7111 | }; | |
| 7112 | } | |
| 7113 | }; | |
| 7114 | ||
| 5450 | 7115 | pub const Constant = enum(u32) { |
| 5451 | 7116 | false, |
| 5452 | 7117 | true, |
| ... | ... | @@ -5516,6 +7181,7 @@ pub const Constant = enum(u32) { |
| 5516 | 7181 | @"and", |
| 5517 | 7182 | @"or", |
| 5518 | 7183 | xor, |
| 7184 | select, | |
| 5519 | 7185 | @"asm", |
| 5520 | 7186 | @"asm sideeffect", |
| 5521 | 7187 | @"asm alignstack", |
| ... | ... | @@ -5627,7 +7293,13 @@ pub const Constant = enum(u32) { |
| 5627 | 7293 | rhs: Constant, |
| 5628 | 7294 | }; |
| 5629 | 7295 | |
| 5630 | pub const Asm = extern struct { | |
| 7296 | pub const Select = extern struct { | |
| 7297 | cond: Constant, | |
| 7298 | lhs: Constant, | |
| 7299 | rhs: Constant, | |
| 7300 | }; | |
| 7301 | ||
| 7302 | pub const Assembly = extern struct { | |
| 5631 | 7303 | type: Type, |
| 5632 | 7304 | assembly: String, |
| 5633 | 7305 | constraints: String, |
| ... | ... | @@ -5651,7 +7323,7 @@ pub const Constant = enum(u32) { |
| 5651 | 7323 | } |
| 5652 | 7324 | |
| 5653 | 7325 | pub fn toValue(self: Constant) Value { |
| 5654 | return @enumFromInt(@intFromEnum(Value.first_constant) + @intFromEnum(self)); | |
| 7326 | return @enumFromInt(Value.first_constant + @intFromEnum(self)); | |
| 5655 | 7327 | } |
| 5656 | 7328 | |
| 5657 | 7329 | pub fn typeOf(self: Constant, builder: *Builder) Type { |
| ... | ... | @@ -5758,6 +7430,7 @@ pub const Constant = enum(u32) { |
| 5758 | 7430 | .@"or", |
| 5759 | 7431 | .xor, |
| 5760 | 7432 | => builder.constantExtraData(Binary, item.data).lhs.typeOf(builder), |
| 7433 | .select => builder.constantExtraData(Select, item.data).lhs.typeOf(builder), | |
| 5761 | 7434 | .@"asm", |
| 5762 | 7435 | .@"asm sideeffect", |
| 5763 | 7436 | .@"asm alignstack", |
| ... | ... | @@ -5852,7 +7525,7 @@ pub const Constant = enum(u32) { |
| 5852 | 7525 | } |
| 5853 | 7526 | }, |
| 5854 | 7527 | .global => |global| switch (global.ptrConst(builder).kind) { |
| 5855 | .alias => |alias| cur = alias.ptrConst(builder).init, | |
| 7528 | .alias => |alias| cur = alias.ptrConst(builder).aliasee, | |
| 5856 | 7529 | .variable, .function => return global, |
| 5857 | 7530 | .replaced => unreachable, |
| 5858 | 7531 | }, |
| ... | ... | @@ -5926,9 +7599,34 @@ pub const Constant = enum(u32) { |
| 5926 | 7599 | .bfloat => 16, |
| 5927 | 7600 | else => unreachable, |
| 5928 | 7601 | } }), |
| 5929 | .float => try writer.print("0x{X:0>16}", .{ | |
| 5930 | @as(u64, @bitCast(@as(f64, @as(f32, @bitCast(item.data))))), | |
| 5931 | }), | |
| 7602 | .float => { | |
| 7603 | const Float = struct { | |
| 7604 | fn Repr(comptime T: type) type { | |
| 7605 | return packed struct(std.meta.Int(.unsigned, @bitSizeOf(T))) { | |
| 7606 | mantissa: std.meta.Int(.unsigned, std.math.floatMantissaBits(T)), | |
| 7607 | exponent: std.meta.Int(.unsigned, std.math.floatExponentBits(T)), | |
| 7608 | sign: u1, | |
| 7609 | }; | |
| 7610 | } | |
| 7611 | }; | |
| 7612 | const Exponent32 = std.meta.FieldType(Float.Repr(f32), .exponent); | |
| 7613 | const Exponent64 = std.meta.FieldType(Float.Repr(f64), .exponent); | |
| 7614 | const repr: Float.Repr(f32) = @bitCast(item.data); | |
| 7615 | try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){ | |
| 7616 | .mantissa = std.math.shl( | |
| 7617 | std.meta.FieldType(Float.Repr(f64), .mantissa), | |
| 7618 | repr.mantissa, | |
| 7619 | std.math.floatMantissaBits(f64) - std.math.floatMantissaBits(f32), | |
| 7620 | ), | |
| 7621 | .exponent = switch (repr.exponent) { | |
| 7622 | std.math.minInt(Exponent32) => std.math.minInt(Exponent64), | |
| 7623 | else => @as(Exponent64, repr.exponent) + | |
| 7624 | (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), | |
| 7625 | std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), | |
| 7626 | }, | |
| 7627 | .sign = repr.sign, | |
| 7628 | }))}); | |
| 7629 | }, | |
| 5932 | 7630 | .double => { |
| 5933 | 7631 | const extra = data.builder.constantExtraData(Double, item.data); |
| 5934 | 7632 | try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo }); |
| ... | ... | @@ -6122,6 +7820,15 @@ pub const Constant = enum(u32) { |
| 6122 | 7820 | extra.rhs.fmt(data.builder), |
| 6123 | 7821 | }); |
| 6124 | 7822 | }, |
| 7823 | .select => |tag| { | |
| 7824 | const extra = data.builder.constantExtraData(Select, item.data); | |
| 7825 | try writer.print("{s} ({%}, {%}, {%})", .{ | |
| 7826 | @tagName(tag), | |
| 7827 | extra.cond.fmt(data.builder), | |
| 7828 | extra.lhs.fmt(data.builder), | |
| 7829 | extra.rhs.fmt(data.builder), | |
| 7830 | }); | |
| 7831 | }, | |
| 6125 | 7832 | .@"asm", |
| 6126 | 7833 | .@"asm sideeffect", |
| 6127 | 7834 | .@"asm alignstack", |
| ... | ... | @@ -6139,7 +7846,7 @@ pub const Constant = enum(u32) { |
| 6139 | 7846 | .@"asm alignstack inteldialect unwind", |
| 6140 | 7847 | .@"asm sideeffect alignstack inteldialect unwind", |
| 6141 | 7848 | => |tag| { |
| 6142 | const extra = data.builder.constantExtraData(Asm, item.data); | |
| 7849 | const extra = data.builder.constantExtraData(Assembly, item.data); | |
| 6143 | 7850 | try writer.print("{s} {\"}, {\"}", .{ |
| 6144 | 7851 | @tagName(tag), |
| 6145 | 7852 | extra.assembly.fmt(data.builder), |
| ... | ... | @@ -6157,27 +7864,31 @@ pub const Constant = enum(u32) { |
| 6157 | 7864 | |
| 6158 | 7865 | pub fn toLlvm(self: Constant, builder: *const Builder) *llvm.Value { |
| 6159 | 7866 | assert(builder.useLibLlvm()); |
| 6160 | return switch (self.unwrap()) { | |
| 7867 | const llvm_value = switch (self.unwrap()) { | |
| 6161 | 7868 | .constant => |constant| builder.llvm.constants.items[constant], |
| 6162 | .global => |global| global.toLlvm(builder), | |
| 7869 | .global => |global| return global.toLlvm(builder), | |
| 6163 | 7870 | }; |
| 7871 | const global = builder.llvm.replacements.get(llvm_value) orelse return llvm_value; | |
| 7872 | return global.toLlvm(builder); | |
| 6164 | 7873 | } |
| 6165 | 7874 | }; |
| 6166 | 7875 | |
| 6167 | 7876 | pub const Value = enum(u32) { |
| 6168 | 7877 | none = std.math.maxInt(u31), |
| 7878 | false = first_constant + @intFromEnum(Constant.false), | |
| 7879 | true = first_constant + @intFromEnum(Constant.true), | |
| 6169 | 7880 | _, |
| 6170 | 7881 | |
| 6171 | const first_constant: Value = @enumFromInt(1 << 31); | |
| 7882 | const first_constant = 1 << 31; | |
| 6172 | 7883 | |
| 6173 | 7884 | pub fn unwrap(self: Value) union(enum) { |
| 6174 | 7885 | instruction: Function.Instruction.Index, |
| 6175 | 7886 | constant: Constant, |
| 6176 | 7887 | } { |
| 6177 | return if (@intFromEnum(self) < @intFromEnum(first_constant)) | |
| 7888 | return if (@intFromEnum(self) < first_constant) | |
| 6178 | 7889 | .{ .instruction = @enumFromInt(@intFromEnum(self)) } |
| 6179 | 7890 | else |
| 6180 | .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) }; | |
| 7891 | .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }; | |
| 6181 | 7892 | } |
| 6182 | 7893 | |
| 6183 | 7894 | pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { |
| ... | ... | @@ -6295,6 +8006,7 @@ pub fn init(options: Options) InitError!Builder { |
| 6295 | 8006 | .types = .{}, |
| 6296 | 8007 | .globals = .{}, |
| 6297 | 8008 | .constants = .{}, |
| 8009 | .replacements = .{}, | |
| 6298 | 8010 | }; |
| 6299 | 8011 | errdefer self.deinit(); |
| 6300 | 8012 | |
| ... | ... | @@ -6304,7 +8016,7 @@ pub fn init(options: Options) InitError!Builder { |
| 6304 | 8016 | if (options.name.len > 0) self.source_filename = try self.string(options.name); |
| 6305 | 8017 | self.initializeLLVMTarget(options.target.cpu.arch); |
| 6306 | 8018 | if (self.useLibLlvm()) self.llvm.module = llvm.Module.createWithName( |
| 6307 | (self.source_filename.slice(&self) orelse "").ptr, | |
| 8019 | (self.source_filename.slice(&self) orelse ""), | |
| 6308 | 8020 | self.llvm.context, |
| 6309 | 8021 | ); |
| 6310 | 8022 | |
| ... | ... | @@ -6349,8 +8061,11 @@ pub fn init(options: Options) InitError!Builder { |
| 6349 | 8061 | inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits| |
| 6350 | 8062 | assert(self.intTypeAssumeCapacity(bits) == |
| 6351 | 8063 | @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); |
| 6352 | inline for (.{0}) |addr_space| | |
| 6353 | assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr); | |
| 8064 | inline for (.{ 0, 4 }) |addr_space_index| { | |
| 8065 | const addr_space: AddrSpace = @enumFromInt(addr_space_index); | |
| 8066 | assert(self.ptrTypeAssumeCapacity(addr_space) == | |
| 8067 | @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space}))); | |
| 8068 | } | |
| 6354 | 8069 | } |
| 6355 | 8070 | |
| 6356 | 8071 | { |
| ... | ... | @@ -6371,6 +8086,20 @@ pub fn init(options: Options) InitError!Builder { |
| 6371 | 8086 | } |
| 6372 | 8087 | |
| 6373 | 8088 | pub fn deinit(self: *Builder) void { |
| 8089 | if (self.useLibLlvm()) { | |
| 8090 | var replacement_it = self.llvm.replacements.keyIterator(); | |
| 8091 | while (replacement_it.next()) |replacement| replacement.*.deleteGlobalValue(); | |
| 8092 | self.llvm.replacements.deinit(self.gpa); | |
| 8093 | self.llvm.constants.deinit(self.gpa); | |
| 8094 | self.llvm.globals.deinit(self.gpa); | |
| 8095 | self.llvm.types.deinit(self.gpa); | |
| 8096 | self.llvm.attributes.deinit(self.gpa); | |
| 8097 | if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids); | |
| 8098 | if (self.llvm.di_builder) |di_builder| di_builder.dispose(); | |
| 8099 | if (self.llvm.module) |module| module.dispose(); | |
| 8100 | self.llvm.context.dispose(); | |
| 8101 | } | |
| 8102 | ||
| 6374 | 8103 | self.module_asm.deinit(self.gpa); |
| 6375 | 8104 | |
| 6376 | 8105 | self.string_map.deinit(self.gpa); |
| ... | ... | @@ -6400,16 +8129,6 @@ pub fn deinit(self: *Builder) void { |
| 6400 | 8129 | self.constant_extra.deinit(self.gpa); |
| 6401 | 8130 | self.constant_limbs.deinit(self.gpa); |
| 6402 | 8131 | |
| 6403 | if (self.useLibLlvm()) { | |
| 6404 | self.llvm.constants.deinit(self.gpa); | |
| 6405 | self.llvm.globals.deinit(self.gpa); | |
| 6406 | self.llvm.types.deinit(self.gpa); | |
| 6407 | self.llvm.attributes.deinit(self.gpa); | |
| 6408 | if (self.llvm.attribute_kind_ids) |attribute_kind_ids| self.gpa.destroy(attribute_kind_ids); | |
| 6409 | if (self.llvm.di_builder) |di_builder| di_builder.dispose(); | |
| 6410 | if (self.llvm.module) |module| module.dispose(); | |
| 6411 | self.llvm.context.dispose(); | |
| 6412 | } | |
| 6413 | 8132 | self.* = undefined; |
| 6414 | 8133 | } |
| 6415 | 8134 | |
| ... | ... | @@ -6763,16 +8482,16 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde |
| 6763 | 8482 | gop.value_ptr.* = {}; |
| 6764 | 8483 | if (self.useLibLlvm()) self.llvm.attributes.appendAssumeCapacity(switch (attribute) { |
| 6765 | 8484 | else => llvm_attr: { |
| 6766 | const kind_id = &self.llvm.attribute_kind_ids.?[@intFromEnum(attribute)]; | |
| 6767 | if (kind_id.* == 0) { | |
| 8485 | const llvm_kind_id = attribute.getKind().toLlvm(self); | |
| 8486 | if (llvm_kind_id.* == 0) { | |
| 6768 | 8487 | const name = @tagName(attribute); |
| 6769 | kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len); | |
| 6770 | assert(kind_id.* != 0); | |
| 8488 | llvm_kind_id.* = llvm.getEnumAttributeKindForName(name.ptr, name.len); | |
| 8489 | assert(llvm_kind_id.* != 0); | |
| 6771 | 8490 | } |
| 6772 | 8491 | break :llvm_attr switch (attribute) { |
| 6773 | 8492 | else => switch (attribute) { |
| 6774 | 8493 | inline else => |value| self.llvm.context.createEnumAttribute( |
| 6775 | kind_id.*, | |
| 8494 | llvm_kind_id.*, | |
| 6776 | 8495 | switch (@TypeOf(value)) { |
| 6777 | 8496 | void => 0, |
| 6778 | 8497 | u32 => value, |
| ... | ... | @@ -6806,7 +8525,7 @@ pub fn attr(self: *Builder, attribute: Attribute) Allocator.Error!Attribute.Inde |
| 6806 | 8525 | .inalloca, |
| 6807 | 8526 | .sret, |
| 6808 | 8527 | .elementtype, |
| 6809 | => |ty| self.llvm.context.createTypeAttribute(kind_id.*, ty.toLlvm(self)), | |
| 8528 | => |ty| self.llvm.context.createTypeAttribute(llvm_kind_id.*, ty.toLlvm(self)), | |
| 6810 | 8529 | .string, .none => unreachable, |
| 6811 | 8530 | }; |
| 6812 | 8531 | }, |
| ... | ... | @@ -6866,10 +8585,10 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo |
| 6866 | 8585 | const global_gop = self.globals.getOrPutAssumeCapacity(id); |
| 6867 | 8586 | if (!global_gop.found_existing) { |
| 6868 | 8587 | global_gop.value_ptr.* = global; |
| 6869 | global_gop.value_ptr.updateAttributes(); | |
| 6870 | const index: Global.Index = @enumFromInt(global_gop.index); | |
| 6871 | index.updateName(self); | |
| 6872 | return index; | |
| 8588 | const global_index: Global.Index = @enumFromInt(global_gop.index); | |
| 8589 | global_index.updateDsoLocal(self); | |
| 8590 | global_index.updateName(self); | |
| 8591 | return global_index; | |
| 6873 | 8592 | } |
| 6874 | 8593 | |
| 6875 | 8594 | const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name); |
| ... | ... | @@ -6883,17 +8602,221 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index { |
| 6883 | 8602 | return @enumFromInt(self.globals.getIndex(name) orelse return null); |
| 6884 | 8603 | } |
| 6885 | 8604 | |
| 8605 | pub fn addAlias( | |
| 8606 | self: *Builder, | |
| 8607 | name: String, | |
| 8608 | ty: Type, | |
| 8609 | addr_space: AddrSpace, | |
| 8610 | aliasee: Constant, | |
| 8611 | ) Allocator.Error!Alias.Index { | |
| 8612 | assert(!name.isAnon()); | |
| 8613 | try self.ensureUnusedTypeCapacity(1, NoExtra, 0); | |
| 8614 | try self.ensureUnusedGlobalCapacity(name); | |
| 8615 | try self.aliases.ensureUnusedCapacity(self.gpa, 1); | |
| 8616 | return self.addAliasAssumeCapacity(name, ty, addr_space, aliasee); | |
| 8617 | } | |
| 8618 | ||
| 8619 | pub fn addAliasAssumeCapacity( | |
| 8620 | self: *Builder, | |
| 8621 | name: String, | |
| 8622 | ty: Type, | |
| 8623 | addr_space: AddrSpace, | |
| 8624 | aliasee: Constant, | |
| 8625 | ) Alias.Index { | |
| 8626 | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity(self.llvm.module.?.addAlias( | |
| 8627 | ty.toLlvm(self), | |
| 8628 | @intFromEnum(addr_space), | |
| 8629 | aliasee.toLlvm(self), | |
| 8630 | name.slice(self).?, | |
| 8631 | )); | |
| 8632 | const alias_index: Alias.Index = @enumFromInt(self.aliases.items.len); | |
| 8633 | self.aliases.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | |
| 8634 | .addr_space = addr_space, | |
| 8635 | .type = ty, | |
| 8636 | .kind = .{ .alias = alias_index }, | |
| 8637 | }), .aliasee = aliasee }); | |
| 8638 | return alias_index; | |
| 8639 | } | |
| 8640 | ||
| 8641 | pub fn addVariable( | |
| 8642 | self: *Builder, | |
| 8643 | name: String, | |
| 8644 | ty: Type, | |
| 8645 | addr_space: AddrSpace, | |
| 8646 | ) Allocator.Error!Variable.Index { | |
| 8647 | assert(!name.isAnon()); | |
| 8648 | try self.ensureUnusedTypeCapacity(1, NoExtra, 0); | |
| 8649 | try self.ensureUnusedGlobalCapacity(name); | |
| 8650 | try self.variables.ensureUnusedCapacity(self.gpa, 1); | |
| 8651 | return self.addVariableAssumeCapacity(ty, name, addr_space); | |
| 8652 | } | |
| 8653 | ||
| 8654 | pub fn addVariableAssumeCapacity( | |
| 8655 | self: *Builder, | |
| 8656 | ty: Type, | |
| 8657 | name: String, | |
| 8658 | addr_space: AddrSpace, | |
| 8659 | ) Variable.Index { | |
| 8660 | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity( | |
| 8661 | self.llvm.module.?.addGlobalInAddressSpace( | |
| 8662 | ty.toLlvm(self), | |
| 8663 | name.slice(self).?, | |
| 8664 | @intFromEnum(addr_space), | |
| 8665 | ), | |
| 8666 | ); | |
| 8667 | const variable_index: Variable.Index = @enumFromInt(self.variables.items.len); | |
| 8668 | self.variables.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | |
| 8669 | .addr_space = addr_space, | |
| 8670 | .type = ty, | |
| 8671 | .kind = .{ .variable = variable_index }, | |
| 8672 | }) }); | |
| 8673 | return variable_index; | |
| 8674 | } | |
| 8675 | ||
| 8676 | pub fn addFunction( | |
| 8677 | self: *Builder, | |
| 8678 | ty: Type, | |
| 8679 | name: String, | |
| 8680 | addr_space: AddrSpace, | |
| 8681 | ) Allocator.Error!Function.Index { | |
| 8682 | assert(!name.isAnon()); | |
| 8683 | try self.ensureUnusedTypeCapacity(1, NoExtra, 0); | |
| 8684 | try self.ensureUnusedGlobalCapacity(name); | |
| 8685 | try self.functions.ensureUnusedCapacity(self.gpa, 1); | |
| 8686 | return self.addFunctionAssumeCapacity(ty, name, addr_space); | |
| 8687 | } | |
| 8688 | ||
| 8689 | pub fn addFunctionAssumeCapacity( | |
| 8690 | self: *Builder, | |
| 8691 | ty: Type, | |
| 8692 | name: String, | |
| 8693 | addr_space: AddrSpace, | |
| 8694 | ) Function.Index { | |
| 8695 | assert(ty.isFunction(self)); | |
| 8696 | if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity( | |
| 8697 | self.llvm.module.?.addFunctionInAddressSpace( | |
| 8698 | name.slice(self).?, | |
| 8699 | ty.toLlvm(self), | |
| 8700 | @intFromEnum(addr_space), | |
| 8701 | ), | |
| 8702 | ); | |
| 8703 | const function_index: Function.Index = @enumFromInt(self.functions.items.len); | |
| 8704 | self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ | |
| 8705 | .addr_space = addr_space, | |
| 8706 | .type = ty, | |
| 8707 | .kind = .{ .function = function_index }, | |
| 8708 | }) }); | |
| 8709 | return function_index; | |
| 8710 | } | |
| 8711 | ||
| 8712 | pub fn getIntrinsic( | |
| 8713 | self: *Builder, | |
| 8714 | id: Intrinsic, | |
| 8715 | overload: []const Type, | |
| 8716 | ) Allocator.Error!Function.Index { | |
| 8717 | const ExpectedContents = extern union { | |
| 8718 | name: [expected_intrinsic_name_len]u8, | |
| 8719 | attrs: extern struct { | |
| 8720 | params: [expected_args_len]Type, | |
| 8721 | fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, | |
| 8722 | attrs: [expected_attrs_len]Attribute.Index, | |
| 8723 | fields: [expected_fields_len]Type, | |
| 8724 | }, | |
| 8725 | }; | |
| 8726 | var stack align(@max(@alignOf(std.heap.StackFallbackAllocator(0)), @alignOf(ExpectedContents))) = | |
| 8727 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | |
| 8728 | const allocator = stack.get(); | |
| 8729 | ||
| 8730 | const name = name: { | |
| 8731 | var buffer = std.ArrayList(u8).init(allocator); | |
| 8732 | defer buffer.deinit(); | |
| 8733 | ||
| 8734 | try buffer.writer().print("llvm.{s}", .{@tagName(id)}); | |
| 8735 | for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)}); | |
| 8736 | break :name try self.string(buffer.items); | |
| 8737 | }; | |
| 8738 | if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; | |
| 8739 | ||
| 8740 | const signature = Intrinsic.signatures.get(id); | |
| 8741 | const param_types = try allocator.alloc(Type, signature.params.len); | |
| 8742 | defer allocator.free(param_types); | |
| 8743 | const function_attributes = try allocator.alloc( | |
| 8744 | Attributes, | |
| 8745 | FunctionAttributes.params_index + (signature.params.len - signature.ret_len), | |
| 8746 | ); | |
| 8747 | defer allocator.free(function_attributes); | |
| 8748 | ||
| 8749 | var attributes: struct { | |
| 8750 | builder: *Builder, | |
| 8751 | list: std.ArrayList(Attribute.Index), | |
| 8752 | ||
| 8753 | fn deinit(state: *@This()) void { | |
| 8754 | state.list.deinit(); | |
| 8755 | state.* = undefined; | |
| 8756 | } | |
| 8757 | ||
| 8758 | fn get(state: *@This(), attributes: []const Attribute) Allocator.Error!Attributes { | |
| 8759 | try state.list.resize(attributes.len); | |
| 8760 | for (state.list.items, attributes) |*item, attribute| | |
| 8761 | item.* = try state.builder.attr(attribute); | |
| 8762 | return state.builder.attrs(state.list.items); | |
| 8763 | } | |
| 8764 | } = .{ .builder = self, .list = std.ArrayList(Attribute.Index).init(allocator) }; | |
| 8765 | defer attributes.deinit(); | |
| 8766 | ||
| 8767 | var overload_index: usize = 0; | |
| 8768 | function_attributes[FunctionAttributes.function_index] = try attributes.get(signature.attrs); | |
| 8769 | function_attributes[FunctionAttributes.return_index] = .none; // needed for void return | |
| 8770 | for (0.., param_types, signature.params) |param_index, *param_type, signature_param| { | |
| 8771 | switch (signature_param.kind) { | |
| 8772 | .type => |ty| param_type.* = ty, | |
| 8773 | .overloaded => { | |
| 8774 | param_type.* = overload[overload_index]; | |
| 8775 | overload_index += 1; | |
| 8776 | }, | |
| 8777 | .matches, .matches_scalar, .matches_changed_scalar => {}, | |
| 8778 | } | |
| 8779 | function_attributes[ | |
| 8780 | if (param_index < signature.ret_len) | |
| 8781 | FunctionAttributes.return_index | |
| 8782 | else | |
| 8783 | FunctionAttributes.params_index + (param_index - signature.ret_len) | |
| 8784 | ] = try attributes.get(signature_param.attrs); | |
| 8785 | } | |
| 8786 | assert(overload_index == overload.len); | |
| 8787 | for (param_types, signature.params) |*param_type, signature_param| { | |
| 8788 | param_type.* = switch (signature_param.kind) { | |
| 8789 | .type, .overloaded => continue, | |
| 8790 | .matches => |param_index| param_types[param_index], | |
| 8791 | .matches_scalar => |param_index| param_types[param_index].scalarType(self), | |
| 8792 | .matches_changed_scalar => |info| try param_types[info.index] | |
| 8793 | .changeScalar(info.scalar, self), | |
| 8794 | }; | |
| 8795 | } | |
| 8796 | ||
| 8797 | const function_index = try self.addFunction(try self.fnType(switch (signature.ret_len) { | |
| 8798 | 0 => .void, | |
| 8799 | 1 => param_types[0], | |
| 8800 | else => try self.structType(.normal, param_types[0..signature.ret_len]), | |
| 8801 | }, param_types[signature.ret_len..], .normal), name, .default); | |
| 8802 | function_index.ptr(self).attributes = try self.fnAttrs(function_attributes); | |
| 8803 | return function_index; | |
| 8804 | } | |
| 8805 | ||
| 6886 | 8806 | pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant { |
| 8807 | const int_value = switch (@typeInfo(@TypeOf(value))) { | |
| 8808 | .Int, .ComptimeInt => value, | |
| 8809 | .Enum => @intFromEnum(value), | |
| 8810 | else => @compileError("intConst expected an integral value, got " ++ @typeName(@TypeOf(value))), | |
| 8811 | }; | |
| 6887 | 8812 | var limbs: [ |
| 6888 | switch (@typeInfo(@TypeOf(value))) { | |
| 8813 | switch (@typeInfo(@TypeOf(int_value))) { | |
| 6889 | 8814 | .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 6890 | .ComptimeInt => std.math.big.int.calcLimbLen(value), | |
| 6891 | else => @compileError( | |
| 6892 | "intConst expected an integral value, got " ++ @typeName(@TypeOf(value)), | |
| 6893 | ), | |
| 8815 | .ComptimeInt => std.math.big.int.calcLimbLen(int_value), | |
| 8816 | else => unreachable, | |
| 6894 | 8817 | } |
| 6895 | 8818 | ]std.math.big.Limb = undefined; |
| 6896 | return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, value).toConst()); | |
| 8819 | return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, int_value).toConst()); | |
| 6897 | 8820 | } |
| 6898 | 8821 | |
| 6899 | 8822 | pub fn intValue(self: *Builder, ty: Type, value: anytype) Allocator.Error!Value { |
| ... | ... | @@ -7301,27 +9224,75 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant) |
| 7301 | 9224 | return (try self.binConst(tag, lhs, rhs)).toValue(); |
| 7302 | 9225 | } |
| 7303 | 9226 | |
| 9227 | pub fn selectConst( | |
| 9228 | self: *Builder, | |
| 9229 | cond: Constant, | |
| 9230 | lhs: Constant, | |
| 9231 | rhs: Constant, | |
| 9232 | ) Allocator.Error!Constant { | |
| 9233 | try self.ensureUnusedConstantCapacity(1, Constant.Select, 0); | |
| 9234 | return self.selectConstAssumeCapacity(cond, lhs, rhs); | |
| 9235 | } | |
| 9236 | ||
| 9237 | pub fn selectValue(self: *Builder, cond: Constant, lhs: Constant, rhs: Constant) Allocator.Error!Value { | |
| 9238 | return (try self.selectConst(cond, lhs, rhs)).toValue(); | |
| 9239 | } | |
| 9240 | ||
| 7304 | 9241 | pub fn asmConst( |
| 7305 | 9242 | self: *Builder, |
| 7306 | 9243 | ty: Type, |
| 7307 | info: Constant.Asm.Info, | |
| 9244 | info: Constant.Assembly.Info, | |
| 7308 | 9245 | assembly: String, |
| 7309 | 9246 | constraints: String, |
| 7310 | 9247 | ) Allocator.Error!Constant { |
| 7311 | try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0); | |
| 9248 | try self.ensureUnusedConstantCapacity(1, Constant.Assembly, 0); | |
| 7312 | 9249 | return self.asmConstAssumeCapacity(ty, info, assembly, constraints); |
| 7313 | 9250 | } |
| 7314 | 9251 | |
| 7315 | 9252 | pub fn asmValue( |
| 7316 | 9253 | self: *Builder, |
| 7317 | 9254 | ty: Type, |
| 7318 | info: Constant.Asm.Info, | |
| 9255 | info: Constant.Assembly.Info, | |
| 7319 | 9256 | assembly: String, |
| 7320 | 9257 | constraints: String, |
| 7321 | 9258 | ) Allocator.Error!Value { |
| 7322 | 9259 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); |
| 7323 | 9260 | } |
| 7324 | 9261 | |
| 9262 | pub fn verify(self: *Builder) error{}!bool { | |
| 9263 | if (self.useLibLlvm()) { | |
| 9264 | var error_message: [*:0]const u8 = undefined; | |
| 9265 | // verifyModule always allocs the error_message even if there is no error | |
| 9266 | defer llvm.disposeMessage(error_message); | |
| 9267 | ||
| 9268 | if (self.llvm.module.?.verify(.ReturnStatus, &error_message).toBool()) { | |
| 9269 | log.err("failed verification of LLVM module:\n{s}\n", .{error_message}); | |
| 9270 | return false; | |
| 9271 | } | |
| 9272 | } | |
| 9273 | return true; | |
| 9274 | } | |
| 9275 | ||
| 9276 | pub fn writeBitcodeToFile(self: *Builder, path: []const u8) Allocator.Error!bool { | |
| 9277 | const path_z = try self.gpa.dupeZ(u8, path); | |
| 9278 | defer self.gpa.free(path_z); | |
| 9279 | return self.writeBitcodeToFileZ(path_z); | |
| 9280 | } | |
| 9281 | ||
| 9282 | pub fn writeBitcodeToFileZ(self: *Builder, path: [*:0]const u8) bool { | |
| 9283 | if (self.useLibLlvm()) { | |
| 9284 | const error_code = self.llvm.module.?.writeBitcodeToFile(path); | |
| 9285 | if (error_code != 0) { | |
| 9286 | log.err("failed dumping LLVM module to \"{s}\": {d}", .{ path, error_code }); | |
| 9287 | return false; | |
| 9288 | } | |
| 9289 | } else { | |
| 9290 | log.err("writing bitcode without libllvm not implemented", .{}); | |
| 9291 | return false; | |
| 9292 | } | |
| 9293 | return true; | |
| 9294 | } | |
| 9295 | ||
| 7325 | 9296 | pub fn dump(self: *Builder) void { |
| 7326 | 9297 | if (self.useLibLlvm()) |
| 7327 | 9298 | self.llvm.module.?.dump() |
| ... | ... | @@ -7413,7 +9384,7 @@ pub fn printUnbuffered( |
| 7413 | 9384 | if (variable.global.getReplacement(self) != .none) continue; |
| 7414 | 9385 | const global = variable.global.ptrConst(self); |
| 7415 | 9386 | try writer.print( |
| 7416 | \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,} | |
| 9387 | \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, } | |
| 7417 | 9388 | \\ |
| 7418 | 9389 | , .{ |
| 7419 | 9390 | variable.global.fmt(self), |
| ... | ... | @@ -7434,557 +9405,521 @@ pub fn printUnbuffered( |
| 7434 | 9405 | need_newline = true; |
| 7435 | 9406 | } |
| 7436 | 9407 | |
| 7437 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; | |
| 7438 | defer attribute_groups.deinit(self.gpa); | |
| 7439 | ||
| 7440 | if (self.functions.items.len > 0) { | |
| 9408 | if (self.aliases.items.len > 0) { | |
| 7441 | 9409 | if (need_newline) try writer.writeByte('\n'); |
| 7442 | for (0.., self.functions.items) |function_i, function| { | |
| 7443 | if (function_i > 0) try writer.writeByte('\n'); | |
| 7444 | const function_index: Function.Index = @enumFromInt(function_i); | |
| 7445 | if (function.global.getReplacement(self) != .none) continue; | |
| 7446 | const global = function.global.ptrConst(self); | |
| 7447 | const params_len = global.type.functionParameters(self).len; | |
| 7448 | const function_attributes = function.attributes.func(self); | |
| 7449 | if (function_attributes != .none) try writer.print( | |
| 7450 | \\; Function Attrs:{} | |
| 7451 | \\ | |
| 7452 | , .{function_attributes.fmt(self)}); | |
| 9410 | for (self.aliases.items) |alias| { | |
| 9411 | if (alias.global.getReplacement(self) != .none) continue; | |
| 9412 | const global = alias.global.ptrConst(self); | |
| 7453 | 9413 | try writer.print( |
| 7454 | \\{s}{}{}{}{}{}{"} {} {}( | |
| 9414 | \\{} ={}{}{}{}{ }{} alias {%}, {%} | |
| 9415 | \\ | |
| 7455 | 9416 | , .{ |
| 7456 | if (function.instructions.len > 0) "define" else "declare", | |
| 9417 | alias.global.fmt(self), | |
| 7457 | 9418 | global.linkage, |
| 7458 | 9419 | global.preemption, |
| 7459 | 9420 | global.visibility, |
| 7460 | 9421 | global.dll_storage_class, |
| 7461 | function.call_conv, | |
| 7462 | function.attributes.ret(self).fmt(self), | |
| 7463 | global.type.functionReturn(self).fmt(self), | |
| 7464 | function.global.fmt(self), | |
| 9422 | alias.thread_local, | |
| 9423 | global.unnamed_addr, | |
| 9424 | global.type.fmt(self), | |
| 9425 | alias.aliasee.fmt(self), | |
| 7465 | 9426 | }); |
| 7466 | for (0..params_len) |arg| { | |
| 7467 | if (arg > 0) try writer.writeAll(", "); | |
| 7468 | try writer.print( | |
| 7469 | \\{%}{"} | |
| 7470 | , .{ | |
| 7471 | global.type.functionParameters(self)[arg].fmt(self), | |
| 7472 | function.attributes.param(arg, self).fmt(self), | |
| 7473 | }); | |
| 7474 | if (function.instructions.len > 0) | |
| 7475 | try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}); | |
| 7476 | } | |
| 7477 | switch (global.type.functionKind(self)) { | |
| 7478 | .normal => {}, | |
| 7479 | .vararg => { | |
| 7480 | if (params_len > 0) try writer.writeAll(", "); | |
| 7481 | try writer.writeAll("..."); | |
| 7482 | }, | |
| 7483 | } | |
| 7484 | try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space }); | |
| 7485 | if (function_attributes != .none) try writer.print(" #{d}", .{ | |
| 7486 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, | |
| 9427 | } | |
| 9428 | need_newline = true; | |
| 9429 | } | |
| 9430 | ||
| 9431 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; | |
| 9432 | defer attribute_groups.deinit(self.gpa); | |
| 9433 | ||
| 9434 | for (0.., self.functions.items) |function_i, function| { | |
| 9435 | if (function.global.getReplacement(self) != .none) continue; | |
| 9436 | if (need_newline) try writer.writeByte('\n'); | |
| 9437 | const function_index: Function.Index = @enumFromInt(function_i); | |
| 9438 | const global = function.global.ptrConst(self); | |
| 9439 | const params_len = global.type.functionParameters(self).len; | |
| 9440 | const function_attributes = function.attributes.func(self); | |
| 9441 | if (function_attributes != .none) try writer.print( | |
| 9442 | \\; Function Attrs:{} | |
| 9443 | \\ | |
| 9444 | , .{function_attributes.fmt(self)}); | |
| 9445 | try writer.print( | |
| 9446 | \\{s}{}{}{}{}{}{"} {} {}( | |
| 9447 | , .{ | |
| 9448 | if (function.instructions.len > 0) "define" else "declare", | |
| 9449 | global.linkage, | |
| 9450 | global.preemption, | |
| 9451 | global.visibility, | |
| 9452 | global.dll_storage_class, | |
| 9453 | function.call_conv, | |
| 9454 | function.attributes.ret(self).fmt(self), | |
| 9455 | global.type.functionReturn(self).fmt(self), | |
| 9456 | function.global.fmt(self), | |
| 9457 | }); | |
| 9458 | for (0..params_len) |arg| { | |
| 9459 | if (arg > 0) try writer.writeAll(", "); | |
| 9460 | try writer.print( | |
| 9461 | \\{%}{"} | |
| 9462 | , .{ | |
| 9463 | global.type.functionParameters(self)[arg].fmt(self), | |
| 9464 | function.attributes.param(arg, self).fmt(self), | |
| 7487 | 9465 | }); |
| 7488 | try writer.print("{}", .{function.alignment}); | |
| 7489 | if (function.instructions.len > 0) { | |
| 7490 | var block_incoming_len: u32 = undefined; | |
| 7491 | try writer.writeAll(" {\n"); | |
| 7492 | for (params_len..function.instructions.len) |instruction_i| { | |
| 7493 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); | |
| 7494 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); | |
| 7495 | switch (instruction.tag) { | |
| 7496 | .add, | |
| 7497 | .@"add nsw", | |
| 7498 | .@"add nuw", | |
| 7499 | .@"add nuw nsw", | |
| 7500 | .@"and", | |
| 7501 | .ashr, | |
| 7502 | .@"ashr exact", | |
| 7503 | .fadd, | |
| 7504 | .@"fadd fast", | |
| 7505 | .@"fcmp false", | |
| 7506 | .@"fcmp fast false", | |
| 7507 | .@"fcmp fast oeq", | |
| 7508 | .@"fcmp fast oge", | |
| 7509 | .@"fcmp fast ogt", | |
| 7510 | .@"fcmp fast ole", | |
| 7511 | .@"fcmp fast olt", | |
| 7512 | .@"fcmp fast one", | |
| 7513 | .@"fcmp fast ord", | |
| 7514 | .@"fcmp fast true", | |
| 7515 | .@"fcmp fast ueq", | |
| 7516 | .@"fcmp fast uge", | |
| 7517 | .@"fcmp fast ugt", | |
| 7518 | .@"fcmp fast ule", | |
| 7519 | .@"fcmp fast ult", | |
| 7520 | .@"fcmp fast une", | |
| 7521 | .@"fcmp fast uno", | |
| 7522 | .@"fcmp oeq", | |
| 7523 | .@"fcmp oge", | |
| 7524 | .@"fcmp ogt", | |
| 7525 | .@"fcmp ole", | |
| 7526 | .@"fcmp olt", | |
| 7527 | .@"fcmp one", | |
| 7528 | .@"fcmp ord", | |
| 7529 | .@"fcmp true", | |
| 7530 | .@"fcmp ueq", | |
| 7531 | .@"fcmp uge", | |
| 7532 | .@"fcmp ugt", | |
| 7533 | .@"fcmp ule", | |
| 7534 | .@"fcmp ult", | |
| 7535 | .@"fcmp une", | |
| 7536 | .@"fcmp uno", | |
| 7537 | .fdiv, | |
| 7538 | .@"fdiv fast", | |
| 7539 | .fmul, | |
| 7540 | .@"fmul fast", | |
| 7541 | .frem, | |
| 7542 | .@"frem fast", | |
| 7543 | .fsub, | |
| 7544 | .@"fsub fast", | |
| 7545 | .@"icmp eq", | |
| 7546 | .@"icmp ne", | |
| 7547 | .@"icmp sge", | |
| 7548 | .@"icmp sgt", | |
| 7549 | .@"icmp sle", | |
| 7550 | .@"icmp slt", | |
| 7551 | .@"icmp uge", | |
| 7552 | .@"icmp ugt", | |
| 7553 | .@"icmp ule", | |
| 7554 | .@"icmp ult", | |
| 7555 | .lshr, | |
| 7556 | .@"lshr exact", | |
| 7557 | .mul, | |
| 7558 | .@"mul nsw", | |
| 7559 | .@"mul nuw", | |
| 7560 | .@"mul nuw nsw", | |
| 7561 | .@"or", | |
| 7562 | .sdiv, | |
| 7563 | .@"sdiv exact", | |
| 7564 | .srem, | |
| 7565 | .shl, | |
| 7566 | .@"shl nsw", | |
| 7567 | .@"shl nuw", | |
| 7568 | .@"shl nuw nsw", | |
| 7569 | .sub, | |
| 7570 | .@"sub nsw", | |
| 7571 | .@"sub nuw", | |
| 7572 | .@"sub nuw nsw", | |
| 7573 | .udiv, | |
| 7574 | .@"udiv exact", | |
| 7575 | .urem, | |
| 7576 | .xor, | |
| 7577 | => |tag| { | |
| 7578 | const extra = | |
| 7579 | function.extraData(Function.Instruction.Binary, instruction.data); | |
| 7580 | try writer.print(" %{} = {s} {%}, {}\n", .{ | |
| 7581 | instruction_index.name(&function).fmt(self), | |
| 7582 | @tagName(tag), | |
| 7583 | extra.lhs.fmt(function_index, self), | |
| 7584 | extra.rhs.fmt(function_index, self), | |
| 7585 | }); | |
| 7586 | }, | |
| 7587 | .addrspacecast, | |
| 7588 | .bitcast, | |
| 7589 | .fpext, | |
| 7590 | .fptosi, | |
| 7591 | .fptoui, | |
| 7592 | .fptrunc, | |
| 7593 | .inttoptr, | |
| 7594 | .ptrtoint, | |
| 7595 | .sext, | |
| 7596 | .sitofp, | |
| 7597 | .trunc, | |
| 7598 | .uitofp, | |
| 7599 | .zext, | |
| 7600 | => |tag| { | |
| 7601 | const extra = | |
| 7602 | function.extraData(Function.Instruction.Cast, instruction.data); | |
| 7603 | try writer.print(" %{} = {s} {%} to {%}\n", .{ | |
| 7604 | instruction_index.name(&function).fmt(self), | |
| 7605 | @tagName(tag), | |
| 7606 | extra.val.fmt(function_index, self), | |
| 7607 | extra.type.fmt(self), | |
| 7608 | }); | |
| 7609 | }, | |
| 7610 | .alloca, | |
| 7611 | .@"alloca inalloca", | |
| 7612 | => |tag| { | |
| 7613 | const extra = | |
| 7614 | function.extraData(Function.Instruction.Alloca, instruction.data); | |
| 7615 | try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{ | |
| 7616 | instruction_index.name(&function).fmt(self), | |
| 7617 | @tagName(tag), | |
| 7618 | extra.type.fmt(self), | |
| 7619 | extra.len.fmt(function_index, self), | |
| 7620 | extra.info.alignment, | |
| 7621 | extra.info.addr_space, | |
| 7622 | }); | |
| 7623 | }, | |
| 7624 | .arg => unreachable, | |
| 7625 | .block => { | |
| 7626 | block_incoming_len = instruction.data; | |
| 7627 | const name = instruction_index.name(&function); | |
| 7628 | if (@intFromEnum(instruction_index) > params_len) | |
| 7629 | try writer.writeByte('\n'); | |
| 7630 | try writer.print("{}:\n", .{name.fmt(self)}); | |
| 7631 | }, | |
| 7632 | .br => |tag| { | |
| 7633 | const target: Function.Block.Index = @enumFromInt(instruction.data); | |
| 7634 | try writer.print(" {s} {%}\n", .{ | |
| 7635 | @tagName(tag), target.toInst(&function).fmt(function_index, self), | |
| 7636 | }); | |
| 7637 | }, | |
| 7638 | .br_cond => { | |
| 7639 | const extra = | |
| 7640 | function.extraData(Function.Instruction.BrCond, instruction.data); | |
| 7641 | try writer.print(" br {%}, {%}, {%}\n", .{ | |
| 7642 | extra.cond.fmt(function_index, self), | |
| 7643 | extra.then.toInst(&function).fmt(function_index, self), | |
| 7644 | extra.@"else".toInst(&function).fmt(function_index, self), | |
| 7645 | }); | |
| 7646 | }, | |
| 7647 | .call, | |
| 7648 | .@"call fast", | |
| 7649 | .@"musttail call", | |
| 7650 | .@"musttail call fast", | |
| 7651 | .@"notail call", | |
| 7652 | .@"notail call fast", | |
| 7653 | .@"tail call", | |
| 7654 | .@"tail call fast", | |
| 7655 | => |tag| { | |
| 7656 | var extra = | |
| 7657 | function.extraDataTrail(Function.Instruction.Call, instruction.data); | |
| 7658 | const args = extra.trail.next(extra.data.args_len, Value, &function); | |
| 7659 | try writer.writeAll(" "); | |
| 7660 | const ret_ty = extra.data.ty.functionReturn(self); | |
| 7661 | switch (ret_ty) { | |
| 7662 | .void => {}, | |
| 7663 | else => try writer.print("%{} = ", .{ | |
| 7664 | instruction_index.name(&function).fmt(self), | |
| 7665 | }), | |
| 7666 | .none => unreachable, | |
| 7667 | } | |
| 7668 | try writer.print("{s}{}{}{} {%} {}(", .{ | |
| 7669 | @tagName(tag), | |
| 7670 | extra.data.info.call_conv, | |
| 7671 | extra.data.attributes.ret(self).fmt(self), | |
| 7672 | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), | |
| 7673 | switch (extra.data.ty.functionKind(self)) { | |
| 7674 | .normal => ret_ty, | |
| 7675 | .vararg => extra.data.ty, | |
| 7676 | }.fmt(self), | |
| 7677 | extra.data.callee.fmt(function_index, self), | |
| 7678 | }); | |
| 7679 | for (0.., args) |arg_index, arg| { | |
| 7680 | if (arg_index > 0) try writer.writeAll(", "); | |
| 7681 | try writer.print("{%}{} {}", .{ | |
| 7682 | arg.typeOf(function_index, self).fmt(self), | |
| 7683 | extra.data.attributes.param(arg_index, self).fmt(self), | |
| 7684 | arg.fmt(function_index, self), | |
| 7685 | }); | |
| 7686 | } | |
| 7687 | try writer.writeByte(')'); | |
| 7688 | const call_function_attributes = extra.data.attributes.func(self); | |
| 7689 | if (call_function_attributes != .none) try writer.print(" #{d}", .{ | |
| 7690 | (try attribute_groups.getOrPutValue( | |
| 7691 | self.gpa, | |
| 7692 | call_function_attributes, | |
| 7693 | {}, | |
| 7694 | )).index, | |
| 7695 | }); | |
| 7696 | try writer.writeByte('\n'); | |
| 7697 | }, | |
| 7698 | .extractelement => |tag| { | |
| 7699 | const extra = function.extraData( | |
| 7700 | Function.Instruction.ExtractElement, | |
| 7701 | instruction.data, | |
| 7702 | ); | |
| 7703 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | |
| 7704 | instruction_index.name(&function).fmt(self), | |
| 7705 | @tagName(tag), | |
| 7706 | extra.val.fmt(function_index, self), | |
| 7707 | extra.index.fmt(function_index, self), | |
| 7708 | }); | |
| 7709 | }, | |
| 7710 | .extractvalue => |tag| { | |
| 7711 | var extra = function.extraDataTrail( | |
| 7712 | Function.Instruction.ExtractValue, | |
| 7713 | instruction.data, | |
| 7714 | ); | |
| 7715 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); | |
| 7716 | try writer.print(" %{} = {s} {%}", .{ | |
| 7717 | instruction_index.name(&function).fmt(self), | |
| 7718 | @tagName(tag), | |
| 7719 | extra.data.val.fmt(function_index, self), | |
| 7720 | }); | |
| 7721 | for (indices) |index| try writer.print(", {d}", .{index}); | |
| 7722 | try writer.writeByte('\n'); | |
| 7723 | }, | |
| 7724 | .fence => |tag| { | |
| 7725 | const info: MemoryAccessInfo = @bitCast(instruction.data); | |
| 7726 | try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering }); | |
| 7727 | }, | |
| 7728 | .fneg, | |
| 7729 | .@"fneg fast", | |
| 7730 | .ret, | |
| 7731 | .@"llvm.ceil.", | |
| 7732 | .@"llvm.cos.", | |
| 7733 | .@"llvm.exp.", | |
| 7734 | .@"llvm.exp2.", | |
| 7735 | .@"llvm.fabs.", | |
| 7736 | .@"llvm.floor.", | |
| 7737 | .@"llvm.log.", | |
| 7738 | .@"llvm.log10.", | |
| 7739 | .@"llvm.log2.", | |
| 7740 | .@"llvm.round.", | |
| 7741 | .@"llvm.sin.", | |
| 7742 | .@"llvm.sqrt.", | |
| 7743 | .@"llvm.trunc.", | |
| 7744 | .@"llvm.bitreverse.", | |
| 7745 | .@"llvm.bswap.", | |
| 7746 | .@"llvm.ctpop.", | |
| 7747 | => |tag| { | |
| 7748 | const val: Value = @enumFromInt(instruction.data); | |
| 7749 | try writer.print(" {s} {%}\n", .{ | |
| 7750 | @tagName(tag), | |
| 7751 | val.fmt(function_index, self), | |
| 7752 | }); | |
| 7753 | }, | |
| 7754 | .getelementptr, | |
| 7755 | .@"getelementptr inbounds", | |
| 7756 | => |tag| { | |
| 7757 | var extra = function.extraDataTrail( | |
| 7758 | Function.Instruction.GetElementPtr, | |
| 7759 | instruction.data, | |
| 7760 | ); | |
| 7761 | const indices = extra.trail.next(extra.data.indices_len, Value, &function); | |
| 7762 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 7763 | instruction_index.name(&function).fmt(self), | |
| 7764 | @tagName(tag), | |
| 7765 | extra.data.type.fmt(self), | |
| 7766 | extra.data.base.fmt(function_index, self), | |
| 7767 | }); | |
| 7768 | for (indices) |index| try writer.print(", {%}", .{ | |
| 7769 | index.fmt(function_index, self), | |
| 7770 | }); | |
| 7771 | try writer.writeByte('\n'); | |
| 7772 | }, | |
| 7773 | .insertelement => |tag| { | |
| 7774 | const extra = function.extraData( | |
| 7775 | Function.Instruction.InsertElement, | |
| 7776 | instruction.data, | |
| 7777 | ); | |
| 7778 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 7779 | instruction_index.name(&function).fmt(self), | |
| 7780 | @tagName(tag), | |
| 7781 | extra.val.fmt(function_index, self), | |
| 7782 | extra.elem.fmt(function_index, self), | |
| 7783 | extra.index.fmt(function_index, self), | |
| 7784 | }); | |
| 7785 | }, | |
| 7786 | .insertvalue => |tag| { | |
| 7787 | var extra = function.extraDataTrail( | |
| 7788 | Function.Instruction.InsertValue, | |
| 7789 | instruction.data, | |
| 7790 | ); | |
| 7791 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); | |
| 7792 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 7793 | instruction_index.name(&function).fmt(self), | |
| 7794 | @tagName(tag), | |
| 7795 | extra.data.val.fmt(function_index, self), | |
| 7796 | extra.data.elem.fmt(function_index, self), | |
| 7797 | }); | |
| 7798 | for (indices) |index| try writer.print(", {d}", .{index}); | |
| 7799 | try writer.writeByte('\n'); | |
| 7800 | }, | |
| 7801 | .@"llvm.maxnum.", | |
| 7802 | .@"llvm.minnum.", | |
| 7803 | .@"llvm.ctlz.", | |
| 7804 | .@"llvm.cttz.", | |
| 7805 | .@"llvm.sadd.sat.", | |
| 7806 | .@"llvm.smax.", | |
| 7807 | .@"llvm.smin.", | |
| 7808 | .@"llvm.smul.fix.sat.", | |
| 7809 | .@"llvm.sshl.sat.", | |
| 7810 | .@"llvm.ssub.sat.", | |
| 7811 | .@"llvm.uadd.sat.", | |
| 7812 | .@"llvm.umax.", | |
| 7813 | .@"llvm.umin.", | |
| 7814 | .@"llvm.umul.fix.sat.", | |
| 7815 | .@"llvm.ushl.sat.", | |
| 7816 | .@"llvm.usub.sat.", | |
| 7817 | => |tag| { | |
| 7818 | const extra = | |
| 7819 | function.extraData(Function.Instruction.Binary, instruction.data); | |
| 7820 | const ty = instruction_index.typeOf(function_index, self); | |
| 7821 | try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{ | |
| 7822 | instruction_index.name(&function).fmt(self), | |
| 7823 | ty.fmt(self), | |
| 7824 | @tagName(tag), | |
| 7825 | ty.fmt(self), | |
| 7826 | extra.lhs.fmt(function_index, self), | |
| 7827 | extra.rhs.fmt(function_index, self), | |
| 7828 | switch (tag) { | |
| 7829 | .@"llvm.smul.fix.sat.", | |
| 7830 | .@"llvm.umul.fix.sat.", | |
| 7831 | => ", i32 0", | |
| 7832 | else => "", | |
| 7833 | }, | |
| 7834 | }); | |
| 7835 | }, | |
| 7836 | .load, | |
| 7837 | .@"load atomic", | |
| 7838 | .@"load atomic volatile", | |
| 7839 | .@"load volatile", | |
| 7840 | => |tag| { | |
| 7841 | const extra = | |
| 7842 | function.extraData(Function.Instruction.Load, instruction.data); | |
| 7843 | try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{ | |
| 7844 | instruction_index.name(&function).fmt(self), | |
| 7845 | @tagName(tag), | |
| 7846 | extra.type.fmt(self), | |
| 7847 | extra.ptr.fmt(function_index, self), | |
| 7848 | extra.info.scope, | |
| 7849 | extra.info.ordering, | |
| 7850 | extra.info.alignment, | |
| 7851 | }); | |
| 7852 | }, | |
| 7853 | .phi, | |
| 7854 | .@"phi fast", | |
| 7855 | => |tag| { | |
| 7856 | var extra = | |
| 7857 | function.extraDataTrail(Function.Instruction.Phi, instruction.data); | |
| 7858 | const vals = extra.trail.next(block_incoming_len, Value, &function); | |
| 7859 | const blocks = | |
| 7860 | extra.trail.next(block_incoming_len, Function.Block.Index, &function); | |
| 7861 | try writer.print(" %{} = {s} {%} ", .{ | |
| 7862 | instruction_index.name(&function).fmt(self), | |
| 7863 | @tagName(tag), | |
| 7864 | vals[0].typeOf(function_index, self).fmt(self), | |
| 7865 | }); | |
| 7866 | for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { | |
| 7867 | if (incoming_index > 0) try writer.writeAll(", "); | |
| 7868 | try writer.print("[ {}, {} ]", .{ | |
| 7869 | incoming_val.fmt(function_index, self), | |
| 7870 | incoming_block.toInst(&function).fmt(function_index, self), | |
| 7871 | }); | |
| 7872 | } | |
| 9466 | if (function.instructions.len > 0) | |
| 9467 | try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}) | |
| 9468 | else | |
| 9469 | try writer.print(" %{d}", .{arg}); | |
| 9470 | } | |
| 9471 | switch (global.type.functionKind(self)) { | |
| 9472 | .normal => {}, | |
| 9473 | .vararg => { | |
| 9474 | if (params_len > 0) try writer.writeAll(", "); | |
| 9475 | try writer.writeAll("..."); | |
| 9476 | }, | |
| 9477 | } | |
| 9478 | try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space }); | |
| 9479 | if (function_attributes != .none) try writer.print(" #{d}", .{ | |
| 9480 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, | |
| 9481 | }); | |
| 9482 | try writer.print("{ }", .{function.alignment}); | |
| 9483 | if (function.instructions.len > 0) { | |
| 9484 | var block_incoming_len: u32 = undefined; | |
| 9485 | try writer.writeAll(" {\n"); | |
| 9486 | for (params_len..function.instructions.len) |instruction_i| { | |
| 9487 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); | |
| 9488 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); | |
| 9489 | switch (instruction.tag) { | |
| 9490 | .add, | |
| 9491 | .@"add nsw", | |
| 9492 | .@"add nuw", | |
| 9493 | .@"add nuw nsw", | |
| 9494 | .@"and", | |
| 9495 | .ashr, | |
| 9496 | .@"ashr exact", | |
| 9497 | .fadd, | |
| 9498 | .@"fadd fast", | |
| 9499 | .@"fcmp false", | |
| 9500 | .@"fcmp fast false", | |
| 9501 | .@"fcmp fast oeq", | |
| 9502 | .@"fcmp fast oge", | |
| 9503 | .@"fcmp fast ogt", | |
| 9504 | .@"fcmp fast ole", | |
| 9505 | .@"fcmp fast olt", | |
| 9506 | .@"fcmp fast one", | |
| 9507 | .@"fcmp fast ord", | |
| 9508 | .@"fcmp fast true", | |
| 9509 | .@"fcmp fast ueq", | |
| 9510 | .@"fcmp fast uge", | |
| 9511 | .@"fcmp fast ugt", | |
| 9512 | .@"fcmp fast ule", | |
| 9513 | .@"fcmp fast ult", | |
| 9514 | .@"fcmp fast une", | |
| 9515 | .@"fcmp fast uno", | |
| 9516 | .@"fcmp oeq", | |
| 9517 | .@"fcmp oge", | |
| 9518 | .@"fcmp ogt", | |
| 9519 | .@"fcmp ole", | |
| 9520 | .@"fcmp olt", | |
| 9521 | .@"fcmp one", | |
| 9522 | .@"fcmp ord", | |
| 9523 | .@"fcmp true", | |
| 9524 | .@"fcmp ueq", | |
| 9525 | .@"fcmp uge", | |
| 9526 | .@"fcmp ugt", | |
| 9527 | .@"fcmp ule", | |
| 9528 | .@"fcmp ult", | |
| 9529 | .@"fcmp une", | |
| 9530 | .@"fcmp uno", | |
| 9531 | .fdiv, | |
| 9532 | .@"fdiv fast", | |
| 9533 | .fmul, | |
| 9534 | .@"fmul fast", | |
| 9535 | .frem, | |
| 9536 | .@"frem fast", | |
| 9537 | .fsub, | |
| 9538 | .@"fsub fast", | |
| 9539 | .@"icmp eq", | |
| 9540 | .@"icmp ne", | |
| 9541 | .@"icmp sge", | |
| 9542 | .@"icmp sgt", | |
| 9543 | .@"icmp sle", | |
| 9544 | .@"icmp slt", | |
| 9545 | .@"icmp uge", | |
| 9546 | .@"icmp ugt", | |
| 9547 | .@"icmp ule", | |
| 9548 | .@"icmp ult", | |
| 9549 | .lshr, | |
| 9550 | .@"lshr exact", | |
| 9551 | .mul, | |
| 9552 | .@"mul nsw", | |
| 9553 | .@"mul nuw", | |
| 9554 | .@"mul nuw nsw", | |
| 9555 | .@"or", | |
| 9556 | .sdiv, | |
| 9557 | .@"sdiv exact", | |
| 9558 | .srem, | |
| 9559 | .shl, | |
| 9560 | .@"shl nsw", | |
| 9561 | .@"shl nuw", | |
| 9562 | .@"shl nuw nsw", | |
| 9563 | .sub, | |
| 9564 | .@"sub nsw", | |
| 9565 | .@"sub nuw", | |
| 9566 | .@"sub nuw nsw", | |
| 9567 | .udiv, | |
| 9568 | .@"udiv exact", | |
| 9569 | .urem, | |
| 9570 | .xor, | |
| 9571 | => |tag| { | |
| 9572 | const extra = function.extraData(Function.Instruction.Binary, instruction.data); | |
| 9573 | try writer.print(" %{} = {s} {%}, {}\n", .{ | |
| 9574 | instruction_index.name(&function).fmt(self), | |
| 9575 | @tagName(tag), | |
| 9576 | extra.lhs.fmt(function_index, self), | |
| 9577 | extra.rhs.fmt(function_index, self), | |
| 9578 | }); | |
| 9579 | }, | |
| 9580 | .addrspacecast, | |
| 9581 | .bitcast, | |
| 9582 | .fpext, | |
| 9583 | .fptosi, | |
| 9584 | .fptoui, | |
| 9585 | .fptrunc, | |
| 9586 | .inttoptr, | |
| 9587 | .ptrtoint, | |
| 9588 | .sext, | |
| 9589 | .sitofp, | |
| 9590 | .trunc, | |
| 9591 | .uitofp, | |
| 9592 | .zext, | |
| 9593 | => |tag| { | |
| 9594 | const extra = function.extraData(Function.Instruction.Cast, instruction.data); | |
| 9595 | try writer.print(" %{} = {s} {%} to {%}\n", .{ | |
| 9596 | instruction_index.name(&function).fmt(self), | |
| 9597 | @tagName(tag), | |
| 9598 | extra.val.fmt(function_index, self), | |
| 9599 | extra.type.fmt(self), | |
| 9600 | }); | |
| 9601 | }, | |
| 9602 | .alloca, | |
| 9603 | .@"alloca inalloca", | |
| 9604 | => |tag| { | |
| 9605 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); | |
| 9606 | try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{ | |
| 9607 | instruction_index.name(&function).fmt(self), | |
| 9608 | @tagName(tag), | |
| 9609 | extra.type.fmt(self), | |
| 9610 | extra.len.fmt(function_index, self), | |
| 9611 | extra.info.alignment, | |
| 9612 | extra.info.addr_space, | |
| 9613 | }); | |
| 9614 | }, | |
| 9615 | .arg => unreachable, | |
| 9616 | .atomicrmw => |tag| { | |
| 9617 | const extra = | |
| 9618 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); | |
| 9619 | try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{ | |
| 9620 | instruction_index.name(&function).fmt(self), | |
| 9621 | @tagName(tag), | |
| 9622 | extra.info.access_kind, | |
| 9623 | @tagName(extra.info.atomic_rmw_operation), | |
| 9624 | extra.ptr.fmt(function_index, self), | |
| 9625 | extra.val.fmt(function_index, self), | |
| 9626 | extra.info.sync_scope, | |
| 9627 | extra.info.success_ordering, | |
| 9628 | extra.info.alignment, | |
| 9629 | }); | |
| 9630 | }, | |
| 9631 | .block => { | |
| 9632 | block_incoming_len = instruction.data; | |
| 9633 | const name = instruction_index.name(&function); | |
| 9634 | if (@intFromEnum(instruction_index) > params_len) | |
| 7873 | 9635 | try writer.writeByte('\n'); |
| 7874 | }, | |
| 7875 | .@"ret void", | |
| 7876 | .@"unreachable", | |
| 7877 | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), | |
| 7878 | .select, | |
| 7879 | .@"select fast", | |
| 7880 | => |tag| { | |
| 7881 | const extra = | |
| 7882 | function.extraData(Function.Instruction.Select, instruction.data); | |
| 7883 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 7884 | instruction_index.name(&function).fmt(self), | |
| 7885 | @tagName(tag), | |
| 7886 | extra.cond.fmt(function_index, self), | |
| 7887 | extra.lhs.fmt(function_index, self), | |
| 7888 | extra.rhs.fmt(function_index, self), | |
| 7889 | }); | |
| 7890 | }, | |
| 7891 | .shufflevector => |tag| { | |
| 7892 | const extra = function.extraData( | |
| 7893 | Function.Instruction.ShuffleVector, | |
| 7894 | instruction.data, | |
| 7895 | ); | |
| 7896 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 7897 | instruction_index.name(&function).fmt(self), | |
| 7898 | @tagName(tag), | |
| 7899 | extra.lhs.fmt(function_index, self), | |
| 7900 | extra.rhs.fmt(function_index, self), | |
| 7901 | extra.mask.fmt(function_index, self), | |
| 7902 | }); | |
| 7903 | }, | |
| 7904 | .store, | |
| 7905 | .@"store atomic", | |
| 7906 | .@"store atomic volatile", | |
| 7907 | .@"store volatile", | |
| 7908 | => |tag| { | |
| 7909 | const extra = | |
| 7910 | function.extraData(Function.Instruction.Store, instruction.data); | |
| 7911 | try writer.print(" {s} {%}, {%}{}{}{,}\n", .{ | |
| 7912 | @tagName(tag), | |
| 7913 | extra.val.fmt(function_index, self), | |
| 7914 | extra.ptr.fmt(function_index, self), | |
| 7915 | extra.info.scope, | |
| 7916 | extra.info.ordering, | |
| 7917 | extra.info.alignment, | |
| 7918 | }); | |
| 7919 | }, | |
| 7920 | .@"switch" => |tag| { | |
| 7921 | var extra = | |
| 7922 | function.extraDataTrail(Function.Instruction.Switch, instruction.data); | |
| 7923 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); | |
| 7924 | const blocks = | |
| 7925 | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); | |
| 7926 | try writer.print(" {s} {%}, {%} [\n", .{ | |
| 7927 | @tagName(tag), | |
| 7928 | extra.data.val.fmt(function_index, self), | |
| 7929 | extra.data.default.toInst(&function).fmt(function_index, self), | |
| 7930 | }); | |
| 7931 | for (vals, blocks) |case_val, case_block| try writer.print( | |
| 7932 | " {%}, {%}\n", | |
| 7933 | .{ | |
| 7934 | case_val.fmt(self), | |
| 7935 | case_block.toInst(&function).fmt(function_index, self), | |
| 7936 | }, | |
| 7937 | ); | |
| 7938 | try writer.writeAll(" ]\n"); | |
| 7939 | }, | |
| 7940 | .unimplemented => |tag| { | |
| 7941 | const ty: Type = @enumFromInt(instruction.data); | |
| 7942 | if (true) { | |
| 7943 | try writer.writeAll(" "); | |
| 7944 | switch (ty) { | |
| 7945 | .none, .void => {}, | |
| 7946 | else => try writer.print("%{} = ", .{ | |
| 7947 | instruction_index.name(&function).fmt(self), | |
| 7948 | }), | |
| 7949 | } | |
| 7950 | try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) }); | |
| 7951 | } else switch (ty) { | |
| 7952 | .none, .void => {}, | |
| 7953 | else => try writer.print(" %{} = load {%}, ptr undef\n", .{ | |
| 7954 | instruction_index.name(&function).fmt(self), | |
| 7955 | ty.fmt(self), | |
| 7956 | }), | |
| 7957 | } | |
| 7958 | }, | |
| 7959 | .va_arg => |tag| { | |
| 7960 | const extra = | |
| 7961 | function.extraData(Function.Instruction.VaArg, instruction.data); | |
| 7962 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | |
| 9636 | try writer.print("{}:\n", .{name.fmt(self)}); | |
| 9637 | }, | |
| 9638 | .br => |tag| { | |
| 9639 | const target: Function.Block.Index = @enumFromInt(instruction.data); | |
| 9640 | try writer.print(" {s} {%}\n", .{ | |
| 9641 | @tagName(tag), target.toInst(&function).fmt(function_index, self), | |
| 9642 | }); | |
| 9643 | }, | |
| 9644 | .br_cond => { | |
| 9645 | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); | |
| 9646 | try writer.print(" br {%}, {%}, {%}\n", .{ | |
| 9647 | extra.cond.fmt(function_index, self), | |
| 9648 | extra.then.toInst(&function).fmt(function_index, self), | |
| 9649 | extra.@"else".toInst(&function).fmt(function_index, self), | |
| 9650 | }); | |
| 9651 | }, | |
| 9652 | .call, | |
| 9653 | .@"call fast", | |
| 9654 | .@"musttail call", | |
| 9655 | .@"musttail call fast", | |
| 9656 | .@"notail call", | |
| 9657 | .@"notail call fast", | |
| 9658 | .@"tail call", | |
| 9659 | .@"tail call fast", | |
| 9660 | => |tag| { | |
| 9661 | var extra = | |
| 9662 | function.extraDataTrail(Function.Instruction.Call, instruction.data); | |
| 9663 | const args = extra.trail.next(extra.data.args_len, Value, &function); | |
| 9664 | try writer.writeAll(" "); | |
| 9665 | const ret_ty = extra.data.ty.functionReturn(self); | |
| 9666 | switch (ret_ty) { | |
| 9667 | .void => {}, | |
| 9668 | else => try writer.print("%{} = ", .{ | |
| 7963 | 9669 | instruction_index.name(&function).fmt(self), |
| 7964 | @tagName(tag), | |
| 7965 | extra.list.fmt(function_index, self), | |
| 7966 | extra.type.fmt(self), | |
| 9670 | }), | |
| 9671 | .none => unreachable, | |
| 9672 | } | |
| 9673 | try writer.print("{s}{}{}{} {%} {}(", .{ | |
| 9674 | @tagName(tag), | |
| 9675 | extra.data.info.call_conv, | |
| 9676 | extra.data.attributes.ret(self).fmt(self), | |
| 9677 | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), | |
| 9678 | switch (extra.data.ty.functionKind(self)) { | |
| 9679 | .normal => ret_ty, | |
| 9680 | .vararg => extra.data.ty, | |
| 9681 | }.fmt(self), | |
| 9682 | extra.data.callee.fmt(function_index, self), | |
| 9683 | }); | |
| 9684 | for (0.., args) |arg_index, arg| { | |
| 9685 | if (arg_index > 0) try writer.writeAll(", "); | |
| 9686 | try writer.print("{%}{} {}", .{ | |
| 9687 | arg.typeOf(function_index, self).fmt(self), | |
| 9688 | extra.data.attributes.param(arg_index, self).fmt(self), | |
| 9689 | arg.fmt(function_index, self), | |
| 7967 | 9690 | }); |
| 7968 | }, | |
| 7969 | .@"llvm.fma." => { | |
| 7970 | const extra = | |
| 7971 | function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data); | |
| 7972 | const ty = instruction_index.typeOf(function_index, self); | |
| 7973 | try writer.print(" %{} = call {%} @llvm.fma.{m}({%}, {%}, {%})\n", .{ | |
| 7974 | instruction_index.name(&function).fmt(self), | |
| 7975 | ty.fmt(self), | |
| 7976 | ty.fmt(self), | |
| 7977 | extra.a.fmt(function_index, self), | |
| 7978 | extra.b.fmt(function_index, self), | |
| 7979 | extra.c.fmt(function_index, self), | |
| 9691 | } | |
| 9692 | try writer.writeByte(')'); | |
| 9693 | const call_function_attributes = extra.data.attributes.func(self); | |
| 9694 | if (call_function_attributes != .none) try writer.print(" #{d}", .{ | |
| 9695 | (try attribute_groups.getOrPutValue( | |
| 9696 | self.gpa, | |
| 9697 | call_function_attributes, | |
| 9698 | {}, | |
| 9699 | )).index, | |
| 9700 | }); | |
| 9701 | try writer.writeByte('\n'); | |
| 9702 | }, | |
| 9703 | .cmpxchg, | |
| 9704 | .@"cmpxchg weak", | |
| 9705 | => |tag| { | |
| 9706 | const extra = | |
| 9707 | function.extraData(Function.Instruction.CmpXchg, instruction.data); | |
| 9708 | try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{ | |
| 9709 | instruction_index.name(&function).fmt(self), | |
| 9710 | @tagName(tag), | |
| 9711 | extra.info.access_kind, | |
| 9712 | extra.ptr.fmt(function_index, self), | |
| 9713 | extra.cmp.fmt(function_index, self), | |
| 9714 | extra.new.fmt(function_index, self), | |
| 9715 | extra.info.sync_scope, | |
| 9716 | extra.info.success_ordering, | |
| 9717 | extra.info.failure_ordering, | |
| 9718 | extra.info.alignment, | |
| 9719 | }); | |
| 9720 | }, | |
| 9721 | .extractelement => |tag| { | |
| 9722 | const extra = | |
| 9723 | function.extraData(Function.Instruction.ExtractElement, instruction.data); | |
| 9724 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | |
| 9725 | instruction_index.name(&function).fmt(self), | |
| 9726 | @tagName(tag), | |
| 9727 | extra.val.fmt(function_index, self), | |
| 9728 | extra.index.fmt(function_index, self), | |
| 9729 | }); | |
| 9730 | }, | |
| 9731 | .extractvalue => |tag| { | |
| 9732 | var extra = function.extraDataTrail( | |
| 9733 | Function.Instruction.ExtractValue, | |
| 9734 | instruction.data, | |
| 9735 | ); | |
| 9736 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); | |
| 9737 | try writer.print(" %{} = {s} {%}", .{ | |
| 9738 | instruction_index.name(&function).fmt(self), | |
| 9739 | @tagName(tag), | |
| 9740 | extra.data.val.fmt(function_index, self), | |
| 9741 | }); | |
| 9742 | for (indices) |index| try writer.print(", {d}", .{index}); | |
| 9743 | try writer.writeByte('\n'); | |
| 9744 | }, | |
| 9745 | .fence => |tag| { | |
| 9746 | const info: MemoryAccessInfo = @bitCast(instruction.data); | |
| 9747 | try writer.print(" {s}{ }{ }", .{ | |
| 9748 | @tagName(tag), | |
| 9749 | info.sync_scope, | |
| 9750 | info.success_ordering, | |
| 9751 | }); | |
| 9752 | }, | |
| 9753 | .fneg, | |
| 9754 | .@"fneg fast", | |
| 9755 | => |tag| { | |
| 9756 | const val: Value = @enumFromInt(instruction.data); | |
| 9757 | try writer.print(" %{} = {s} {%}\n", .{ | |
| 9758 | instruction_index.name(&function).fmt(self), | |
| 9759 | @tagName(tag), | |
| 9760 | val.fmt(function_index, self), | |
| 9761 | }); | |
| 9762 | }, | |
| 9763 | .getelementptr, | |
| 9764 | .@"getelementptr inbounds", | |
| 9765 | => |tag| { | |
| 9766 | var extra = function.extraDataTrail( | |
| 9767 | Function.Instruction.GetElementPtr, | |
| 9768 | instruction.data, | |
| 9769 | ); | |
| 9770 | const indices = extra.trail.next(extra.data.indices_len, Value, &function); | |
| 9771 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 9772 | instruction_index.name(&function).fmt(self), | |
| 9773 | @tagName(tag), | |
| 9774 | extra.data.type.fmt(self), | |
| 9775 | extra.data.base.fmt(function_index, self), | |
| 9776 | }); | |
| 9777 | for (indices) |index| try writer.print(", {%}", .{ | |
| 9778 | index.fmt(function_index, self), | |
| 9779 | }); | |
| 9780 | try writer.writeByte('\n'); | |
| 9781 | }, | |
| 9782 | .insertelement => |tag| { | |
| 9783 | const extra = | |
| 9784 | function.extraData(Function.Instruction.InsertElement, instruction.data); | |
| 9785 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 9786 | instruction_index.name(&function).fmt(self), | |
| 9787 | @tagName(tag), | |
| 9788 | extra.val.fmt(function_index, self), | |
| 9789 | extra.elem.fmt(function_index, self), | |
| 9790 | extra.index.fmt(function_index, self), | |
| 9791 | }); | |
| 9792 | }, | |
| 9793 | .insertvalue => |tag| { | |
| 9794 | var extra = | |
| 9795 | function.extraDataTrail(Function.Instruction.InsertValue, instruction.data); | |
| 9796 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); | |
| 9797 | try writer.print(" %{} = {s} {%}, {%}", .{ | |
| 9798 | instruction_index.name(&function).fmt(self), | |
| 9799 | @tagName(tag), | |
| 9800 | extra.data.val.fmt(function_index, self), | |
| 9801 | extra.data.elem.fmt(function_index, self), | |
| 9802 | }); | |
| 9803 | for (indices) |index| try writer.print(", {d}", .{index}); | |
| 9804 | try writer.writeByte('\n'); | |
| 9805 | }, | |
| 9806 | .load, | |
| 9807 | .@"load atomic", | |
| 9808 | => |tag| { | |
| 9809 | const extra = function.extraData(Function.Instruction.Load, instruction.data); | |
| 9810 | try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ | |
| 9811 | instruction_index.name(&function).fmt(self), | |
| 9812 | @tagName(tag), | |
| 9813 | extra.info.access_kind, | |
| 9814 | extra.type.fmt(self), | |
| 9815 | extra.ptr.fmt(function_index, self), | |
| 9816 | extra.info.sync_scope, | |
| 9817 | extra.info.success_ordering, | |
| 9818 | extra.info.alignment, | |
| 9819 | }); | |
| 9820 | }, | |
| 9821 | .phi, | |
| 9822 | .@"phi fast", | |
| 9823 | => |tag| { | |
| 9824 | var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data); | |
| 9825 | const vals = extra.trail.next(block_incoming_len, Value, &function); | |
| 9826 | const blocks = | |
| 9827 | extra.trail.next(block_incoming_len, Function.Block.Index, &function); | |
| 9828 | try writer.print(" %{} = {s} {%} ", .{ | |
| 9829 | instruction_index.name(&function).fmt(self), | |
| 9830 | @tagName(tag), | |
| 9831 | vals[0].typeOf(function_index, self).fmt(self), | |
| 9832 | }); | |
| 9833 | for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { | |
| 9834 | if (incoming_index > 0) try writer.writeAll(", "); | |
| 9835 | try writer.print("[ {}, {} ]", .{ | |
| 9836 | incoming_val.fmt(function_index, self), | |
| 9837 | incoming_block.toInst(&function).fmt(function_index, self), | |
| 7980 | 9838 | }); |
| 7981 | }, | |
| 7982 | } | |
| 9839 | } | |
| 9840 | try writer.writeByte('\n'); | |
| 9841 | }, | |
| 9842 | .ret => |tag| { | |
| 9843 | const val: Value = @enumFromInt(instruction.data); | |
| 9844 | try writer.print(" {s} {%}\n", .{ | |
| 9845 | @tagName(tag), | |
| 9846 | val.fmt(function_index, self), | |
| 9847 | }); | |
| 9848 | }, | |
| 9849 | .@"ret void", | |
| 9850 | .@"unreachable", | |
| 9851 | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), | |
| 9852 | .select, | |
| 9853 | .@"select fast", | |
| 9854 | => |tag| { | |
| 9855 | const extra = function.extraData(Function.Instruction.Select, instruction.data); | |
| 9856 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 9857 | instruction_index.name(&function).fmt(self), | |
| 9858 | @tagName(tag), | |
| 9859 | extra.cond.fmt(function_index, self), | |
| 9860 | extra.lhs.fmt(function_index, self), | |
| 9861 | extra.rhs.fmt(function_index, self), | |
| 9862 | }); | |
| 9863 | }, | |
| 9864 | .shufflevector => |tag| { | |
| 9865 | const extra = | |
| 9866 | function.extraData(Function.Instruction.ShuffleVector, instruction.data); | |
| 9867 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ | |
| 9868 | instruction_index.name(&function).fmt(self), | |
| 9869 | @tagName(tag), | |
| 9870 | extra.lhs.fmt(function_index, self), | |
| 9871 | extra.rhs.fmt(function_index, self), | |
| 9872 | extra.mask.fmt(function_index, self), | |
| 9873 | }); | |
| 9874 | }, | |
| 9875 | .store, | |
| 9876 | .@"store atomic", | |
| 9877 | => |tag| { | |
| 9878 | const extra = function.extraData(Function.Instruction.Store, instruction.data); | |
| 9879 | try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ | |
| 9880 | @tagName(tag), | |
| 9881 | extra.info.access_kind, | |
| 9882 | extra.val.fmt(function_index, self), | |
| 9883 | extra.ptr.fmt(function_index, self), | |
| 9884 | extra.info.sync_scope, | |
| 9885 | extra.info.success_ordering, | |
| 9886 | extra.info.alignment, | |
| 9887 | }); | |
| 9888 | }, | |
| 9889 | .@"switch" => |tag| { | |
| 9890 | var extra = | |
| 9891 | function.extraDataTrail(Function.Instruction.Switch, instruction.data); | |
| 9892 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); | |
| 9893 | const blocks = | |
| 9894 | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); | |
| 9895 | try writer.print(" {s} {%}, {%} [\n", .{ | |
| 9896 | @tagName(tag), | |
| 9897 | extra.data.val.fmt(function_index, self), | |
| 9898 | extra.data.default.toInst(&function).fmt(function_index, self), | |
| 9899 | }); | |
| 9900 | for (vals, blocks) |case_val, case_block| try writer.print( | |
| 9901 | " {%}, {%}\n", | |
| 9902 | .{ | |
| 9903 | case_val.fmt(self), | |
| 9904 | case_block.toInst(&function).fmt(function_index, self), | |
| 9905 | }, | |
| 9906 | ); | |
| 9907 | try writer.writeAll(" ]\n"); | |
| 9908 | }, | |
| 9909 | .va_arg => |tag| { | |
| 9910 | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); | |
| 9911 | try writer.print(" %{} = {s} {%}, {%}\n", .{ | |
| 9912 | instruction_index.name(&function).fmt(self), | |
| 9913 | @tagName(tag), | |
| 9914 | extra.list.fmt(function_index, self), | |
| 9915 | extra.type.fmt(self), | |
| 9916 | }); | |
| 9917 | }, | |
| 7983 | 9918 | } |
| 7984 | try writer.writeByte('}'); | |
| 7985 | 9919 | } |
| 7986 | try writer.writeByte('\n'); | |
| 9920 | try writer.writeByte('}'); | |
| 7987 | 9921 | } |
| 9922 | try writer.writeByte('\n'); | |
| 7988 | 9923 | need_newline = true; |
| 7989 | 9924 | } |
| 7990 | 9925 | |
| ... | ... | @@ -8080,7 +10015,7 @@ fn fnTypeAssumeCapacity( |
| 8080 | 10015 | gop.key_ptr.* = {}; |
| 8081 | 10016 | gop.value_ptr.* = {}; |
| 8082 | 10017 | self.type_items.appendAssumeCapacity(.{ |
| 8083 | .tag = .function, | |
| 10018 | .tag = tag, | |
| 8084 | 10019 | .data = self.addTypeExtraAssumeCapacity(Type.Function{ |
| 8085 | 10020 | .ret = ret, |
| 8086 | 10021 | .params_len = @intCast(params.len), |
| ... | ... | @@ -9378,7 +11313,7 @@ fn icmpConstAssumeCapacity( |
| 9378 | 11313 | .data = self.addConstantExtraAssumeCapacity(data), |
| 9379 | 11314 | }); |
| 9380 | 11315 | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 9381 | llvm.constICmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)), | |
| 11316 | llvm.constICmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)), | |
| 9382 | 11317 | ); |
| 9383 | 11318 | } |
| 9384 | 11319 | return @enumFromInt(gop.index); |
| ... | ... | @@ -9415,7 +11350,7 @@ fn fcmpConstAssumeCapacity( |
| 9415 | 11350 | .data = self.addConstantExtraAssumeCapacity(data), |
| 9416 | 11351 | }); |
| 9417 | 11352 | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( |
| 9418 | llvm.constFCmp(@enumFromInt(@intFromEnum(cond)), lhs.toLlvm(self), rhs.toLlvm(self)), | |
| 11353 | llvm.constFCmp(cond.toLlvm(), lhs.toLlvm(self), rhs.toLlvm(self)), | |
| 9419 | 11354 | ); |
| 9420 | 11355 | } |
| 9421 | 11356 | return @enumFromInt(gop.index); |
| ... | ... | @@ -9601,16 +11536,52 @@ fn binConstAssumeCapacity( |
| 9601 | 11536 | return @enumFromInt(gop.index); |
| 9602 | 11537 | } |
| 9603 | 11538 | |
| 11539 | comptime { | |
| 11540 | _ = &selectValue; | |
| 11541 | } | |
| 11542 | ||
| 11543 | fn selectConstAssumeCapacity(self: *Builder, cond: Constant, lhs: Constant, rhs: Constant) Constant { | |
| 11544 | const Adapter = struct { | |
| 11545 | builder: *const Builder, | |
| 11546 | pub fn hash(_: @This(), key: Constant.Select) u32 { | |
| 11547 | return @truncate(std.hash.Wyhash.hash( | |
| 11548 | std.hash.uint32(@intFromEnum(Constant.Tag.select)), | |
| 11549 | std.mem.asBytes(&key), | |
| 11550 | )); | |
| 11551 | } | |
| 11552 | pub fn eql(ctx: @This(), lhs_key: Constant.Select, _: void, rhs_index: usize) bool { | |
| 11553 | if (ctx.builder.constant_items.items(.tag)[rhs_index] != .select) return false; | |
| 11554 | const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; | |
| 11555 | const rhs_extra = ctx.builder.constantExtraData(Constant.Select, rhs_data); | |
| 11556 | return std.meta.eql(lhs_key, rhs_extra); | |
| 11557 | } | |
| 11558 | }; | |
| 11559 | const data = Constant.Select{ .cond = cond, .lhs = lhs, .rhs = rhs }; | |
| 11560 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); | |
| 11561 | if (!gop.found_existing) { | |
| 11562 | gop.key_ptr.* = {}; | |
| 11563 | gop.value_ptr.* = {}; | |
| 11564 | self.constant_items.appendAssumeCapacity(.{ | |
| 11565 | .tag = .select, | |
| 11566 | .data = self.addConstantExtraAssumeCapacity(data), | |
| 11567 | }); | |
| 11568 | if (self.useLibLlvm()) self.llvm.constants.appendAssumeCapacity( | |
| 11569 | cond.toLlvm(self).constSelect(lhs.toLlvm(self), rhs.toLlvm(self)), | |
| 11570 | ); | |
| 11571 | } | |
| 11572 | return @enumFromInt(gop.index); | |
| 11573 | } | |
| 11574 | ||
| 9604 | 11575 | fn asmConstAssumeCapacity( |
| 9605 | 11576 | self: *Builder, |
| 9606 | 11577 | ty: Type, |
| 9607 | info: Constant.Asm.Info, | |
| 11578 | info: Constant.Assembly.Info, | |
| 9608 | 11579 | assembly: String, |
| 9609 | 11580 | constraints: String, |
| 9610 | 11581 | ) Constant { |
| 9611 | 11582 | assert(ty.functionKind(self) == .normal); |
| 9612 | 11583 | |
| 9613 | const Key = struct { tag: Constant.Tag, extra: Constant.Asm }; | |
| 11584 | const Key = struct { tag: Constant.Tag, extra: Constant.Assembly }; | |
| 9614 | 11585 | const Adapter = struct { |
| 9615 | 11586 | builder: *const Builder, |
| 9616 | 11587 | pub fn hash(_: @This(), key: Key) u32 { |
| ... | ... | @@ -9622,7 +11593,7 @@ fn asmConstAssumeCapacity( |
| 9622 | 11593 | pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { |
| 9623 | 11594 | if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; |
| 9624 | 11595 | const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; |
| 9625 | const rhs_extra = ctx.builder.constantExtraData(Constant.Asm, rhs_data); | |
| 11596 | const rhs_extra = ctx.builder.constantExtraData(Constant.Assembly, rhs_data); | |
| 9626 | 11597 | return std.meta.eql(lhs_key.extra, rhs_extra); |
| 9627 | 11598 | } |
| 9628 | 11599 | }; |
src/codegen/llvm/bindings.zig+14-315| ... | ... | @@ -93,17 +93,6 @@ pub const Context = opaque { |
| 93 | 93 | pub const constString = LLVMConstStringInContext; |
| 94 | 94 | extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) *Value; |
| 95 | 95 | |
| 96 | pub const constStruct = LLVMConstStructInContext; | |
| 97 | extern fn LLVMConstStructInContext( | |
| 98 | C: *Context, | |
| 99 | ConstantVals: [*]const *Value, | |
| 100 | Count: c_uint, | |
| 101 | Packed: Bool, | |
| 102 | ) *Value; | |
| 103 | ||
| 104 | pub const createBasicBlock = LLVMCreateBasicBlockInContext; | |
| 105 | extern fn LLVMCreateBasicBlockInContext(C: *Context, Name: [*:0]const u8) *BasicBlock; | |
| 106 | ||
| 107 | 96 | pub const appendBasicBlock = LLVMAppendBasicBlockInContext; |
| 108 | 97 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) *BasicBlock; |
| 109 | 98 | |
| ... | ... | @@ -115,18 +104,18 @@ pub const Context = opaque { |
| 115 | 104 | }; |
| 116 | 105 | |
| 117 | 106 | pub const Value = opaque { |
| 118 | pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex; | |
| 119 | extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void; | |
| 107 | pub const addAttributeAtIndex = LLVMAddAttributeAtIndex; | |
| 108 | extern fn LLVMAddAttributeAtIndex(F: *Value, Idx: AttributeIndex, A: *Attribute) void; | |
| 120 | 109 | |
| 121 | 110 | pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex; |
| 122 | 111 | extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void; |
| 123 | 112 | |
| 113 | pub const removeStringAttributeAtIndex = LLVMRemoveStringAttributeAtIndex; | |
| 114 | extern fn LLVMRemoveStringAttributeAtIndex(F: *Value, Idx: AttributeIndex, K: [*]const u8, KLen: c_uint) void; | |
| 115 | ||
| 124 | 116 | pub const getFirstBasicBlock = LLVMGetFirstBasicBlock; |
| 125 | 117 | extern fn LLVMGetFirstBasicBlock(Fn: *Value) ?*BasicBlock; |
| 126 | 118 | |
| 127 | pub const appendExistingBasicBlock = LLVMAppendExistingBasicBlock; | |
| 128 | extern fn LLVMAppendExistingBasicBlock(Fn: *Value, BB: *BasicBlock) void; | |
| 129 | ||
| 130 | 119 | pub const addIncoming = LLVMAddIncoming; |
| 131 | 120 | extern fn LLVMAddIncoming( |
| 132 | 121 | PhiNode: *Value, |
| ... | ... | @@ -135,9 +124,6 @@ pub const Value = opaque { |
| 135 | 124 | Count: c_uint, |
| 136 | 125 | ) void; |
| 137 | 126 | |
| 138 | pub const getNextInstruction = LLVMGetNextInstruction; | |
| 139 | extern fn LLVMGetNextInstruction(Inst: *Value) ?*Value; | |
| 140 | ||
| 141 | 127 | pub const setGlobalConstant = LLVMSetGlobalConstant; |
| 142 | 128 | extern fn LLVMSetGlobalConstant(GlobalVar: *Value, IsConstant: Bool) void; |
| 143 | 129 | |
| ... | ... | @@ -156,33 +142,18 @@ pub const Value = opaque { |
| 156 | 142 | pub const setSection = LLVMSetSection; |
| 157 | 143 | extern fn LLVMSetSection(Global: *Value, Section: [*:0]const u8) void; |
| 158 | 144 | |
| 159 | pub const deleteGlobal = LLVMDeleteGlobal; | |
| 160 | extern fn LLVMDeleteGlobal(GlobalVar: *Value) void; | |
| 145 | pub const removeGlobalValue = ZigLLVMRemoveGlobalValue; | |
| 146 | extern fn ZigLLVMRemoveGlobalValue(GlobalVal: *Value) void; | |
| 161 | 147 | |
| 162 | pub const getNextGlobalAlias = LLVMGetNextGlobalAlias; | |
| 163 | extern fn LLVMGetNextGlobalAlias(GA: *Value) *Value; | |
| 148 | pub const eraseGlobalValue = ZigLLVMEraseGlobalValue; | |
| 149 | extern fn ZigLLVMEraseGlobalValue(GlobalVal: *Value) void; | |
| 164 | 150 | |
| 165 | pub const getAliasee = LLVMAliasGetAliasee; | |
| 166 | extern fn LLVMAliasGetAliasee(Alias: *Value) *Value; | |
| 151 | pub const deleteGlobalValue = ZigLLVMDeleteGlobalValue; | |
| 152 | extern fn ZigLLVMDeleteGlobalValue(GlobalVal: *Value) void; | |
| 167 | 153 | |
| 168 | 154 | pub const setAliasee = LLVMAliasSetAliasee; |
| 169 | 155 | extern fn LLVMAliasSetAliasee(Alias: *Value, Aliasee: *Value) void; |
| 170 | 156 | |
| 171 | pub const constZExtOrBitCast = LLVMConstZExtOrBitCast; | |
| 172 | extern fn LLVMConstZExtOrBitCast(ConstantVal: *Value, ToType: *Type) *Value; | |
| 173 | ||
| 174 | pub const constNeg = LLVMConstNeg; | |
| 175 | extern fn LLVMConstNeg(ConstantVal: *Value) *Value; | |
| 176 | ||
| 177 | pub const constNSWNeg = LLVMConstNSWNeg; | |
| 178 | extern fn LLVMConstNSWNeg(ConstantVal: *Value) *Value; | |
| 179 | ||
| 180 | pub const constNUWNeg = LLVMConstNUWNeg; | |
| 181 | extern fn LLVMConstNUWNeg(ConstantVal: *Value) *Value; | |
| 182 | ||
| 183 | pub const constNot = LLVMConstNot; | |
| 184 | extern fn LLVMConstNot(ConstantVal: *Value) *Value; | |
| 185 | ||
| 186 | 157 | pub const constAdd = LLVMConstAdd; |
| 187 | 158 | extern fn LLVMConstAdd(LHSConstant: *Value, RHSConstant: *Value) *Value; |
| 188 | 159 | |
| ... | ... | @@ -306,9 +277,6 @@ pub const Value = opaque { |
| 306 | 277 | pub const setVolatile = LLVMSetVolatile; |
| 307 | 278 | extern fn LLVMSetVolatile(MemoryAccessInst: *Value, IsVolatile: Bool) void; |
| 308 | 279 | |
| 309 | pub const setAtomicSingleThread = LLVMSetAtomicSingleThread; | |
| 310 | extern fn LLVMSetAtomicSingleThread(AtomicInst: *Value, SingleThread: Bool) void; | |
| 311 | ||
| 312 | 280 | pub const setAlignment = LLVMSetAlignment; |
| 313 | 281 | extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void; |
| 314 | 282 | |
| ... | ... | @@ -327,32 +295,17 @@ pub const Value = opaque { |
| 327 | 295 | pub const fnSetSubprogram = ZigLLVMFnSetSubprogram; |
| 328 | 296 | extern fn ZigLLVMFnSetSubprogram(f: *Value, subprogram: *DISubprogram) void; |
| 329 | 297 | |
| 330 | pub const setValueName = LLVMSetValueName; | |
| 331 | extern fn LLVMSetValueName(Val: *Value, Name: [*:0]const u8) void; | |
| 332 | ||
| 333 | pub const setValueName2 = LLVMSetValueName2; | |
| 298 | pub const setValueName = LLVMSetValueName2; | |
| 334 | 299 | extern fn LLVMSetValueName2(Val: *Value, Name: [*]const u8, NameLen: usize) void; |
| 335 | 300 | |
| 336 | pub const getValueName = LLVMGetValueName; | |
| 337 | extern fn LLVMGetValueName(Val: *Value) [*:0]const u8; | |
| 338 | ||
| 339 | 301 | pub const takeName = ZigLLVMTakeName; |
| 340 | 302 | extern fn ZigLLVMTakeName(new_owner: *Value, victim: *Value) void; |
| 341 | 303 | |
| 342 | pub const deleteFunction = LLVMDeleteFunction; | |
| 343 | extern fn LLVMDeleteFunction(Fn: *Value) void; | |
| 344 | ||
| 345 | pub const addSretAttr = ZigLLVMAddSretAttr; | |
| 346 | extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void; | |
| 347 | ||
| 348 | pub const setCallSret = ZigLLVMSetCallSret; | |
| 349 | extern fn ZigLLVMSetCallSret(Call: *Value, return_type: *Type) void; | |
| 350 | ||
| 351 | 304 | pub const getParam = LLVMGetParam; |
| 352 | 305 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; |
| 353 | 306 | |
| 354 | pub const setInitializer = LLVMSetInitializer; | |
| 355 | extern fn LLVMSetInitializer(GlobalVar: *Value, ConstantVal: *Value) void; | |
| 307 | pub const setInitializer = ZigLLVMSetInitializer; | |
| 308 | extern fn ZigLLVMSetInitializer(GlobalVar: *Value, ConstantVal: ?*Value) void; | |
| 356 | 309 | |
| 357 | 310 | pub const setDLLStorageClass = LLVMSetDLLStorageClass; |
| 358 | 311 | extern fn LLVMSetDLLStorageClass(Global: *Value, Class: DLLStorageClass) void; |
| ... | ... | @@ -363,21 +316,6 @@ pub const Value = opaque { |
| 363 | 316 | pub const replaceAllUsesWith = LLVMReplaceAllUsesWith; |
| 364 | 317 | extern fn LLVMReplaceAllUsesWith(OldVal: *Value, NewVal: *Value) void; |
| 365 | 318 | |
| 366 | pub const getLinkage = LLVMGetLinkage; | |
| 367 | extern fn LLVMGetLinkage(Global: *Value) Linkage; | |
| 368 | ||
| 369 | pub const getUnnamedAddress = LLVMGetUnnamedAddress; | |
| 370 | extern fn LLVMGetUnnamedAddress(Global: *Value) Bool; | |
| 371 | ||
| 372 | pub const getAlignment = LLVMGetAlignment; | |
| 373 | extern fn LLVMGetAlignment(V: *Value) c_uint; | |
| 374 | ||
| 375 | pub const addFunctionAttr = ZigLLVMAddFunctionAttr; | |
| 376 | extern fn ZigLLVMAddFunctionAttr(Fn: *Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; | |
| 377 | ||
| 378 | pub const addByValAttr = ZigLLVMAddByValAttr; | |
| 379 | extern fn ZigLLVMAddByValAttr(Fn: *Value, ArgNo: c_uint, type: *Type) void; | |
| 380 | ||
| 381 | 319 | pub const attachMetaData = ZigLLVMAttachMetaData; |
| 382 | 320 | extern fn ZigLLVMAttachMetaData(GlobalVar: *Value, DIG: *DIGlobalVariableExpression) void; |
| 383 | 321 | |
| ... | ... | @@ -389,9 +327,6 @@ pub const Type = opaque { |
| 389 | 327 | pub const constNull = LLVMConstNull; |
| 390 | 328 | extern fn LLVMConstNull(Ty: *Type) *Value; |
| 391 | 329 | |
| 392 | pub const constAllOnes = LLVMConstAllOnes; | |
| 393 | extern fn LLVMConstAllOnes(Ty: *Type) *Value; | |
| 394 | ||
| 395 | 330 | pub const constInt = LLVMConstInt; |
| 396 | 331 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) *Value; |
| 397 | 332 | |
| ... | ... | @@ -479,39 +414,18 @@ pub const Module = opaque { |
| 479 | 414 | pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel; |
| 480 | 415 | extern fn ZigLLVMSetModuleCodeModel(module: *Module, code_model: CodeModel) void; |
| 481 | 416 | |
| 482 | pub const addFunction = LLVMAddFunction; | |
| 483 | extern fn LLVMAddFunction(*Module, Name: [*:0]const u8, FunctionTy: *Type) *Value; | |
| 484 | ||
| 485 | 417 | pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace; |
| 486 | 418 | extern fn ZigLLVMAddFunctionInAddressSpace(*Module, Name: [*:0]const u8, FunctionTy: *Type, AddressSpace: c_uint) *Value; |
| 487 | 419 | |
| 488 | pub const getNamedFunction = LLVMGetNamedFunction; | |
| 489 | extern fn LLVMGetNamedFunction(*Module, Name: [*:0]const u8) ?*Value; | |
| 490 | ||
| 491 | pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration; | |
| 492 | extern fn LLVMGetIntrinsicDeclaration(Mod: *Module, ID: c_uint, ParamTypes: ?[*]const *Type, ParamCount: usize) *Value; | |
| 493 | ||
| 494 | 420 | pub const printToString = LLVMPrintModuleToString; |
| 495 | 421 | extern fn LLVMPrintModuleToString(*Module) [*:0]const u8; |
| 496 | 422 | |
| 497 | pub const addGlobal = LLVMAddGlobal; | |
| 498 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) *Value; | |
| 499 | ||
| 500 | 423 | pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace; |
| 501 | 424 | extern fn LLVMAddGlobalInAddressSpace(M: *Module, Ty: *Type, Name: [*:0]const u8, AddressSpace: c_uint) *Value; |
| 502 | 425 | |
| 503 | pub const getNamedGlobal = LLVMGetNamedGlobal; | |
| 504 | extern fn LLVMGetNamedGlobal(M: *Module, Name: [*:0]const u8) ?*Value; | |
| 505 | ||
| 506 | 426 | pub const dump = LLVMDumpModule; |
| 507 | 427 | extern fn LLVMDumpModule(M: *Module) void; |
| 508 | 428 | |
| 509 | pub const getFirstGlobalAlias = LLVMGetFirstGlobalAlias; | |
| 510 | extern fn LLVMGetFirstGlobalAlias(M: *Module) *Value; | |
| 511 | ||
| 512 | pub const getLastGlobalAlias = LLVMGetLastGlobalAlias; | |
| 513 | extern fn LLVMGetLastGlobalAlias(M: *Module) *Value; | |
| 514 | ||
| 515 | 429 | pub const addAlias = LLVMAddAlias2; |
| 516 | 430 | extern fn LLVMAddAlias2( |
| 517 | 431 | M: *Module, |
| ... | ... | @@ -521,16 +435,6 @@ pub const Module = opaque { |
| 521 | 435 | Name: [*:0]const u8, |
| 522 | 436 | ) *Value; |
| 523 | 437 | |
| 524 | pub const getNamedGlobalAlias = LLVMGetNamedGlobalAlias; | |
| 525 | extern fn LLVMGetNamedGlobalAlias( | |
| 526 | M: *Module, | |
| 527 | /// Empirically, LLVM will call strlen() on `Name` and so it | |
| 528 | /// must be both null terminated and also have `NameLen` set | |
| 529 | /// to the size. | |
| 530 | Name: [*:0]const u8, | |
| 531 | NameLen: usize, | |
| 532 | ) ?*Value; | |
| 533 | ||
| 534 | 438 | pub const setTarget = LLVMSetTarget; |
| 535 | 439 | extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void; |
| 536 | 440 | |
| ... | ... | @@ -553,9 +457,6 @@ pub const Module = opaque { |
| 553 | 457 | extern fn LLVMWriteBitcodeToFile(M: *Module, Path: [*:0]const u8) c_int; |
| 554 | 458 | }; |
| 555 | 459 | |
| 556 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; | |
| 557 | extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint; | |
| 558 | ||
| 559 | 460 | pub const disposeMessage = LLVMDisposeMessage; |
| 560 | 461 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; |
| 561 | 462 | |
| ... | ... | @@ -616,12 +517,6 @@ pub const Builder = opaque { |
| 616 | 517 | Instr: ?*Value, |
| 617 | 518 | ) void; |
| 618 | 519 | |
| 619 | pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd; | |
| 620 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; | |
| 621 | ||
| 622 | pub const getInsertBlock = LLVMGetInsertBlock; | |
| 623 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; | |
| 624 | ||
| 625 | 520 | pub const buildZExt = LLVMBuildZExt; |
| 626 | 521 | extern fn LLVMBuildZExt( |
| 627 | 522 | *Builder, |
| ... | ... | @@ -630,14 +525,6 @@ pub const Builder = opaque { |
| 630 | 525 | Name: [*:0]const u8, |
| 631 | 526 | ) *Value; |
| 632 | 527 | |
| 633 | pub const buildZExtOrBitCast = LLVMBuildZExtOrBitCast; | |
| 634 | extern fn LLVMBuildZExtOrBitCast( | |
| 635 | *Builder, | |
| 636 | Val: *Value, | |
| 637 | DestTy: *Type, | |
| 638 | Name: [*:0]const u8, | |
| 639 | ) *Value; | |
| 640 | ||
| 641 | 528 | pub const buildSExt = LLVMBuildSExt; |
| 642 | 529 | extern fn LLVMBuildSExt( |
| 643 | 530 | *Builder, |
| ... | ... | @@ -646,14 +533,6 @@ pub const Builder = opaque { |
| 646 | 533 | Name: [*:0]const u8, |
| 647 | 534 | ) *Value; |
| 648 | 535 | |
| 649 | pub const buildSExtOrBitCast = LLVMBuildSExtOrBitCast; | |
| 650 | extern fn LLVMBuildSExtOrBitCast( | |
| 651 | *Builder, | |
| 652 | Val: *Value, | |
| 653 | DestTy: *Type, | |
| 654 | Name: [*:0]const u8, | |
| 655 | ) *Value; | |
| 656 | ||
| 657 | 536 | pub const buildCall = LLVMBuildCall2; |
| 658 | 537 | extern fn LLVMBuildCall2( |
| 659 | 538 | *Builder, |
| ... | ... | @@ -664,18 +543,6 @@ pub const Builder = opaque { |
| 664 | 543 | Name: [*:0]const u8, |
| 665 | 544 | ) *Value; |
| 666 | 545 | |
| 667 | pub const buildCallOld = ZigLLVMBuildCall; | |
| 668 | extern fn ZigLLVMBuildCall( | |
| 669 | *Builder, | |
| 670 | *Type, | |
| 671 | Fn: *Value, | |
| 672 | Args: [*]const *Value, | |
| 673 | NumArgs: c_uint, | |
| 674 | CC: CallConv, | |
| 675 | attr: CallAttr, | |
| 676 | Name: [*:0]const u8, | |
| 677 | ) *Value; | |
| 678 | ||
| 679 | 546 | pub const buildRetVoid = LLVMBuildRetVoid; |
| 680 | 547 | extern fn LLVMBuildRetVoid(*Builder) *Value; |
| 681 | 548 | |
| ... | ... | @@ -694,12 +561,6 @@ pub const Builder = opaque { |
| 694 | 561 | pub const buildLoad = LLVMBuildLoad2; |
| 695 | 562 | extern fn LLVMBuildLoad2(*Builder, Ty: *Type, PointerVal: *Value, Name: [*:0]const u8) *Value; |
| 696 | 563 | |
| 697 | pub const buildNeg = LLVMBuildNeg; | |
| 698 | extern fn LLVMBuildNeg(*Builder, V: *Value, Name: [*:0]const u8) *Value; | |
| 699 | ||
| 700 | pub const buildNot = LLVMBuildNot; | |
| 701 | extern fn LLVMBuildNot(*Builder, V: *Value, Name: [*:0]const u8) *Value; | |
| 702 | ||
| 703 | 564 | pub const buildFAdd = LLVMBuildFAdd; |
| 704 | 565 | extern fn LLVMBuildFAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 705 | 566 | |
| ... | ... | @@ -712,12 +573,6 @@ pub const Builder = opaque { |
| 712 | 573 | pub const buildNUWAdd = LLVMBuildNUWAdd; |
| 713 | 574 | extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 714 | 575 | |
| 715 | pub const buildSAddSat = ZigLLVMBuildSAddSat; | |
| 716 | extern fn ZigLLVMBuildSAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 717 | ||
| 718 | pub const buildUAddSat = ZigLLVMBuildUAddSat; | |
| 719 | extern fn ZigLLVMBuildUAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 720 | ||
| 721 | 576 | pub const buildFSub = LLVMBuildFSub; |
| 722 | 577 | extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 723 | 578 | |
| ... | ... | @@ -733,12 +588,6 @@ pub const Builder = opaque { |
| 733 | 588 | pub const buildNUWSub = LLVMBuildNUWSub; |
| 734 | 589 | extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 735 | 590 | |
| 736 | pub const buildSSubSat = ZigLLVMBuildSSubSat; | |
| 737 | extern fn ZigLLVMBuildSSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 738 | ||
| 739 | pub const buildUSubSat = ZigLLVMBuildUSubSat; | |
| 740 | extern fn ZigLLVMBuildUSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 741 | ||
| 742 | 591 | pub const buildFMul = LLVMBuildFMul; |
| 743 | 592 | extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 744 | 593 | |
| ... | ... | @@ -751,12 +600,6 @@ pub const Builder = opaque { |
| 751 | 600 | pub const buildNUWMul = LLVMBuildNUWMul; |
| 752 | 601 | extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 753 | 602 | |
| 754 | pub const buildSMulFixSat = ZigLLVMBuildSMulFixSat; | |
| 755 | extern fn ZigLLVMBuildSMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 756 | ||
| 757 | pub const buildUMulFixSat = ZigLLVMBuildUMulFixSat; | |
| 758 | extern fn ZigLLVMBuildUMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 759 | ||
| 760 | 603 | pub const buildUDiv = LLVMBuildUDiv; |
| 761 | 604 | extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 762 | 605 | |
| ... | ... | @@ -799,21 +642,12 @@ pub const Builder = opaque { |
| 799 | 642 | pub const buildNSWShl = ZigLLVMBuildNSWShl; |
| 800 | 643 | extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 801 | 644 | |
| 802 | pub const buildSShlSat = ZigLLVMBuildSShlSat; | |
| 803 | extern fn ZigLLVMBuildSShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 804 | ||
| 805 | pub const buildUShlSat = ZigLLVMBuildUShlSat; | |
| 806 | extern fn ZigLLVMBuildUShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; | |
| 807 | ||
| 808 | 645 | pub const buildOr = LLVMBuildOr; |
| 809 | 646 | extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 810 | 647 | |
| 811 | 648 | pub const buildXor = LLVMBuildXor; |
| 812 | 649 | extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 813 | 650 | |
| 814 | pub const buildIntCast2 = LLVMBuildIntCast2; | |
| 815 | extern fn LLVMBuildIntCast2(*Builder, Val: *Value, DestTy: *Type, IsSigned: Bool, Name: [*:0]const u8) *Value; | |
| 816 | ||
| 817 | 651 | pub const buildBitCast = LLVMBuildBitCast; |
| 818 | 652 | extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value; |
| 819 | 653 | |
| ... | ... | @@ -999,102 +833,6 @@ pub const Builder = opaque { |
| 999 | 833 | Name: [*:0]const u8, |
| 1000 | 834 | ) *Value; |
| 1001 | 835 | |
| 1002 | pub const buildMemSet = ZigLLVMBuildMemSet; | |
| 1003 | extern fn ZigLLVMBuildMemSet( | |
| 1004 | B: *Builder, | |
| 1005 | Ptr: *Value, | |
| 1006 | Val: *Value, | |
| 1007 | Len: *Value, | |
| 1008 | Align: c_uint, | |
| 1009 | is_volatile: bool, | |
| 1010 | ) *Value; | |
| 1011 | ||
| 1012 | pub const buildMemCpy = ZigLLVMBuildMemCpy; | |
| 1013 | extern fn ZigLLVMBuildMemCpy( | |
| 1014 | B: *Builder, | |
| 1015 | Dst: *Value, | |
| 1016 | DstAlign: c_uint, | |
| 1017 | Src: *Value, | |
| 1018 | SrcAlign: c_uint, | |
| 1019 | Size: *Value, | |
| 1020 | is_volatile: bool, | |
| 1021 | ) *Value; | |
| 1022 | ||
| 1023 | pub const buildMaxNum = ZigLLVMBuildMaxNum; | |
| 1024 | extern fn ZigLLVMBuildMaxNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1025 | ||
| 1026 | pub const buildMinNum = ZigLLVMBuildMinNum; | |
| 1027 | extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1028 | ||
| 1029 | pub const buildCeil = ZigLLVMBuildCeil; | |
| 1030 | extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1031 | ||
| 1032 | pub const buildCos = ZigLLVMBuildCos; | |
| 1033 | extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1034 | ||
| 1035 | pub const buildExp = ZigLLVMBuildExp; | |
| 1036 | extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1037 | ||
| 1038 | pub const buildExp2 = ZigLLVMBuildExp2; | |
| 1039 | extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1040 | ||
| 1041 | pub const buildFAbs = ZigLLVMBuildFAbs; | |
| 1042 | extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1043 | ||
| 1044 | pub const buildFloor = ZigLLVMBuildFloor; | |
| 1045 | extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1046 | ||
| 1047 | pub const buildLog = ZigLLVMBuildLog; | |
| 1048 | extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1049 | ||
| 1050 | pub const buildLog10 = ZigLLVMBuildLog10; | |
| 1051 | extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1052 | ||
| 1053 | pub const buildLog2 = ZigLLVMBuildLog2; | |
| 1054 | extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1055 | ||
| 1056 | pub const buildRound = ZigLLVMBuildRound; | |
| 1057 | extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1058 | ||
| 1059 | pub const buildSin = ZigLLVMBuildSin; | |
| 1060 | extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1061 | ||
| 1062 | pub const buildSqrt = ZigLLVMBuildSqrt; | |
| 1063 | extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1064 | ||
| 1065 | pub const buildFTrunc = ZigLLVMBuildFTrunc; | |
| 1066 | extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1067 | ||
| 1068 | pub const buildBitReverse = ZigLLVMBuildBitReverse; | |
| 1069 | extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1070 | ||
| 1071 | pub const buildBSwap = ZigLLVMBuildBSwap; | |
| 1072 | extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1073 | ||
| 1074 | pub const buildCTPop = ZigLLVMBuildCTPop; | |
| 1075 | extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; | |
| 1076 | ||
| 1077 | pub const buildCTLZ = ZigLLVMBuildCTLZ; | |
| 1078 | extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1079 | ||
| 1080 | pub const buildCTTZ = ZigLLVMBuildCTTZ; | |
| 1081 | extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1082 | ||
| 1083 | pub const buildFMA = ZigLLVMBuildFMA; | |
| 1084 | extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value; | |
| 1085 | ||
| 1086 | pub const buildUMax = ZigLLVMBuildUMax; | |
| 1087 | extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1088 | ||
| 1089 | pub const buildUMin = ZigLLVMBuildUMin; | |
| 1090 | extern fn ZigLLVMBuildUMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1091 | ||
| 1092 | pub const buildSMax = ZigLLVMBuildSMax; | |
| 1093 | extern fn ZigLLVMBuildSMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1094 | ||
| 1095 | pub const buildSMin = ZigLLVMBuildSMin; | |
| 1096 | extern fn ZigLLVMBuildSMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; | |
| 1097 | ||
| 1098 | 836 | pub const buildExactUDiv = LLVMBuildExactUDiv; |
| 1099 | 837 | extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; |
| 1100 | 838 | |
| ... | ... | @@ -1116,39 +854,6 @@ pub const Builder = opaque { |
| 1116 | 854 | pub const buildShuffleVector = LLVMBuildShuffleVector; |
| 1117 | 855 | extern fn LLVMBuildShuffleVector(*Builder, V1: *Value, V2: *Value, Mask: *Value, Name: [*:0]const u8) *Value; |
| 1118 | 856 | |
| 1119 | pub const buildAndReduce = ZigLLVMBuildAndReduce; | |
| 1120 | extern fn ZigLLVMBuildAndReduce(B: *Builder, Val: *Value) *Value; | |
| 1121 | ||
| 1122 | pub const buildOrReduce = ZigLLVMBuildOrReduce; | |
| 1123 | extern fn ZigLLVMBuildOrReduce(B: *Builder, Val: *Value) *Value; | |
| 1124 | ||
| 1125 | pub const buildXorReduce = ZigLLVMBuildXorReduce; | |
| 1126 | extern fn ZigLLVMBuildXorReduce(B: *Builder, Val: *Value) *Value; | |
| 1127 | ||
| 1128 | pub const buildIntMaxReduce = ZigLLVMBuildIntMaxReduce; | |
| 1129 | extern fn ZigLLVMBuildIntMaxReduce(B: *Builder, Val: *Value, is_signed: bool) *Value; | |
| 1130 | ||
| 1131 | pub const buildIntMinReduce = ZigLLVMBuildIntMinReduce; | |
| 1132 | extern fn ZigLLVMBuildIntMinReduce(B: *Builder, Val: *Value, is_signed: bool) *Value; | |
| 1133 | ||
| 1134 | pub const buildFPMaxReduce = ZigLLVMBuildFPMaxReduce; | |
| 1135 | extern fn ZigLLVMBuildFPMaxReduce(B: *Builder, Val: *Value) *Value; | |
| 1136 | ||
| 1137 | pub const buildFPMinReduce = ZigLLVMBuildFPMinReduce; | |
| 1138 | extern fn ZigLLVMBuildFPMinReduce(B: *Builder, Val: *Value) *Value; | |
| 1139 | ||
| 1140 | pub const buildAddReduce = ZigLLVMBuildAddReduce; | |
| 1141 | extern fn ZigLLVMBuildAddReduce(B: *Builder, Val: *Value) *Value; | |
| 1142 | ||
| 1143 | pub const buildMulReduce = ZigLLVMBuildMulReduce; | |
| 1144 | extern fn ZigLLVMBuildMulReduce(B: *Builder, Val: *Value) *Value; | |
| 1145 | ||
| 1146 | pub const buildFPAddReduce = ZigLLVMBuildFPAddReduce; | |
| 1147 | extern fn ZigLLVMBuildFPAddReduce(B: *Builder, Acc: *Value, Val: *Value) *Value; | |
| 1148 | ||
| 1149 | pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce; | |
| 1150 | extern fn ZigLLVMBuildFPMulReduce(B: *Builder, Acc: *Value, Val: *Value) *Value; | |
| 1151 | ||
| 1152 | 857 | pub const setFastMath = ZigLLVMSetFastMath; |
| 1153 | 858 | extern fn ZigLLVMSetFastMath(B: *Builder, on_state: bool) void; |
| 1154 | 859 | |
| ... | ... | @@ -1563,9 +1268,6 @@ extern fn ZigLLVMWriteImportLibrary( |
| 1563 | 1268 | kill_at: bool, |
| 1564 | 1269 | ) bool; |
| 1565 | 1270 | |
| 1566 | pub const setCallElemTypeAttr = ZigLLVMSetCallElemTypeAttr; | |
| 1567 | extern fn ZigLLVMSetCallElemTypeAttr(Call: *Value, arg_index: usize, return_type: *Type) void; | |
| 1568 | ||
| 1569 | 1271 | pub const Linkage = enum(c_uint) { |
| 1570 | 1272 | External, |
| 1571 | 1273 | AvailableExternally, |
| ... | ... | @@ -1784,9 +1486,6 @@ pub const DIGlobalVariable = opaque { |
| 1784 | 1486 | pub const DIGlobalVariableExpression = opaque { |
| 1785 | 1487 | pub const getVariable = ZigLLVMGlobalGetVariable; |
| 1786 | 1488 | extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable; |
| 1787 | ||
| 1788 | pub const getExpression = ZigLLVMGlobalGetExpression; | |
| 1789 | extern fn ZigLLVMGlobalGetExpression(global_variable: *DIGlobalVariableExpression) *DIGlobalExpression; | |
| 1790 | 1489 | }; |
| 1791 | 1490 | pub const DIType = opaque { |
| 1792 | 1491 | pub const toScope = ZigLLVMTypeToScope; |
src/value.zig+2-2| ... | ... | @@ -3831,7 +3831,7 @@ pub const Value = struct { |
| 3831 | 3831 | |
| 3832 | 3832 | /// If the value is represented in-memory as a series of bytes that all |
| 3833 | 3833 | /// have the same value, return that byte value, otherwise null. |
| 3834 | pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?Value { | |
| 3834 | pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?u8 { | |
| 3835 | 3835 | const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null; |
| 3836 | 3836 | assert(abi_size >= 1); |
| 3837 | 3837 | const byte_buffer = try mod.gpa.alloc(u8, abi_size); |
| ... | ... | @@ -3852,7 +3852,7 @@ pub const Value = struct { |
| 3852 | 3852 | for (byte_buffer[1..]) |byte| { |
| 3853 | 3853 | if (byte != first_byte) return null; |
| 3854 | 3854 | } |
| 3855 | return try mod.intValue(Type.u8, first_byte); | |
| 3855 | return first_byte; | |
| 3856 | 3856 | } |
| 3857 | 3857 | |
| 3858 | 3858 | pub fn isGenericPoison(val: Value) bool { |
src/zig_llvm.cpp+34-436| ... | ... | @@ -78,30 +78,6 @@ |
| 78 | 78 | |
| 79 | 79 | using namespace llvm; |
| 80 | 80 | |
| 81 | void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) { | |
| 82 | initializeLoopStrengthReducePass(*unwrap(R)); | |
| 83 | } | |
| 84 | ||
| 85 | void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) { | |
| 86 | initializeLowerIntrinsicsPass(*unwrap(R)); | |
| 87 | } | |
| 88 | ||
| 89 | char *ZigLLVMGetHostCPUName(void) { | |
| 90 | return strdup((const char *)sys::getHostCPUName().bytes_begin()); | |
| 91 | } | |
| 92 | ||
| 93 | char *ZigLLVMGetNativeFeatures(void) { | |
| 94 | SubtargetFeatures features; | |
| 95 | ||
| 96 | StringMap<bool> host_features; | |
| 97 | if (sys::getHostCPUFeatures(host_features)) { | |
| 98 | for (auto &F : host_features) | |
| 99 | features.AddFeature(F.first(), F.second); | |
| 100 | } | |
| 101 | ||
| 102 | return strdup((const char *)StringRef(features.getString()).bytes_begin()); | |
| 103 | } | |
| 104 | ||
| 105 | 81 | #ifndef NDEBUG |
| 106 | 82 | static const bool assertions_on = true; |
| 107 | 83 | #else |
| ... | ... | @@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri |
| 179 | 155 | return reinterpret_cast<LLVMTargetMachineRef>(TM); |
| 180 | 156 | } |
| 181 | 157 | |
| 182 | unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) { | |
| 183 | return unwrap(TD)->getStackAlignment().value(); | |
| 184 | } | |
| 185 | ||
| 186 | unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { | |
| 187 | return unwrap(TD)->getProgramAddressSpace(); | |
| 188 | } | |
| 189 | ||
| 190 | 158 | namespace { |
| 191 | 159 | // LLVM's time profiler can provide a hierarchy view of the time spent |
| 192 | 160 | // in each component. It generates JSON report in Chrome's "Trace Event" |
| ... | ... | @@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 410 | 378 | return false; |
| 411 | 379 | } |
| 412 | 380 | |
| 413 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { | |
| 414 | return wrap(Type::getTokenTy(*unwrap(context_ref))); | |
| 415 | } | |
| 416 | ||
| 417 | ||
| 418 | ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { | |
| 381 | void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { | |
| 419 | 382 | static OptBisect opt_bisect; |
| 420 | 383 | opt_bisect.setLimit(limit); |
| 421 | 384 | unwrap(context_ref)->setOptPassGate(opt_bisect); |
| ... | ... | @@ -426,241 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, |
| 426 | 389 | return wrap(func); |
| 427 | 390 | } |
| 428 | 391 | |
| 429 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, | |
| 430 | LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, | |
| 431 | const char *Name) | |
| 432 | { | |
| 433 | FunctionType *FTy = unwrap<FunctionType>(Ty); | |
| 434 | CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn), | |
| 435 | ArrayRef(unwrap(Args), NumArgs), Name); | |
| 436 | call_inst->setCallingConv(static_cast<CallingConv::ID>(CC)); | |
| 437 | switch (attr) { | |
| 438 | case ZigLLVM_CallAttrAuto: | |
| 392 | void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) { | |
| 393 | CallInst::TailCallKind TCK; | |
| 394 | switch (TailCallKind) { | |
| 395 | case ZigLLVMTailCallKindNone: | |
| 396 | TCK = CallInst::TCK_None; | |
| 439 | 397 | break; |
| 440 | case ZigLLVM_CallAttrNeverTail: | |
| 441 | call_inst->setTailCallKind(CallInst::TCK_NoTail); | |
| 398 | case ZigLLVMTailCallKindTail: | |
| 399 | TCK = CallInst::TCK_Tail; | |
| 442 | 400 | break; |
| 443 | case ZigLLVM_CallAttrNeverInline: | |
| 444 | call_inst->addFnAttr(Attribute::NoInline); | |
| 401 | case ZigLLVMTailCallKindMustTail: | |
| 402 | TCK = CallInst::TCK_MustTail; | |
| 445 | 403 | break; |
| 446 | case ZigLLVM_CallAttrAlwaysTail: | |
| 447 | call_inst->setTailCallKind(CallInst::TCK_MustTail); | |
| 404 | case ZigLLVMTailCallKindNoTail: | |
| 405 | TCK = CallInst::TCK_NoTail; | |
| 448 | 406 | break; |
| 449 | case ZigLLVM_CallAttrAlwaysInline: | |
| 450 | call_inst->addFnAttr(Attribute::AlwaysInline); | |
| 451 | break; | |
| 452 | } | |
| 453 | return wrap(call_inst); | |
| 454 | } | |
| 455 | ||
| 456 | ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, CallInst::TailCallKind TailCallKind) { | |
| 457 | unwrap<CallInst>(Call)->setTailCallKind(TailCallKind); | |
| 458 | } | |
| 459 | ||
| 460 | void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) { | |
| 461 | if (isa<Function>(unwrap(Val))) { | |
| 462 | unwrap<Function>(Val)->addAttributeAtIndex(Idx, unwrap(A)); | |
| 463 | } else { | |
| 464 | unwrap<CallInst>(Val)->addAttributeAtIndex(Idx, unwrap(A)); | |
| 465 | 407 | } |
| 466 | } | |
| 467 | ||
| 468 | LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, | |
| 469 | LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile) | |
| 470 | { | |
| 471 | CallInst *call_inst = unwrap(B)->CreateMemCpy(unwrap(Dst), | |
| 472 | MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign), unwrap(Size), isVolatile); | |
| 473 | return wrap(call_inst); | |
| 474 | } | |
| 475 | ||
| 476 | LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, | |
| 477 | unsigned Align, bool isVolatile) | |
| 478 | { | |
| 479 | CallInst *call_inst = unwrap(B)->CreateMemSet(unwrap(Ptr), unwrap(Val), unwrap(Size), | |
| 480 | MaybeAlign(Align), isVolatile); | |
| 481 | return wrap(call_inst); | |
| 482 | } | |
| 483 | ||
| 484 | LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 485 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ceil, unwrap(V), nullptr, name); | |
| 486 | return wrap(call_inst); | |
| 487 | } | |
| 488 | ||
| 489 | LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 490 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::cos, unwrap(V), nullptr, name); | |
| 491 | return wrap(call_inst); | |
| 492 | } | |
| 493 | ||
| 494 | LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 495 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp, unwrap(V), nullptr, name); | |
| 496 | return wrap(call_inst); | |
| 497 | } | |
| 498 | ||
| 499 | LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 500 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp2, unwrap(V), nullptr, name); | |
| 501 | return wrap(call_inst); | |
| 502 | } | |
| 503 | ||
| 504 | LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 505 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::fabs, unwrap(V), nullptr, name); | |
| 506 | return wrap(call_inst); | |
| 507 | } | |
| 508 | ||
| 509 | LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 510 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::floor, unwrap(V), nullptr, name); | |
| 511 | return wrap(call_inst); | |
| 512 | } | |
| 513 | ||
| 514 | LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 515 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log, unwrap(V), nullptr, name); | |
| 516 | return wrap(call_inst); | |
| 517 | } | |
| 518 | ||
| 519 | LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 520 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log10, unwrap(V), nullptr, name); | |
| 521 | return wrap(call_inst); | |
| 522 | } | |
| 523 | ||
| 524 | LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 525 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log2, unwrap(V), nullptr, name); | |
| 526 | return wrap(call_inst); | |
| 527 | } | |
| 528 | ||
| 529 | LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 530 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::round, unwrap(V), nullptr, name); | |
| 531 | return wrap(call_inst); | |
| 532 | } | |
| 533 | ||
| 534 | LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 535 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sin, unwrap(V), nullptr, name); | |
| 536 | return wrap(call_inst); | |
| 537 | } | |
| 538 | ||
| 539 | LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 540 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sqrt, unwrap(V), nullptr, name); | |
| 541 | return wrap(call_inst); | |
| 542 | } | |
| 543 | ||
| 544 | LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 545 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::trunc, unwrap(V), nullptr, name); | |
| 546 | return wrap(call_inst); | |
| 547 | } | |
| 548 | ||
| 549 | LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 550 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name); | |
| 551 | return wrap(call_inst); | |
| 552 | } | |
| 553 | ||
| 554 | LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 555 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name); | |
| 556 | return wrap(call_inst); | |
| 557 | } | |
| 558 | ||
| 559 | LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) { | |
| 560 | CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name); | |
| 561 | return wrap(call_inst); | |
| 562 | } | |
| 563 | ||
| 564 | LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 565 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 566 | return wrap(call_inst); | |
| 567 | } | |
| 568 | ||
| 569 | LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 570 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 571 | return wrap(call_inst); | |
| 572 | } | |
| 573 | ||
| 574 | LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) { | |
| 575 | llvm::Type* types[1] = { | |
| 576 | unwrap(A)->getType(), | |
| 577 | }; | |
| 578 | llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)}; | |
| 579 | ||
| 580 | CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name); | |
| 581 | return wrap(call_inst); | |
| 582 | } | |
| 583 | ||
| 584 | LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 585 | CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name); | |
| 586 | return wrap(call_inst); | |
| 587 | } | |
| 588 | ||
| 589 | LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 590 | CallInst *call_inst = unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS), name); | |
| 591 | return wrap(call_inst); | |
| 592 | } | |
| 593 | ||
| 594 | LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 595 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umax, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 596 | return wrap(call_inst); | |
| 597 | } | |
| 598 | ||
| 599 | LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 600 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umin, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 601 | return wrap(call_inst); | |
| 602 | } | |
| 603 | ||
| 604 | LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 605 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smax, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 606 | return wrap(call_inst); | |
| 607 | } | |
| 608 | ||
| 609 | LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 610 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smin, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 611 | return wrap(call_inst); | |
| 612 | } | |
| 613 | ||
| 614 | LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 615 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 616 | return wrap(call_inst); | |
| 617 | } | |
| 618 | ||
| 619 | LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 620 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::uadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 621 | return wrap(call_inst); | |
| 622 | } | |
| 623 | ||
| 624 | LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 625 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ssub_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 626 | return wrap(call_inst); | |
| 627 | } | |
| 628 | ||
| 629 | LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 630 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::usub_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 631 | return wrap(call_inst); | |
| 632 | } | |
| 633 | ||
| 634 | LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 635 | llvm::Type* types[1] = { | |
| 636 | unwrap(LHS)->getType(), | |
| 637 | }; | |
| 638 | // pass scale = 0 as third argument | |
| 639 | llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)}; | |
| 640 | ||
| 641 | CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::smul_fix_sat, types, values, nullptr, name); | |
| 642 | return wrap(call_inst); | |
| 643 | } | |
| 644 | ||
| 645 | LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 646 | llvm::Type* types[1] = { | |
| 647 | unwrap(LHS)->getType(), | |
| 648 | }; | |
| 649 | // pass scale = 0 as third argument | |
| 650 | llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)}; | |
| 651 | ||
| 652 | CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::umul_fix_sat, types, values, nullptr, name); | |
| 653 | return wrap(call_inst); | |
| 654 | } | |
| 655 | ||
| 656 | LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 657 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sshl_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 658 | return wrap(call_inst); | |
| 659 | } | |
| 660 | ||
| 661 | LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { | |
| 662 | CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ushl_sat, unwrap(LHS), unwrap(RHS), nullptr, name); | |
| 663 | return wrap(call_inst); | |
| 408 | unwrap<CallInst>(Call)->setTailCallKind(TCK); | |
| 664 | 409 | } |
| 665 | 410 | |
| 666 | 411 | void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) { |
| ... | ... | @@ -1181,82 +926,10 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) { |
| 1181 | 926 | } |
| 1182 | 927 | } |
| 1183 | 928 | |
| 1184 | void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) { | |
| 1185 | if (isa<Function>(unwrap(Val))) { | |
| 1186 | Function *func = unwrap<Function>(Val); | |
| 1187 | AttrBuilder attr_builder(func->getContext()); | |
| 1188 | Type *llvm_type = unwrap<Type>(type_val); | |
| 1189 | attr_builder.addByValAttr(llvm_type); | |
| 1190 | func->addParamAttrs(ArgNo, attr_builder); | |
| 1191 | } else { | |
| 1192 | CallInst *call = unwrap<CallInst>(Val); | |
| 1193 | AttrBuilder attr_builder(call->getContext()); | |
| 1194 | Type *llvm_type = unwrap<Type>(type_val); | |
| 1195 | attr_builder.addByValAttr(llvm_type); | |
| 1196 | // NOTE: +1 here since index 0 refers to the return value | |
| 1197 | call->addAttributeAtIndex(ArgNo + 1, attr_builder.getAttribute(Attribute::ByVal)); | |
| 1198 | } | |
| 1199 | } | |
| 1200 | ||
| 1201 | void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) { | |
| 1202 | Function *func = unwrap<Function>(fn_ref); | |
| 1203 | AttrBuilder attr_builder(func->getContext()); | |
| 1204 | Type *llvm_type = unwrap<Type>(type_val); | |
| 1205 | attr_builder.addStructRetAttr(llvm_type); | |
| 1206 | func->addParamAttrs(0, attr_builder); | |
| 1207 | } | |
| 1208 | ||
| 1209 | void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty) { | |
| 1210 | Function *func = unwrap<Function>(fn_ref); | |
| 1211 | AttrBuilder attr_builder(func->getContext()); | |
| 1212 | Type *llvm_type = unwrap<Type>(elem_ty); | |
| 1213 | attr_builder.addTypeAttr(Attribute::ElementType, llvm_type); | |
| 1214 | func->addParamAttrs(arg_index, attr_builder); | |
| 1215 | } | |
| 1216 | ||
| 1217 | void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) { | |
| 1218 | Function *func = unwrap<Function>(fn_ref); | |
| 1219 | func->addFnAttr(attr_name, attr_value); | |
| 1220 | } | |
| 1221 | ||
| 1222 | 929 | void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { |
| 1223 | 930 | cl::ParseCommandLineOptions(argc, argv); |
| 1224 | 931 | } |
| 1225 | 932 | |
| 1226 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { | |
| 1227 | return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin(); | |
| 1228 | } | |
| 1229 | ||
| 1230 | const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) { | |
| 1231 | return (const char*)Triple::getVendorTypeName((Triple::VendorType)vendor).bytes_begin(); | |
| 1232 | } | |
| 1233 | ||
| 1234 | const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) { | |
| 1235 | const char* name = (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin(); | |
| 1236 | if (strcmp(name, "macosx") == 0) return "macos"; | |
| 1237 | return name; | |
| 1238 | } | |
| 1239 | ||
| 1240 | const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) { | |
| 1241 | return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin(); | |
| 1242 | } | |
| 1243 | ||
| 1244 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, | |
| 1245 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, | |
| 1246 | ZigLLVM_ObjectFormatType *oformat) | |
| 1247 | { | |
| 1248 | char *native_triple = LLVMGetDefaultTargetTriple(); | |
| 1249 | Triple triple(Triple::normalize(native_triple)); | |
| 1250 | ||
| 1251 | *arch_type = (ZigLLVM_ArchType)triple.getArch(); | |
| 1252 | *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); | |
| 1253 | *os_type = (ZigLLVM_OSType)triple.getOS(); | |
| 1254 | *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); | |
| 1255 | *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat(); | |
| 1256 | ||
| 1257 | free(native_triple); | |
| 1258 | } | |
| 1259 | ||
| 1260 | 933 | void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) { |
| 1261 | 934 | unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); |
| 1262 | 935 | unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4); |
| ... | ... | @@ -1314,50 +987,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe |
| 1314 | 987 | return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name)); |
| 1315 | 988 | } |
| 1316 | 989 | |
| 1317 | void ZigLLVMSetTailCall(LLVMValueRef Call) { | |
| 1318 | unwrap<CallInst>(Call)->setTailCallKind(CallInst::TCK_MustTail); | |
| 1319 | } | |
| 1320 | ||
| 1321 | void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) { | |
| 1322 | CallInst *call_inst = unwrap<CallInst>(Call); | |
| 1323 | Type *llvm_type = unwrap<Type>(return_type); | |
| 1324 | call_inst->addParamAttr(AttributeList::ReturnIndex, | |
| 1325 | Attribute::getWithStructRetType(call_inst->getContext(), llvm_type)); | |
| 1326 | } | |
| 1327 | ||
| 1328 | void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type) { | |
| 1329 | CallInst *call_inst = unwrap<CallInst>(Call); | |
| 1330 | Type *llvm_type = unwrap<Type>(return_type); | |
| 1331 | call_inst->addParamAttr(arg_index, | |
| 1332 | Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); | |
| 1333 | } | |
| 1334 | ||
| 1335 | void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { | |
| 1336 | unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data)); | |
| 1337 | } | |
| 1338 | ||
| 1339 | void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, ZigLLVM_CallingConv cc) { | |
| 1340 | unwrap<Function>(function)->setCallingConv(static_cast<CallingConv::ID>(cc)); | |
| 1341 | } | |
| 1342 | ||
| 1343 | class MyOStream: public raw_ostream { | |
| 1344 | public: | |
| 1345 | MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) : | |
| 1346 | raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) { | |
| 1347 | ||
| 1348 | } | |
| 1349 | void write_impl(const char *ptr, size_t len) override { | |
| 1350 | append_diagnostic(context, ptr, len); | |
| 1351 | pos += len; | |
| 1352 | } | |
| 1353 | uint64_t current_pos() const override { | |
| 1354 | return pos; | |
| 1355 | } | |
| 1356 | void (*append_diagnostic)(void *, const char *, size_t); | |
| 1357 | void *context; | |
| 1358 | size_t pos; | |
| 1359 | }; | |
| 1360 | ||
| 1361 | 990 | bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, |
| 1362 | 991 | const char *output_lib_path, bool kill_at) |
| 1363 | 992 | { |
| ... | ... | @@ -1489,72 +1118,41 @@ bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disab |
| 1489 | 1118 | return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output); |
| 1490 | 1119 | } |
| 1491 | 1120 | |
| 1492 | inline LLVMAttributeRef wrap(Attribute Attr) { | |
| 1493 | return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer()); | |
| 1494 | } | |
| 1495 | ||
| 1496 | inline Attribute unwrap(LLVMAttributeRef Attr) { | |
| 1497 | return Attribute::fromRawPointer(Attr); | |
| 1498 | } | |
| 1499 | ||
| 1500 | LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1501 | return wrap(unwrap(B)->CreateAndReduce(unwrap(Val))); | |
| 1502 | } | |
| 1503 | ||
| 1504 | LLVMValueRef ZigLLVMBuildOrReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1505 | return wrap(unwrap(B)->CreateOrReduce(unwrap(Val))); | |
| 1506 | } | |
| 1507 | ||
| 1508 | LLVMValueRef ZigLLVMBuildXorReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1509 | return wrap(unwrap(B)->CreateXorReduce(unwrap(Val))); | |
| 1510 | } | |
| 1511 | ||
| 1512 | LLVMValueRef ZigLLVMBuildIntMaxReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed) { | |
| 1513 | return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Val), is_signed)); | |
| 1514 | } | |
| 1515 | ||
| 1516 | LLVMValueRef ZigLLVMBuildIntMinReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed) { | |
| 1517 | return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Val), is_signed)); | |
| 1518 | } | |
| 1519 | ||
| 1520 | LLVMValueRef ZigLLVMBuildFPMaxReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1521 | return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Val))); | |
| 1522 | } | |
| 1523 | ||
| 1524 | LLVMValueRef ZigLLVMBuildFPMinReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1525 | return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Val))); | |
| 1526 | } | |
| 1527 | ||
| 1528 | LLVMValueRef ZigLLVMBuildAddReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1529 | return wrap(unwrap(B)->CreateAddReduce(unwrap(Val))); | |
| 1121 | void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) { | |
| 1122 | unwrap(new_owner)->takeName(unwrap(victim)); | |
| 1530 | 1123 | } |
| 1531 | 1124 | |
| 1532 | LLVMValueRef ZigLLVMBuildMulReduce(LLVMBuilderRef B, LLVMValueRef Val) { | |
| 1533 | return wrap(unwrap(B)->CreateMulReduce(unwrap(Val))); | |
| 1125 | void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal) { | |
| 1126 | unwrap<GlobalValue>(GlobalVal)->removeFromParent(); | |
| 1534 | 1127 | } |
| 1535 | 1128 | |
| 1536 | LLVMValueRef ZigLLVMBuildFPAddReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) { | |
| 1537 | return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc), unwrap(Val))); | |
| 1129 | void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal) { | |
| 1130 | unwrap<GlobalValue>(GlobalVal)->eraseFromParent(); | |
| 1538 | 1131 | } |
| 1539 | 1132 | |
| 1540 | LLVMValueRef ZigLLVMBuildFPMulReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val) { | |
| 1541 | return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc), unwrap(Val))); | |
| 1133 | void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal) { | |
| 1134 | auto *GV = unwrap<GlobalValue>(GlobalVal); | |
| 1135 | assert(GV->getParent() == nullptr); | |
| 1136 | switch (GV->getValueID()) { | |
| 1137 | #define HANDLE_GLOBAL_VALUE(NAME) \ | |
| 1138 | case Value::NAME##Val: \ | |
| 1139 | delete static_cast<NAME *>(GV); \ | |
| 1140 | break; | |
| 1141 | #include <llvm/IR/Value.def> | |
| 1142 | default: llvm_unreachable("Expected global value"); | |
| 1143 | } | |
| 1542 | 1144 | } |
| 1543 | 1145 | |
| 1544 | void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim) { | |
| 1545 | unwrap(new_owner)->takeName(unwrap(victim)); | |
| 1146 | void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal) { | |
| 1147 | unwrap<GlobalVariable>(GlobalVar)->setInitializer(ConstantVal ? unwrap<Constant>(ConstantVal) : nullptr); | |
| 1546 | 1148 | } |
| 1547 | 1149 | |
| 1548 | 1150 | ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression) { |
| 1549 | 	return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable()); | |
| 1550 | } | |
| 1551 | ||
| 1552 | ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression) { | |
| 1553 | 	return reinterpret_cast<ZigLLVMDIGlobalExpression*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getExpression()); | |
| 1151 | return reinterpret_cast<ZigLLVMDIGlobalVariable*>(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)->getVariable()); | |
| 1554 | 1152 | } |
| 1555 | 1153 | |
| 1556 | 1154 | void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) { |
| 1557 | 	unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)); | |
| 1155 | unwrap<GlobalVariable>(Val)->addDebugInfo(reinterpret_cast<DIGlobalVariableExpression*>(global_variable_expression)); | |
| 1558 | 1156 | } |
| 1559 | 1157 | |
| 1560 | 1158 | static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, ""); |
src/zig_llvm.h+13-105| ... | ... | @@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint; |
| 43 | 43 | struct ZigLLVMDINode; |
| 44 | 44 | struct ZigLLVMMDString; |
| 45 | 45 | |
| 46 | ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); | |
| 47 | ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | |
| 48 | ||
| 49 | /// Caller must free memory with LLVMDisposeMessage | |
| 50 | ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); | |
| 51 | ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); | |
| 52 | ||
| 53 | 46 | ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, |
| 54 | 47 | char **error_message, bool is_debug, |
| 55 | 48 | bool is_small, bool time_report, bool tsan, bool lto, |
| ... | ... | @@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co |
| 67 | 60 | const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, |
| 68 | 61 | LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name); |
| 69 | 62 | |
| 70 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); | |
| 71 | ||
| 72 | 63 | ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit); |
| 73 | 64 | |
| 74 | 65 | ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, |
| 75 | 66 | LLVMTypeRef FunctionTy, unsigned AddressSpace); |
| 76 | 67 | |
| 68 | enum ZigLLVMTailCallKind { | |
| 69 | ZigLLVMTailCallKindNone, | |
| 70 | ZigLLVMTailCallKindTail, | |
| 71 | ZigLLVMTailCallKindMustTail, | |
| 72 | ZigLLVMTailCallKindNoTail, | |
| 73 | }; | |
| 74 | ||
| 75 | ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind); | |
| 76 | ||
| 77 | 77 | enum ZigLLVM_CallingConv { |
| 78 | 78 | ZigLLVM_C = 0, |
| 79 | 79 | ZigLLVM_Fast = 8, |
| ... | ... | @@ -122,66 +122,6 @@ enum ZigLLVM_CallingConv { |
| 122 | 122 | ZigLLVM_MaxID = 1023, |
| 123 | 123 | }; |
| 124 | 124 | |
| 125 | enum ZigLLVM_CallAttr { | |
| 126 | ZigLLVM_CallAttrAuto, | |
| 127 | ZigLLVM_CallAttrNeverTail, | |
| 128 | ZigLLVM_CallAttrNeverInline, | |
| 129 | ZigLLVM_CallAttrAlwaysTail, | |
| 130 | ZigLLVM_CallAttrAlwaysInline, | |
| 131 | }; | |
| 132 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type, | |
| 133 | LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC, | |
| 134 | enum ZigLLVM_CallAttr attr, const char *Name); | |
| 135 | ||
| 136 | ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A); | |
| 137 | ||
| 138 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, | |
| 139 | LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile); | |
| 140 | ||
| 141 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, | |
| 142 | unsigned Align, bool isVolatile); | |
| 143 | ||
| 144 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 145 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 146 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 147 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 148 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 149 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 150 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 151 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 152 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 153 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 154 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 155 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 156 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 157 | ||
| 158 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 159 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 160 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name); | |
| 161 | ||
| 162 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 163 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 164 | ||
| 165 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name); | |
| 166 | ||
| 167 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 168 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 169 | ||
| 170 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 171 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 172 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 173 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 174 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 175 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 176 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 177 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 178 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name); | |
| 179 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name); | |
| 180 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 181 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); | |
| 182 | ZIG_EXTERN_C LLVMValueRef LLVMBuildVectorSplat(LLVMBuilderRef B, unsigned elem_count, LLVMValueRef V, const char *Name); | |
| 183 | ||
| 184 | ||
| 185 | 125 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, |
| 186 | 126 | const char *name); |
| 187 | 127 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, |
| ... | ... | @@ -345,22 +285,10 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu |
| 345 | 285 | struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref); |
| 346 | 286 | |
| 347 | 287 | ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); |
| 348 | ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call); | |
| 349 | ZIG_EXTERN_C void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type); | |
| 350 | ZIG_EXTERN_C void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type); | |
| 351 | ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data); | |
| 352 | ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc); | |
| 353 | ||
| 354 | ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); | |
| 355 | ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val); | |
| 356 | ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val); | |
| 357 | ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty); | |
| 358 | ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); | |
| 359 | 288 | |
| 360 | 289 | ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); |
| 361 | 290 | |
| 362 | 291 | ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression); |
| 363 | ZIG_EXTERN_C ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression); | |
| 364 | 292 | ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression); |
| 365 | 293 | |
| 366 | 294 | |
| ... | ... | @@ -563,19 +491,11 @@ enum ZigLLVM_ObjectFormatType { |
| 563 | 491 | ZigLLVM_XCOFF, |
| 564 | 492 | }; |
| 565 | 493 | |
| 566 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAndReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 567 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildOrReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 568 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildXorReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 569 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildIntMaxReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed); | |
| 570 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildIntMinReduce(LLVMBuilderRef B, LLVMValueRef Val, bool is_signed); | |
| 571 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMaxReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 572 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMinReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 573 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAddReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 574 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMulReduce(LLVMBuilderRef B, LLVMValueRef Val); | |
| 575 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPAddReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val); | |
| 576 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFPMulReduce(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Val); | |
| 577 | ||
| 578 | 494 | ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim); |
| 495 | ZIG_EXTERN_C void ZigLLVMRemoveGlobalValue(LLVMValueRef GlobalVal); | |
| 496 | ZIG_EXTERN_C void ZigLLVMEraseGlobalValue(LLVMValueRef GlobalVal); | |
| 497 | ZIG_EXTERN_C void ZigLLVMDeleteGlobalValue(LLVMValueRef GlobalVal); | |
| 498 | ZIG_EXTERN_C void ZigLLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal); | |
| 579 | 499 | |
| 580 | 500 | #define ZigLLVM_DIFlags_Zero 0U |
| 581 | 501 | #define ZigLLVM_DIFlags_Private 1U |
| ... | ... | @@ -610,11 +530,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim); |
| 610 | 530 | #define ZigLLVM_DIFlags_LittleEndian (1U << 28) |
| 611 | 531 | #define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29) |
| 612 | 532 | |
| 613 | ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch); | |
| 614 | ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor); | |
| 615 | ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os); | |
| 616 | ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi); | |
| 617 | ||
| 618 | 533 | ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output); |
| 619 | 534 | ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output); |
| 620 | 535 | ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output); |
| ... | ... | @@ -625,11 +540,4 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil |
| 625 | 540 | ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch, |
| 626 | 541 | const char *output_lib_path, bool kill_at); |
| 627 | 542 | |
| 628 | ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, | |
| 629 | enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type, | |
| 630 | enum ZigLLVM_ObjectFormatType *oformat); | |
| 631 | ||
| 632 | ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD); | |
| 633 | ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD); | |
| 634 | ||
| 635 | 543 | #endif |