| ... | @@ -822,7 +822,7 @@ pub const Object = struct { | ... | @@ -822,7 +822,7 @@ pub const Object = struct { |
| 822 | type_map: TypeMap, | 822 | type_map: TypeMap, |
| 823 | di_type_map: DITypeMap, | 823 | di_type_map: DITypeMap, |
| 824 | /// The LLVM global table which holds the names corresponding to Zig errors. | 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 | /// the compilation are known. | 826 | /// the compilation are known. |
| 827 | error_name_table: Builder.Variable.Index, | 827 | error_name_table: Builder.Variable.Index, |
| 828 | /// This map is usually very close to empty. It tracks only the cases when a | 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,7 +850,7 @@ pub const Object = struct { |
| 850 | | 850 | |
| 851 | pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); | 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 | /// want to iterate over it while adding entries to it. | 854 | /// want to iterate over it while adding entries to it. |
| 855 | pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); | 855 | pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); |
| 856 | | 856 | |
| ... | @@ -1026,17 +1026,6 @@ pub const Object = struct { | ... | @@ -1026,17 +1026,6 @@ pub const Object = struct { |
| 1026 | self.* = undefined; | 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 | fn genErrorNameTable(o: *Object) Allocator.Error!void { | 1029 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| 1041 | // If o.error_name_table is null, then it was not referenced by any instructions. | 1030 | // If o.error_name_table is null, then it was not referenced by any instructions. |
| 1042 | if (o.error_name_table == .none) return; | 1031 | if (o.error_name_table == .none) return; |
| ... | @@ -1175,12 +1164,22 @@ pub const Object = struct { | ... | @@ -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 { | 1167 | pub const EmitOptions = struct { |
| 1179 | var sub_prog_node = prog_node.start("LLVM Emit Object", 0); | 1168 | pre_ir_path: ?[]const u8, |
| 1180 | sub_prog_node.activate(); | 1169 | pre_bc_path: ?[]const u8, |
| 1181 | sub_prog_node.context.refresh(); | 1170 | bin_path: ?[*:0]const u8, |
| 1182 | defer sub_prog_node.end(); | 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 | try self.resolveExportExternCollisions(); | 1183 | try self.resolveExportExternCollisions(); |
| 1185 | try self.genErrorNameTable(); | 1184 | try self.genErrorNameTable(); |
| 1186 | try self.genCmpLtErrorsLenFunction(); | 1185 | try self.genCmpLtErrorsLenFunction(); |
| ... | @@ -1206,7 +1205,7 @@ pub const Object = struct { | ... | @@ -1206,7 +1205,7 @@ pub const Object = struct { |
| 1206 | dib.finalize(); | 1205 | dib.finalize(); |
| 1207 | } | 1206 | } |
| 1208 | | 1207 | |
| 1209 | if (comp.verbose_llvm_ir) |path| { | 1208 | if (options.pre_ir_path) |path| { |
| 1210 | if (std.mem.eql(u8, path, "-")) { | 1209 | if (std.mem.eql(u8, path, "-")) { |
| 1211 | self.builder.dump(); | 1210 | self.builder.dump(); |
| 1212 | } else { | 1211 | } else { |
| ... | @@ -1214,91 +1213,72 @@ pub const Object = struct { | ... | @@ -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); | 1216 | if (options.pre_bc_path) |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; | | |
| 1225 | | 1217 | |
| 1226 | if (std.debug.runtime_safety and !try self.builder.verify()) { | 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 | @panic("LLVM module verification failed"); | 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| | 1222 | const emit_asm_msg = options.asm_path orelse "(none)"; |
| 1233 | try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) | 1223 | const emit_bin_msg = options.bin_path orelse "(none)"; |
| 1234 | else | 1224 | const post_llvm_ir_msg = options.post_ir_path orelse "(none)"; |
| 1235 | null; | 1225 | const post_llvm_bc_msg = options.post_bc_path orelse "(none)"; |
| 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)"; | | |
| 1245 | log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{ | 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 | 1230 | if (options.asm_path == null and options.bin_path == null and |
| 1250 | emit_llvm_ir_path == null and emit_llvm_bc_path == null) return; | 1231 | options.post_ir_path == null and options.post_bc_path == null) return; |
| 1251 | | 1232 | |
| 1252 | if (!self.builder.useLibLlvm()) { | 1233 | if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve |
| 1253 | log.err("emitting without libllvm not implemented", .{}); | | |
| 1254 | return error.FailedToEmit; | | |
| 1255 | } | | |
| 1256 | | 1234 | |
| 1257 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. | 1235 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 1258 | // So we call the entire pipeline multiple times if this is requested. | 1236 | // So we call the entire pipeline multiple times if this is requested. |
| 1259 | var error_message: [*:0]const u8 = undefined; | 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 | if (self.target_machine.emitToFile( | 1241 | if (self.target_machine.emitToFile( |
| 1262 | self.builder.llvm.module.?, | 1242 | self.builder.llvm.module.?, |
| 1263 | &error_message, | 1243 | &error_message, |
| 1264 | comp.bin_file.options.optimize_mode == .Debug, | 1244 | options.is_debug, |
| 1265 | comp.bin_file.options.optimize_mode == .ReleaseSmall, | 1245 | options.is_small, |
| 1266 | comp.time_report, | 1246 | options.time_report, |
| 1267 | comp.bin_file.options.tsan, | 1247 | options.sanitize_thread, |
| 1268 | comp.bin_file.options.lto, | 1248 | options.lto, |
| 1269 | null, | 1249 | null, |
| 1270 | emit_bin_path, | 1250 | emit_bin_path, |
| 1271 | emit_llvm_ir_path, | 1251 | post_ir_path, |
| 1272 | null, | 1252 | null, |
| 1273 | )) { | 1253 | )) { |
| 1274 | defer llvm.disposeMessage(error_message); | 1254 | defer llvm.disposeMessage(error_message); |
| 1275 | | 1255 | |
| 1276 | log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{ | 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 | return error.FailedToEmit; | 1259 | return error.FailedToEmit; |
| 1280 | } | 1260 | } |
| 1281 | emit_bin_path = null; | 1261 | emit_bin_path = null; |
| 1282 | emit_llvm_ir_path = null; | 1262 | post_ir_path = null; |
| 1283 | } | 1263 | } |
| 1284 | | 1264 | |
| 1285 | if (self.target_machine.emitToFile( | 1265 | if (self.target_machine.emitToFile( |
| 1286 | self.builder.llvm.module.?, | 1266 | self.builder.llvm.module.?, |
| 1287 | &error_message, | 1267 | &error_message, |
| 1288 | comp.bin_file.options.optimize_mode == .Debug, | 1268 | options.is_debug, |
| 1289 | comp.bin_file.options.optimize_mode == .ReleaseSmall, | 1269 | options.is_small, |
| 1290 | comp.time_report, | 1270 | options.time_report, |
| 1291 | comp.bin_file.options.tsan, | 1271 | options.sanitize_thread, |
| 1292 | comp.bin_file.options.lto, | 1272 | options.lto, |
| 1293 | emit_asm_path, | 1273 | options.asm_path, |
| 1294 | emit_bin_path, | 1274 | emit_bin_path, |
| 1295 | emit_llvm_ir_path, | 1275 | post_ir_path, |
| 1296 | emit_llvm_bc_path, | 1276 | options.post_bc_path, |
| 1297 | )) { | 1277 | )) { |
| 1298 | defer llvm.disposeMessage(error_message); | 1278 | defer llvm.disposeMessage(error_message); |
| 1299 | | 1279 | |
| 1300 | log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ | 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 | error_message, | 1282 | error_message, |
| 1303 | }); | 1283 | }); |
| 1304 | return error.FailedToEmit; | 1284 | return error.FailedToEmit; |
| ... | @@ -1307,17 +1287,19 @@ pub const Object = struct { | ... | @@ -1307,17 +1287,19 @@ pub const Object = struct { |
| 1307 | | 1287 | |
| 1308 | pub fn updateFunc( | 1288 | pub fn updateFunc( |
| 1309 | o: *Object, | 1289 | o: *Object, |
| 1310 | mod: *Module, | 1290 | zcu: *Module, |
| 1311 | func_index: InternPool.Index, | 1291 | func_index: InternPool.Index, |
| 1312 | air: Air, | 1292 | air: Air, |
| 1313 | liveness: Liveness, | 1293 | liveness: Liveness, |
| 1314 | ) !void { | 1294 | ) !void { |
| 1315 | const func = mod.funcInfo(func_index); | 1295 | const func = zcu.funcInfo(func_index); |
| 1316 | const decl_index = func.owner_decl; | 1296 | const decl_index = func.owner_decl; |
| 1317 | const decl = mod.declPtr(decl_index); | 1297 | const decl = zcu.declPtr(decl_index); |
| 1318 | const fn_info = mod.typeToFunc(decl.ty).?; | 1298 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 1319 | const target = mod.getTarget(); | 1299 | const owner_mod = namespace.file_scope.mod; |
| 1320 | const ip = &mod.intern_pool; | 1300 | const fn_info = zcu.typeToFunc(decl.ty).?; |
| | 1301 | const target = zcu.getTarget(); |
| | 1302 | const ip = &zcu.intern_pool; |
| 1321 | | 1303 | |
| 1322 | var dg: DeclGen = .{ | 1304 | var dg: DeclGen = .{ |
| 1323 | .object = o, | 1305 | .object = o, |
| ... | @@ -1352,7 +1334,7 @@ pub const Object = struct { | ... | @@ -1352,7 +1334,7 @@ pub const Object = struct { |
| 1352 | } | 1334 | } |
| 1353 | | 1335 | |
| 1354 | // TODO: disable this if safety is off for the function scope | 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 | if (ssp_buf_size != 0) { | 1338 | if (ssp_buf_size != 0) { |
| 1357 | try attributes.addFnAttr(.sspstrong, &o.builder); | 1339 | try attributes.addFnAttr(.sspstrong, &o.builder); |
| 1358 | try attributes.addFnAttr(.{ .string = .{ | 1340 | try attributes.addFnAttr(.{ .string = .{ |
| ... | @@ -1362,7 +1344,7 @@ pub const Object = struct { | ... | @@ -1362,7 +1344,7 @@ pub const Object = struct { |
| 1362 | } | 1344 | } |
| 1363 | | 1345 | |
| 1364 | // TODO: disable this if safety is off for the function scope | 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 | try attributes.addFnAttr(.{ .string = .{ | 1348 | try attributes.addFnAttr(.{ .string = .{ |
| 1367 | .kind = try o.builder.string("probe-stack"), | 1349 | .kind = try o.builder.string("probe-stack"), |
| 1368 | .value = try o.builder.string("__zig_probe_stack"), | 1350 | .value = try o.builder.string("__zig_probe_stack"), |
| ... | @@ -1385,20 +1367,22 @@ pub const Object = struct { | ... | @@ -1385,20 +1367,22 @@ pub const Object = struct { |
| 1385 | var llvm_arg_i: u32 = 0; | 1367 | var llvm_arg_i: u32 = 0; |
| 1386 | | 1368 | |
| 1387 | // This gets the LLVM values from the function and stores them in `dg.args`. | 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 | const ret_ptr: Builder.Value = if (sret) param: { | 1371 | const ret_ptr: Builder.Value = if (sret) param: { |
| 1390 | const param = wip.arg(llvm_arg_i); | 1372 | const param = wip.arg(llvm_arg_i); |
| 1391 | llvm_arg_i += 1; | 1373 | llvm_arg_i += 1; |
| 1392 | break :param param; | 1374 | break :param param; |
| 1393 | } else .none; | 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 | .signed => try attributes.addRetAttr(.signext, &o.builder), | 1378 | .signed => try attributes.addRetAttr(.signext, &o.builder), |
| 1397 | .unsigned => try attributes.addRetAttr(.zeroext, &o.builder), | 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 | 1382 | const comp = zcu.comp; |
| 1401 | mod.comp.config.any_error_tracing; | 1383 | |
| | 1384 | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and |
| | 1385 | comp.config.any_error_tracing; |
| 1402 | | 1386 | |
| 1403 | const err_ret_trace: Builder.Value = if (err_return_tracing) param: { | 1387 | const err_ret_trace: Builder.Value = if (err_return_tracing) param: { |
| 1404 | const param = wip.arg(llvm_arg_i); | 1388 | const param = wip.arg(llvm_arg_i); |
| ... | @@ -1426,8 +1410,8 @@ pub const Object = struct { | ... | @@ -1426,8 +1410,8 @@ pub const Object = struct { |
| 1426 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); | 1410 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); |
| 1427 | const param = wip.arg(llvm_arg_i); | 1411 | const param = wip.arg(llvm_arg_i); |
| 1428 | | 1412 | |
| 1429 | if (isByRef(param_ty, mod)) { | 1413 | if (isByRef(param_ty, zcu)) { |
| 1430 | const alignment = param_ty.abiAlignment(mod).toLlvm(); | 1414 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1431 | const param_llvm_ty = param.typeOfWip(&wip); | 1415 | const param_llvm_ty = param.typeOfWip(&wip); |
| 1432 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); | 1416 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1433 | _ = try wip.store(.normal, param, arg_ptr, alignment); | 1417 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| ... | @@ -1443,12 +1427,12 @@ pub const Object = struct { | ... | @@ -1443,12 +1427,12 @@ pub const Object = struct { |
| 1443 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | 1427 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1444 | const param_llvm_ty = try o.lowerType(param_ty); | 1428 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1445 | const param = wip.arg(llvm_arg_i); | 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 | try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); | 1432 | try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); |
| 1449 | llvm_arg_i += 1; | 1433 | llvm_arg_i += 1; |
| 1450 | | 1434 | |
| 1451 | if (isByRef(param_ty, mod)) { | 1435 | if (isByRef(param_ty, zcu)) { |
| 1452 | args.appendAssumeCapacity(param); | 1436 | args.appendAssumeCapacity(param); |
| 1453 | } else { | 1437 | } else { |
| 1454 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); | 1438 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); |
| ... | @@ -1458,12 +1442,12 @@ pub const Object = struct { | ... | @@ -1458,12 +1442,12 @@ pub const Object = struct { |
| 1458 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | 1442 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1459 | const param_llvm_ty = try o.lowerType(param_ty); | 1443 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1460 | const param = wip.arg(llvm_arg_i); | 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 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); | 1447 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); |
| 1464 | llvm_arg_i += 1; | 1448 | llvm_arg_i += 1; |
| 1465 | | 1449 | |
| 1466 | if (isByRef(param_ty, mod)) { | 1450 | if (isByRef(param_ty, zcu)) { |
| 1467 | args.appendAssumeCapacity(param); | 1451 | args.appendAssumeCapacity(param); |
| 1468 | } else { | 1452 | } else { |
| 1469 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); | 1453 | args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); |
| ... | @@ -1476,11 +1460,11 @@ pub const Object = struct { | ... | @@ -1476,11 +1460,11 @@ pub const Object = struct { |
| 1476 | llvm_arg_i += 1; | 1460 | llvm_arg_i += 1; |
| 1477 | | 1461 | |
| 1478 | const param_llvm_ty = try o.lowerType(param_ty); | 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 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); | 1464 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1481 | _ = try wip.store(.normal, param, arg_ptr, alignment); | 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 | arg_ptr | 1468 | arg_ptr |
| 1485 | else | 1469 | else |
| 1486 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); | 1470 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | @@ -1488,14 +1472,14 @@ pub const Object = struct { | ... | @@ -1488,14 +1472,14 @@ pub const Object = struct { |
| 1488 | .slice => { | 1472 | .slice => { |
| 1489 | assert(!it.byval_attr); | 1473 | assert(!it.byval_attr); |
| 1490 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | 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 | if (math.cast(u5, it.zig_index - 1)) |i| { | 1477 | if (math.cast(u5, it.zig_index - 1)) |i| { |
| 1494 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { | 1478 | if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { |
| 1495 | try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); | 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 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 1483 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 1500 | } | 1484 | } |
| 1501 | if (ptr_info.flags.is_const) { | 1485 | if (ptr_info.flags.is_const) { |
| ... | @@ -1504,7 +1488,7 @@ pub const Object = struct { | ... | @@ -1504,7 +1488,7 @@ pub const Object = struct { |
| 1504 | const elem_align = (if (ptr_info.flags.alignment != .none) | 1488 | const elem_align = (if (ptr_info.flags.alignment != .none) |
| 1505 | @as(InternPool.Alignment, ptr_info.flags.alignment) | 1489 | @as(InternPool.Alignment, ptr_info.flags.alignment) |
| 1506 | else | 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 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); | 1492 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1509 | const ptr_param = wip.arg(llvm_arg_i); | 1493 | const ptr_param = wip.arg(llvm_arg_i); |
| 1510 | llvm_arg_i += 1; | 1494 | llvm_arg_i += 1; |
| ... | @@ -1521,7 +1505,7 @@ pub const Object = struct { | ... | @@ -1521,7 +1505,7 @@ pub const Object = struct { |
| 1521 | const field_types = it.types_buffer[0..it.types_len]; | 1505 | const field_types = it.types_buffer[0..it.types_len]; |
| 1522 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | 1506 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1523 | const param_llvm_ty = try o.lowerType(param_ty); | 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 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target); | 1509 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target); |
| 1526 | const llvm_ty = try o.builder.structType(.normal, field_types); | 1510 | const llvm_ty = try o.builder.structType(.normal, field_types); |
| 1527 | for (0..field_types.len) |field_i| { | 1511 | for (0..field_types.len) |field_i| { |
| ... | @@ -1533,7 +1517,7 @@ pub const Object = struct { | ... | @@ -1533,7 +1517,7 @@ pub const Object = struct { |
| 1533 | _ = try wip.store(.normal, param, field_ptr, alignment); | 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 | args.appendAssumeCapacity(if (is_by_ref) | 1521 | args.appendAssumeCapacity(if (is_by_ref) |
| 1538 | arg_ptr | 1522 | arg_ptr |
| 1539 | else | 1523 | else |
| ... | @@ -1551,11 +1535,11 @@ pub const Object = struct { | ... | @@ -1551,11 +1535,11 @@ pub const Object = struct { |
| 1551 | const param = wip.arg(llvm_arg_i); | 1535 | const param = wip.arg(llvm_arg_i); |
| 1552 | llvm_arg_i += 1; | 1536 | llvm_arg_i += 1; |
| 1553 | | 1537 | |
| 1554 | const alignment = param_ty.abiAlignment(mod).toLlvm(); | 1538 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1555 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); | 1539 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1556 | _ = try wip.store(.normal, param, arg_ptr, alignment); | 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 | arg_ptr | 1543 | arg_ptr |
| 1560 | else | 1544 | else |
| 1561 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); | 1545 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | @@ -1566,11 +1550,11 @@ pub const Object = struct { | ... | @@ -1566,11 +1550,11 @@ pub const Object = struct { |
| 1566 | const param = wip.arg(llvm_arg_i); | 1550 | const param = wip.arg(llvm_arg_i); |
| 1567 | llvm_arg_i += 1; | 1551 | llvm_arg_i += 1; |
| 1568 | | 1552 | |
| 1569 | const alignment = param_ty.abiAlignment(mod).toLlvm(); | 1553 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1570 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); | 1554 | const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); |
| 1571 | _ = try wip.store(.normal, param, arg_ptr, alignment); | 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 | arg_ptr | 1558 | arg_ptr |
| 1575 | else | 1559 | else |
| 1576 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); | 1560 | try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); |
| ... | @@ -1584,14 +1568,12 @@ pub const Object = struct { | ... | @@ -1584,14 +1568,12 @@ pub const Object = struct { |
| 1584 | var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; | 1568 | var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; |
| 1585 | var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; | 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 | if (o.di_builder) |dib| { | 1571 | if (o.di_builder) |dib| { |
| 1590 | di_file = try o.getDIFile(gpa, namespace.file_scope); | 1572 | di_file = try o.getDIFile(gpa, namespace.file_scope); |
| 1591 | | 1573 | |
| 1592 | const line_number = decl.src_line + 1; | 1574 | const line_number = decl.src_line + 1; |
| 1593 | const is_internal_linkage = decl.val.getExternFunc(mod) == null and | 1575 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null and |
| 1594 | !mod.decl_exports.contains(decl_index); | 1576 | !zcu.decl_exports.contains(decl_index); |
| 1595 | const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type) | 1577 | const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type) |
| 1596 | llvm.DIFlags.NoReturn | 1578 | llvm.DIFlags.NoReturn |
| 1597 | else | 1579 | else |
| ... | @@ -1608,7 +1590,7 @@ pub const Object = struct { | ... | @@ -1608,7 +1590,7 @@ pub const Object = struct { |
| 1608 | true, // is definition | 1590 | true, // is definition |
| 1609 | line_number + func.lbrace_line, // scope line | 1591 | line_number + func.lbrace_line, // scope line |
| 1610 | llvm.DIFlags.StaticMember | noret_bit, | 1592 | llvm.DIFlags.StaticMember | noret_bit, |
| 1611 | mod.comp.bin_file.options.optimize_mode != .Debug, | 1593 | owner_mod.optimize_mode != .Debug, |
| 1612 | null, // decl_subprogram | 1594 | null, // decl_subprogram |
| 1613 | ); | 1595 | ); |
| 1614 | try o.di_map.put(gpa, decl, subprogram.toNode()); | 1596 | try o.di_map.put(gpa, decl, subprogram.toNode()); |
| ... | @@ -1618,8 +1600,6 @@ pub const Object = struct { | ... | @@ -1618,8 +1600,6 @@ pub const Object = struct { |
| 1618 | di_scope = subprogram.toScope(); | 1600 | di_scope = subprogram.toScope(); |
| 1619 | } | 1601 | } |
| 1620 | | 1602 | |
| 1621 | const single_threaded = namespace.file_scope.mod.single_threaded; | | |
| 1622 | | | |
| 1623 | var fg: FuncGen = .{ | 1603 | var fg: FuncGen = .{ |
| 1624 | .gpa = gpa, | 1604 | .gpa = gpa, |
| 1625 | .air = air, | 1605 | .air = air, |
| ... | @@ -1631,7 +1611,7 @@ pub const Object = struct { | ... | @@ -1631,7 +1611,7 @@ pub const Object = struct { |
| 1631 | .arg_index = 0, | 1611 | .arg_index = 0, |
| 1632 | .func_inst_table = .{}, | 1612 | .func_inst_table = .{}, |
| 1633 | .blocks = .{}, | 1613 | .blocks = .{}, |
| 1634 | .sync_scope = if (single_threaded) .singlethread else .system, | 1614 | .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, |
| 1635 | .di_scope = di_scope, | 1615 | .di_scope = di_scope, |
| 1636 | .di_file = di_file, | 1616 | .di_file = di_file, |
| 1637 | .base_line = dg.decl.src_line, | 1617 | .base_line = dg.decl.src_line, |
| ... | @@ -1645,7 +1625,7 @@ pub const Object = struct { | ... | @@ -1645,7 +1625,7 @@ pub const Object = struct { |
| 1645 | fg.genBody(air.getMainBody()) catch |err| switch (err) { | 1625 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 1646 | error.CodegenFail => { | 1626 | error.CodegenFail => { |
| 1647 | decl.analysis = .codegen_failure; | 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 | dg.err_msg = null; | 1629 | dg.err_msg = null; |
| 1650 | return; | 1630 | return; |
| 1651 | }, | 1631 | }, |
| ... | @@ -1654,7 +1634,7 @@ pub const Object = struct { | ... | @@ -1654,7 +1634,7 @@ pub const Object = struct { |
| 1654 | | 1634 | |
| 1655 | try fg.wip.finish(); | 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 | pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { | 1640 | pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { |
| ... | @@ -2933,22 +2913,24 @@ pub const Object = struct { | ... | @@ -2933,22 +2913,24 @@ pub const Object = struct { |
| 2933 | o: *Object, | 2913 | o: *Object, |
| 2934 | decl_index: InternPool.DeclIndex, | 2914 | decl_index: InternPool.DeclIndex, |
| 2935 | ) Allocator.Error!Builder.Function.Index { | 2915 | ) Allocator.Error!Builder.Function.Index { |
| 2936 | const mod = o.module; | 2916 | const zcu = o.module; |
| 2937 | const ip = &mod.intern_pool; | 2917 | const ip = &zcu.intern_pool; |
| 2938 | const gpa = o.gpa; | 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 | const zig_fn_type = decl.ty; | 2922 | const zig_fn_type = decl.ty; |
| 2941 | const gop = try o.decl_map.getOrPut(gpa, decl_index); | 2923 | const gop = try o.decl_map.getOrPut(gpa, decl_index); |
| 2942 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; | 2924 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; |
| 2943 | | 2925 | |
| 2944 | assert(decl.has_tv); | 2926 | assert(decl.has_tv); |
| 2945 | const fn_info = mod.typeToFunc(zig_fn_type).?; | 2927 | const fn_info = zcu.typeToFunc(zig_fn_type).?; |
| 2946 | const target = mod.getTarget(); | 2928 | const target = owner_mod.resolved_target.result; |
| 2947 | const sret = firstParamSRet(fn_info, mod); | 2929 | const sret = firstParamSRet(fn_info, zcu); |
| 2948 | | 2930 | |
| 2949 | const function_index = try o.builder.addFunction( | 2931 | const function_index = try o.builder.addFunction( |
| 2950 | try o.lowerType(zig_fn_type), | 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 | toLlvmAddressSpace(decl.@"addrspace", target), | 2934 | toLlvmAddressSpace(decl.@"addrspace", target), |
| 2953 | ); | 2935 | ); |
| 2954 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; | 2936 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| ... | @@ -2956,7 +2938,7 @@ pub const Object = struct { | ... | @@ -2956,7 +2938,7 @@ pub const Object = struct { |
| 2956 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 2938 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 2957 | defer attributes.deinit(&o.builder); | 2939 | defer attributes.deinit(&o.builder); |
| 2958 | | 2940 | |
| 2959 | const is_extern = decl.isExtern(mod); | 2941 | const is_extern = decl.isExtern(zcu); |
| 2960 | if (!is_extern) { | 2942 | if (!is_extern) { |
| 2961 | function_index.setLinkage(.internal, &o.builder); | 2943 | function_index.setLinkage(.internal, &o.builder); |
| 2962 | function_index.setUnnamedAddr(.unnamed_addr, &o.builder); | 2944 | function_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| ... | @@ -2966,7 +2948,7 @@ pub const Object = struct { | ... | @@ -2966,7 +2948,7 @@ pub const Object = struct { |
| 2966 | .kind = try o.builder.string("wasm-import-name"), | 2948 | .kind = try o.builder.string("wasm-import-name"), |
| 2967 | .value = try o.builder.string(ip.stringToSlice(decl.name)), | 2949 | .value = try o.builder.string(ip.stringToSlice(decl.name)), |
| 2968 | } }, &o.builder); | 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 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ | 2952 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ |
| 2971 | .kind = try o.builder.string("wasm-import-module"), | 2953 | .kind = try o.builder.string("wasm-import-module"), |
| 2972 | .value = try o.builder.string(lib_name), | 2954 | .value = try o.builder.string(lib_name), |
| ... | @@ -2987,8 +2969,8 @@ pub const Object = struct { | ... | @@ -2987,8 +2969,8 @@ pub const Object = struct { |
| 2987 | llvm_arg_i += 1; | 2969 | llvm_arg_i += 1; |
| 2988 | } | 2970 | } |
| 2989 | | 2971 | |
| 2990 | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and | 2972 | const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and |
| 2991 | mod.comp.config.any_error_tracing; | 2973 | zcu.comp.config.any_error_tracing; |
| 2992 | | 2974 | |
| 2993 | if (err_return_tracing) { | 2975 | if (err_return_tracing) { |
| 2994 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | 2976 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| ... | @@ -3009,7 +2991,7 @@ pub const Object = struct { | ... | @@ -3009,7 +2991,7 @@ pub const Object = struct { |
| 3009 | function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder); | 2991 | function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder); |
| 3010 | | 2992 | |
| 3011 | // Function attributes that are independent of analysis results of the function body. | 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 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); | 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,14 +3004,14 @@ pub const Object = struct { |
| 3022 | .byval => { | 3004 | .byval => { |
| 3023 | const param_index = it.zig_index - 1; | 3005 | const param_index = it.zig_index - 1; |
| 3024 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); | 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 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); | 3008 | try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); |
| 3027 | } | 3009 | } |
| 3028 | }, | 3010 | }, |
| 3029 | .byref => { | 3011 | .byref => { |
| 3030 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | 3012 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 3031 | const param_llvm_ty = try o.lowerType(param_ty); | 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 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); | 3015 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); |
| 3034 | }, | 3016 | }, |
| 3035 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), | 3017 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), |
| ... | @@ -3055,13 +3037,14 @@ pub const Object = struct { | ... | @@ -3055,13 +3037,14 @@ pub const Object = struct { |
| 3055 | fn addCommonFnAttributes( | 3037 | fn addCommonFnAttributes( |
| 3056 | o: *Object, | 3038 | o: *Object, |
| 3057 | attributes: *Builder.FunctionAttributes.Wip, | 3039 | attributes: *Builder.FunctionAttributes.Wip, |
| | 3040 | owner_mod: *Package.Module, |
| 3058 | ) Allocator.Error!void { | 3041 | ) Allocator.Error!void { |
| 3059 | const comp = o.module.comp; | 3042 | const comp = o.module.comp; |
| 3060 | | 3043 | |
| 3061 | if (!comp.bin_file.options.red_zone) { | 3044 | if (!owner_mod.red_zone) { |
| 3062 | try attributes.addFnAttr(.noredzone, &o.builder); | 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 | try attributes.addFnAttr(.{ .string = .{ | 3048 | try attributes.addFnAttr(.{ .string = .{ |
| 3066 | .kind = try o.builder.string("frame-pointer"), | 3049 | .kind = try o.builder.string("frame-pointer"), |
| 3067 | .value = try o.builder.string("none"), | 3050 | .value = try o.builder.string("none"), |
| ... | @@ -3073,7 +3056,7 @@ pub const Object = struct { | ... | @@ -3073,7 +3056,7 @@ pub const Object = struct { |
| 3073 | } }, &o.builder); | 3056 | } }, &o.builder); |
| 3074 | } | 3057 | } |
| 3075 | try attributes.addFnAttr(.nounwind, &o.builder); | 3058 | try attributes.addFnAttr(.nounwind, &o.builder); |
| 3076 | if (comp.unwind_tables) { | 3059 | if (owner_mod.unwind_tables) { |
| 3077 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); | 3060 | try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); |
| 3078 | } | 3061 | } |
| 3079 | if (comp.skip_linker_dependencies or comp.no_builtin) { | 3062 | if (comp.skip_linker_dependencies or comp.no_builtin) { |
| ... | @@ -3084,26 +3067,27 @@ pub const Object = struct { | ... | @@ -3084,26 +3067,27 @@ pub const Object = struct { |
| 3084 | // overflow instead of performing memcpy. | 3067 | // overflow instead of performing memcpy. |
| 3085 | try attributes.addFnAttr(.nobuiltin, &o.builder); | 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 | try attributes.addFnAttr(.minsize, &o.builder); | 3071 | try attributes.addFnAttr(.minsize, &o.builder); |
| 3089 | try attributes.addFnAttr(.optsize, &o.builder); | 3072 | try attributes.addFnAttr(.optsize, &o.builder); |
| 3090 | } | 3073 | } |
| 3091 | if (comp.bin_file.options.tsan) { | 3074 | if (owner_mod.sanitize_thread) { |
| 3092 | try attributes.addFnAttr(.sanitize_thread, &o.builder); | 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 | try attributes.addFnAttr(.{ .string = .{ | 3079 | try attributes.addFnAttr(.{ .string = .{ |
| 3096 | .kind = try o.builder.string("target-cpu"), | 3080 | .kind = try o.builder.string("target-cpu"), |
| 3097 | .value = try o.builder.string(s), | 3081 | .value = try o.builder.string(s), |
| 3098 | } }, &o.builder); | 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 | try attributes.addFnAttr(.{ .string = .{ | 3085 | try attributes.addFnAttr(.{ .string = .{ |
| 3102 | .kind = try o.builder.string("target-features"), | 3086 | .kind = try o.builder.string("target-features"), |
| 3103 | .value = try o.builder.string(std.mem.span(s)), | 3087 | .value = try o.builder.string(std.mem.span(s)), |
| 3104 | } }, &o.builder); | 3088 | } }, &o.builder); |
| 3105 | } | 3089 | } |
| 3106 | if (comp.getTarget().cpu.arch.isBpf()) { | 3090 | if (target.cpu.arch.isBpf()) { |
| 3107 | try attributes.addFnAttr(.{ .string = .{ | 3091 | try attributes.addFnAttr(.{ .string = .{ |
| 3108 | .kind = try o.builder.string("no-builtins"), | 3092 | .kind = try o.builder.string("no-builtins"), |
| 3109 | .value = .empty, | 3093 | .value = .empty, |
| ... | @@ -4646,6 +4630,100 @@ pub const Object = struct { | ... | @@ -4646,6 +4630,100 @@ pub const Object = struct { |
| 4646 | .field_index = @intCast(field_index), | 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 | pub const DeclGen = struct { | 4729 | pub const DeclGen = struct { |
| ... | @@ -4654,6 +4732,13 @@ pub const DeclGen = struct { | ... | @@ -4654,6 +4732,13 @@ pub const DeclGen = struct { |
| 4654 | decl_index: InternPool.DeclIndex, | 4732 | decl_index: InternPool.DeclIndex, |
| 4655 | err_msg: ?*Module.ErrorMsg, | 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 | fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { | 4742 | fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 4658 | @setCold(true); | 4743 | @setCold(true); |
| 4659 | assert(dg.err_msg == null); | 4744 | assert(dg.err_msg == null); |
| ... | @@ -5614,7 +5699,7 @@ pub const FuncGen = struct { | ... | @@ -5614,7 +5699,7 @@ pub const FuncGen = struct { |
| 5614 | const o = self.dg.object; | 5699 | const o = self.dg.object; |
| 5615 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 5700 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5616 | const operand = try self.resolveInst(un_op); | 5701 | const operand = try self.resolveInst(un_op); |
| 5617 | const llvm_fn = try self.getCmpLtErrorsLenFunction(); | 5702 | const llvm_fn = try o.getCmpLtErrorsLenFunction(); |
| 5618 | return self.wip.call( | 5703 | return self.wip.call( |
| 5619 | .normal, | 5704 | .normal, |
| 5620 | .fastcc, | 5705 | .fastcc, |
| ... | @@ -6547,11 +6632,13 @@ pub const FuncGen = struct { | ... | @@ -6547,11 +6632,13 @@ pub const FuncGen = struct { |
| 6547 | const dib = o.di_builder orelse return .none; | 6632 | const dib = o.di_builder orelse return .none; |
| 6548 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; | 6633 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; |
| 6549 | | 6634 | |
| 6550 | const mod = o.module; | 6635 | const zcu = o.module; |
| 6551 | const func = mod.funcInfo(ty_fn.func); | 6636 | const func = zcu.funcInfo(ty_fn.func); |
| 6552 | const decl_index = func.owner_decl; | 6637 | const decl_index = func.owner_decl; |
| 6553 | const decl = mod.declPtr(decl_index); | 6638 | const decl = zcu.declPtr(decl_index); |
| 6554 | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); | 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 | self.di_file = di_file; | 6642 | self.di_file = di_file; |
| 6556 | const line_number = decl.src_line + 1; | 6643 | const line_number = decl.src_line + 1; |
| 6557 | const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2(); | 6644 | const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2(); |
| ... | @@ -6562,18 +6649,18 @@ pub const FuncGen = struct { | ... | @@ -6562,18 +6649,18 @@ pub const FuncGen = struct { |
| 6562 | .base_line = self.base_line, | 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); | 6654 | const is_internal_linkage = !zcu.decl_exports.contains(decl_index); |
| 6568 | const fn_ty = try mod.funcType(.{ | 6655 | const fn_ty = try zcu.funcType(.{ |
| 6569 | .param_types = &.{}, | 6656 | .param_types = &.{}, |
| 6570 | .return_type = .void_type, | 6657 | .return_type = .void_type, |
| 6571 | }); | 6658 | }); |
| 6572 | const fn_di_ty = try o.lowerDebugType(fn_ty, .full); | 6659 | const fn_di_ty = try o.lowerDebugType(fn_ty, .full); |
| 6573 | const subprogram = dib.createFunction( | 6660 | const subprogram = dib.createFunction( |
| 6574 | di_file.toScope(), | 6661 | di_file.toScope(), |
| 6575 | mod.intern_pool.stringToSlice(decl.name), | 6662 | zcu.intern_pool.stringToSlice(decl.name), |
| 6576 | mod.intern_pool.stringToSlice(fqn), | 6663 | zcu.intern_pool.stringToSlice(fqn), |
| 6577 | di_file, | 6664 | di_file, |
| 6578 | line_number, | 6665 | line_number, |
| 6579 | fn_di_ty, | 6666 | fn_di_ty, |
| ... | @@ -6581,7 +6668,7 @@ pub const FuncGen = struct { | ... | @@ -6581,7 +6668,7 @@ pub const FuncGen = struct { |
| 6581 | true, // is definition | 6668 | true, // is definition |
| 6582 | line_number + func.lbrace_line, // scope line | 6669 | line_number + func.lbrace_line, // scope line |
| 6583 | llvm.DIFlags.StaticMember, | 6670 | llvm.DIFlags.StaticMember, |
| 6584 | mod.comp.bin_file.options.optimize_mode != .Debug, | 6671 | owner_mod.optimize_mode != .Debug, |
| 6585 | null, // decl_subprogram | 6672 | null, // decl_subprogram |
| 6586 | ); | 6673 | ); |
| 6587 | | 6674 | |
| ... | @@ -6676,11 +6763,12 @@ pub const FuncGen = struct { | ... | @@ -6676,11 +6763,12 @@ pub const FuncGen = struct { |
| 6676 | null; | 6763 | null; |
| 6677 | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); | 6764 | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); |
| 6678 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); | 6765 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 6679 | const mod = o.module; | 6766 | const zcu = o.module; |
| 6680 | if (isByRef(operand_ty, mod)) { | 6767 | const owner_mod = self.dg.ownerModule(); |
| | 6768 | if (isByRef(operand_ty, zcu)) { |
| 6681 | _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); | 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) { | 6770 | } else if (owner_mod.optimize_mode == .Debug) { |
| 6683 | const alignment = operand_ty.abiAlignment(mod).toLlvm(); | 6771 | const alignment = operand_ty.abiAlignment(zcu).toLlvm(); |
| 6684 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); | 6772 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); |
| 6685 | _ = try self.wip.store(.normal, operand, alloca, alignment); | 6773 | _ = try self.wip.store(.normal, operand, alloca, alignment); |
| 6686 | _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); | 6774 | _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| ... | @@ -8729,9 +8817,10 @@ pub const FuncGen = struct { | ... | @@ -8729,9 +8817,10 @@ pub const FuncGen = struct { |
| 8729 | | 8817 | |
| 8730 | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); | 8818 | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); |
| 8731 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); | 8819 | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| | 8820 | const owner_mod = self.dg.ownerModule(); |
| 8732 | if (isByRef(inst_ty, mod)) { | 8821 | if (isByRef(inst_ty, mod)) { |
| 8733 | _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); | 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 | const alignment = inst_ty.abiAlignment(mod).toLlvm(); | 8824 | const alignment = inst_ty.abiAlignment(mod).toLlvm(); |
| 8736 | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); | 8825 | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); |
| 8737 | _ = try self.wip.store(.normal, arg_val, alloca, alignment); | 8826 | _ = try self.wip.store(.normal, arg_val, alloca, alignment); |
| ... | @@ -8821,7 +8910,8 @@ pub const FuncGen = struct { | ... | @@ -8821,7 +8910,8 @@ pub const FuncGen = struct { |
| 8821 | len, | 8910 | len, |
| 8822 | if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, | 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 | try self.valgrindMarkUndef(dest_ptr, len); | 8915 | try self.valgrindMarkUndef(dest_ptr, len); |
| 8826 | } | 8916 | } |
| 8827 | return .none; | 8917 | return .none; |
| ... | @@ -9137,7 +9227,8 @@ pub const FuncGen = struct { | ... | @@ -9137,7 +9227,8 @@ pub const FuncGen = struct { |
| 9137 | } else { | 9227 | } else { |
| 9138 | _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); | 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 | try self.valgrindMarkUndef(dest_ptr, len); | 9232 | try self.valgrindMarkUndef(dest_ptr, len); |
| 9142 | } | 9233 | } |
| 9143 | return .none; | 9234 | return .none; |
| ... | @@ -9488,24 +9579,25 @@ pub const FuncGen = struct { | ... | @@ -9488,24 +9579,25 @@ pub const FuncGen = struct { |
| 9488 | | 9579 | |
| 9489 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { | 9580 | fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { |
| 9490 | const o = self.dg.object; | 9581 | const o = self.dg.object; |
| 9491 | const mod = o.module; | 9582 | const zcu = o.module; |
| 9492 | const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; | 9583 | const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; |
| 9493 | | 9584 | |
| 9494 | // TODO: detect when the type changes and re-emit this function. | 9585 | // TODO: detect when the type changes and re-emit this function. |
| 9495 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); | 9586 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); |
| 9496 | if (gop.found_existing) return gop.value_ptr.*; | 9587 | if (gop.found_existing) return gop.value_ptr.*; |
| 9497 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); | 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 | const function_index = try o.builder.addFunction( | 9592 | const function_index = try o.builder.addFunction( |
| 9501 | try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), | 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)}), | 9594 | try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}), |
| 9503 | toLlvmAddressSpace(.generic, mod.getTarget()), | 9595 | toLlvmAddressSpace(.generic, target), |
| 9504 | ); | 9596 | ); |
| 9505 | | 9597 | |
| 9506 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 9598 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9507 | defer attributes.deinit(&o.builder); | 9599 | defer attributes.deinit(&o.builder); |
| 9508 | try o.addCommonFnAttributes(&attributes); | 9600 | try o.addCommonFnAttributes(&attributes, zcu.root_mod); |
| 9509 | | 9601 | |
| 9510 | function_index.setLinkage(.internal, &o.builder); | 9602 | function_index.setLinkage(.internal, &o.builder); |
| 9511 | function_index.setCallConv(.fastcc, &o.builder); | 9603 | function_index.setCallConv(.fastcc, &o.builder); |
| ... | @@ -9524,7 +9616,7 @@ pub const FuncGen = struct { | ... | @@ -9524,7 +9616,7 @@ pub const FuncGen = struct { |
| 9524 | | 9616 | |
| 9525 | for (0..enum_type.names.len) |field_index| { | 9617 | for (0..enum_type.names.len) |field_index| { |
| 9526 | const this_tag_int_value = try o.lowerValue( | 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 | try wip_switch.addCase(this_tag_int_value, named_block, &wip); | 9621 | try wip_switch.addCase(this_tag_int_value, named_block, &wip); |
| 9530 | } | 9622 | } |
| ... | @@ -9544,7 +9636,7 @@ pub const FuncGen = struct { | ... | @@ -9544,7 +9636,7 @@ pub const FuncGen = struct { |
| 9544 | const operand = try self.resolveInst(un_op); | 9636 | const operand = try self.resolveInst(un_op); |
| 9545 | const enum_ty = self.typeOf(un_op); | 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 | return self.wip.call( | 9640 | return self.wip.call( |
| 9549 | .normal, | 9641 | .normal, |
| 9550 | .fastcc, | 9642 | .fastcc, |
| ... | @@ -9556,100 +9648,6 @@ pub const FuncGen = struct { | ... | @@ -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 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | 9651 | fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 9654 | const o = self.dg.object; | 9652 | const o = self.dg.object; |
| 9655 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 9653 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |