| ... | ... | @@ -235,7 +235,7 @@ const ideal_factor = 3; |
| 235 | 235 | const minimum_text_block_size = 64; |
| 236 | 236 | pub const min_text_capacity = padToIdeal(minimum_text_block_size); |
| 237 | 237 | |
| 238 | | pub fn open( |
| 238 | pub fn createEmpty( |
| 239 | 239 | arena: Allocator, |
| 240 | 240 | comp: *Compilation, |
| 241 | 241 | emit: Compilation.Emit, |
| ... | ... | @@ -243,36 +243,96 @@ pub fn open( |
| 243 | 243 | ) !*Coff { |
| 244 | 244 | const target = comp.root_mod.resolved_target.result; |
| 245 | 245 | assert(target.ofmt == .coff); |
| 246 | const optimize_mode = comp.root_mod.optimize_mode; |
| 247 | const output_mode = comp.config.output_mode; |
| 248 | const link_mode = comp.config.link_mode; |
| 249 | const use_llvm = comp.config.use_llvm; |
| 250 | const use_lld = build_options.have_llvm and comp.config.use_lld; |
| 246 | 251 | |
| 247 | | const self = try createEmpty(arena, comp, emit, options); |
| 248 | | errdefer self.base.destroy(); |
| 252 | const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { |
| 253 | 0...32 => .p32, |
| 254 | 33...64 => .p64, |
| 255 | else => return error.UnsupportedCOFFArchitecture, |
| 256 | }; |
| 257 | const page_size: u32 = switch (target.cpu.arch) { |
| 258 | else => 0x1000, |
| 259 | }; |
| 249 | 260 | |
| 250 | | const use_lld = build_options.have_llvm and comp.config.use_lld; |
| 251 | | const use_llvm = comp.config.use_llvm; |
| 261 | // If using LLD to link, this code should produce an object file so that it |
| 262 | // can be passed to LLD. |
| 263 | // If using LLVM to generate the object file for the zig compilation unit, |
| 264 | // we need a place to put the object file so that it can be subsequently |
| 265 | // handled. |
| 266 | const zcu_object_sub_path = if (!use_lld and !use_llvm) |
| 267 | null |
| 268 | else |
| 269 | try std.fmt.allocPrint(arena, "{s}.obj", .{emit.sub_path}); |
| 270 | |
| 271 | const self = try arena.create(Coff); |
| 272 | self.* = .{ |
| 273 | .base = .{ |
| 274 | .tag = .coff, |
| 275 | .comp = comp, |
| 276 | .emit = emit, |
| 277 | .zcu_object_sub_path = zcu_object_sub_path, |
| 278 | .stack_size = options.stack_size orelse 16777216, |
| 279 | .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), |
| 280 | .print_gc_sections = options.print_gc_sections, |
| 281 | .allow_shlib_undefined = options.allow_shlib_undefined orelse false, |
| 282 | .file = null, |
| 283 | .disable_lld_caching = options.disable_lld_caching, |
| 284 | .build_id = options.build_id, |
| 285 | .rpath_list = options.rpath_list, |
| 286 | .force_undefined_symbols = options.force_undefined_symbols, |
| 287 | }, |
| 288 | .ptr_width = ptr_width, |
| 289 | .page_size = page_size, |
| 290 | |
| 291 | .data_directories = [1]coff.ImageDataDirectory{.{ |
| 292 | .virtual_address = 0, |
| 293 | .size = 0, |
| 294 | }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, |
| 295 | |
| 296 | .image_base = options.image_base orelse switch (output_mode) { |
| 297 | .Exe => switch (target.cpu.arch) { |
| 298 | .aarch64 => 0x140000000, |
| 299 | .x86_64, .x86 => 0x400000, |
| 300 | else => unreachable, |
| 301 | }, |
| 302 | .Lib => 0x10000000, |
| 303 | .Obj => 0, |
| 304 | }, |
| 305 | |
| 306 | .subsystem = options.subsystem, |
| 307 | .tsaware = options.tsaware, |
| 308 | .nxcompat = options.nxcompat, |
| 309 | .dynamicbase = options.dynamicbase, |
| 310 | .major_subsystem_version = options.major_subsystem_version orelse 6, |
| 311 | .minor_subsystem_version = options.minor_subsystem_version orelse 0, |
| 312 | .lib_dirs = options.lib_dirs, |
| 313 | .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse |
| 314 | return error.EntryAddressTooBig, |
| 315 | .module_definition_file = options.module_definition_file, |
| 316 | .pdb_out_path = options.pdb_out_path, |
| 317 | }; |
| 318 | if (use_llvm and comp.config.have_zcu) { |
| 319 | self.llvm_object = try LlvmObject.create(arena, comp); |
| 320 | } |
| 321 | errdefer self.base.destroy(); |
| 252 | 322 | |
| 253 | 323 | if (use_lld and use_llvm) { |
| 254 | 324 | // LLVM emits the object file; LLD links it into the final product. |
| 255 | 325 | return self; |
| 256 | 326 | } |
| 257 | 327 | |
| 258 | | const sub_path = if (!use_lld) emit.sub_path else p: { |
| 259 | | // Open a temporary object file, not the final output file because we |
| 260 | | // want to link with LLD. |
| 261 | | const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ |
| 262 | | emit.sub_path, target.ofmt.fileExt(target.cpu.arch), |
| 263 | | }); |
| 264 | | self.base.zcu_object_sub_path = o_file_path; |
| 265 | | break :p o_file_path; |
| 266 | | }; |
| 267 | | |
| 328 | // What path should this COFF linker code output to? |
| 329 | // If using LLD to link, this code should produce an object file so that it |
| 330 | // can be passed to LLD. |
| 331 | const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; |
| 268 | 332 | self.base.file = try emit.directory.handle.createFile(sub_path, .{ |
| 269 | | .truncate = false, |
| 333 | .truncate = true, |
| 270 | 334 | .read = true, |
| 271 | | .mode = link.File.determineMode( |
| 272 | | use_lld, |
| 273 | | comp.config.output_mode, |
| 274 | | comp.config.link_mode, |
| 275 | | ), |
| 335 | .mode = link.File.determineMode(use_lld, output_mode, link_mode), |
| 276 | 336 | }); |
| 277 | 337 | |
| 278 | 338 | assert(self.llvm_object == null); |
| ... | ... | @@ -367,75 +427,15 @@ pub fn open( |
| 367 | 427 | return self; |
| 368 | 428 | } |
| 369 | 429 | |
| 370 | | pub fn createEmpty( |
| 430 | pub fn open( |
| 371 | 431 | arena: Allocator, |
| 372 | 432 | comp: *Compilation, |
| 373 | 433 | emit: Compilation.Emit, |
| 374 | 434 | options: link.File.OpenOptions, |
| 375 | 435 | ) !*Coff { |
| 376 | | const target = comp.root_mod.resolved_target.result; |
| 377 | | const optimize_mode = comp.root_mod.optimize_mode; |
| 378 | | const output_mode = comp.config.output_mode; |
| 379 | | const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { |
| 380 | | 0...32 => .p32, |
| 381 | | 33...64 => .p64, |
| 382 | | else => return error.UnsupportedCOFFArchitecture, |
| 383 | | }; |
| 384 | | const page_size: u32 = switch (target.cpu.arch) { |
| 385 | | else => 0x1000, |
| 386 | | }; |
| 387 | | const self = try arena.create(Coff); |
| 388 | | self.* = .{ |
| 389 | | .base = .{ |
| 390 | | .tag = .coff, |
| 391 | | .comp = comp, |
| 392 | | .emit = emit, |
| 393 | | .stack_size = options.stack_size orelse 16777216, |
| 394 | | .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), |
| 395 | | .print_gc_sections = options.print_gc_sections, |
| 396 | | .allow_shlib_undefined = options.allow_shlib_undefined orelse false, |
| 397 | | .file = null, |
| 398 | | .disable_lld_caching = options.disable_lld_caching, |
| 399 | | .build_id = options.build_id, |
| 400 | | .rpath_list = options.rpath_list, |
| 401 | | .force_undefined_symbols = options.force_undefined_symbols, |
| 402 | | }, |
| 403 | | .ptr_width = ptr_width, |
| 404 | | .page_size = page_size, |
| 405 | | |
| 406 | | .data_directories = [1]coff.ImageDataDirectory{.{ |
| 407 | | .virtual_address = 0, |
| 408 | | .size = 0, |
| 409 | | }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, |
| 410 | | |
| 411 | | .image_base = options.image_base orelse switch (output_mode) { |
| 412 | | .Exe => switch (target.cpu.arch) { |
| 413 | | .aarch64 => 0x140000000, |
| 414 | | .x86_64, .x86 => 0x400000, |
| 415 | | else => unreachable, |
| 416 | | }, |
| 417 | | .Lib => 0x10000000, |
| 418 | | .Obj => 0, |
| 419 | | }, |
| 420 | | |
| 421 | | .subsystem = options.subsystem, |
| 422 | | .tsaware = options.tsaware, |
| 423 | | .nxcompat = options.nxcompat, |
| 424 | | .dynamicbase = options.dynamicbase, |
| 425 | | .major_subsystem_version = options.major_subsystem_version orelse 6, |
| 426 | | .minor_subsystem_version = options.minor_subsystem_version orelse 0, |
| 427 | | .lib_dirs = options.lib_dirs, |
| 428 | | .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse |
| 429 | | return error.EntryAddressTooBig, |
| 430 | | .module_definition_file = options.module_definition_file, |
| 431 | | .pdb_out_path = options.pdb_out_path, |
| 432 | | }; |
| 433 | | |
| 434 | | const use_llvm = comp.config.use_llvm; |
| 435 | | if (use_llvm and comp.config.have_zcu) { |
| 436 | | self.llvm_object = try LlvmObject.create(arena, comp); |
| 437 | | } |
| 438 | | return self; |
| 436 | // TODO: restore saved linker state, don't truncate the file, and |
| 437 | // participate in incremental compilation. |
| 438 | return createEmpty(arena, comp, emit, options); |
| 439 | 439 | } |
| 440 | 440 | |
| 441 | 441 | pub fn deinit(self: *Coff) void { |