| ... | ... | @@ -822,7 +822,7 @@ pub const Object = struct { |
| 822 | 822 | type_map: TypeMap, |
| 823 | 823 | di_type_map: DITypeMap, |
| 824 | 824 | /// The LLVM global table which holds the names corresponding to Zig errors. |
| 825 | | /// Note that the values are not added until flushModule, when all errors in |
| 825 | /// Note that the values are not added until `emit`, when all errors in |
| 826 | 826 | /// the compilation are known. |
| 827 | 827 | error_name_table: Builder.Variable.Index, |
| 828 | 828 | /// This map is usually very close to empty. It tracks only the cases when a |
| ... | ... | @@ -850,7 +850,7 @@ pub const Object = struct { |
| 850 | 850 | |
| 851 | 851 | pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); |
| 852 | 852 | |
| 853 | | /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we |
| 853 | /// This is an ArrayHashMap as opposed to a HashMap because in `emit` we |
| 854 | 854 | /// want to iterate over it while adding entries to it. |
| 855 | 855 | pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); |
| 856 | 856 | |
| ... | ... | @@ -1026,17 +1026,6 @@ pub const Object = struct { |
| 1026 | 1026 | self.* = undefined; |
| 1027 | 1027 | } |
| 1028 | 1028 | |
| 1029 | | fn locPath( |
| 1030 | | arena: Allocator, |
| 1031 | | opt_loc: ?Compilation.EmitLoc, |
| 1032 | | cache_directory: Compilation.Directory, |
| 1033 | | ) !?[*:0]u8 { |
| 1034 | | const loc = opt_loc orelse return null; |
| 1035 | | const directory = loc.directory orelse cache_directory; |
| 1036 | | const slice = try directory.joinZ(arena, &[_][]const u8{loc.basename}); |
| 1037 | | return slice.ptr; |
| 1038 | | } |
| 1039 | | |
| 1040 | 1029 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| 1041 | 1030 | // If o.error_name_table is null, then it was not referenced by any instructions. |
| 1042 | 1031 | if (o.error_name_table == .none) return; |
| ... | ... | @@ -1175,12 +1164,22 @@ pub const Object = struct { |
| 1175 | 1164 | } |
| 1176 | 1165 | } |
| 1177 | 1166 | |
| 1178 | | pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 1179 | | var sub_prog_node = prog_node.start("LLVM Emit Object", 0); |
| 1180 | | sub_prog_node.activate(); |
| 1181 | | sub_prog_node.context.refresh(); |
| 1182 | | defer sub_prog_node.end(); |
| 1167 | pub const EmitOptions = struct { |
| 1168 | pre_ir_path: ?[]const u8, |
| 1169 | pre_bc_path: ?[]const u8, |
| 1170 | bin_path: ?[*:0]const u8, |
| 1171 | emit_asm: ?[*:0]const u8, |
| 1172 | post_ir_path: ?[*:0]const u8, |
| 1173 | post_bc_path: ?[*:0]const u8, |
| 1174 | |
| 1175 | is_debug: bool, |
| 1176 | is_small: bool, |
| 1177 | time_report: bool, |
| 1178 | sanitize_thread: bool, |
| 1179 | lto: bool, |
| 1180 | }; |
| 1183 | 1181 | |
| 1182 | pub fn emit(self: *Object, options: EmitOptions) !void { |
| 1184 | 1183 | try self.resolveExportExternCollisions(); |
| 1185 | 1184 | try self.genErrorNameTable(); |
| 1186 | 1185 | try self.genCmpLtErrorsLenFunction(); |
| ... | ... | @@ -1206,7 +1205,7 @@ pub const Object = struct { |
| 1206 | 1205 | dib.finalize(); |
| 1207 | 1206 | } |
| 1208 | 1207 | |
| 1209 | | if (comp.verbose_llvm_ir) |path| { |
| 1208 | if (options.pre_ir_path) |path| { |
| 1210 | 1209 | if (std.mem.eql(u8, path, "-")) { |
| 1211 | 1210 | self.builder.dump(); |
| 1212 | 1211 | } else { |
| ... | ... | @@ -1214,91 +1213,72 @@ pub const Object = struct { |
| 1214 | 1213 | } |
| 1215 | 1214 | } |
| 1216 | 1215 | |
| 1217 | | if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path); |
| 1218 | | |
| 1219 | | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); |
| 1220 | | defer arena_allocator.deinit(); |
| 1221 | | const arena = arena_allocator.allocator(); |
| 1222 | | |
| 1223 | | const mod = comp.module.?; |
| 1224 | | const cache_dir = mod.zig_cache_artifact_directory; |
| 1216 | if (options.pre_bc_path) |path| _ = try self.builder.writeBitcodeToFile(path); |
| 1225 | 1217 | |
| 1226 | 1218 | if (std.debug.runtime_safety and !try self.builder.verify()) { |
| 1227 | | if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| |
| 1228 | | _ = self.builder.printToFileZ(emit_llvm_ir_path); |
| 1229 | 1219 | @panic("LLVM module verification failed"); |
| 1230 | 1220 | } |
| 1231 | 1221 | |
| 1232 | | var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| |
| 1233 | | try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) |
| 1234 | | else |
| 1235 | | null; |
| 1236 | | |
| 1237 | | const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir); |
| 1238 | | var emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir); |
| 1239 | | const emit_llvm_bc_path = try locPath(arena, comp.emit_llvm_bc, cache_dir); |
| 1240 | | |
| 1241 | | const emit_asm_msg = emit_asm_path orelse "(none)"; |
| 1242 | | const emit_bin_msg = emit_bin_path orelse "(none)"; |
| 1243 | | const emit_llvm_ir_msg = emit_llvm_ir_path orelse "(none)"; |
| 1244 | | const emit_llvm_bc_msg = emit_llvm_bc_path orelse "(none)"; |
| 1222 | const emit_asm_msg = options.asm_path orelse "(none)"; |
| 1223 | const emit_bin_msg = options.bin_path orelse "(none)"; |
| 1224 | const post_llvm_ir_msg = options.post_ir_path orelse "(none)"; |
| 1225 | const post_llvm_bc_msg = options.post_bc_path orelse "(none)"; |
| 1245 | 1226 | log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{ |
| 1246 | | emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, |
| 1227 | emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, |
| 1247 | 1228 | }); |
| 1248 | 1229 | |
| 1249 | | if (emit_asm_path == null and emit_bin_path == null and |
| 1250 | | emit_llvm_ir_path == null and emit_llvm_bc_path == null) return; |
| 1230 | if (options.asm_path == null and options.bin_path == null and |
| 1231 | options.post_ir_path == null and options.post_bc_path == null) return; |
| 1251 | 1232 | |
| 1252 | | if (!self.builder.useLibLlvm()) { |
| 1253 | | log.err("emitting without libllvm not implemented", .{}); |
| 1254 | | return error.FailedToEmit; |
| 1255 | | } |
| 1233 | if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve |
| 1256 | 1234 | |
| 1257 | 1235 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 1258 | 1236 | // So we call the entire pipeline multiple times if this is requested. |
| 1259 | 1237 | var error_message: [*:0]const u8 = undefined; |
| 1260 | | if (emit_asm_path != null and emit_bin_path != null) { |
| 1238 | var emit_bin_path = options.bin_path; |
| 1239 | var post_ir_path = options.post_ir_path; |
| 1240 | if (options.asm_path != null and options.bin_path != null) { |
| 1261 | 1241 | if (self.target_machine.emitToFile( |
| 1262 | 1242 | self.builder.llvm.module.?, |
| 1263 | 1243 | &error_message, |
| 1264 | | comp.bin_file.options.optimize_mode == .Debug, |
| 1265 | | comp.bin_file.options.optimize_mode == .ReleaseSmall, |
| 1266 | | comp.time_report, |
| 1267 | | comp.bin_file.options.tsan, |
| 1268 | | comp.bin_file.options.lto, |
| 1244 | options.is_debug, |
| 1245 | options.is_small, |
| 1246 | options.time_report, |
| 1247 | options.sanitize_thread, |
| 1248 | options.lto, |
| 1269 | 1249 | null, |
| 1270 | 1250 | emit_bin_path, |
| 1271 | | emit_llvm_ir_path, |
| 1251 | post_ir_path, |
| 1272 | 1252 | null, |
| 1273 | 1253 | )) { |
| 1274 | 1254 | defer llvm.disposeMessage(error_message); |
| 1275 | 1255 | |
| 1276 | 1256 | log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{ |
| 1277 | | emit_bin_msg, emit_llvm_ir_msg, error_message, |
| 1257 | emit_bin_msg, post_llvm_ir_msg, error_message, |
| 1278 | 1258 | }); |
| 1279 | 1259 | return error.FailedToEmit; |
| 1280 | 1260 | } |
| 1281 | 1261 | emit_bin_path = null; |
| 1282 | | emit_llvm_ir_path = null; |
| 1262 | post_ir_path = null; |
| 1283 | 1263 | } |
| 1284 | 1264 | |
| 1285 | 1265 | if (self.target_machine.emitToFile( |
| 1286 | 1266 | self.builder.llvm.module.?, |
| 1287 | 1267 | &error_message, |
| 1288 | | comp.bin_file.options.optimize_mode == .Debug, |
| 1289 | | comp.bin_file.options.optimize_mode == .ReleaseSmall, |
| 1290 | | comp.time_report, |
| 1291 | | comp.bin_file.options.tsan, |
| 1292 | | comp.bin_file.options.lto, |
| 1293 | | emit_asm_path, |
| 1268 | options.is_debug, |
| 1269 | options.is_small, |
| 1270 | options.time_report, |
| 1271 | options.sanitize_thread, |
| 1272 | options.lto, |
| 1273 | options.asm_path, |
| 1294 | 1274 | emit_bin_path, |
| 1295 | | emit_llvm_ir_path, |
| 1296 | | emit_llvm_bc_path, |
| 1275 | post_ir_path, |
| 1276 | options.post_bc_path, |
| 1297 | 1277 | )) { |
| 1298 | 1278 | defer llvm.disposeMessage(error_message); |
| 1299 | 1279 | |
| 1300 | 1280 | log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ |
| 1301 | | emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, |
| 1281 | emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, |
| 1302 | 1282 | error_message, |
| 1303 | 1283 | }); |
| 1304 | 1284 | return error.FailedToEmit; |
| ... | ... | @@ -1307,17 +1287,19 @@ pub const Object = struct { |
| 1307 | 1287 | |
| 1308 | 1288 | pub fn updateFunc( |
| 1309 | 1289 | o: *Object, |
| 1310 | | mod: *Module, |
| 1290 | zcu: *Module, |
| 1311 | 1291 | func_index: InternPool.Index, |
| 1312 | 1292 | air: Air, |
| 1313 | 1293 | liveness: Liveness, |
| 1314 | 1294 | ) !void { |
| 1315 | | const func = mod.funcInfo(func_index); |
| 1295 | const func = zcu.funcInfo(func_index); |
| 1316 | 1296 | const decl_index = func.owner_decl; |
| 1317 | | const decl = mod.declPtr(decl_index); |
| 1318 | | const fn_info = mod.typeToFunc(decl.ty).?; |
| 1319 | | const target = mod.getTarget(); |
| 1320 | | const ip = &mod.intern_pool; |
| 1297 | const decl = zcu.declPtr(decl_index); |
| 1298 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 1299 | const owner_mod = namespace.file_scope.mod; |
| 1300 | const fn_info = zcu.typeToFunc(decl.ty).?; |
| 1301 | const target = zcu.getTarget(); |
| 1302 | const ip = &zcu.intern_pool; |
| 1321 | 1303 | |
| 1322 | 1304 | var dg: DeclGen = .{ |
| 1323 | 1305 | .object = o, |
| ... | ... | @@ -1352,7 +1334,7 @@ pub const Object = struct { |
| 1352 | 1334 | } |
| 1353 | 1335 | |
| 1354 | 1336 | // TODO: disable this if safety is off for the function scope |
| 1355 | | const ssp_buf_size = mod.comp.bin_file.options.stack_protector; |
| 1337 | const ssp_buf_size = owner_mod.stack_protector; |
| 1356 | 1338 | if (ssp_buf_size != 0) { |
| 1357 | 1339 | try attributes.addFnAttr(.sspstrong, &o.builder); |
| 1358 | 1340 | try attributes.addFnAttr(.{ .string = .{ |
| ... | ... | @@ -1362,7 +1344,7 @@ pub const Object = struct { |
| 1362 | 1344 | } |
| 1363 | 1345 | |
| 1364 | 1346 | // TODO: disable this if safety is off for the function scope |
| 1365 | | if (mod.comp.bin_file.options.stack_check) { |
| 1347 | if (owner_mod.stack_check) { |
| 1366 | 1348 | try attributes.addFnAttr(.{ .string = .{ |
| 1367 | 1349 | .kind = try o.builder.string("probe-stack"), |
| 1368 | 1350 | .value = try o.builder.string("__zig_probe_stack"), |
| ... | ... | @@ -1385,20 +1367,22 @@ pub const Object = struct { |
| 1385 | 1367 | var llvm_arg_i: u32 = 0; |
| 1386 | 1368 | |
| 1387 | 1369 | // This gets the LLVM values from the function and stores them in `dg.args`. |
| 1388 | | const sret = firstParamSRet(fn_info, mod); |
| 1370 | const sret = firstParamSRet(fn_info, zcu); |
| 1389 | 1371 | const ret_ptr: Builder.Value = if (sret) param: { |
| 1390 | 1372 | const param = wip.arg(llvm_arg_i); |
| 1391 | 1373 | llvm_arg_i += 1; |
| 1392 | 1374 | break :param param; |
| 1393 | 1375 | } else .none; |
| 1394 | 1376 | |
| 1395 | | if (ccAbiPromoteInt(fn_info.cc, mod, Type.fromInterned(fn_info.return_type))) |s| switch (s) { |
| 1377 | if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) { |
| 1396 | 1378 | .signed => try attributes.addRetAttr(.signext, &o.builder), |
| 1397 | 1379 | .unsigned => try attributes.addRetAttr(.zeroext, &o.builder), |
| 1398 | 1380 | }; |
| 1399 | 1381 | |
| 1400 | | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and |
| 1401 | | mod.comp.config.any_error_tracing; |
| 1382 | const comp = zcu.comp; |
| 1383 | |
| 1384 | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and |
| 1385 | comp.config.any_error_tracing; |
| 1402 | 1386 | |
| 1403 | 1387 | const err_ret_trace: Builder.Value = if (err_return_tracing) param: { |
| 1404 | 1388 | const param = wip.arg(llvm_arg_i); |
| ... | ... | @@ -1426,8 +1410,8 @@ pub const Object = struct { |
| 1426 | 1410 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); |
| 1427 | 1411 | const param = wip.arg(llvm_arg_i); |
| 1428 | 1412 | |
| 1429 | | if (isByRef(param_ty, mod)) { |
| 1430 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1413 | if (isByRef(param_ty, zcu)) { |
| 1414 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1431 | 1415 | const param_llvm_ty = param.typeOfWip(&wip); |
| 1432 | 1416 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1433 | 1417 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| ... | ... | @@ -1443,12 +1427,12 @@ pub const Object = struct { |
| 1443 | 1427 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1444 | 1428 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1445 | 1429 | const param = wip.arg(llvm_arg_i); |
| 1446 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1430 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1447 | 1431 | |
| 1448 | 1432 | try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1449 | 1433 | llvm_arg_i += 1; |
| 1450 | 1434 | |
| 1451 | | if (isByRef(param_ty, mod)) { |
| 1435 | if (isByRef(param_ty, zcu)) { |
| 1452 | 1436 | args.appendAssumeCapacity(param); |
| 1453 | 1437 | } else { |
| 1454 | 1438 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); |
| ... | ... | @@ -1458,12 +1442,12 @@ pub const Object = struct { |
| 1458 | 1442 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1459 | 1443 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1460 | 1444 | const param = wip.arg(llvm_arg_i); |
| 1461 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1445 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1462 | 1446 | |
| 1463 | 1447 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| 1464 | 1448 | llvm_arg_i += 1; |
| 1465 | 1449 | |
| 1466 | | if (isByRef(param_ty, mod)) { |
| 1450 | if (isByRef(param_ty, zcu)) { |
| 1467 | 1451 | args.appendAssumeCapacity(param); |
| 1468 | 1452 | } else { |
| 1469 | 1453 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); |
| ... | ... | @@ -1476,11 +1460,11 @@ pub const Object = struct { |
| 1476 | 1460 | llvm_arg_i += 1; |
| 1477 | 1461 | |
| 1478 | 1462 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1479 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1463 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1480 | 1464 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1481 | 1465 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1482 | 1466 | |
| 1483 | | args.appendAssumeCapacity(if (isByRef(param_ty, mod)) |
| 1467 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| 1484 | 1468 | arg_ptr |
| 1485 | 1469 | else |
| 1486 | 1470 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | ... | @@ -1488,14 +1472,14 @@ pub const Object = struct { |
| 1488 | 1472 | .slice => { |
| 1489 | 1473 | assert(!it.byval_attr); |
| 1490 | 1474 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1491 | | const ptr_info = param_ty.ptrInfo(mod); |
| 1475 | const ptr_info = param_ty.ptrInfo(zcu); |
| 1492 | 1476 | |
| 1493 | 1477 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1494 | 1478 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1495 | 1479 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); |
| 1496 | 1480 | } |
| 1497 | 1481 | } |
| 1498 | | if (param_ty.zigTypeTag(mod) != .Optional) { |
| 1482 | if (param_ty.zigTypeTag(zcu) != .Optional) { |
| 1499 | 1483 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 1500 | 1484 | } |
| 1501 | 1485 | if (ptr_info.flags.is_const) { |
| ... | ... | @@ -1504,7 +1488,7 @@ pub const Object = struct { |
| 1504 | 1488 | const elem_align = (if (ptr_info.flags.alignment != .none) |
| 1505 | 1489 | @as(InternPool.Alignment, ptr_info.flags.alignment) |
| 1506 | 1490 | else |
| 1507 | | Type.fromInterned(ptr_info.child).abiAlignment(mod).max(.@"1")).toLlvm(); |
| 1491 | Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); |
| 1508 | 1492 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1509 | 1493 | const ptr_param = wip.arg(llvm_arg_i); |
| 1510 | 1494 | llvm_arg_i += 1; |
| ... | ... | @@ -1521,7 +1505,7 @@ pub const Object = struct { |
| 1521 | 1505 | const field_types = it.types_buffer[0..it.types_len]; |
| 1522 | 1506 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1523 | 1507 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1524 | | const param_alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1508 | const param_alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1525 | 1509 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target); |
| 1526 | 1510 | const llvm_ty = try o.builder.structType(.normal, field_types); |
| 1527 | 1511 | for (0..field_types.len) |field_i| { |
| ... | ... | @@ -1533,7 +1517,7 @@ pub const Object = struct { |
| 1533 | 1517 | _ = try wip.store(.normal, param, field_ptr, alignment); |
| 1534 | 1518 | } |
| 1535 | 1519 | |
| 1536 | | const is_by_ref = isByRef(param_ty, mod); |
| 1520 | const is_by_ref = isByRef(param_ty, zcu); |
| 1537 | 1521 | args.appendAssumeCapacity(if (is_by_ref) |
| 1538 | 1522 | arg_ptr |
| 1539 | 1523 | else |
| ... | ... | @@ -1551,11 +1535,11 @@ pub const Object = struct { |
| 1551 | 1535 | const param = wip.arg(llvm_arg_i); |
| 1552 | 1536 | llvm_arg_i += 1; |
| 1553 | 1537 | |
| 1554 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1538 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1555 | 1539 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1556 | 1540 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1557 | 1541 | |
| 1558 | | args.appendAssumeCapacity(if (isByRef(param_ty, mod)) |
| 1542 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| 1559 | 1543 | arg_ptr |
| 1560 | 1544 | else |
| 1561 | 1545 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | ... | @@ -1566,11 +1550,11 @@ pub const Object = struct { |
| 1566 | 1550 | const param = wip.arg(llvm_arg_i); |
| 1567 | 1551 | llvm_arg_i += 1; |
| 1568 | 1552 | |
| 1569 | | const alignment = param_ty.abiAlignment(mod).toLlvm(); |
| 1553 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1570 | 1554 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1571 | 1555 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1572 | 1556 | |
| 1573 | | args.appendAssumeCapacity(if (isByRef(param_ty, mod)) |
| 1557 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| 1574 | 1558 | arg_ptr |
| 1575 | 1559 | else |
| 1576 | 1560 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | ... | @@ -1584,14 +1568,12 @@ pub const Object = struct { |
| 1584 | 1568 | var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; |
| 1585 | 1569 | var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; |
| 1586 | 1570 | |
| 1587 | | const namespace = mod.namespacePtr(decl.src_namespace); |
| 1588 | | |
| 1589 | 1571 | if (o.di_builder) |dib| { |
| 1590 | 1572 | di_file = try o.getDIFile(gpa, namespace.file_scope); |
| 1591 | 1573 | |
| 1592 | 1574 | const line_number = decl.src_line + 1; |
| 1593 | | const is_internal_linkage = decl.val.getExternFunc(mod) == null and |
| 1594 | | !mod.decl_exports.contains(decl_index); |
| 1575 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null and |
| 1576 | !zcu.decl_exports.contains(decl_index); |
| 1595 | 1577 | const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type) |
| 1596 | 1578 | llvm.DIFlags.NoReturn |
| 1597 | 1579 | else |
| ... | ... | @@ -1608,7 +1590,7 @@ pub const Object = struct { |
| 1608 | 1590 | true, // is definition |
| 1609 | 1591 | line_number + func.lbrace_line, // scope line |
| 1610 | 1592 | llvm.DIFlags.StaticMember | noret_bit, |
| 1611 | | mod.comp.bin_file.options.optimize_mode != .Debug, |
| 1593 | owner_mod.optimize_mode != .Debug, |
| 1612 | 1594 | null, // decl_subprogram |
| 1613 | 1595 | ); |
| 1614 | 1596 | try o.di_map.put(gpa, decl, subprogram.toNode()); |
| ... | ... | @@ -1618,8 +1600,6 @@ pub const Object = struct { |
| 1618 | 1600 | di_scope = subprogram.toScope(); |
| 1619 | 1601 | } |
| 1620 | 1602 | |
| 1621 | | const single_threaded = namespace.file_scope.mod.single_threaded; |
| 1622 | | |
| 1623 | 1603 | var fg: FuncGen = .{ |
| 1624 | 1604 | .gpa = gpa, |
| 1625 | 1605 | .air = air, |
| ... | ... | @@ -1631,7 +1611,7 @@ pub const Object = struct { |
| 1631 | 1611 | .arg_index = 0, |
| 1632 | 1612 | .func_inst_table = .{}, |
| 1633 | 1613 | .blocks = .{}, |
| 1634 | | .sync_scope = if (single_threaded) .singlethread else .system, |
| 1614 | .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, |
| 1635 | 1615 | .di_scope = di_scope, |
| 1636 | 1616 | .di_file = di_file, |
| 1637 | 1617 | .base_line = dg.decl.src_line, |
| ... | ... | @@ -1645,7 +1625,7 @@ pub const Object = struct { |
| 1645 | 1625 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 1646 | 1626 | error.CodegenFail => { |
| 1647 | 1627 | decl.analysis = .codegen_failure; |
| 1648 | | try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?); |
| 1628 | try zcu.failed_decls.put(zcu.gpa, decl_index, dg.err_msg.?); |
| 1649 | 1629 | dg.err_msg = null; |
| 1650 | 1630 | return; |
| 1651 | 1631 | }, |
| ... | ... | @@ -1654,7 +1634,7 @@ pub const Object = struct { |
| 1654 | 1634 | |
| 1655 | 1635 | try fg.wip.finish(); |
| 1656 | 1636 | |
| 1657 | | try o.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); |
| 1637 | try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index)); |
| 1658 | 1638 | } |
| 1659 | 1639 | |
| 1660 | 1640 | pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { |
| ... | ... | @@ -2933,22 +2913,24 @@ pub const Object = struct { |
| 2933 | 2913 | o: *Object, |
| 2934 | 2914 | decl_index: InternPool.DeclIndex, |
| 2935 | 2915 | ) Allocator.Error!Builder.Function.Index { |
| 2936 | | const mod = o.module; |
| 2937 | | const ip = &mod.intern_pool; |
| 2916 | const zcu = o.module; |
| 2917 | const ip = &zcu.intern_pool; |
| 2938 | 2918 | const gpa = o.gpa; |
| 2939 | | const decl = mod.declPtr(decl_index); |
| 2919 | const decl = zcu.declPtr(decl_index); |
| 2920 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 2921 | const owner_mod = namespace.file_scope.mod; |
| 2940 | 2922 | const zig_fn_type = decl.ty; |
| 2941 | 2923 | const gop = try o.decl_map.getOrPut(gpa, decl_index); |
| 2942 | 2924 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; |
| 2943 | 2925 | |
| 2944 | 2926 | assert(decl.has_tv); |
| 2945 | | const fn_info = mod.typeToFunc(zig_fn_type).?; |
| 2946 | | const target = mod.getTarget(); |
| 2947 | | const sret = firstParamSRet(fn_info, mod); |
| 2927 | const fn_info = zcu.typeToFunc(zig_fn_type).?; |
| 2928 | const target = owner_mod.resolved_target.result; |
| 2929 | const sret = firstParamSRet(fn_info, zcu); |
| 2948 | 2930 | |
| 2949 | 2931 | const function_index = try o.builder.addFunction( |
| 2950 | 2932 | try o.lowerType(zig_fn_type), |
| 2951 | | try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))), |
| 2933 | try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))), |
| 2952 | 2934 | toLlvmAddressSpace(decl.@"addrspace", target), |
| 2953 | 2935 | ); |
| 2954 | 2936 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| ... | ... | @@ -2956,7 +2938,7 @@ pub const Object = struct { |
| 2956 | 2938 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 2957 | 2939 | defer attributes.deinit(&o.builder); |
| 2958 | 2940 | |
| 2959 | | const is_extern = decl.isExtern(mod); |
| 2941 | const is_extern = decl.isExtern(zcu); |
| 2960 | 2942 | if (!is_extern) { |
| 2961 | 2943 | function_index.setLinkage(.internal, &o.builder); |
| 2962 | 2944 | function_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| ... | ... | @@ -2966,7 +2948,7 @@ pub const Object = struct { |
| 2966 | 2948 | .kind = try o.builder.string("wasm-import-name"), |
| 2967 | 2949 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| 2968 | 2950 | } }, &o.builder); |
| 2969 | | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { |
| 2951 | if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| { |
| 2970 | 2952 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ |
| 2971 | 2953 | .kind = try o.builder.string("wasm-import-module"), |
| 2972 | 2954 | .value = try o.builder.string(lib_name), |
| ... | ... | @@ -2987,8 +2969,8 @@ pub const Object = struct { |
| 2987 | 2969 | llvm_arg_i += 1; |
| 2988 | 2970 | } |
| 2989 | 2971 | |
| 2990 | | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and |
| 2991 | | mod.comp.config.any_error_tracing; |
| 2972 | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and |
| 2973 | zcu.comp.config.any_error_tracing; |
| 2992 | 2974 | |
| 2993 | 2975 | if (err_return_tracing) { |
| 2994 | 2976 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| ... | ... | @@ -3009,7 +2991,7 @@ pub const Object = struct { |
| 3009 | 2991 | function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder); |
| 3010 | 2992 | |
| 3011 | 2993 | // Function attributes that are independent of analysis results of the function body. |
| 3012 | | try o.addCommonFnAttributes(&attributes); |
| 2994 | try o.addCommonFnAttributes(&attributes, owner_mod); |
| 3013 | 2995 | |
| 3014 | 2996 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); |
| 3015 | 2997 | |
| ... | ... | @@ -3022,14 +3004,14 @@ pub const Object = struct { |
| 3022 | 3004 | .byval => { |
| 3023 | 3005 | const param_index = it.zig_index - 1; |
| 3024 | 3006 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); |
| 3025 | | if (!isByRef(param_ty, mod)) { |
| 3007 | if (!isByRef(param_ty, zcu)) { |
| 3026 | 3008 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 3027 | 3009 | } |
| 3028 | 3010 | }, |
| 3029 | 3011 | .byref => { |
| 3030 | 3012 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 3031 | 3013 | const param_llvm_ty = try o.lowerType(param_ty); |
| 3032 | | const alignment = param_ty.abiAlignment(mod); |
| 3014 | const alignment = param_ty.abiAlignment(zcu); |
| 3033 | 3015 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); |
| 3034 | 3016 | }, |
| 3035 | 3017 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), |
| ... | ... | @@ -3055,13 +3037,14 @@ pub const Object = struct { |
| 3055 | 3037 | fn addCommonFnAttributes( |
| 3056 | 3038 | o: *Object, |
| 3057 | 3039 | attributes: *Builder.FunctionAttributes.Wip, |
| 3040 | owner_mod: *Package.Module, |
| 3058 | 3041 | ) Allocator.Error!void { |
| 3059 | 3042 | const comp = o.module.comp; |
| 3060 | 3043 | |
| 3061 | | if (!comp.bin_file.options.red_zone) { |
| 3044 | if (!owner_mod.red_zone) { |
| 3062 | 3045 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 3063 | 3046 | } |
| 3064 | | if (comp.bin_file.options.omit_frame_pointer) { |
| 3047 | if (owner_mod.omit_frame_pointer) { |
| 3065 | 3048 | try attributes.addFnAttr(.{ .string = .{ |
| 3066 | 3049 | .kind = try o.builder.string("frame-pointer"), |
| 3067 | 3050 | .value = try o.builder.string("none"), |
| ... | ... | @@ -3073,7 +3056,7 @@ pub const Object = struct { |
| 3073 | 3056 | } }, &o.builder); |
| 3074 | 3057 | } |
| 3075 | 3058 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 3076 | | if (comp.unwind_tables) { |
| 3059 | if (owner_mod.unwind_tables) { |
| 3077 | 3060 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 3078 | 3061 | } |
| 3079 | 3062 | if (comp.skip_linker_dependencies or comp.no_builtin) { |
| ... | ... | @@ -3084,26 +3067,27 @@ pub const Object = struct { |
| 3084 | 3067 | // overflow instead of performing memcpy. |
| 3085 | 3068 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 3086 | 3069 | } |
| 3087 | | if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { |
| 3070 | if (owner_mod.optimize_mode == .ReleaseSmall) { |
| 3088 | 3071 | try attributes.addFnAttr(.minsize, &o.builder); |
| 3089 | 3072 | try attributes.addFnAttr(.optsize, &o.builder); |
| 3090 | 3073 | } |
| 3091 | | if (comp.bin_file.options.tsan) { |
| 3074 | if (owner_mod.sanitize_thread) { |
| 3092 | 3075 | try attributes.addFnAttr(.sanitize_thread, &o.builder); |
| 3093 | 3076 | } |
| 3094 | | if (comp.getTarget().cpu.model.llvm_name) |s| { |
| 3077 | const target = owner_mod.resolved_target.result; |
| 3078 | if (target.cpu.model.llvm_name) |s| { |
| 3095 | 3079 | try attributes.addFnAttr(.{ .string = .{ |
| 3096 | 3080 | .kind = try o.builder.string("target-cpu"), |
| 3097 | 3081 | .value = try o.builder.string(s), |
| 3098 | 3082 | } }, &o.builder); |
| 3099 | 3083 | } |
| 3100 | | if (comp.bin_file.options.llvm_cpu_features) |s| { |
| 3084 | if (owner_mod.resolved_target.llvm_cpu_features) |s| { |
| 3101 | 3085 | try attributes.addFnAttr(.{ .string = .{ |
| 3102 | 3086 | .kind = try o.builder.string("target-features"), |
| 3103 | 3087 | .value = try o.builder.string(std.mem.span(s)), |
| 3104 | 3088 | } }, &o.builder); |
| 3105 | 3089 | } |
| 3106 | | if (comp.getTarget().cpu.arch.isBpf()) { |
| 3090 | if (target.cpu.arch.isBpf()) { |
| 3107 | 3091 | try attributes.addFnAttr(.{ .string = .{ |
| 3108 | 3092 | .kind = try o.builder.string("no-builtins"), |
| 3109 | 3093 | .value = .empty, |
| ... | ... | @@ -4646,6 +4630,100 @@ pub const Object = struct { |
| 4646 | 4630 | .field_index = @intCast(field_index), |
| 4647 | 4631 | }); |
| 4648 | 4632 | } |
| 4633 | |
| 4634 | fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index { |
| 4635 | const name = try o.builder.string(lt_errors_fn_name); |
| 4636 | if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; |
| 4637 | |
| 4638 | const zcu = o.module; |
| 4639 | const target = zcu.root_mod.resolved_target.result; |
| 4640 | const function_index = try o.builder.addFunction( |
| 4641 | try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal), |
| 4642 | name, |
| 4643 | toLlvmAddressSpace(.generic, target), |
| 4644 | ); |
| 4645 | |
| 4646 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4647 | defer attributes.deinit(&o.builder); |
| 4648 | try o.addCommonFnAttributes(&attributes, zcu.root_mod); |
| 4649 | |
| 4650 | function_index.setLinkage(.internal, &o.builder); |
| 4651 | function_index.setCallConv(.fastcc, &o.builder); |
| 4652 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 4653 | return function_index; |
| 4654 | } |
| 4655 | |
| 4656 | fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { |
| 4657 | const zcu = o.module; |
| 4658 | const ip = &zcu.intern_pool; |
| 4659 | const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type; |
| 4660 | |
| 4661 | // TODO: detect when the type changes and re-emit this function. |
| 4662 | const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); |
| 4663 | if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; |
| 4664 | errdefer assert(o.decl_map.remove(enum_type.decl)); |
| 4665 | |
| 4666 | const usize_ty = try o.lowerType(Type.usize); |
| 4667 | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); |
| 4668 | const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu); |
| 4669 | const target = zcu.root_mod.resolved_target.result; |
| 4670 | const function_index = try o.builder.addFunction( |
| 4671 | try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), |
| 4672 | try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), |
| 4673 | toLlvmAddressSpace(.generic, target), |
| 4674 | ); |
| 4675 | |
| 4676 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4677 | defer attributes.deinit(&o.builder); |
| 4678 | try o.addCommonFnAttributes(&attributes, zcu.root_mod); |
| 4679 | |
| 4680 | function_index.setLinkage(.internal, &o.builder); |
| 4681 | function_index.setCallConv(.fastcc, &o.builder); |
| 4682 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 4683 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| 4684 | |
| 4685 | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 4686 | defer wip.deinit(); |
| 4687 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 4688 | |
| 4689 | const bad_value_block = try wip.block(1, "BadValue"); |
| 4690 | const tag_int_value = wip.arg(0); |
| 4691 | var wip_switch = |
| 4692 | try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len)); |
| 4693 | defer wip_switch.finish(&wip); |
| 4694 | |
| 4695 | for (0..enum_type.names.len) |field_index| { |
| 4696 | const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index])); |
| 4697 | const name_init = try o.builder.stringNullConst(name); |
| 4698 | const name_variable_index = |
| 4699 | try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); |
| 4700 | try name_variable_index.setInitializer(name_init, &o.builder); |
| 4701 | name_variable_index.setLinkage(.private, &o.builder); |
| 4702 | name_variable_index.setMutability(.constant, &o.builder); |
| 4703 | name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 4704 | name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); |
| 4705 | |
| 4706 | const name_val = try o.builder.structValue(ret_ty, &.{ |
| 4707 | name_variable_index.toConst(&o.builder), |
| 4708 | try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), |
| 4709 | }); |
| 4710 | |
| 4711 | const return_block = try wip.block(1, "Name"); |
| 4712 | const this_tag_int_value = try o.lowerValue( |
| 4713 | (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| 4714 | ); |
| 4715 | try wip_switch.addCase(this_tag_int_value, return_block, &wip); |
| 4716 | |
| 4717 | wip.cursor = .{ .block = return_block }; |
| 4718 | _ = try wip.ret(name_val); |
| 4719 | } |
| 4720 | |
| 4721 | wip.cursor = .{ .block = bad_value_block }; |
| 4722 | _ = try wip.@"unreachable"(); |
| 4723 | |
| 4724 | try wip.finish(); |
| 4725 | return function_index; |
| 4726 | } |
| 4649 | 4727 | }; |
| 4650 | 4728 | |
| 4651 | 4729 | pub const DeclGen = struct { |
| ... | ... | @@ -4654,6 +4732,13 @@ pub const DeclGen = struct { |
| 4654 | 4732 | decl_index: InternPool.DeclIndex, |
| 4655 | 4733 | err_msg: ?*Module.ErrorMsg, |
| 4656 | 4734 | |
| 4735 | fn ownerModule(dg: DeclGen) *Package.Module { |
| 4736 | const o = dg.object; |
| 4737 | const zcu = o.module; |
| 4738 | const namespace = zcu.namespacePtr(dg.decl.src_namespace); |
| 4739 | return namespace.file_scope.mod; |
| 4740 | } |
| 4741 | |
| 4657 | 4742 | fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 4658 | 4743 | @setCold(true); |
| 4659 | 4744 | assert(dg.err_msg == null); |
| ... | ... | @@ -5614,7 +5699,7 @@ pub const FuncGen = struct { |
| 5614 | 5699 | const o = self.dg.object; |
| 5615 | 5700 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5616 | 5701 | const operand = try self.resolveInst(un_op); |
| 5617 | | const llvm_fn = try self.getCmpLtErrorsLenFunction(); |
| 5702 | const llvm_fn = try o.getCmpLtErrorsLenFunction(); |
| 5618 | 5703 | return self.wip.call( |
| 5619 | 5704 | .normal, |
| 5620 | 5705 | .fastcc, |
| ... | ... | @@ -6547,11 +6632,13 @@ pub const FuncGen = struct { |
| 6547 | 6632 | const dib = o.di_builder orelse return .none; |
| 6548 | 6633 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; |
| 6549 | 6634 | |
| 6550 | | const mod = o.module; |
| 6551 | | const func = mod.funcInfo(ty_fn.func); |
| 6635 | const zcu = o.module; |
| 6636 | const func = zcu.funcInfo(ty_fn.func); |
| 6552 | 6637 | const decl_index = func.owner_decl; |
| 6553 | | const decl = mod.declPtr(decl_index); |
| 6554 | | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| 6638 | const decl = zcu.declPtr(decl_index); |
| 6639 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 6640 | const owner_mod = namespace.file_scope.mod; |
| 6641 | const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope); |
| 6555 | 6642 | self.di_file = di_file; |
| 6556 | 6643 | const line_number = decl.src_line + 1; |
| 6557 | 6644 | const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2(); |
| ... | ... | @@ -6562,18 +6649,18 @@ pub const FuncGen = struct { |
| 6562 | 6649 | .base_line = self.base_line, |
| 6563 | 6650 | }); |
| 6564 | 6651 | |
| 6565 | | const fqn = try decl.getFullyQualifiedName(mod); |
| 6652 | const fqn = try decl.getFullyQualifiedName(zcu); |
| 6566 | 6653 | |
| 6567 | | const is_internal_linkage = !mod.decl_exports.contains(decl_index); |
| 6568 | | const fn_ty = try mod.funcType(.{ |
| 6654 | const is_internal_linkage = !zcu.decl_exports.contains(decl_index); |
| 6655 | const fn_ty = try zcu.funcType(.{ |
| 6569 | 6656 | .param_types = &.{}, |
| 6570 | 6657 | .return_type = .void_type, |
| 6571 | 6658 | }); |
| 6572 | 6659 | const fn_di_ty = try o.lowerDebugType(fn_ty, .full); |
| 6573 | 6660 | const subprogram = dib.createFunction( |
| 6574 | 6661 | di_file.toScope(), |
| 6575 | | mod.intern_pool.stringToSlice(decl.name), |
| 6576 | | mod.intern_pool.stringToSlice(fqn), |
| 6662 | zcu.intern_pool.stringToSlice(decl.name), |
| 6663 | zcu.intern_pool.stringToSlice(fqn), |
| 6577 | 6664 | di_file, |
| 6578 | 6665 | line_number, |
| 6579 | 6666 | fn_di_ty, |
| ... | ... | @@ -6581,7 +6668,7 @@ pub const FuncGen = struct { |
| 6581 | 6668 | true, // is definition |
| 6582 | 6669 | line_number + func.lbrace_line, // scope line |
| 6583 | 6670 | llvm.DIFlags.StaticMember, |
| 6584 | | mod.comp.bin_file.options.optimize_mode != .Debug, |
| 6671 | owner_mod.optimize_mode != .Debug, |
| 6585 | 6672 | null, // decl_subprogram |
| 6586 | 6673 | ); |
| 6587 | 6674 | |
| ... | ... | @@ -6676,11 +6763,12 @@ pub const FuncGen = struct { |
| 6676 | 6763 | null; |
| 6677 | 6764 | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); |
| 6678 | 6765 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 6679 | | const mod = o.module; |
| 6680 | | if (isByRef(operand_ty, mod)) { |
| 6766 | const zcu = o.module; |
| 6767 | const owner_mod = self.dg.ownerModule(); |
| 6768 | if (isByRef(operand_ty, zcu)) { |
| 6681 | 6769 | _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 6682 | | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 6683 | | const alignment = operand_ty.abiAlignment(mod).toLlvm(); |
| 6770 | } else if (owner_mod.optimize_mode == .Debug) { |
| 6771 | const alignment = operand_ty.abiAlignment(zcu).toLlvm(); |
| 6684 | 6772 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); |
| 6685 | 6773 | _ = try self.wip.store(.normal, operand, alloca, alignment); |
| 6686 | 6774 | _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| ... | ... | @@ -8729,9 +8817,10 @@ pub const FuncGen = struct { |
| 8729 | 8817 | |
| 8730 | 8818 | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); |
| 8731 | 8819 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 8820 | const owner_mod = self.dg.ownerModule(); |
| 8732 | 8821 | if (isByRef(inst_ty, mod)) { |
| 8733 | 8822 | _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 8734 | | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 8823 | } else if (owner_mod.optimize_mode == .Debug) { |
| 8735 | 8824 | const alignment = inst_ty.abiAlignment(mod).toLlvm(); |
| 8736 | 8825 | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); |
| 8737 | 8826 | _ = try self.wip.store(.normal, arg_val, alloca, alignment); |
| ... | ... | @@ -8821,7 +8910,8 @@ pub const FuncGen = struct { |
| 8821 | 8910 | len, |
| 8822 | 8911 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, |
| 8823 | 8912 | ); |
| 8824 | | if (safety and mod.comp.bin_file.options.valgrind) { |
| 8913 | const owner_mod = self.dg.ownerModule(); |
| 8914 | if (safety and owner_mod.valgrind) { |
| 8825 | 8915 | try self.valgrindMarkUndef(dest_ptr, len); |
| 8826 | 8916 | } |
| 8827 | 8917 | return .none; |
| ... | ... | @@ -9137,7 +9227,8 @@ pub const FuncGen = struct { |
| 9137 | 9227 | } else { |
| 9138 | 9228 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); |
| 9139 | 9229 | } |
| 9140 | | if (safety and mod.comp.bin_file.options.valgrind) { |
| 9230 | const owner_mod = self.dg.ownerModule(); |
| 9231 | if (safety and owner_mod.valgrind) { |
| 9141 | 9232 | try self.valgrindMarkUndef(dest_ptr, len); |
| 9142 | 9233 | } |
| 9143 | 9234 | return .none; |
| ... | ... | @@ -9488,24 +9579,25 @@ pub const FuncGen = struct { |
| 9488 | 9579 | |
| 9489 | 9580 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| 9490 | 9581 | const o = self.dg.object; |
| 9491 | | const mod = o.module; |
| 9492 | | const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; |
| 9582 | const zcu = o.module; |
| 9583 | const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; |
| 9493 | 9584 | |
| 9494 | 9585 | // TODO: detect when the type changes and re-emit this function. |
| 9495 | 9586 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); |
| 9496 | 9587 | if (gop.found_existing) return gop.value_ptr.*; |
| 9497 | 9588 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); |
| 9498 | 9589 | |
| 9499 | | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9590 | const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu); |
| 9591 | const target = zcu.root_mod.resolved_target.result; |
| 9500 | 9592 | const function_index = try o.builder.addFunction( |
| 9501 | 9593 | try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), |
| 9502 | | try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}), |
| 9503 | | toLlvmAddressSpace(.generic, mod.getTarget()), |
| 9594 | try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}), |
| 9595 | toLlvmAddressSpace(.generic, target), |
| 9504 | 9596 | ); |
| 9505 | 9597 | |
| 9506 | 9598 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9507 | 9599 | defer attributes.deinit(&o.builder); |
| 9508 | | try o.addCommonFnAttributes(&attributes); |
| 9600 | try o.addCommonFnAttributes(&attributes, zcu.root_mod); |
| 9509 | 9601 | |
| 9510 | 9602 | function_index.setLinkage(.internal, &o.builder); |
| 9511 | 9603 | function_index.setCallConv(.fastcc, &o.builder); |
| ... | ... | @@ -9524,7 +9616,7 @@ pub const FuncGen = struct { |
| 9524 | 9616 | |
| 9525 | 9617 | for (0..enum_type.names.len) |field_index| { |
| 9526 | 9618 | const this_tag_int_value = try o.lowerValue( |
| 9527 | | (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| 9619 | (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| 9528 | 9620 | ); |
| 9529 | 9621 | try wip_switch.addCase(this_tag_int_value, named_block, &wip); |
| 9530 | 9622 | } |
| ... | ... | @@ -9544,7 +9636,7 @@ pub const FuncGen = struct { |
| 9544 | 9636 | const operand = try self.resolveInst(un_op); |
| 9545 | 9637 | const enum_ty = self.typeOf(un_op); |
| 9546 | 9638 | |
| 9547 | | const llvm_fn = try self.getEnumTagNameFunction(enum_ty); |
| 9639 | const llvm_fn = try o.getEnumTagNameFunction(enum_ty); |
| 9548 | 9640 | return self.wip.call( |
| 9549 | 9641 | .normal, |
| 9550 | 9642 | .fastcc, |
| ... | ... | @@ -9556,100 +9648,6 @@ pub const FuncGen = struct { |
| 9556 | 9648 | ); |
| 9557 | 9649 | } |
| 9558 | 9650 | |
| 9559 | | fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| 9560 | | const o = self.dg.object; |
| 9561 | | const mod = o.module; |
| 9562 | | const ip = &mod.intern_pool; |
| 9563 | | const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type; |
| 9564 | | |
| 9565 | | // TODO: detect when the type changes and re-emit this function. |
| 9566 | | const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); |
| 9567 | | if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; |
| 9568 | | errdefer assert(o.decl_map.remove(enum_type.decl)); |
| 9569 | | |
| 9570 | | const usize_ty = try o.lowerType(Type.usize); |
| 9571 | | const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); |
| 9572 | | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9573 | | const function_index = try o.builder.addFunction( |
| 9574 | | try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), |
| 9575 | | try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), |
| 9576 | | toLlvmAddressSpace(.generic, mod.getTarget()), |
| 9577 | | ); |
| 9578 | | |
| 9579 | | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9580 | | defer attributes.deinit(&o.builder); |
| 9581 | | try o.addCommonFnAttributes(&attributes); |
| 9582 | | |
| 9583 | | function_index.setLinkage(.internal, &o.builder); |
| 9584 | | function_index.setCallConv(.fastcc, &o.builder); |
| 9585 | | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9586 | | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| 9587 | | |
| 9588 | | var wip = try Builder.WipFunction.init(&o.builder, function_index); |
| 9589 | | defer wip.deinit(); |
| 9590 | | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 9591 | | |
| 9592 | | const bad_value_block = try wip.block(1, "BadValue"); |
| 9593 | | const tag_int_value = wip.arg(0); |
| 9594 | | var wip_switch = |
| 9595 | | try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len)); |
| 9596 | | defer wip_switch.finish(&wip); |
| 9597 | | |
| 9598 | | for (0..enum_type.names.len) |field_index| { |
| 9599 | | const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index])); |
| 9600 | | const name_init = try o.builder.stringNullConst(name); |
| 9601 | | const name_variable_index = |
| 9602 | | try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); |
| 9603 | | try name_variable_index.setInitializer(name_init, &o.builder); |
| 9604 | | name_variable_index.setLinkage(.private, &o.builder); |
| 9605 | | name_variable_index.setMutability(.constant, &o.builder); |
| 9606 | | name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 9607 | | name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); |
| 9608 | | |
| 9609 | | const name_val = try o.builder.structValue(ret_ty, &.{ |
| 9610 | | name_variable_index.toConst(&o.builder), |
| 9611 | | try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), |
| 9612 | | }); |
| 9613 | | |
| 9614 | | const return_block = try wip.block(1, "Name"); |
| 9615 | | const this_tag_int_value = try o.lowerValue( |
| 9616 | | (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| 9617 | | ); |
| 9618 | | try wip_switch.addCase(this_tag_int_value, return_block, &wip); |
| 9619 | | |
| 9620 | | wip.cursor = .{ .block = return_block }; |
| 9621 | | _ = try wip.ret(name_val); |
| 9622 | | } |
| 9623 | | |
| 9624 | | wip.cursor = .{ .block = bad_value_block }; |
| 9625 | | _ = try wip.@"unreachable"(); |
| 9626 | | |
| 9627 | | try wip.finish(); |
| 9628 | | return function_index; |
| 9629 | | } |
| 9630 | | |
| 9631 | | fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index { |
| 9632 | | const o = self.dg.object; |
| 9633 | | |
| 9634 | | const name = try o.builder.string(lt_errors_fn_name); |
| 9635 | | if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; |
| 9636 | | |
| 9637 | | const function_index = try o.builder.addFunction( |
| 9638 | | try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal), |
| 9639 | | name, |
| 9640 | | toLlvmAddressSpace(.generic, o.module.getTarget()), |
| 9641 | | ); |
| 9642 | | |
| 9643 | | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9644 | | defer attributes.deinit(&o.builder); |
| 9645 | | try o.addCommonFnAttributes(&attributes); |
| 9646 | | |
| 9647 | | function_index.setLinkage(.internal, &o.builder); |
| 9648 | | function_index.setCallConv(.fastcc, &o.builder); |
| 9649 | | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 9650 | | return function_index; |
| 9651 | | } |
| 9652 | | |
| 9653 | 9651 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9654 | 9652 | const o = self.dg.object; |
| 9655 | 9653 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |