| ... | @@ -359,7 +359,7 @@ const DataLayoutBuilder = struct { | ... | @@ -359,7 +359,7 @@ const DataLayoutBuilder = struct { |
| 359 | .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix. | 359 | .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix. |
| 360 | // Other symbols get a `_` prefix. | 360 | // Other symbols get a `_` prefix. |
| 361 | .coff => switch (self.target.os.tag) { | 361 | .coff => switch (self.target.os.tag) { |
| 362 | .windows => switch (self.target.cpu.arch) { | 362 | .uefi, .windows => switch (self.target.cpu.arch) { |
| 363 | .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual | 363 | .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual |
| 364 | // prefix. Regular C symbols get a `_` prefix. Functions with `__stdcall`, | 364 | // prefix. Regular C symbols get a `_` prefix. Functions with `__stdcall`, |
| 365 | //`__fastcall`, and `__vectorcall` have custom mangling that appends `@N` | 365 | //`__fastcall`, and `__vectorcall` have custom mangling that appends `@N` |
| ... | @@ -794,7 +794,7 @@ pub const Object = struct { | ... | @@ -794,7 +794,7 @@ pub const Object = struct { |
| 794 | builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( | 794 | builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( |
| 795 | DW.LANG.C99, | 795 | DW.LANG.C99, |
| 796 | builder.llvm.di_builder.?.createFile(options.root_name, compile_unit_dir_z), | 796 | builder.llvm.di_builder.?.createFile(options.root_name, compile_unit_dir_z), |
| 797 | producer.toSlice(&builder).?, | 797 | producer.slice(&builder).?, |
| 798 | options.optimize_mode != .Debug, | 798 | options.optimize_mode != .Debug, |
| 799 | "", // flags | 799 | "", // flags |
| 800 | 0, // runtime version | 800 | 0, // runtime version |
| ... | @@ -830,7 +830,7 @@ pub const Object = struct { | ... | @@ -830,7 +830,7 @@ pub const Object = struct { |
| 830 | | 830 | |
| 831 | target_machine = llvm.TargetMachine.create( | 831 | target_machine = llvm.TargetMachine.create( |
| 832 | builder.llvm.target.?, | 832 | builder.llvm.target.?, |
| 833 | builder.target_triple.toSlice(&builder).?, | 833 | builder.target_triple.slice(&builder).?, |
| 834 | if (options.target.cpu.model.llvm_name) |s| s.ptr else null, | 834 | if (options.target.cpu.model.llvm_name) |s| s.ptr else null, |
| 835 | options.llvm_cpu_features, | 835 | options.llvm_cpu_features, |
| 836 | opt_level, | 836 | opt_level, |
| ... | @@ -861,7 +861,7 @@ pub const Object = struct { | ... | @@ -861,7 +861,7 @@ pub const Object = struct { |
| 861 | defer llvm.disposeMessage(rep); | 861 | defer llvm.disposeMessage(rep); |
| 862 | std.testing.expectEqualStrings( | 862 | std.testing.expectEqualStrings( |
| 863 | std.mem.span(rep), | 863 | std.mem.span(rep), |
| 864 | builder.data_layout.toSlice(&builder).?, | 864 | builder.data_layout.slice(&builder).?, |
| 865 | ) catch unreachable; | 865 | ) catch unreachable; |
| 866 | } | 866 | } |
| 867 | } | 867 | } |
| ... | @@ -963,7 +963,7 @@ pub const Object = struct { | ... | @@ -963,7 +963,7 @@ pub const Object = struct { |
| 963 | | 963 | |
| 964 | llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ | 964 | llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ |
| 965 | global_index.toConst(), | 965 | global_index.toConst(), |
| 966 | try o.builder.intConst(llvm_usize_ty, name.toSlice(&o.builder).?.len), | 966 | try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len), |
| 967 | }); | 967 | }); |
| 968 | } | 968 | } |
| 969 | | 969 | |
| ... | @@ -1223,6 +1223,7 @@ pub const Object = struct { | ... | @@ -1223,6 +1223,7 @@ pub const Object = struct { |
| 1223 | const func = mod.funcInfo(func_index); | 1223 | const func = mod.funcInfo(func_index); |
| 1224 | const decl_index = func.owner_decl; | 1224 | const decl_index = func.owner_decl; |
| 1225 | const decl = mod.declPtr(decl_index); | 1225 | const decl = mod.declPtr(decl_index); |
| | 1226 | const fn_info = mod.typeToFunc(decl.ty).?; |
| 1226 | const target = mod.getTarget(); | 1227 | const target = mod.getTarget(); |
| 1227 | const ip = &mod.intern_pool; | 1228 | const ip = &mod.intern_pool; |
| 1228 | | 1229 | |
| ... | @@ -1237,28 +1238,43 @@ pub const Object = struct { | ... | @@ -1237,28 +1238,43 @@ pub const Object = struct { |
| 1237 | const global = function.ptrConst(&o.builder).global; | 1238 | const global = function.ptrConst(&o.builder).global; |
| 1238 | const llvm_func = global.toLlvm(&o.builder); | 1239 | const llvm_func = global.toLlvm(&o.builder); |
| 1239 | | 1240 | |
| | 1241 | var attributes = try function.ptrConst(&o.builder).attributes.toWip(&o.builder); |
| | 1242 | defer attributes.deinit(&o.builder); |
| | 1243 | |
| 1240 | if (func.analysis(ip).is_noinline) { | 1244 | if (func.analysis(ip).is_noinline) { |
| | 1245 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1241 | o.addFnAttr(llvm_func, "noinline"); | 1246 | o.addFnAttr(llvm_func, "noinline"); |
| 1242 | } else { | 1247 | } else { |
| | 1248 | _ = try attributes.removeFnAttr(.@"noinline"); |
| 1243 | Object.removeFnAttr(llvm_func, "noinline"); | 1249 | Object.removeFnAttr(llvm_func, "noinline"); |
| 1244 | } | 1250 | } |
| 1245 | | 1251 | |
| 1246 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { | 1252 | if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| { |
| | 1253 | try attributes.addFnAttr(.{ .alignstack = Builder.Alignment.fromByteUnits(alignment) }, &o.builder); |
| | 1254 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| 1247 | o.addFnAttrInt(llvm_func, "alignstack", alignment); | 1255 | o.addFnAttrInt(llvm_func, "alignstack", alignment); |
| 1248 | o.addFnAttr(llvm_func, "noinline"); | 1256 | o.addFnAttr(llvm_func, "noinline"); |
| 1249 | } else { | 1257 | } else { |
| | 1258 | _ = try attributes.removeFnAttr(.alignstack); |
| 1250 | Object.removeFnAttr(llvm_func, "alignstack"); | 1259 | Object.removeFnAttr(llvm_func, "alignstack"); |
| 1251 | } | 1260 | } |
| 1252 | | 1261 | |
| 1253 | if (func.analysis(ip).is_cold) { | 1262 | if (func.analysis(ip).is_cold) { |
| | 1263 | try attributes.addFnAttr(.cold, &o.builder); |
| 1254 | o.addFnAttr(llvm_func, "cold"); | 1264 | o.addFnAttr(llvm_func, "cold"); |
| 1255 | } else { | 1265 | } else { |
| | 1266 | _ = try attributes.removeFnAttr(.cold); |
| 1256 | Object.removeFnAttr(llvm_func, "cold"); | 1267 | Object.removeFnAttr(llvm_func, "cold"); |
| 1257 | } | 1268 | } |
| 1258 | | 1269 | |
| 1259 | // TODO: disable this if safety is off for the function scope | 1270 | // TODO: disable this if safety is off for the function scope |
| 1260 | const ssp_buf_size = mod.comp.bin_file.options.stack_protector; | 1271 | const ssp_buf_size = mod.comp.bin_file.options.stack_protector; |
| 1261 | if (ssp_buf_size != 0) { | 1272 | if (ssp_buf_size != 0) { |
| | 1273 | try attributes.addFnAttr(.sspstrong, &o.builder); |
| | 1274 | try attributes.addFnAttr(.{ .string = .{ |
| | 1275 | .kind = try o.builder.string("stack-protector-buffer-size"), |
| | 1276 | .value = try o.builder.fmt("{d}", .{ssp_buf_size}), |
| | 1277 | } }, &o.builder); |
| 1262 | var buf: [12]u8 = undefined; | 1278 | var buf: [12]u8 = undefined; |
| 1263 | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; | 1279 | const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; |
| 1264 | o.addFnAttr(llvm_func, "sspstrong"); | 1280 | o.addFnAttr(llvm_func, "sspstrong"); |
| ... | @@ -1267,8 +1283,16 @@ pub const Object = struct { | ... | @@ -1267,8 +1283,16 @@ pub const Object = struct { |
| 1267 | | 1283 | |
| 1268 | // TODO: disable this if safety is off for the function scope | 1284 | // TODO: disable this if safety is off for the function scope |
| 1269 | if (mod.comp.bin_file.options.stack_check) { | 1285 | if (mod.comp.bin_file.options.stack_check) { |
| | 1286 | try attributes.addFnAttr(.{ .string = .{ |
| | 1287 | .kind = try o.builder.string("probe-stack"), |
| | 1288 | .value = try o.builder.string("__zig_probe_stack"), |
| | 1289 | } }, &o.builder); |
| 1270 | o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); | 1290 | o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); |
| 1271 | } else if (target.os.tag == .uefi) { | 1291 | } else if (target.os.tag == .uefi) { |
| | 1292 | try attributes.addFnAttr(.{ .string = .{ |
| | 1293 | .kind = try o.builder.string("no-stack-arg-probe"), |
| | 1294 | .value = .empty, |
| | 1295 | } }, &o.builder); |
| 1272 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); | 1296 | o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); |
| 1273 | } | 1297 | } |
| 1274 | | 1298 | |
| ... | @@ -1286,18 +1310,22 @@ pub const Object = struct { | ... | @@ -1286,18 +1310,22 @@ pub const Object = struct { |
| 1286 | var llvm_arg_i: u32 = 0; | 1310 | var llvm_arg_i: u32 = 0; |
| 1287 | | 1311 | |
| 1288 | // This gets the LLVM values from the function and stores them in `dg.args`. | 1312 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| 1289 | const fn_info = mod.typeToFunc(decl.ty).?; | | |
| 1290 | const sret = firstParamSRet(fn_info, mod); | 1313 | const sret = firstParamSRet(fn_info, mod); |
| 1291 | const ret_ptr: Builder.Value = if (sret) param: { | 1314 | const ret_ptr: Builder.Value = if (sret) param: { |
| 1292 | const param = wip.arg(llvm_arg_i); | 1315 | const param = wip.arg(llvm_arg_i); |
| 1293 | llvm_arg_i += 1; | 1316 | llvm_arg_i += 1; |
| 1294 | break :param param; | 1317 | break :param param; |
| 1295 | } else .none; | 1318 | } else .none; |
| 1296 | const gpa = o.gpa; | | |
| 1297 | | 1319 | |
| 1298 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { | 1320 | if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { |
| 1299 | .signed => o.addAttr(llvm_func, 0, "signext"), | 1321 | .signed => { |
| 1300 | .unsigned => o.addAttr(llvm_func, 0, "zeroext"), | 1322 | try attributes.addRetAttr(.signext, &o.builder); |
| | 1323 | o.addAttr(llvm_func, 0, "signext"); |
| | 1324 | }, |
| | 1325 | .unsigned => { |
| | 1326 | try attributes.addRetAttr(.zeroext, &o.builder); |
| | 1327 | o.addAttr(llvm_func, 0, "zeroext"); |
| | 1328 | }, |
| 1301 | }; | 1329 | }; |
| 1302 | | 1330 | |
| 1303 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and | 1331 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and |
| ... | @@ -1312,6 +1340,7 @@ pub const Object = struct { | ... | @@ -1312,6 +1340,7 @@ pub const Object = struct { |
| 1312 | // This is the list of args we will use that correspond directly to the AIR arg | 1340 | // This is the list of args we will use that correspond directly to the AIR arg |
| 1313 | // instructions. Depending on the calling convention, this list is not necessarily | 1341 | // instructions. Depending on the calling convention, this list is not necessarily |
| 1314 | // a bijection with the actual LLVM parameters of the function. | 1342 | // a bijection with the actual LLVM parameters of the function. |
| | 1343 | const gpa = o.gpa; |
| 1315 | var args: std.ArrayListUnmanaged(Builder.Value) = .{}; | 1344 | var args: std.ArrayListUnmanaged(Builder.Value) = .{}; |
| 1316 | defer args.deinit(gpa); | 1345 | defer args.deinit(gpa); |
| 1317 | | 1346 | |
| ... | @@ -1337,7 +1366,7 @@ pub const Object = struct { | ... | @@ -1337,7 +1366,7 @@ pub const Object = struct { |
| 1337 | } else { | 1366 | } else { |
| 1338 | args.appendAssumeCapacity(param); | 1367 | args.appendAssumeCapacity(param); |
| 1339 | | 1368 | |
| 1340 | o.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, @intCast(llvm_arg_i)); | 1369 | try o.addByValParamAttrsOld(&attributes, llvm_func, param_ty, param_index, fn_info, llvm_arg_i); |
| 1341 | } | 1370 | } |
| 1342 | llvm_arg_i += 1; | 1371 | llvm_arg_i += 1; |
| 1343 | }, | 1372 | }, |
| ... | @@ -1347,7 +1376,7 @@ pub const Object = struct { | ... | @@ -1347,7 +1376,7 @@ pub const Object = struct { |
| 1347 | const param = wip.arg(llvm_arg_i); | 1376 | const param = wip.arg(llvm_arg_i); |
| 1348 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 1377 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1349 | | 1378 | |
| 1350 | o.addByRefParamAttrs(llvm_func, @intCast(llvm_arg_i), @intCast(alignment.toByteUnits() orelse 0), it.byval_attr, param_llvm_ty); | 1379 | try o.addByRefParamAttrsOld(&attributes, llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1351 | llvm_arg_i += 1; | 1380 | llvm_arg_i += 1; |
| 1352 | | 1381 | |
| 1353 | if (isByRef(param_ty, mod)) { | 1382 | if (isByRef(param_ty, mod)) { |
| ... | @@ -1362,7 +1391,8 @@ pub const Object = struct { | ... | @@ -1362,7 +1391,8 @@ pub const Object = struct { |
| 1362 | const param = wip.arg(llvm_arg_i); | 1391 | const param = wip.arg(llvm_arg_i); |
| 1363 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 1392 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 1364 | | 1393 | |
| 1365 | o.addArgAttr(llvm_func, @intCast(llvm_arg_i), "noundef"); | 1394 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| | 1395 | o.addArgAttr(llvm_func, llvm_arg_i, "noundef"); |
| 1366 | llvm_arg_i += 1; | 1396 | llvm_arg_i += 1; |
| 1367 | | 1397 | |
| 1368 | if (isByRef(param_ty, mod)) { | 1398 | if (isByRef(param_ty, mod)) { |
| ... | @@ -1398,21 +1428,28 @@ pub const Object = struct { | ... | @@ -1398,21 +1428,28 @@ pub const Object = struct { |
| 1398 | | 1428 | |
| 1399 | if (math.cast(u5, it.zig_index - 1)) |i| { | 1429 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1400 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | 1430 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1401 | o.addArgAttr(llvm_func, @intCast(llvm_arg_i), "noalias"); | 1431 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| | 1432 | o.addArgAttr(llvm_func, llvm_arg_i, "noalias"); |
| 1402 | } | 1433 | } |
| 1403 | } | 1434 | } |
| 1404 | if (param_ty.zigTypeTag(mod) != .Optional) { | 1435 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1405 | o.addArgAttr(llvm_func, @intCast(llvm_arg_i), "nonnull"); | 1436 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 1437 | o.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); |
| 1406 | } | 1438 | } |
| 1407 | if (ptr_info.flags.is_const) { | 1439 | if (ptr_info.flags.is_const) { |
| 1408 | o.addArgAttr(llvm_func, @intCast(llvm_arg_i), "readonly"); | 1440 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| | 1441 | o.addArgAttr(llvm_func, llvm_arg_i, "readonly"); |
| 1409 | } | 1442 | } |
| 1410 | const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse | 1443 | const elem_align = Builder.Alignment.fromByteUnits( |
| 1411 | @max(ptr_info.child.toType().abiAlignment(mod), 1); | 1444 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 1412 | o.addArgAttrInt(llvm_func, @intCast(llvm_arg_i), "align", elem_align); | 1445 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| 1413 | const ptr_param = wip.arg(llvm_arg_i + 0); | 1446 | ); |
| 1414 | const len_param = wip.arg(llvm_arg_i + 1); | 1447 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1415 | llvm_arg_i += 2; | 1448 | o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); |
| | 1449 | const ptr_param = wip.arg(llvm_arg_i); |
| | 1450 | llvm_arg_i += 1; |
| | 1451 | const len_param = wip.arg(llvm_arg_i); |
| | 1452 | llvm_arg_i += 1; |
| 1416 | | 1453 | |
| 1417 | const slice_llvm_ty = try o.lowerType(param_ty); | 1454 | const slice_llvm_ty = try o.lowerType(param_ty); |
| 1418 | args.appendAssumeCapacity( | 1455 | args.appendAssumeCapacity( |
| ... | @@ -1482,6 +1519,8 @@ pub const Object = struct { | ... | @@ -1482,6 +1519,8 @@ pub const Object = struct { |
| 1482 | } | 1519 | } |
| 1483 | } | 1520 | } |
| 1484 | | 1521 | |
| | 1522 | function.ptr(&o.builder).attributes = try attributes.finish(&o.builder); |
| | 1523 | |
| 1485 | var di_file: ?*llvm.DIFile = null; | 1524 | var di_file: ?*llvm.DIFile = null; |
| 1486 | var di_scope: ?*llvm.DIScope = null; | 1525 | var di_scope: ?*llvm.DIScope = null; |
| 1487 | | 1526 | |
| ... | @@ -1618,7 +1657,7 @@ pub const Object = struct { | ... | @@ -1618,7 +1657,7 @@ pub const Object = struct { |
| 1618 | llvm_global.setDLLStorageClass(.Default); | 1657 | llvm_global.setDLLStorageClass(.Default); |
| 1619 | } | 1658 | } |
| 1620 | if (self.di_map.get(decl)) |di_node| { | 1659 | if (self.di_map.get(decl)) |di_node| { |
| 1621 | const decl_name_slice = decl_name.toSlice(&self.builder).?; | 1660 | const decl_name_slice = decl_name.slice(&self.builder).?; |
| 1622 | if (try decl.isFunction(mod)) { | 1661 | if (try decl.isFunction(mod)) { |
| 1623 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); | 1662 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1624 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len); | 1663 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, decl_name_slice.ptr, decl_name_slice.len); |
| ... | @@ -1655,7 +1694,7 @@ pub const Object = struct { | ... | @@ -1655,7 +1694,7 @@ pub const Object = struct { |
| 1655 | llvm_global.setDLLStorageClass(.DLLExport); | 1694 | llvm_global.setDLLStorageClass(.DLLExport); |
| 1656 | } | 1695 | } |
| 1657 | if (self.di_map.get(decl)) |di_node| { | 1696 | if (self.di_map.get(decl)) |di_node| { |
| 1658 | const exp_name_slice = exp_name.toSlice(&self.builder).?; | 1697 | const exp_name_slice = exp_name.slice(&self.builder).?; |
| 1659 | if (try decl.isFunction(mod)) { | 1698 | if (try decl.isFunction(mod)) { |
| 1660 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); | 1699 | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1661 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len); | 1700 | const linkage_name = llvm.MDString.get(self.builder.llvm.context, exp_name_slice.ptr, exp_name_slice.len); |
| ... | @@ -2816,7 +2855,7 @@ pub const Object = struct { | ... | @@ -2816,7 +2855,7 @@ pub const Object = struct { |
| 2816 | const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))); | 2855 | const fqn = try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))); |
| 2817 | | 2856 | |
| 2818 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); | 2857 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 2819 | const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace)); | 2858 | const llvm_fn = o.llvm_module.addFunctionInAddressSpace(fqn.slice(&o.builder).?, fn_type.toLlvm(&o.builder), @intFromEnum(llvm_addrspace)); |
| 2820 | | 2859 | |
| 2821 | var global = Builder.Global{ | 2860 | var global = Builder.Global{ |
| 2822 | .type = fn_type, | 2861 | .type = fn_type, |
| ... | @@ -2826,6 +2865,9 @@ pub const Object = struct { | ... | @@ -2826,6 +2865,9 @@ pub const Object = struct { |
| 2826 | .global = @enumFromInt(o.builder.globals.count()), | 2865 | .global = @enumFromInt(o.builder.globals.count()), |
| 2827 | }; | 2866 | }; |
| 2828 | | 2867 | |
| | 2868 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 2869 | defer attributes.deinit(&o.builder); |
| | 2870 | |
| 2829 | const is_extern = decl.isExtern(mod); | 2871 | const is_extern = decl.isExtern(mod); |
| 2830 | if (!is_extern) { | 2872 | if (!is_extern) { |
| 2831 | global.linkage = .internal; | 2873 | global.linkage = .internal; |
| ... | @@ -2834,43 +2876,64 @@ pub const Object = struct { | ... | @@ -2834,43 +2876,64 @@ pub const Object = struct { |
| 2834 | llvm_fn.setUnnamedAddr(.True); | 2876 | llvm_fn.setUnnamedAddr(.True); |
| 2835 | } else { | 2877 | } else { |
| 2836 | if (target.isWasm()) { | 2878 | if (target.isWasm()) { |
| | 2879 | try attributes.addFnAttr(.{ .string = .{ |
| | 2880 | .kind = try o.builder.string("wasm-import-name"), |
| | 2881 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| | 2882 | } }, &o.builder); |
| 2837 | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); | 2883 | o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name)); |
| 2838 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { | 2884 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2839 | if (!std.mem.eql(u8, lib_name, "c")) { | 2885 | if (!std.mem.eql(u8, lib_name, "c")) { |
| | 2886 | try attributes.addFnAttr(.{ .string = .{ |
| | 2887 | .kind = try o.builder.string("wasm-import-module"), |
| | 2888 | .value = try o.builder.string(lib_name), |
| | 2889 | } }, &o.builder); |
| 2840 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); | 2890 | o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); |
| 2841 | } | 2891 | } |
| 2842 | } | 2892 | } |
| 2843 | } | 2893 | } |
| 2844 | } | 2894 | } |
| 2845 | | 2895 | |
| | 2896 | var llvm_arg_i: u32 = 0; |
| 2846 | if (sret) { | 2897 | if (sret) { |
| 2847 | o.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0 | 2898 | // Sret pointers must not be address 0 |
| 2848 | o.addArgAttr(llvm_fn, 0, "noalias"); | 2899 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 2900 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| | 2901 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); // Sret pointers must not be address 0 |
| | 2902 | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| | 2903 | |
| | 2904 | const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); |
| | 2905 | try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder); |
| | 2906 | llvm_fn.addSretAttr(raw_llvm_ret_ty.toLlvm(&o.builder)); |
| 2849 | | 2907 | |
| 2850 | const raw_llvm_ret_ty = (try o.lowerType(fn_info.return_type.toType())).toLlvm(&o.builder); | 2908 | llvm_arg_i += 1; |
| 2851 | llvm_fn.addSretAttr(raw_llvm_ret_ty); | | |
| 2852 | } | 2909 | } |
| 2853 | | 2910 | |
| 2854 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and | 2911 | const err_return_tracing = fn_info.return_type.toType().isError(mod) and |
| 2855 | mod.comp.bin_file.options.error_return_tracing; | 2912 | mod.comp.bin_file.options.error_return_tracing; |
| 2856 | | 2913 | |
| 2857 | if (err_return_tracing) { | 2914 | if (err_return_tracing) { |
| 2858 | o.addArgAttr(llvm_fn, @intFromBool(sret), "nonnull"); | 2915 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 2916 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| | 2917 | llvm_arg_i += 1; |
| 2859 | } | 2918 | } |
| 2860 | | 2919 | |
| 2861 | switch (fn_info.cc) { | 2920 | switch (fn_info.cc) { |
| 2862 | .Unspecified, .Inline => { | 2921 | .Unspecified, .Inline => { |
| | 2922 | function.call_conv = .fastcc; |
| 2863 | llvm_fn.setFunctionCallConv(.Fast); | 2923 | llvm_fn.setFunctionCallConv(.Fast); |
| 2864 | }, | 2924 | }, |
| 2865 | .Naked => { | 2925 | .Naked => { |
| | 2926 | try attributes.addFnAttr(.naked, &o.builder); |
| 2866 | o.addFnAttr(llvm_fn, "naked"); | 2927 | o.addFnAttr(llvm_fn, "naked"); |
| 2867 | }, | 2928 | }, |
| 2868 | .Async => { | 2929 | .Async => { |
| | 2930 | function.call_conv = .fastcc; |
| 2869 | llvm_fn.setFunctionCallConv(.Fast); | 2931 | llvm_fn.setFunctionCallConv(.Fast); |
| 2870 | @panic("TODO: LLVM backend lower async function"); | 2932 | @panic("TODO: LLVM backend lower async function"); |
| 2871 | }, | 2933 | }, |
| 2872 | else => { | 2934 | else => { |
| 2873 | llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target)); | 2935 | function.call_conv = toLlvmCallConv(fn_info.cc, target); |
| | 2936 | llvm_fn.setFunctionCallConv(@enumFromInt(@intFromEnum(function.call_conv))); |
| 2874 | }, | 2937 | }, |
| 2875 | } | 2938 | } |
| 2876 | | 2939 | |
| ... | @@ -2880,9 +2943,10 @@ pub const Object = struct { | ... | @@ -2880,9 +2943,10 @@ pub const Object = struct { |
| 2880 | } | 2943 | } |
| 2881 | | 2944 | |
| 2882 | // Function attributes that are independent of analysis results of the function body. | 2945 | // Function attributes that are independent of analysis results of the function body. |
| 2883 | o.addCommonFnAttributes(llvm_fn); | 2946 | try o.addCommonFnAttributes(&attributes, llvm_fn); |
| 2884 | | 2947 | |
| 2885 | if (fn_info.return_type == .noreturn_type) { | 2948 | if (fn_info.return_type == .noreturn_type) { |
| | 2949 | try attributes.addFnAttr(.noreturn, &o.builder); |
| 2886 | o.addFnAttr(llvm_fn, "noreturn"); | 2950 | o.addFnAttr(llvm_fn, "noreturn"); |
| 2887 | } | 2951 | } |
| 2888 | | 2952 | |
| ... | @@ -2890,23 +2954,24 @@ pub const Object = struct { | ... | @@ -2890,23 +2954,24 @@ pub const Object = struct { |
| 2890 | // because functions with bodies are handled in `updateFunc`. | 2954 | // because functions with bodies are handled in `updateFunc`. |
| 2891 | if (is_extern) { | 2955 | if (is_extern) { |
| 2892 | var it = iterateParamTypes(o, fn_info); | 2956 | var it = iterateParamTypes(o, fn_info); |
| 2893 | it.llvm_index += @intFromBool(sret); | 2957 | it.llvm_index = llvm_arg_i; |
| 2894 | it.llvm_index += @intFromBool(err_return_tracing); | | |
| 2895 | while (try it.next()) |lowering| switch (lowering) { | 2958 | while (try it.next()) |lowering| switch (lowering) { |
| 2896 | .byval => { | 2959 | .byval => { |
| 2897 | const param_index = it.zig_index - 1; | 2960 | const param_index = it.zig_index - 1; |
| 2898 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); | 2961 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 2899 | if (!isByRef(param_ty, mod)) { | 2962 | if (!isByRef(param_ty, mod)) { |
| 2900 | o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); | 2963 | try o.addByValParamAttrsOld(&attributes, llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 2901 | } | 2964 | } |
| 2902 | }, | 2965 | }, |
| 2903 | .byref => { | 2966 | .byref => { |
| 2904 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1]; | 2967 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1]; |
| 2905 | const param_llvm_ty = try o.lowerType(param_ty.toType()); | 2968 | const param_llvm_ty = try o.lowerType(param_ty.toType()); |
| 2906 | const alignment = param_ty.toType().abiAlignment(mod); | 2969 | const alignment = |
| 2907 | o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 2970 | Builder.Alignment.fromByteUnits(param_ty.toType().abiAlignment(mod)); |
| | 2971 | try o.addByRefParamAttrsOld(&attributes, llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 2908 | }, | 2972 | }, |
| 2909 | .byref_mut => { | 2973 | .byref_mut => { |
| | 2974 | try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder); |
| 2910 | o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); | 2975 | o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); |
| 2911 | }, | 2976 | }, |
| 2912 | // No attributes needed for these. | 2977 | // No attributes needed for these. |
| ... | @@ -2924,25 +2989,42 @@ pub const Object = struct { | ... | @@ -2924,25 +2989,42 @@ pub const Object = struct { |
| 2924 | }; | 2989 | }; |
| 2925 | } | 2990 | } |
| 2926 | | 2991 | |
| | 2992 | function.attributes = try attributes.finish(&o.builder); |
| | 2993 | |
| 2927 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); | 2994 | try o.builder.llvm.globals.append(o.gpa, llvm_fn); |
| 2928 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); | 2995 | gop.value_ptr.* = try o.builder.addGlobal(fqn, global); |
| 2929 | try o.builder.functions.append(o.gpa, function); | 2996 | try o.builder.functions.append(o.gpa, function); |
| 2930 | return global.kind.function; | 2997 | return global.kind.function; |
| 2931 | } | 2998 | } |
| 2932 | | 2999 | |
| 2933 | fn addCommonFnAttributes(o: *Object, llvm_fn: *llvm.Value) void { | 3000 | fn addCommonFnAttributes( |
| | 3001 | o: *Object, |
| | 3002 | attributes: *Builder.FunctionAttributes.Wip, |
| | 3003 | llvm_fn: *llvm.Value, |
| | 3004 | ) Allocator.Error!void { |
| 2934 | const comp = o.module.comp; | 3005 | const comp = o.module.comp; |
| 2935 | | 3006 | |
| 2936 | if (!comp.bin_file.options.red_zone) { | 3007 | if (!comp.bin_file.options.red_zone) { |
| | 3008 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 2937 | o.addFnAttr(llvm_fn, "noredzone"); | 3009 | o.addFnAttr(llvm_fn, "noredzone"); |
| 2938 | } | 3010 | } |
| 2939 | if (comp.bin_file.options.omit_frame_pointer) { | 3011 | if (comp.bin_file.options.omit_frame_pointer) { |
| | 3012 | try attributes.addFnAttr(.{ .string = .{ |
| | 3013 | .kind = try o.builder.string("frame-pointer"), |
| | 3014 | .value = try o.builder.string("none"), |
| | 3015 | } }, &o.builder); |
| 2940 | o.addFnAttrString(llvm_fn, "frame-pointer", "none"); | 3016 | o.addFnAttrString(llvm_fn, "frame-pointer", "none"); |
| 2941 | } else { | 3017 | } else { |
| | 3018 | try attributes.addFnAttr(.{ .string = .{ |
| | 3019 | .kind = try o.builder.string("frame-pointer"), |
| | 3020 | .value = try o.builder.string("all"), |
| | 3021 | } }, &o.builder); |
| 2942 | o.addFnAttrString(llvm_fn, "frame-pointer", "all"); | 3022 | o.addFnAttrString(llvm_fn, "frame-pointer", "all"); |
| 2943 | } | 3023 | } |
| | 3024 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 2944 | o.addFnAttr(llvm_fn, "nounwind"); | 3025 | o.addFnAttr(llvm_fn, "nounwind"); |
| 2945 | if (comp.unwind_tables) { | 3026 | if (comp.unwind_tables) { |
| | 3027 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 2946 | o.addFnAttrInt(llvm_fn, "uwtable", 2); | 3028 | o.addFnAttrInt(llvm_fn, "uwtable", 2); |
| 2947 | } | 3029 | } |
| 2948 | if (comp.bin_file.options.skip_linker_dependencies or | 3030 | if (comp.bin_file.options.skip_linker_dependencies or |
| ... | @@ -2953,22 +3035,38 @@ pub const Object = struct { | ... | @@ -2953,22 +3035,38 @@ pub const Object = struct { |
| 2953 | // and llvm detects that the body is equivalent to memcpy, it may replace the | 3035 | // and llvm detects that the body is equivalent to memcpy, it may replace the |
| 2954 | // body of memcpy with a call to memcpy, which would then cause a stack | 3036 | // body of memcpy with a call to memcpy, which would then cause a stack |
| 2955 | // overflow instead of performing memcpy. | 3037 | // overflow instead of performing memcpy. |
| | 3038 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 2956 | o.addFnAttr(llvm_fn, "nobuiltin"); | 3039 | o.addFnAttr(llvm_fn, "nobuiltin"); |
| 2957 | } | 3040 | } |
| 2958 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { | 3041 | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { |
| | 3042 | try attributes.addFnAttr(.minsize, &o.builder); |
| | 3043 | try attributes.addFnAttr(.optsize, &o.builder); |
| 2959 | o.addFnAttr(llvm_fn, "minsize"); | 3044 | o.addFnAttr(llvm_fn, "minsize"); |
| 2960 | o.addFnAttr(llvm_fn, "optsize"); | 3045 | o.addFnAttr(llvm_fn, "optsize"); |
| 2961 | } | 3046 | } |
| 2962 | if (comp.bin_file.options.tsan) { | 3047 | if (comp.bin_file.options.tsan) { |
| | 3048 | try attributes.addFnAttr(.sanitize_thread, &o.builder); |
| 2963 | o.addFnAttr(llvm_fn, "sanitize_thread"); | 3049 | o.addFnAttr(llvm_fn, "sanitize_thread"); |
| 2964 | } | 3050 | } |
| 2965 | if (comp.getTarget().cpu.model.llvm_name) |s| { | 3051 | if (comp.getTarget().cpu.model.llvm_name) |s| { |
| | 3052 | try attributes.addFnAttr(.{ .string = .{ |
| | 3053 | .kind = try o.builder.string("target-cpu"), |
| | 3054 | .value = try o.builder.string(s), |
| | 3055 | } }, &o.builder); |
| 2966 | llvm_fn.addFunctionAttr("target-cpu", s); | 3056 | llvm_fn.addFunctionAttr("target-cpu", s); |
| 2967 | } | 3057 | } |
| 2968 | if (comp.bin_file.options.llvm_cpu_features) |s| { | 3058 | if (comp.bin_file.options.llvm_cpu_features) |s| { |
| | 3059 | try attributes.addFnAttr(.{ .string = .{ |
| | 3060 | .kind = try o.builder.string("target-features"), |
| | 3061 | .value = try o.builder.string(std.mem.span(s)), |
| | 3062 | } }, &o.builder); |
| 2969 | llvm_fn.addFunctionAttr("target-features", s); | 3063 | llvm_fn.addFunctionAttr("target-features", s); |
| 2970 | } | 3064 | } |
| 2971 | if (comp.getTarget().cpu.arch.isBpf()) { | 3065 | if (comp.getTarget().cpu.arch.isBpf()) { |
| | 3066 | try attributes.addFnAttr(.{ .string = .{ |
| | 3067 | .kind = try o.builder.string("no-builtins"), |
| | 3068 | .value = .empty, |
| | 3069 | } }, &o.builder); |
| 2972 | llvm_fn.addFunctionAttr("no-builtins", ""); | 3070 | llvm_fn.addFunctionAttr("no-builtins", ""); |
| 2973 | } | 3071 | } |
| 2974 | } | 3072 | } |
| ... | @@ -3002,7 +3100,7 @@ pub const Object = struct { | ... | @@ -3002,7 +3100,7 @@ pub const Object = struct { |
| 3002 | fqn; | 3100 | fqn; |
| 3003 | const llvm_global = o.llvm_module.addGlobalInAddressSpace( | 3101 | const llvm_global = o.llvm_module.addGlobalInAddressSpace( |
| 3004 | global.type.toLlvm(&o.builder), | 3102 | global.type.toLlvm(&o.builder), |
| 3005 | fqn.toSlice(&o.builder).?, | 3103 | fqn.slice(&o.builder).?, |
| 3006 | @intFromEnum(global.addr_space), | 3104 | @intFromEnum(global.addr_space), |
| 3007 | ); | 3105 | ); |
| 3008 | | 3106 | |
| ... | @@ -4403,47 +4501,114 @@ pub const Object = struct { | ... | @@ -4403,47 +4501,114 @@ pub const Object = struct { |
| 4403 | | 4501 | |
| 4404 | fn addByValParamAttrs( | 4502 | fn addByValParamAttrs( |
| 4405 | o: *Object, | 4503 | o: *Object, |
| | 4504 | attributes: *Builder.FunctionAttributes.Wip, |
| | 4505 | param_ty: Type, |
| | 4506 | param_index: u32, |
| | 4507 | fn_info: InternPool.Key.FuncType, |
| | 4508 | llvm_arg_i: u32, |
| | 4509 | ) Allocator.Error!void { |
| | 4510 | const mod = o.module; |
| | 4511 | if (param_ty.isPtrAtRuntime(mod)) { |
| | 4512 | const ptr_info = param_ty.ptrInfo(mod); |
| | 4513 | if (math.cast(u5, param_index)) |i| { |
| | 4514 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| | 4515 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| | 4516 | } |
| | 4517 | } |
| | 4518 | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { |
| | 4519 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 4520 | } |
| | 4521 | if (ptr_info.flags.is_const) { |
| | 4522 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| | 4523 | } |
| | 4524 | const elem_align = Builder.Alignment.fromByteUnits( |
| | 4525 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| | 4526 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| | 4527 | ); |
| | 4528 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| | 4529 | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { |
| | 4530 | .signed => try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder), |
| | 4531 | .unsigned => try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder), |
| | 4532 | }; |
| | 4533 | } |
| | 4534 | |
| | 4535 | fn addByRefParamAttrs( |
| | 4536 | o: *Object, |
| | 4537 | attributes: *Builder.FunctionAttributes.Wip, |
| | 4538 | llvm_arg_i: u32, |
| | 4539 | alignment: Builder.Alignment, |
| | 4540 | byval_attr: bool, |
| | 4541 | param_llvm_ty: Builder.Type, |
| | 4542 | ) Allocator.Error!void { |
| | 4543 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 4544 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| | 4545 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| | 4546 | if (byval_attr) { |
| | 4547 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| | 4548 | } |
| | 4549 | } |
| | 4550 | |
| | 4551 | fn addByValParamAttrsOld( |
| | 4552 | o: *Object, |
| | 4553 | attributes: *Builder.FunctionAttributes.Wip, |
| 4406 | llvm_fn: *llvm.Value, | 4554 | llvm_fn: *llvm.Value, |
| 4407 | param_ty: Type, | 4555 | param_ty: Type, |
| 4408 | param_index: u32, | 4556 | param_index: u32, |
| 4409 | fn_info: InternPool.Key.FuncType, | 4557 | fn_info: InternPool.Key.FuncType, |
| 4410 | llvm_arg_i: u32, | 4558 | llvm_arg_i: u32, |
| 4411 | ) void { | 4559 | ) Allocator.Error!void { |
| 4412 | const mod = o.module; | 4560 | const mod = o.module; |
| 4413 | if (param_ty.isPtrAtRuntime(mod)) { | 4561 | if (param_ty.isPtrAtRuntime(mod)) { |
| 4414 | const ptr_info = param_ty.ptrInfo(mod); | 4562 | const ptr_info = param_ty.ptrInfo(mod); |
| 4415 | if (math.cast(u5, param_index)) |i| { | 4563 | if (math.cast(u5, param_index)) |i| { |
| 4416 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | 4564 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| | 4565 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 4417 | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); | 4566 | o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); |
| 4418 | } | 4567 | } |
| 4419 | } | 4568 | } |
| 4420 | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { | 4569 | if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { |
| | 4570 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4421 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | 4571 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4422 | } | 4572 | } |
| 4423 | if (ptr_info.flags.is_const) { | 4573 | if (ptr_info.flags.is_const) { |
| | 4574 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4424 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); | 4575 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4425 | } | 4576 | } |
| 4426 | const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse | 4577 | const elem_align = Builder.Alignment.fromByteUnits( |
| 4427 | @max(ptr_info.child.toType().abiAlignment(mod), 1); | 4578 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 4428 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); | 4579 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| | 4580 | ); |
| | 4581 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| | 4582 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align.toByteUnits() orelse 0); |
| 4429 | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { | 4583 | } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { |
| 4430 | .signed => o.addArgAttr(llvm_fn, llvm_arg_i, "signext"), | 4584 | .signed => { |
| 4431 | .unsigned => o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), | 4585 | try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder); |
| | 4586 | o.addArgAttr(llvm_fn, llvm_arg_i, "signext"); |
| | 4587 | }, |
| | 4588 | .unsigned => { |
| | 4589 | try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder); |
| | 4590 | o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"); |
| | 4591 | }, |
| 4432 | }; | 4592 | }; |
| 4433 | } | 4593 | } |
| 4434 | | 4594 | |
| 4435 | fn addByRefParamAttrs( | 4595 | fn addByRefParamAttrsOld( |
| 4436 | o: *Object, | 4596 | o: *Object, |
| | 4597 | attributes: *Builder.FunctionAttributes.Wip, |
| 4437 | llvm_fn: *llvm.Value, | 4598 | llvm_fn: *llvm.Value, |
| 4438 | llvm_arg_i: u32, | 4599 | llvm_arg_i: u32, |
| 4439 | alignment: u32, | 4600 | alignment: Builder.Alignment, |
| 4440 | byval_attr: bool, | 4601 | byval_attr: bool, |
| 4441 | param_llvm_ty: Builder.Type, | 4602 | param_llvm_ty: Builder.Type, |
| 4442 | ) void { | 4603 | ) Allocator.Error!void { |
| | 4604 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| | 4605 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| | 4606 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); |
| 4443 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); | 4607 | o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); |
| 4444 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); | 4608 | o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); |
| 4445 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); | 4609 | o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment.toByteUnits() orelse 0); |
| 4446 | if (byval_attr) { | 4610 | if (byval_attr) { |
| | 4611 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 4447 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); | 4612 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); |
| 4448 | } | 4613 | } |
| 4449 | } | 4614 | } |
| ... | @@ -4841,10 +5006,10 @@ pub const FuncGen = struct { | ... | @@ -4841,10 +5006,10 @@ pub const FuncGen = struct { |
| 4841 | .slice_ptr => try self.airSliceField(inst, 0), | 5006 | .slice_ptr => try self.airSliceField(inst, 0), |
| 4842 | .slice_len => try self.airSliceField(inst, 1), | 5007 | .slice_len => try self.airSliceField(inst, 1), |
| 4843 | | 5008 | |
| 4844 | .call => try self.airCall(inst, .Auto), | 5009 | .call => try self.airCall(inst, .auto), |
| 4845 | .call_always_tail => try self.airCall(inst, .AlwaysTail), | 5010 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 4846 | .call_never_tail => try self.airCall(inst, .NeverTail), | 5011 | .call_never_tail => try self.airCall(inst, .never_tail), |
| 4847 | .call_never_inline => try self.airCall(inst, .NeverInline), | 5012 | .call_never_inline => try self.airCall(inst, .never_inline), |
| 4848 | | 5013 | |
| 4849 | .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0), | 5014 | .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0), |
| 4850 | .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1), | 5015 | .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1), |
| ... | @@ -4953,7 +5118,15 @@ pub const FuncGen = struct { | ... | @@ -4953,7 +5118,15 @@ pub const FuncGen = struct { |
| 4953 | } | 5118 | } |
| 4954 | } | 5119 | } |
| 4955 | | 5120 | |
| 4956 | fn airCall(self: *FuncGen, inst: Air.Inst.Index, attr: llvm.CallAttr) !Builder.Value { | 5121 | pub const CallAttr = enum { |
| | 5122 | Auto, |
| | 5123 | NeverTail, |
| | 5124 | NeverInline, |
| | 5125 | AlwaysTail, |
| | 5126 | AlwaysInline, |
| | 5127 | }; |
| | 5128 | |
| | 5129 | fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !Builder.Value { |
| 4957 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 5130 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 4958 | const extra = self.air.extraData(Air.Call, pl_op.payload); | 5131 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 4959 | const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); | 5132 | const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); |
| ... | @@ -4972,14 +5145,25 @@ pub const FuncGen = struct { | ... | @@ -4972,14 +5145,25 @@ pub const FuncGen = struct { |
| 4972 | const target = mod.getTarget(); | 5145 | const target = mod.getTarget(); |
| 4973 | const sret = firstParamSRet(fn_info, mod); | 5146 | const sret = firstParamSRet(fn_info, mod); |
| 4974 | | 5147 | |
| 4975 | var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa); | 5148 | var llvm_args = std.ArrayList(Builder.Value).init(self.gpa); |
| 4976 | defer llvm_args.deinit(); | 5149 | defer llvm_args.deinit(); |
| 4977 | | 5150 | |
| | 5151 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 5152 | defer attributes.deinit(&o.builder); |
| | 5153 | |
| | 5154 | switch (modifier) { |
| | 5155 | .auto, .never_tail, .always_tail => {}, |
| | 5156 | .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder), |
| | 5157 | .async_kw, .no_async, .always_inline, .compile_time => unreachable, |
| | 5158 | } |
| | 5159 | |
| 4978 | const ret_ptr = if (!sret) null else blk: { | 5160 | const ret_ptr = if (!sret) null else blk: { |
| 4979 | const llvm_ret_ty = try o.lowerType(return_type); | 5161 | const llvm_ret_ty = try o.lowerType(return_type); |
| | 5162 | try attributes.addParamAttr(0, .{ .sret = llvm_ret_ty }, &o.builder); |
| | 5163 | |
| 4980 | const alignment = Builder.Alignment.fromByteUnits(return_type.abiAlignment(mod)); | 5164 | const alignment = Builder.Alignment.fromByteUnits(return_type.abiAlignment(mod)); |
| 4981 | const ret_ptr = try self.buildAlloca(llvm_ret_ty, alignment); | 5165 | const ret_ptr = try self.buildAlloca(llvm_ret_ty, alignment); |
| 4982 | try llvm_args.append(ret_ptr.toLlvm(&self.wip)); | 5166 | try llvm_args.append(ret_ptr); |
| 4983 | break :blk ret_ptr; | 5167 | break :blk ret_ptr; |
| 4984 | }; | 5168 | }; |
| 4985 | | 5169 | |
| ... | @@ -4987,7 +5171,7 @@ pub const FuncGen = struct { | ... | @@ -4987,7 +5171,7 @@ pub const FuncGen = struct { |
| 4987 | o.module.comp.bin_file.options.error_return_tracing; | 5171 | o.module.comp.bin_file.options.error_return_tracing; |
| 4988 | if (err_return_tracing) { | 5172 | if (err_return_tracing) { |
| 4989 | assert(self.err_ret_trace != .none); | 5173 | assert(self.err_ret_trace != .none); |
| 4990 | try llvm_args.append(self.err_ret_trace.toLlvm(&self.wip)); | 5174 | try llvm_args.append(self.err_ret_trace); |
| 4991 | } | 5175 | } |
| 4992 | | 5176 | |
| 4993 | var it = iterateParamTypes(o, fn_info); | 5177 | var it = iterateParamTypes(o, fn_info); |
| ... | @@ -5001,9 +5185,9 @@ pub const FuncGen = struct { | ... | @@ -5001,9 +5185,9 @@ pub const FuncGen = struct { |
| 5001 | if (isByRef(param_ty, mod)) { | 5185 | if (isByRef(param_ty, mod)) { |
| 5002 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 5186 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 5003 | const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); | 5187 | const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); |
| 5004 | try llvm_args.append(loaded.toLlvm(&self.wip)); | 5188 | try llvm_args.append(loaded); |
| 5005 | } else { | 5189 | } else { |
| 5006 | try llvm_args.append(llvm_arg.toLlvm(&self.wip)); | 5190 | try llvm_args.append(llvm_arg); |
| 5007 | } | 5191 | } |
| 5008 | }, | 5192 | }, |
| 5009 | .byref => { | 5193 | .byref => { |
| ... | @@ -5011,13 +5195,13 @@ pub const FuncGen = struct { | ... | @@ -5011,13 +5195,13 @@ pub const FuncGen = struct { |
| 5011 | const param_ty = self.typeOf(arg); | 5195 | const param_ty = self.typeOf(arg); |
| 5012 | const llvm_arg = try self.resolveInst(arg); | 5196 | const llvm_arg = try self.resolveInst(arg); |
| 5013 | if (isByRef(param_ty, mod)) { | 5197 | if (isByRef(param_ty, mod)) { |
| 5014 | try llvm_args.append(llvm_arg.toLlvm(&self.wip)); | 5198 | try llvm_args.append(llvm_arg); |
| 5015 | } else { | 5199 | } else { |
| 5016 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 5200 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 5017 | const param_llvm_ty = llvm_arg.typeOfWip(&self.wip); | 5201 | const param_llvm_ty = llvm_arg.typeOfWip(&self.wip); |
| 5018 | const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); | 5202 | const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); |
| 5019 | _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment); | 5203 | _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment); |
| 5020 | try llvm_args.append(arg_ptr.toLlvm(&self.wip)); | 5204 | try llvm_args.append(arg_ptr); |
| 5021 | } | 5205 | } |
| 5022 | }, | 5206 | }, |
| 5023 | .byref_mut => { | 5207 | .byref_mut => { |
| ... | @@ -5034,7 +5218,7 @@ pub const FuncGen = struct { | ... | @@ -5034,7 +5218,7 @@ pub const FuncGen = struct { |
| 5034 | } else { | 5218 | } else { |
| 5035 | _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment); | 5219 | _ = try self.wip.store(.normal, llvm_arg, arg_ptr, alignment); |
| 5036 | } | 5220 | } |
| 5037 | try llvm_args.append(arg_ptr.toLlvm(&self.wip)); | 5221 | try llvm_args.append(arg_ptr); |
| 5038 | }, | 5222 | }, |
| 5039 | .abi_sized_int => { | 5223 | .abi_sized_int => { |
| 5040 | const arg = args[it.zig_index - 1]; | 5224 | const arg = args[it.zig_index - 1]; |
| ... | @@ -5045,7 +5229,7 @@ pub const FuncGen = struct { | ... | @@ -5045,7 +5229,7 @@ pub const FuncGen = struct { |
| 5045 | if (isByRef(param_ty, mod)) { | 5229 | if (isByRef(param_ty, mod)) { |
| 5046 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); | 5230 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 5047 | const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, ""); | 5231 | const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, ""); |
| 5048 | try llvm_args.append(loaded.toLlvm(&self.wip)); | 5232 | try llvm_args.append(loaded); |
| 5049 | } else { | 5233 | } else { |
| 5050 | // LLVM does not allow bitcasting structs so we must allocate | 5234 | // LLVM does not allow bitcasting structs so we must allocate |
| 5051 | // a local, store as one type, and then load as another type. | 5235 | // a local, store as one type, and then load as another type. |
| ... | @@ -5056,7 +5240,7 @@ pub const FuncGen = struct { | ... | @@ -5056,7 +5240,7 @@ pub const FuncGen = struct { |
| 5056 | const int_ptr = try self.buildAlloca(int_llvm_ty, alignment); | 5240 | const int_ptr = try self.buildAlloca(int_llvm_ty, alignment); |
| 5057 | _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment); | 5241 | _ = try self.wip.store(.normal, llvm_arg, int_ptr, alignment); |
| 5058 | const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, ""); | 5242 | const loaded = try self.wip.load(.normal, int_llvm_ty, int_ptr, alignment, ""); |
| 5059 | try llvm_args.append(loaded.toLlvm(&self.wip)); | 5243 | try llvm_args.append(loaded); |
| 5060 | } | 5244 | } |
| 5061 | }, | 5245 | }, |
| 5062 | .slice => { | 5246 | .slice => { |
| ... | @@ -5064,7 +5248,7 @@ pub const FuncGen = struct { | ... | @@ -5064,7 +5248,7 @@ pub const FuncGen = struct { |
| 5064 | const llvm_arg = try self.resolveInst(arg); | 5248 | const llvm_arg = try self.resolveInst(arg); |
| 5065 | const ptr = try self.wip.extractValue(llvm_arg, &.{0}, ""); | 5249 | const ptr = try self.wip.extractValue(llvm_arg, &.{0}, ""); |
| 5066 | const len = try self.wip.extractValue(llvm_arg, &.{1}, ""); | 5250 | const len = try self.wip.extractValue(llvm_arg, &.{1}, ""); |
| 5067 | try llvm_args.appendSlice(&.{ ptr.toLlvm(&self.wip), len.toLlvm(&self.wip) }); | 5251 | try llvm_args.appendSlice(&.{ ptr, len }); |
| 5068 | }, | 5252 | }, |
| 5069 | .multiple_llvm_types => { | 5253 | .multiple_llvm_types => { |
| 5070 | const arg = args[it.zig_index - 1]; | 5254 | const arg = args[it.zig_index - 1]; |
| ... | @@ -5086,14 +5270,14 @@ pub const FuncGen = struct { | ... | @@ -5086,14 +5270,14 @@ pub const FuncGen = struct { |
| 5086 | Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); | 5270 | Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 5087 | const field_ptr = try self.wip.gepStruct(llvm_ty, arg_ptr, i, ""); | 5271 | const field_ptr = try self.wip.gepStruct(llvm_ty, arg_ptr, i, ""); |
| 5088 | const loaded = try self.wip.load(.normal, field_ty, field_ptr, alignment, ""); | 5272 | const loaded = try self.wip.load(.normal, field_ty, field_ptr, alignment, ""); |
| 5089 | llvm_args.appendAssumeCapacity(loaded.toLlvm(&self.wip)); | 5273 | llvm_args.appendAssumeCapacity(loaded); |
| 5090 | } | 5274 | } |
| 5091 | }, | 5275 | }, |
| 5092 | .as_u16 => { | 5276 | .as_u16 => { |
| 5093 | const arg = args[it.zig_index - 1]; | 5277 | const arg = args[it.zig_index - 1]; |
| 5094 | const llvm_arg = try self.resolveInst(arg); | 5278 | const llvm_arg = try self.resolveInst(arg); |
| 5095 | const casted = try self.wip.cast(.bitcast, llvm_arg, .i16, ""); | 5279 | const casted = try self.wip.cast(.bitcast, llvm_arg, .i16, ""); |
| 5096 | try llvm_args.append(casted.toLlvm(&self.wip)); | 5280 | try llvm_args.append(casted); |
| 5097 | }, | 5281 | }, |
| 5098 | .float_array => |count| { | 5282 | .float_array => |count| { |
| 5099 | const arg = args[it.zig_index - 1]; | 5283 | const arg = args[it.zig_index - 1]; |
| ... | @@ -5110,7 +5294,7 @@ pub const FuncGen = struct { | ... | @@ -5110,7 +5294,7 @@ pub const FuncGen = struct { |
| 5110 | const array_ty = try o.builder.arrayType(count, float_ty); | 5294 | const array_ty = try o.builder.arrayType(count, float_ty); |
| 5111 | | 5295 | |
| 5112 | const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); | 5296 | const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); |
| 5113 | try llvm_args.append(loaded.toLlvm(&self.wip)); | 5297 | try llvm_args.append(loaded); |
| 5114 | }, | 5298 | }, |
| 5115 | .i32_array, .i64_array => |arr_len| { | 5299 | .i32_array, .i64_array => |arr_len| { |
| 5116 | const elem_size: u8 = if (lowering == .i32_array) 32 else 64; | 5300 | const elem_size: u8 = if (lowering == .i32_array) 32 else 64; |
| ... | @@ -5127,24 +5311,10 @@ pub const FuncGen = struct { | ... | @@ -5127,24 +5311,10 @@ pub const FuncGen = struct { |
| 5127 | const array_ty = | 5311 | const array_ty = |
| 5128 | try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); | 5312 | try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); |
| 5129 | const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); | 5313 | const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); |
| 5130 | try llvm_args.append(loaded.toLlvm(&self.wip)); | 5314 | try llvm_args.append(loaded); |
| 5131 | }, | 5315 | }, |
| 5132 | }; | 5316 | }; |
| 5133 | | 5317 | |
| 5134 | const llvm_fn_ty = try o.lowerType(zig_fn_ty); | | |
| 5135 | const call = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( | | |
| 5136 | self.builder.buildCall( | | |
| 5137 | llvm_fn_ty.toLlvm(&o.builder), | | |
| 5138 | llvm_fn.toLlvm(&self.wip), | | |
| 5139 | llvm_args.items.ptr, | | |
| 5140 | @intCast(llvm_args.items.len), | | |
| 5141 | toLlvmCallConv(fn_info.cc, target), | | |
| 5142 | attr, | | |
| 5143 | "", | | |
| 5144 | ), | | |
| 5145 | &self.wip, | | |
| 5146 | ); | | |
| 5147 | | | |
| 5148 | if (callee_ty.zigTypeTag(mod) == .Pointer) { | 5318 | if (callee_ty.zigTypeTag(mod) == .Pointer) { |
| 5149 | // Add argument attributes for function pointer calls. | 5319 | // Add argument attributes for function pointer calls. |
| 5150 | it = iterateParamTypes(o, fn_info); | 5320 | it = iterateParamTypes(o, fn_info); |
| ... | @@ -5155,19 +5325,17 @@ pub const FuncGen = struct { | ... | @@ -5155,19 +5325,17 @@ pub const FuncGen = struct { |
| 5155 | const param_index = it.zig_index - 1; | 5325 | const param_index = it.zig_index - 1; |
| 5156 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); | 5326 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 5157 | if (!isByRef(param_ty, mod)) { | 5327 | if (!isByRef(param_ty, mod)) { |
| 5158 | o.addByValParamAttrs(call.toLlvm(&self.wip), param_ty, param_index, fn_info, it.llvm_index - 1); | 5328 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 5159 | } | 5329 | } |
| 5160 | }, | 5330 | }, |
| 5161 | .byref => { | 5331 | .byref => { |
| 5162 | const param_index = it.zig_index - 1; | 5332 | const param_index = it.zig_index - 1; |
| 5163 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); | 5333 | const param_ty = fn_info.param_types.get(ip)[param_index].toType(); |
| 5164 | const param_llvm_ty = try o.lowerType(param_ty); | 5334 | const param_llvm_ty = try o.lowerType(param_ty); |
| 5165 | const alignment = param_ty.abiAlignment(mod); | 5335 | const alignment = Builder.Alignment.fromByteUnits(param_ty.abiAlignment(mod)); |
| 5166 | o.addByRefParamAttrs(call.toLlvm(&self.wip), it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); | 5336 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); |
| 5167 | }, | | |
| 5168 | .byref_mut => { | | |
| 5169 | o.addArgAttr(call.toLlvm(&self.wip), it.llvm_index - 1, "noundef"); | | |
| 5170 | }, | 5337 | }, |
| | 5338 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), |
| 5171 | // No attributes needed for these. | 5339 | // No attributes needed for these. |
| 5172 | .no_bits, | 5340 | .no_bits, |
| 5173 | .abi_sized_int, | 5341 | .abi_sized_int, |
| ... | @@ -5186,23 +5354,40 @@ pub const FuncGen = struct { | ... | @@ -5186,23 +5354,40 @@ pub const FuncGen = struct { |
| 5186 | | 5354 | |
| 5187 | if (math.cast(u5, it.zig_index - 1)) |i| { | 5355 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 5188 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | 5356 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 5189 | o.addArgAttr(call.toLlvm(&self.wip), llvm_arg_i, "noalias"); | 5357 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 5190 | } | 5358 | } |
| 5191 | } | 5359 | } |
| 5192 | if (param_ty.zigTypeTag(mod) != .Optional) { | 5360 | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 5193 | o.addArgAttr(call.toLlvm(&self.wip), llvm_arg_i, "nonnull"); | 5361 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 5194 | } | 5362 | } |
| 5195 | if (ptr_info.flags.is_const) { | 5363 | if (ptr_info.flags.is_const) { |
| 5196 | o.addArgAttr(call.toLlvm(&self.wip), llvm_arg_i, "readonly"); | 5364 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 5197 | } | 5365 | } |
| 5198 | const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse | 5366 | const elem_align = Builder.Alignment.fromByteUnits( |
| 5199 | @max(ptr_info.child.toType().abiAlignment(mod), 1); | 5367 | ptr_info.flags.alignment.toByteUnitsOptional() orelse |
| 5200 | o.addArgAttrInt(call.toLlvm(&self.wip), llvm_arg_i, "align", elem_align); | 5368 | @max(ptr_info.child.toType().abiAlignment(mod), 1), |
| | 5369 | ); |
| | 5370 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 5201 | }, | 5371 | }, |
| 5202 | }; | 5372 | }; |
| 5203 | } | 5373 | } |
| 5204 | | 5374 | |
| 5205 | if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) { | 5375 | const call = try self.wip.call( |
| | 5376 | switch (modifier) { |
| | 5377 | .auto, .never_inline => .normal, |
| | 5378 | .never_tail => .notail, |
| | 5379 | .always_tail => .musttail, |
| | 5380 | .async_kw, .no_async, .always_inline, .compile_time => unreachable, |
| | 5381 | }, |
| | 5382 | toLlvmCallConv(fn_info.cc, target), |
| | 5383 | try attributes.finish(&o.builder), |
| | 5384 | try o.lowerType(zig_fn_ty), |
| | 5385 | llvm_fn, |
| | 5386 | llvm_args.items, |
| | 5387 | "", |
| | 5388 | ); |
| | 5389 | |
| | 5390 | if (fn_info.return_type == .noreturn_type and modifier != .always_tail) { |
| 5206 | return .none; | 5391 | return .none; |
| 5207 | } | 5392 | } |
| 5208 | | 5393 | |
| ... | @@ -5211,9 +5396,7 @@ pub const FuncGen = struct { | ... | @@ -5211,9 +5396,7 @@ pub const FuncGen = struct { |
| 5211 | } | 5396 | } |
| 5212 | | 5397 | |
| 5213 | const llvm_ret_ty = try o.lowerType(return_type); | 5398 | const llvm_ret_ty = try o.lowerType(return_type); |
| 5214 | | | |
| 5215 | if (ret_ptr) |rp| { | 5399 | if (ret_ptr) |rp| { |
| 5216 | call.toLlvm(&self.wip).setCallSret(llvm_ret_ty.toLlvm(&o.builder)); | | |
| 5217 | if (isByRef(return_type, mod)) { | 5400 | if (isByRef(return_type, mod)) { |
| 5218 | return rp; | 5401 | return rp; |
| 5219 | } else { | 5402 | } else { |
| ... | @@ -5269,25 +5452,24 @@ pub const FuncGen = struct { | ... | @@ -5269,25 +5452,24 @@ pub const FuncGen = struct { |
| 5269 | // ptr null, ; stack trace | 5452 | // ptr null, ; stack trace |
| 5270 | // ptr @2, ; addr (null ?usize) | 5453 | // ptr @2, ; addr (null ?usize) |
| 5271 | // ) | 5454 | // ) |
| 5272 | const args = [4]*llvm.Value{ | | |
| 5273 | msg_ptr.toLlvm(&o.builder), | | |
| 5274 | (try o.builder.intConst(llvm_usize, msg_len)).toLlvm(&o.builder), | | |
| 5275 | (try o.builder.nullConst(.ptr)).toLlvm(&o.builder), | | |
| 5276 | null_opt_addr_global.toLlvm(&o.builder), | | |
| 5277 | }; | | |
| 5278 | const panic_func = mod.funcInfo(mod.panic_func_index); | 5455 | const panic_func = mod.funcInfo(mod.panic_func_index); |
| 5279 | const panic_decl = mod.declPtr(panic_func.owner_decl); | 5456 | const panic_decl = mod.declPtr(panic_func.owner_decl); |
| 5280 | const fn_info = mod.typeToFunc(panic_decl.ty).?; | 5457 | const fn_info = mod.typeToFunc(panic_decl.ty).?; |
| 5281 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); | 5458 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl); |
| 5282 | _ = (try fg.wip.unimplemented(.void, "")).finish(fg.builder.buildCall( | 5459 | _ = try fg.wip.call( |
| 5283 | (try o.lowerType(panic_decl.ty)).toLlvm(&o.builder), | 5460 | .normal, |
| 5284 | panic_global.toLlvm(&o.builder), | | |
| 5285 | &args, | | |
| 5286 | args.len, | | |
| 5287 | toLlvmCallConv(fn_info.cc, target), | 5461 | toLlvmCallConv(fn_info.cc, target), |
| 5288 | .Auto, | 5462 | .none, |
| | 5463 | panic_global.typeOf(&o.builder), |
| | 5464 | panic_global.toValue(&o.builder), |
| | 5465 | &.{ |
| | 5466 | msg_ptr.toValue(), |
| | 5467 | try o.builder.intValue(llvm_usize, msg_len), |
| | 5468 | try o.builder.nullValue(.ptr), |
| | 5469 | null_opt_addr_global.toValue(), |
| | 5470 | }, |
| 5289 | "", | 5471 | "", |
| 5290 | ), &fg.wip); | 5472 | ); |
| 5291 | _ = try fg.wip.@"unreachable"(); | 5473 | _ = try fg.wip.@"unreachable"(); |
| 5292 | } | 5474 | } |
| 5293 | | 5475 | |
| ... | @@ -5395,7 +5577,7 @@ pub const FuncGen = struct { | ... | @@ -5395,7 +5577,7 @@ pub const FuncGen = struct { |
| 5395 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | 5577 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); |
| 5396 | | 5578 | |
| 5397 | const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) }; | 5579 | const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) }; |
| 5398 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 5580 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 5399 | llvm_fn_ty.toLlvm(&o.builder), | 5581 | llvm_fn_ty.toLlvm(&o.builder), |
| 5400 | llvm_fn, | 5582 | llvm_fn, |
| 5401 | &args, | 5583 | &args, |
| ... | @@ -5422,7 +5604,7 @@ pub const FuncGen = struct { | ... | @@ -5422,7 +5604,7 @@ pub const FuncGen = struct { |
| 5422 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | 5604 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); |
| 5423 | | 5605 | |
| 5424 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; | 5606 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; |
| 5425 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 5607 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 5426 | llvm_fn_ty.toLlvm(&o.builder), | 5608 | llvm_fn_ty.toLlvm(&o.builder), |
| 5427 | llvm_fn, | 5609 | llvm_fn, |
| 5428 | &args, | 5610 | &args, |
| ... | @@ -5449,7 +5631,7 @@ pub const FuncGen = struct { | ... | @@ -5449,7 +5631,7 @@ pub const FuncGen = struct { |
| 5449 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); | 5631 | o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); |
| 5450 | | 5632 | |
| 5451 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; | 5633 | const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; |
| 5452 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 5634 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 5453 | llvm_fn_ty.toLlvm(&o.builder), | 5635 | llvm_fn_ty.toLlvm(&o.builder), |
| 5454 | llvm_fn, | 5636 | llvm_fn, |
| 5455 | &args, | 5637 | &args, |
| ... | @@ -5495,16 +5677,15 @@ pub const FuncGen = struct { | ... | @@ -5495,16 +5677,15 @@ pub const FuncGen = struct { |
| 5495 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 5677 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5496 | const operand = try self.resolveInst(un_op); | 5678 | const operand = try self.resolveInst(un_op); |
| 5497 | const llvm_fn = try self.getCmpLtErrorsLenFunction(); | 5679 | const llvm_fn = try self.getCmpLtErrorsLenFunction(); |
| 5498 | const args: [1]*llvm.Value = .{operand.toLlvm(&self.wip)}; | 5680 | return self.wip.call( |
| 5499 | return (try self.wip.unimplemented(.i1, "")).finish(self.builder.buildCall( | 5681 | .normal, |
| 5500 | llvm_fn.typeOf(&o.builder).toLlvm(&o.builder), | 5682 | .fastcc, |
| 5501 | llvm_fn.toLlvm(&o.builder), | 5683 | .none, |
| 5502 | &args, | 5684 | llvm_fn.typeOf(&o.builder), |
| 5503 | args.len, | 5685 | llvm_fn.toValue(&o.builder), |
| 5504 | .Fast, | 5686 | &.{operand}, |
| 5505 | .Auto, | | |
| 5506 | "", | 5687 | "", |
| 5507 | ), &self.wip); | 5688 | ); |
| 5508 | } | 5689 | } |
| 5509 | | 5690 | |
| 5510 | fn cmp( | 5691 | fn cmp( |
| ... | @@ -5953,16 +6134,15 @@ pub const FuncGen = struct { | ... | @@ -5953,16 +6134,15 @@ pub const FuncGen = struct { |
| 5953 | } | 6134 | } |
| 5954 | | 6135 | |
| 5955 | const libc_fn = try self.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); | 6136 | const libc_fn = try self.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); |
| 5956 | const params = [1]*llvm.Value{extended.toLlvm(&self.wip)}; | 6137 | return self.wip.call( |
| 5957 | return (try self.wip.unimplemented(dest_llvm_ty, "")).finish(self.builder.buildCall( | 6138 | .normal, |
| 5958 | libc_fn.typeOf(&o.builder).toLlvm(&o.builder), | 6139 | .ccc, |
| 5959 | libc_fn.toLlvm(&o.builder), | 6140 | .none, |
| 5960 | &params, | 6141 | libc_fn.typeOf(&o.builder), |
| 5961 | params.len, | 6142 | libc_fn.toValue(&o.builder), |
| 5962 | .C, | 6143 | &.{extended}, |
| 5963 | .Auto, | | |
| 5964 | "", | 6144 | "", |
| 5965 | ), &self.wip); | 6145 | ); |
| 5966 | } | 6146 | } |
| 5967 | | 6147 | |
| 5968 | fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { | 6148 | fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { |
| ... | @@ -6013,16 +6193,15 @@ pub const FuncGen = struct { | ... | @@ -6013,16 +6193,15 @@ pub const FuncGen = struct { |
| 6013 | | 6193 | |
| 6014 | const operand_llvm_ty = try o.lowerType(operand_ty); | 6194 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 6015 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); | 6195 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); |
| 6016 | const params = [1]*llvm.Value{operand.toLlvm(&self.wip)}; | 6196 | var result = try self.wip.call( |
| 6017 | var result = (try self.wip.unimplemented(libc_ret_ty, "")).finish(self.builder.buildCall( | 6197 | .normal, |
| 6018 | libc_fn.typeOf(&o.builder).toLlvm(&o.builder), | 6198 | .ccc, |
| 6019 | libc_fn.toLlvm(&o.builder), | 6199 | .none, |
| 6020 | &params, | 6200 | libc_fn.typeOf(&o.builder), |
| 6021 | params.len, | 6201 | libc_fn.toValue(&o.builder), |
| 6022 | .C, | 6202 | &.{operand}, |
| 6023 | .Auto, | | |
| 6024 | "", | 6203 | "", |
| 6025 | ), &self.wip); | 6204 | ); |
| 6026 | | 6205 | |
| 6027 | if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, ""); | 6206 | if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, ""); |
| 6028 | if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, ""); | 6207 | if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, ""); |
| ... | @@ -6843,6 +7022,9 @@ pub const FuncGen = struct { | ... | @@ -6843,6 +7022,9 @@ pub const FuncGen = struct { |
| 6843 | } | 7022 | } |
| 6844 | } | 7023 | } |
| 6845 | | 7024 | |
| | 7025 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 7026 | defer attributes.deinit(&o.builder); |
| | 7027 | |
| 6846 | const ret_llvm_ty = switch (return_count) { | 7028 | const ret_llvm_ty = switch (return_count) { |
| 6847 | 0 => .void, | 7029 | 0 => .void, |
| 6848 | 1 => llvm_ret_types[0], | 7030 | 1 => llvm_ret_types[0], |
| ... | @@ -6861,7 +7043,7 @@ pub const FuncGen = struct { | ... | @@ -6861,7 +7043,7 @@ pub const FuncGen = struct { |
| 6861 | .ATT, | 7043 | .ATT, |
| 6862 | .False, | 7044 | .False, |
| 6863 | ); | 7045 | ); |
| 6864 | const call = (try self.wip.unimplemented(ret_llvm_ty, "")).finish(self.builder.buildCall( | 7046 | const call = (try self.wip.unimplemented(ret_llvm_ty, "")).finish(self.builder.buildCallOld( |
| 6865 | llvm_fn_ty.toLlvm(&o.builder), | 7047 | llvm_fn_ty.toLlvm(&o.builder), |
| 6866 | asm_fn, | 7048 | asm_fn, |
| 6867 | llvm_param_values.ptr, | 7049 | llvm_param_values.ptr, |
| ... | @@ -6872,6 +7054,7 @@ pub const FuncGen = struct { | ... | @@ -6872,6 +7054,7 @@ pub const FuncGen = struct { |
| 6872 | ), &self.wip); | 7054 | ), &self.wip); |
| 6873 | for (llvm_param_attrs[0..param_count], 0..) |llvm_elem_ty, i| { | 7055 | for (llvm_param_attrs[0..param_count], 0..) |llvm_elem_ty, i| { |
| 6874 | if (llvm_elem_ty != .none) { | 7056 | if (llvm_elem_ty != .none) { |
| | 7057 | try attributes.addParamAttr(i, .{ .elementtype = llvm_elem_ty }, &o.builder); |
| 6875 | llvm.setCallElemTypeAttr(call.toLlvm(&self.wip), i, llvm_elem_ty.toLlvm(&o.builder)); | 7058 | llvm.setCallElemTypeAttr(call.toLlvm(&self.wip), i, llvm_elem_ty.toLlvm(&o.builder)); |
| 6876 | } | 7059 | } |
| 6877 | } | 7060 | } |
| ... | @@ -7287,7 +7470,7 @@ pub const FuncGen = struct { | ... | @@ -7287,7 +7470,7 @@ pub const FuncGen = struct { |
| 7287 | const args: [1]*llvm.Value = .{ | 7470 | const args: [1]*llvm.Value = .{ |
| 7288 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), | 7471 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), |
| 7289 | }; | 7472 | }; |
| 7290 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCall( | 7473 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( |
| 7291 | (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder), | 7474 | (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder), |
| 7292 | llvm_fn, | 7475 | llvm_fn, |
| 7293 | &args, | 7476 | &args, |
| ... | @@ -7308,7 +7491,7 @@ pub const FuncGen = struct { | ... | @@ -7308,7 +7491,7 @@ pub const FuncGen = struct { |
| 7308 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), | 7491 | (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), |
| 7309 | operand.toLlvm(&self.wip), | 7492 | operand.toLlvm(&self.wip), |
| 7310 | }; | 7493 | }; |
| 7311 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCall( | 7494 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( |
| 7312 | (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder), | 7495 | (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder), |
| 7313 | llvm_fn, | 7496 | llvm_fn, |
| 7314 | &args, | 7497 | &args, |
| ... | @@ -7425,7 +7608,7 @@ pub const FuncGen = struct { | ... | @@ -7425,7 +7608,7 @@ pub const FuncGen = struct { |
| 7425 | }); | 7608 | }); |
| 7426 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal); | 7609 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal); |
| 7427 | const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); | 7610 | const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); |
| 7428 | const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCall( | 7611 | const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld( |
| 7429 | llvm_fn_ty.toLlvm(&o.builder), | 7612 | llvm_fn_ty.toLlvm(&o.builder), |
| 7430 | llvm_fn, | 7613 | llvm_fn, |
| 7431 | &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) }, | 7614 | &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) }, |
| ... | @@ -7768,7 +7951,7 @@ pub const FuncGen = struct { | ... | @@ -7768,7 +7951,7 @@ pub const FuncGen = struct { |
| 7768 | ); | 7951 | ); |
| 7769 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal); | 7952 | const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal); |
| 7770 | const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish( | 7953 | const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish( |
| 7771 | self.builder.buildCall( | 7954 | self.builder.buildCallOld( |
| 7772 | llvm_fn_ty.toLlvm(&o.builder), | 7955 | llvm_fn_ty.toLlvm(&o.builder), |
| 7773 | llvm_fn, | 7956 | llvm_fn, |
| 7774 | &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) }, | 7957 | &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) }, |
| ... | @@ -7818,29 +8001,23 @@ pub const FuncGen = struct { | ... | @@ -7818,29 +8001,23 @@ pub const FuncGen = struct { |
| 7818 | const o = self.dg.object; | 8001 | const o = self.dg.object; |
| 7819 | assert(args_vectors.len <= 3); | 8002 | assert(args_vectors.len <= 3); |
| 7820 | | 8003 | |
| 7821 | const llvm_fn_ty = llvm_fn.typeOf(&o.builder); | | |
| 7822 | const llvm_scalar_ty = llvm_fn_ty.functionReturn(&o.builder); | | |
| 7823 | | | |
| 7824 | var i: usize = 0; | 8004 | var i: usize = 0; |
| 7825 | var result = result_vector; | 8005 | var result = result_vector; |
| 7826 | while (i < vector_len) : (i += 1) { | 8006 | while (i < vector_len) : (i += 1) { |
| 7827 | const index_i32 = try o.builder.intValue(.i32, i); | 8007 | const index_i32 = try o.builder.intValue(.i32, i); |
| 7828 | | 8008 | |
| 7829 | var args: [3]*llvm.Value = undefined; | 8009 | var args: [3]Builder.Value = undefined; |
| 7830 | for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| { | 8010 | for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| { |
| 7831 | arg_elem.* = (try self.wip.extractElement(arg_vector, index_i32, "")).toLlvm(&self.wip); | 8011 | arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, ""); |
| 7832 | } | 8012 | } |
| 7833 | const result_elem = (try self.wip.unimplemented(llvm_scalar_ty, "")).finish( | 8013 | const result_elem = try self.wip.call( |
| 7834 | self.builder.buildCall( | 8014 | .normal, |
| 7835 | llvm_fn_ty.toLlvm(&o.builder), | 8015 | .ccc, |
| 7836 | llvm_fn.toLlvm(&o.builder), | 8016 | .none, |
| 7837 | &args, | 8017 | llvm_fn.typeOf(&o.builder), |
| 7838 | @intCast(args_vectors.len), | 8018 | llvm_fn.toValue(&o.builder), |
| 7839 | .C, | 8019 | args[0..args_vectors.len], |
| 7840 | .Auto, | 8020 | "", |
| 7841 | "", | | |
| 7842 | ), | | |
| 7843 | &self.wip, | | |
| 7844 | ); | 8021 | ); |
| 7845 | result = try self.wip.insertElement(result, result_elem, index_i32, ""); | 8022 | result = try self.wip.insertElement(result, result_elem, index_i32, ""); |
| 7846 | } | 8023 | } |
| ... | @@ -7861,7 +8038,7 @@ pub const FuncGen = struct { | ... | @@ -7861,7 +8038,7 @@ pub const FuncGen = struct { |
| 7861 | }; | 8038 | }; |
| 7862 | | 8039 | |
| 7863 | const fn_type = try o.builder.fnType(return_type, param_types, .normal); | 8040 | const fn_type = try o.builder.fnType(return_type, param_types, .normal); |
| 7864 | const f = o.llvm_module.addFunction(fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); | 8041 | const f = o.llvm_module.addFunction(fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 7865 | | 8042 | |
| 7866 | var global = Builder.Global{ | 8043 | var global = Builder.Global{ |
| 7867 | .type = fn_type, | 8044 | .type = fn_type, |
| ... | @@ -7942,20 +8119,15 @@ pub const FuncGen = struct { | ... | @@ -7942,20 +8119,15 @@ pub const FuncGen = struct { |
| 7942 | return self.wip.icmp(int_cond, result, zero_vector, ""); | 8119 | return self.wip.icmp(int_cond, result, zero_vector, ""); |
| 7943 | } | 8120 | } |
| 7944 | | 8121 | |
| 7945 | const llvm_fn_ty = libc_fn.typeOf(&o.builder); | 8122 | const result = try self.wip.call( |
| 7946 | const llvm_params = [2]*llvm.Value{ params[0].toLlvm(&self.wip), params[1].toLlvm(&self.wip) }; | 8123 | .normal, |
| 7947 | const result = (try self.wip.unimplemented( | 8124 | .ccc, |
| 7948 | llvm_fn_ty.functionReturn(&o.builder), | 8125 | .none, |
| 7949 | "", | 8126 | libc_fn.typeOf(&o.builder), |
| 7950 | )).finish(self.builder.buildCall( | 8127 | libc_fn.toValue(&o.builder), |
| 7951 | libc_fn.typeOf(&o.builder).toLlvm(&o.builder), | 8128 | &params, |
| 7952 | libc_fn.toLlvm(&o.builder), | | |
| 7953 | &llvm_params, | | |
| 7954 | llvm_params.len, | | |
| 7955 | .C, | | |
| 7956 | .Auto, | | |
| 7957 | "", | 8129 | "", |
| 7958 | ), &self.wip); | 8130 | ); |
| 7959 | return self.wip.icmp(int_cond, result, zero.toValue(), ""); | 8131 | return self.wip.icmp(int_cond, result, zero.toValue(), ""); |
| 7960 | } | 8132 | } |
| 7961 | | 8133 | |
| ... | @@ -8085,7 +8257,7 @@ pub const FuncGen = struct { | ... | @@ -8085,7 +8257,7 @@ pub const FuncGen = struct { |
| 8085 | ); | 8257 | ); |
| 8086 | var llvm_params: [params_len]*llvm.Value = undefined; | 8258 | var llvm_params: [params_len]*llvm.Value = undefined; |
| 8087 | for (&llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(&self.wip); | 8259 | for (&llvm_params, params) |*llvm_param, param| llvm_param.* = param.toLlvm(&self.wip); |
| 8088 | return (try self.wip.unimplemented(llvm_ty, "")).finish(self.builder.buildCall( | 8260 | return (try self.wip.unimplemented(llvm_ty, "")).finish(self.builder.buildCallOld( |
| 8089 | llvm_fn_ty.toLlvm(&o.builder), | 8261 | llvm_fn_ty.toLlvm(&o.builder), |
| 8090 | llvm_fn, | 8262 | llvm_fn, |
| 8091 | &llvm_params, | 8263 | &llvm_params, |
| ... | @@ -8311,17 +8483,16 @@ pub const FuncGen = struct { | ... | @@ -8311,17 +8483,16 @@ pub const FuncGen = struct { |
| 8311 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | 8483 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8312 | }); | 8484 | }); |
| 8313 | | 8485 | |
| 8314 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); | 8486 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8315 | const params = [1]*llvm.Value{operand.toLlvm(&self.wip)}; | 8487 | return self.wip.call( |
| 8316 | return (try self.wip.unimplemented(dest_llvm_ty, "")).finish(self.builder.buildCall( | 8488 | .normal, |
| 8317 | llvm_fn.typeOf(&o.builder).toLlvm(&o.builder), | 8489 | .ccc, |
| 8318 | llvm_fn.toLlvm(&o.builder), | 8490 | .none, |
| 8319 | &params, | 8491 | libc_fn.typeOf(&o.builder), |
| 8320 | params.len, | 8492 | libc_fn.toValue(&o.builder), |
| 8321 | .C, | 8493 | &.{operand}, |
| 8322 | .Auto, | | |
| 8323 | "", | 8494 | "", |
| 8324 | ), &self.wip); | 8495 | ); |
| 8325 | } | 8496 | } |
| 8326 | } | 8497 | } |
| 8327 | | 8498 | |
| ... | @@ -8346,17 +8517,16 @@ pub const FuncGen = struct { | ... | @@ -8346,17 +8517,16 @@ pub const FuncGen = struct { |
| 8346 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | 8517 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8347 | }); | 8518 | }); |
| 8348 | | 8519 | |
| 8349 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); | 8520 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8350 | const params = [1]*llvm.Value{operand.toLlvm(&self.wip)}; | 8521 | return self.wip.call( |
| 8351 | return (try self.wip.unimplemented(dest_llvm_ty, "")).finish(self.builder.buildCall( | 8522 | .normal, |
| 8352 | llvm_fn.typeOf(&o.builder).toLlvm(&o.builder), | 8523 | .ccc, |
| 8353 | llvm_fn.toLlvm(&o.builder), | 8524 | .none, |
| 8354 | &params, | 8525 | libc_fn.typeOf(&o.builder), |
| 8355 | params.len, | 8526 | libc_fn.toValue(&o.builder), |
| 8356 | .C, | 8527 | &.{operand}, |
| 8357 | .Auto, | | |
| 8358 | "", | 8528 | "", |
| 8359 | ), &self.wip); | 8529 | ); |
| 8360 | } | 8530 | } |
| 8361 | } | 8531 | } |
| 8362 | | 8532 | |
| ... | @@ -8657,7 +8827,7 @@ pub const FuncGen = struct { | ... | @@ -8657,7 +8827,7 @@ pub const FuncGen = struct { |
| 8657 | _ = inst; | 8827 | _ = inst; |
| 8658 | const o = self.dg.object; | 8828 | const o = self.dg.object; |
| 8659 | const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); | 8829 | const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); |
| 8660 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 8830 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 8661 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), | 8831 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), |
| 8662 | llvm_fn, | 8832 | llvm_fn, |
| 8663 | undefined, | 8833 | undefined, |
| ... | @@ -8674,7 +8844,7 @@ pub const FuncGen = struct { | ... | @@ -8674,7 +8844,7 @@ pub const FuncGen = struct { |
| 8674 | _ = inst; | 8844 | _ = inst; |
| 8675 | const o = self.dg.object; | 8845 | const o = self.dg.object; |
| 8676 | const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); | 8846 | const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); |
| 8677 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 8847 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 8678 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), | 8848 | (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), |
| 8679 | llvm_fn, | 8849 | llvm_fn, |
| 8680 | undefined, | 8850 | undefined, |
| ... | @@ -8701,7 +8871,7 @@ pub const FuncGen = struct { | ... | @@ -8701,7 +8871,7 @@ pub const FuncGen = struct { |
| 8701 | const params = [_]*llvm.Value{ | 8871 | const params = [_]*llvm.Value{ |
| 8702 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), | 8872 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 8703 | }; | 8873 | }; |
| 8704 | const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCall( | 8874 | const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCallOld( |
| 8705 | (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder), | 8875 | (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder), |
| 8706 | llvm_fn, | 8876 | llvm_fn, |
| 8707 | &params, | 8877 | &params, |
| ... | @@ -8727,7 +8897,7 @@ pub const FuncGen = struct { | ... | @@ -8727,7 +8897,7 @@ pub const FuncGen = struct { |
| 8727 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), | 8897 | (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), |
| 8728 | }; | 8898 | }; |
| 8729 | const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( | 8899 | const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( |
| 8730 | self.builder.buildCall( | 8900 | self.builder.buildCallOld( |
| 8731 | llvm_fn_ty.toLlvm(&o.builder), | 8901 | llvm_fn_ty.toLlvm(&o.builder), |
| 8732 | llvm_fn, | 8902 | llvm_fn, |
| 8733 | &params, | 8903 | &params, |
| ... | @@ -9256,7 +9426,7 @@ pub const FuncGen = struct { | ... | @@ -9256,7 +9426,7 @@ pub const FuncGen = struct { |
| 9256 | Builder.Constant.false.toLlvm(&o.builder), | 9426 | Builder.Constant.false.toLlvm(&o.builder), |
| 9257 | }; | 9427 | }; |
| 9258 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | 9428 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( |
| 9259 | self.builder.buildCall( | 9429 | self.builder.buildCallOld( |
| 9260 | llvm_fn_ty.toLlvm(&o.builder), | 9430 | llvm_fn_ty.toLlvm(&o.builder), |
| 9261 | fn_val, | 9431 | fn_val, |
| 9262 | &params, | 9432 | &params, |
| ... | @@ -9283,7 +9453,7 @@ pub const FuncGen = struct { | ... | @@ -9283,7 +9453,7 @@ pub const FuncGen = struct { |
| 9283 | | 9453 | |
| 9284 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | 9454 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; |
| 9285 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | 9455 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( |
| 9286 | self.builder.buildCall( | 9456 | self.builder.buildCallOld( |
| 9287 | llvm_fn_ty.toLlvm(&o.builder), | 9457 | llvm_fn_ty.toLlvm(&o.builder), |
| 9288 | fn_val, | 9458 | fn_val, |
| 9289 | &params, | 9459 | &params, |
| ... | @@ -9331,7 +9501,7 @@ pub const FuncGen = struct { | ... | @@ -9331,7 +9501,7 @@ pub const FuncGen = struct { |
| 9331 | | 9501 | |
| 9332 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | 9502 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; |
| 9333 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( | 9503 | const wrong_size_result = (try self.wip.unimplemented(llvm_operand_ty, "")).finish( |
| 9334 | self.builder.buildCall( | 9504 | self.builder.buildCallOld( |
| 9335 | llvm_fn_ty.toLlvm(&o.builder), | 9505 | llvm_fn_ty.toLlvm(&o.builder), |
| 9336 | fn_val, | 9506 | fn_val, |
| 9337 | &params, | 9507 | &params, |
| ... | @@ -9389,16 +9559,15 @@ pub const FuncGen = struct { | ... | @@ -9389,16 +9559,15 @@ pub const FuncGen = struct { |
| 9389 | const enum_ty = self.typeOf(un_op); | 9559 | const enum_ty = self.typeOf(un_op); |
| 9390 | | 9560 | |
| 9391 | const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); | 9561 | const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); |
| 9392 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | 9562 | return self.wip.call( |
| 9393 | return (try self.wip.unimplemented(.i1, "")).finish(self.builder.buildCall( | 9563 | .normal, |
| 9394 | llvm_fn.typeOf(&o.builder).toLlvm(&o.builder), | 9564 | .fastcc, |
| 9395 | llvm_fn.toLlvm(&o.builder), | 9565 | .none, |
| 9396 | &params, | 9566 | llvm_fn.typeOf(&o.builder), |
| 9397 | params.len, | 9567 | llvm_fn.toValue(&o.builder), |
| 9398 | .Fast, | 9568 | &.{operand}, |
| 9399 | .Auto, | | |
| 9400 | "", | 9569 | "", |
| 9401 | ), &self.wip); | 9570 | ); |
| 9402 | } | 9571 | } |
| 9403 | | 9572 | |
| 9404 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { | 9573 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| ... | @@ -9416,13 +9585,16 @@ pub const FuncGen = struct { | ... | @@ -9416,13 +9585,16 @@ pub const FuncGen = struct { |
| 9416 | fqn.fmt(&mod.intern_pool), | 9585 | fqn.fmt(&mod.intern_pool), |
| 9417 | }); | 9586 | }); |
| 9418 | | 9587 | |
| | 9588 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 9589 | defer attributes.deinit(&o.builder); |
| | 9590 | |
| 9419 | const fn_type = try o.builder.fnType(.i1, &.{ | 9591 | const fn_type = try o.builder.fnType(.i1, &.{ |
| 9420 | try o.lowerType(enum_type.tag_ty.toType()), | 9592 | try o.lowerType(enum_type.tag_ty.toType()), |
| 9421 | }, .normal); | 9593 | }, .normal); |
| 9422 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); | 9594 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9423 | fn_val.setLinkage(.Internal); | 9595 | fn_val.setLinkage(.Internal); |
| 9424 | fn_val.setFunctionCallConv(.Fast); | 9596 | fn_val.setFunctionCallConv(.Fast); |
| 9425 | o.addCommonFnAttributes(fn_val); | 9597 | try o.addCommonFnAttributes(&attributes, fn_val); |
| 9426 | | 9598 | |
| 9427 | var global = Builder.Global{ | 9599 | var global = Builder.Global{ |
| 9428 | .linkage = .internal, | 9600 | .linkage = .internal, |
| ... | @@ -9431,6 +9603,8 @@ pub const FuncGen = struct { | ... | @@ -9431,6 +9603,8 @@ pub const FuncGen = struct { |
| 9431 | }; | 9603 | }; |
| 9432 | var function = Builder.Function{ | 9604 | var function = Builder.Function{ |
| 9433 | .global = @enumFromInt(o.builder.globals.count()), | 9605 | .global = @enumFromInt(o.builder.globals.count()), |
| | 9606 | .call_conv = .fastcc, |
| | 9607 | .attributes = try attributes.finish(&o.builder), |
| 9434 | }; | 9608 | }; |
| 9435 | try o.builder.llvm.globals.append(self.gpa, fn_val); | 9609 | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9436 | _ = try o.builder.addGlobal(llvm_fn_name, global); | 9610 | _ = try o.builder.addGlobal(llvm_fn_name, global); |
| ... | @@ -9470,19 +9644,14 @@ pub const FuncGen = struct { | ... | @@ -9470,19 +9644,14 @@ pub const FuncGen = struct { |
| 9470 | const enum_ty = self.typeOf(un_op); | 9644 | const enum_ty = self.typeOf(un_op); |
| 9471 | | 9645 | |
| 9472 | const llvm_fn = try self.getEnumTagNameFunction(enum_ty); | 9646 | const llvm_fn = try self.getEnumTagNameFunction(enum_ty); |
| 9473 | const llvm_fn_ty = llvm_fn.typeOf(&o.builder); | 9647 | return self.wip.call( |
| 9474 | const params = [_]*llvm.Value{operand.toLlvm(&self.wip)}; | 9648 | .normal, |
| 9475 | return (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( | 9649 | .fastcc, |
| 9476 | self.builder.buildCall( | 9650 | .none, |
| 9477 | llvm_fn_ty.toLlvm(&o.builder), | 9651 | llvm_fn.typeOf(&o.builder), |
| 9478 | llvm_fn.toLlvm(&o.builder), | 9652 | llvm_fn.toValue(&o.builder), |
| 9479 | &params, | 9653 | &.{operand}, |
| 9480 | params.len, | 9654 | "", |
| 9481 | .Fast, | | |
| 9482 | .Auto, | | |
| 9483 | "", | | |
| 9484 | ), | | |
| 9485 | &self.wip, | | |
| 9486 | ); | 9655 | ); |
| 9487 | } | 9656 | } |
| 9488 | | 9657 | |
| ... | @@ -9499,16 +9668,19 @@ pub const FuncGen = struct { | ... | @@ -9499,16 +9668,19 @@ pub const FuncGen = struct { |
| 9499 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); | 9668 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9500 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); | 9669 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); |
| 9501 | | 9670 | |
| | 9671 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 9672 | defer attributes.deinit(&o.builder); |
| | 9673 | |
| 9502 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); | 9674 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); |
| 9503 | const usize_ty = try o.lowerType(Type.usize); | 9675 | const usize_ty = try o.lowerType(Type.usize); |
| 9504 | | 9676 | |
| 9505 | const fn_type = try o.builder.fnType(ret_ty, &.{ | 9677 | const fn_type = try o.builder.fnType(ret_ty, &.{ |
| 9506 | try o.lowerType(enum_type.tag_ty.toType()), | 9678 | try o.lowerType(enum_type.tag_ty.toType()), |
| 9507 | }, .normal); | 9679 | }, .normal); |
| 9508 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); | 9680 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9509 | fn_val.setLinkage(.Internal); | 9681 | fn_val.setLinkage(.Internal); |
| 9510 | fn_val.setFunctionCallConv(.Fast); | 9682 | fn_val.setFunctionCallConv(.Fast); |
| 9511 | o.addCommonFnAttributes(fn_val); | 9683 | try o.addCommonFnAttributes(&attributes, fn_val); |
| 9512 | | 9684 | |
| 9513 | var global = Builder.Global{ | 9685 | var global = Builder.Global{ |
| 9514 | .linkage = .internal, | 9686 | .linkage = .internal, |
| ... | @@ -9517,6 +9689,8 @@ pub const FuncGen = struct { | ... | @@ -9517,6 +9689,8 @@ pub const FuncGen = struct { |
| 9517 | }; | 9689 | }; |
| 9518 | var function = Builder.Function{ | 9690 | var function = Builder.Function{ |
| 9519 | .global = @enumFromInt(o.builder.globals.count()), | 9691 | .global = @enumFromInt(o.builder.globals.count()), |
| | 9692 | .call_conv = .fastcc, |
| | 9693 | .attributes = try attributes.finish(&o.builder), |
| 9520 | }; | 9694 | }; |
| 9521 | try o.builder.llvm.globals.append(self.gpa, fn_val); | 9695 | try o.builder.llvm.globals.append(self.gpa, fn_val); |
| 9522 | gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); | 9696 | gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); |
| ... | @@ -9561,7 +9735,7 @@ pub const FuncGen = struct { | ... | @@ -9561,7 +9735,7 @@ pub const FuncGen = struct { |
| 9561 | | 9735 | |
| 9562 | const slice_val = try o.builder.structValue(ret_ty, &.{ | 9736 | const slice_val = try o.builder.structValue(ret_ty, &.{ |
| 9563 | global_index.toConst(), | 9737 | global_index.toConst(), |
| 9564 | try o.builder.intConst(usize_ty, name.toSlice(&o.builder).?.len), | 9738 | try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), |
| 9565 | }); | 9739 | }); |
| 9566 | | 9740 | |
| 9567 | const return_block = try wip.block(1, "Name"); | 9741 | const return_block = try wip.block(1, "Name"); |
| ... | @@ -9590,11 +9764,14 @@ pub const FuncGen = struct { | ... | @@ -9590,11 +9764,14 @@ pub const FuncGen = struct { |
| 9590 | // Function signature: fn (anyerror) bool | 9764 | // Function signature: fn (anyerror) bool |
| 9591 | | 9765 | |
| 9592 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); | 9766 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); |
| 9593 | const llvm_fn = o.llvm_module.addFunction(name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); | 9767 | const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| | 9768 | |
| | 9769 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 9770 | defer attributes.deinit(&o.builder); |
| 9594 | | 9771 | |
| 9595 | llvm_fn.setLinkage(.Internal); | 9772 | llvm_fn.setLinkage(.Internal); |
| 9596 | llvm_fn.setFunctionCallConv(.Fast); | 9773 | llvm_fn.setFunctionCallConv(.Fast); |
| 9597 | o.addCommonFnAttributes(llvm_fn); | 9774 | try o.addCommonFnAttributes(&attributes, llvm_fn); |
| 9598 | | 9775 | |
| 9599 | var global = Builder.Global{ | 9776 | var global = Builder.Global{ |
| 9600 | .linkage = .internal, | 9777 | .linkage = .internal, |
| ... | @@ -9603,6 +9780,8 @@ pub const FuncGen = struct { | ... | @@ -9603,6 +9780,8 @@ pub const FuncGen = struct { |
| 9603 | }; | 9780 | }; |
| 9604 | var function = Builder.Function{ | 9781 | var function = Builder.Function{ |
| 9605 | .global = @enumFromInt(o.builder.globals.count()), | 9782 | .global = @enumFromInt(o.builder.globals.count()), |
| | 9783 | .call_conv = .fastcc, |
| | 9784 | .attributes = try attributes.finish(&o.builder), |
| 9606 | }; | 9785 | }; |
| 9607 | | 9786 | |
| 9608 | try o.builder.llvm.globals.append(self.gpa, llvm_fn); | 9787 | try o.builder.llvm.globals.append(self.gpa, llvm_fn); |
| ... | @@ -9731,18 +9910,14 @@ pub const FuncGen = struct { | ... | @@ -9731,18 +9910,14 @@ pub const FuncGen = struct { |
| 9731 | // accum = f(accum, vec[i]); | 9910 | // accum = f(accum, vec[i]); |
| 9732 | const accum = try self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, ""); | 9911 | const accum = try self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, ""); |
| 9733 | const element = try self.wip.extractElement(operand_vector, i, ""); | 9912 | const element = try self.wip.extractElement(operand_vector, i, ""); |
| 9734 | const params = [2]*llvm.Value{ accum.toLlvm(&self.wip), element.toLlvm(&self.wip) }; | 9913 | const new_accum = try self.wip.call( |
| 9735 | const new_accum = (try self.wip.unimplemented(llvm_result_ty, "")).finish( | 9914 | .normal, |
| 9736 | self.builder.buildCall( | 9915 | .ccc, |
| 9737 | llvm_fn.typeOf(&o.builder).toLlvm(&o.builder), | 9916 | .none, |
| 9738 | llvm_fn.toLlvm(&o.builder), | 9917 | llvm_fn.typeOf(&o.builder), |
| 9739 | &params, | 9918 | llvm_fn.toValue(&o.builder), |
| 9740 | params.len, | 9919 | &.{ accum, element }, |
| 9741 | .C, | 9920 | "", |
| 9742 | .Auto, | | |
| 9743 | "", | | |
| 9744 | ), | | |
| 9745 | &self.wip, | | |
| 9746 | ); | 9921 | ); |
| 9747 | _ = try self.wip.store(.normal, new_accum, accum_ptr, .default); | 9922 | _ = try self.wip.store(.normal, new_accum, accum_ptr, .default); |
| 9748 | | 9923 | |
| ... | @@ -10190,7 +10365,7 @@ pub const FuncGen = struct { | ... | @@ -10190,7 +10365,7 @@ pub const FuncGen = struct { |
| 10190 | (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder), | 10365 | (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder), |
| 10191 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder), | 10366 | (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder), |
| 10192 | }; | 10367 | }; |
| 10193 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCall( | 10368 | _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( |
| 10194 | llvm_fn_ty.toLlvm(&o.builder), | 10369 | llvm_fn_ty.toLlvm(&o.builder), |
| 10195 | fn_val, | 10370 | fn_val, |
| 10196 | &params, | 10371 | &params, |
| ... | @@ -10222,7 +10397,7 @@ pub const FuncGen = struct { | ... | @@ -10222,7 +10397,7 @@ pub const FuncGen = struct { |
| 10222 | | 10397 | |
| 10223 | const args: [0]*llvm.Value = .{}; | 10398 | const args: [0]*llvm.Value = .{}; |
| 10224 | const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{}); | 10399 | const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{}); |
| 10225 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCall( | 10400 | return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( |
| 10226 | (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder), | 10401 | (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder), |
| 10227 | llvm_fn, | 10402 | llvm_fn, |
| 10228 | &args, | 10403 | &args, |
| ... | @@ -10252,12 +10427,15 @@ pub const FuncGen = struct { | ... | @@ -10252,12 +10427,15 @@ pub const FuncGen = struct { |
| 10252 | const dimension = pl_op.payload; | 10427 | const dimension = pl_op.payload; |
| 10253 | if (dimension >= 3) return o.builder.intValue(.i32, 1); | 10428 | if (dimension >= 3) return o.builder.intValue(.i32, 1); |
| 10254 | | 10429 | |
| | 10430 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| | 10431 | defer attributes.deinit(&o.builder); |
| | 10432 | |
| 10255 | // Fetch the dispatch pointer, which points to this structure: | 10433 | // Fetch the dispatch pointer, which points to this structure: |
| 10256 | // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 | 10434 | // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 |
| 10257 | const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); | 10435 | const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); |
| 10258 | const args: [0]*llvm.Value = .{}; | 10436 | const args: [0]*llvm.Value = .{}; |
| 10259 | const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant); | 10437 | const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant); |
| 10260 | const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCall( | 10438 | const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCallOld( |
| 10261 | (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder), | 10439 | (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder), |
| 10262 | llvm_fn, | 10440 | llvm_fn, |
| 10263 | &args, | 10441 | &args, |
| ... | @@ -10266,6 +10444,9 @@ pub const FuncGen = struct { | ... | @@ -10266,6 +10444,9 @@ pub const FuncGen = struct { |
| 10266 | .Auto, | 10444 | .Auto, |
| 10267 | "", | 10445 | "", |
| 10268 | ), &self.wip); | 10446 | ), &self.wip); |
| | 10447 | try attributes.addRetAttr(.{ |
| | 10448 | .@"align" = comptime Builder.Alignment.fromByteUnits(4), |
| | 10449 | }, &o.builder); |
| 10269 | o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4); | 10450 | o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4); |
| 10270 | | 10451 | |
| 10271 | // Load the work_group_* member from the struct as u16. | 10452 | // Load the work_group_* member from the struct as u16. |
| ... | @@ -10298,7 +10479,7 @@ pub const FuncGen = struct { | ... | @@ -10298,7 +10479,7 @@ pub const FuncGen = struct { |
| 10298 | const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space | 10479 | const undef_init = try o.builder.undefConst(.ptr); // TODO: Address space |
| 10299 | | 10480 | |
| 10300 | const name = try o.builder.string("__zig_err_name_table"); | 10481 | const name = try o.builder.string("__zig_err_name_table"); |
| 10301 | const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.toSlice(&o.builder).?); | 10482 | const error_name_table_global = o.llvm_module.addGlobal(Builder.Type.ptr.toLlvm(&o.builder), name.slice(&o.builder).?); |
| 10302 | error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder)); | 10483 | error_name_table_global.setInitializer(undef_init.toLlvm(&o.builder)); |
| 10303 | error_name_table_global.setLinkage(.Private); | 10484 | error_name_table_global.setLinkage(.Private); |
| 10304 | error_name_table_global.setGlobalConstant(.True); | 10485 | error_name_table_global.setGlobalConstant(.True); |
| ... | @@ -10751,7 +10932,7 @@ pub const FuncGen = struct { | ... | @@ -10751,7 +10932,7 @@ pub const FuncGen = struct { |
| 10751 | ); | 10932 | ); |
| 10752 | | 10933 | |
| 10753 | const call = (try fg.wip.unimplemented(llvm_usize, "")).finish( | 10934 | const call = (try fg.wip.unimplemented(llvm_usize, "")).finish( |
| 10754 | fg.builder.buildCall(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""), | 10935 | fg.builder.buildCallOld(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""), |
| 10755 | &fg.wip, | 10936 | &fg.wip, |
| 10756 | ); | 10937 | ); |
| 10757 | return call; | 10938 | return call; |
| ... | @@ -10991,33 +11172,33 @@ fn toLlvmAtomicRmwBinOp( | ... | @@ -10991,33 +11172,33 @@ fn toLlvmAtomicRmwBinOp( |
| 10991 | }; | 11172 | }; |
| 10992 | } | 11173 | } |
| 10993 | | 11174 | |
| 10994 | fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.CallConv { | 11175 | fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) Builder.CallConv { |
| 10995 | return switch (cc) { | 11176 | return switch (cc) { |
| 10996 | .Unspecified, .Inline, .Async => .Fast, | 11177 | .Unspecified, .Inline, .Async => .fastcc, |
| 10997 | .C, .Naked => .C, | 11178 | .C, .Naked => .ccc, |
| 10998 | .Stdcall => .X86_StdCall, | 11179 | .Stdcall => .x86_stdcallcc, |
| 10999 | .Fastcall => .X86_FastCall, | 11180 | .Fastcall => .x86_fastcallcc, |
| 11000 | .Vectorcall => return switch (target.cpu.arch) { | 11181 | .Vectorcall => return switch (target.cpu.arch) { |
| 11001 | .x86, .x86_64 => .X86_VectorCall, | 11182 | .x86, .x86_64 => .x86_vectorcallcc, |
| 11002 | .aarch64, .aarch64_be, .aarch64_32 => .AArch64_VectorCall, | 11183 | .aarch64, .aarch64_be, .aarch64_32 => .aarch64_vector_pcs, |
| 11003 | else => unreachable, | 11184 | else => unreachable, |
| 11004 | }, | 11185 | }, |
| 11005 | .Thiscall => .X86_ThisCall, | 11186 | .Thiscall => .x86_thiscallcc, |
| 11006 | .APCS => .ARM_APCS, | 11187 | .APCS => .arm_apcscc, |
| 11007 | .AAPCS => .ARM_AAPCS, | 11188 | .AAPCS => .arm_aapcscc, |
| 11008 | .AAPCSVFP => .ARM_AAPCS_VFP, | 11189 | .AAPCSVFP => .arm_aapcs_vfpcc, |
| 11009 | .Interrupt => return switch (target.cpu.arch) { | 11190 | .Interrupt => return switch (target.cpu.arch) { |
| 11010 | .x86, .x86_64 => .X86_INTR, | 11191 | .x86, .x86_64 => .x86_intrcc, |
| 11011 | .avr => .AVR_INTR, | 11192 | .avr => .avr_intrcc, |
| 11012 | .msp430 => .MSP430_INTR, | 11193 | .msp430 => .msp430_intrcc, |
| 11013 | else => unreachable, | 11194 | else => unreachable, |
| 11014 | }, | 11195 | }, |
| 11015 | .Signal => .AVR_SIGNAL, | 11196 | .Signal => .avr_signalcc, |
| 11016 | .SysV => .X86_64_SysV, | 11197 | .SysV => .x86_64_sysvcc, |
| 11017 | .Win64 => .Win64, | 11198 | .Win64 => .win64cc, |
| 11018 | .Kernel => return switch (target.cpu.arch) { | 11199 | .Kernel => return switch (target.cpu.arch) { |
| 11019 | .nvptx, .nvptx64 => .PTX_Kernel, | 11200 | .nvptx, .nvptx64 => .ptx_kernel, |
| 11020 | .amdgcn => .AMDGPU_KERNEL, | 11201 | .amdgcn => .amdgpu_kernel, |
| 11021 | else => unreachable, | 11202 | else => unreachable, |
| 11022 | }, | 11203 | }, |
| 11023 | }; | 11204 | }; |