@@ -3774,6 +3774,245 @@ final class SwiftDriverTests: XCTestCase {
37743774 try checkSupplementaryOutputFileMap ( format: " bitstream " , . bitstreamOptimizationRecord)
37753775 }
37763776
3777+ func testOptimizationRecordPathUserProvidedPath( ) throws {
3778+
3779+ do {
3780+ var driver = try Driver ( args: [
3781+ " swiftc " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/test.opt.yaml " ,
3782+ " -c " , " test.swift "
3783+ ] )
3784+ let plannedJobs = try driver. planBuild ( )
3785+ let compileJob = try XCTUnwrap ( plannedJobs. first { $0. kind == . compile } )
3786+
3787+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/test.opt.yaml " ) ) ) ) )
3788+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) )
3789+ }
3790+
3791+ // Test primary file mode with multiple files and explicit path
3792+ do {
3793+ var driver = try Driver ( args: [
3794+ " swiftc " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/primary.opt.yaml " ,
3795+ " -c " , " file1.swift " , " file2.swift "
3796+ ] )
3797+ let plannedJobs = try driver. planBuild ( )
3798+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3799+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3800+
3801+ for compileJob in compileJobs {
3802+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3803+ " Each compile job should have -save-optimization-record-path flag " )
3804+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/primary.opt.yaml " ) ) ) ) ,
3805+ " Each compile job should have the user-provided path " )
3806+ }
3807+ }
3808+
3809+ do {
3810+ var driver = try Driver ( args: [
3811+ " swiftc " , " -wmo " , " -save-optimization-record " , " -save-optimization-record-path " , " /tmp/wmo.opt.yaml " ,
3812+ " -c " , " test.swift "
3813+ ] )
3814+ let plannedJobs = try driver. planBuild ( )
3815+ let compileJob = try XCTUnwrap ( plannedJobs. first { $0. kind == . compile } )
3816+
3817+ XCTAssertTrue ( compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/wmo.opt.yaml " ) ) ) ) )
3818+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) )
3819+ }
3820+
3821+ // Test multithreaded WMO with multiple optimization record paths
3822+ do {
3823+ var driver = try Driver ( args: [
3824+ " swiftc " , " -wmo " , " -num-threads " , " 4 " , " -save-optimization-record " ,
3825+ " -save-optimization-record-path " , " /tmp/mt1.opt.yaml " ,
3826+ " -save-optimization-record-path " , " /tmp/mt2.opt.yaml " ,
3827+ " -c " , " test1.swift " , " test2.swift "
3828+ ] )
3829+ let plannedJobs = try driver. planBuild ( )
3830+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3831+
3832+ XCTAssertGreaterThanOrEqual ( compileJobs. count, 1 , " Should have at least one compile job " )
3833+
3834+ var foundPaths : Set < String > = [ ]
3835+ for compileJob in compileJobs {
3836+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3837+ " Each compile job should have -save-optimization-record-path flag " )
3838+
3839+ if compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/mt1.opt.yaml " ) ) ) ) {
3840+ foundPaths. insert ( " /tmp/mt1.opt.yaml " )
3841+ }
3842+ if compileJob. commandLine. contains ( . path( VirtualPath . absolute ( try AbsolutePath ( validating: " /tmp/mt2.opt.yaml " ) ) ) ) {
3843+ foundPaths. insert ( " /tmp/mt2.opt.yaml " )
3844+ }
3845+ }
3846+
3847+ XCTAssertGreaterThanOrEqual ( foundPaths. count, 1 ,
3848+ " At least one of the provided optimization record paths should be used " )
3849+ }
3850+ }
3851+
3852+ func testOptimizationRecordWithOutputFileMap( ) throws {
3853+ try withTemporaryDirectory { path in
3854+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3855+ let file1 = path. appending ( component: " file1.swift " )
3856+ let file2 = path. appending ( component: " file2.swift " )
3857+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3858+ let optRecord2 = path. appending ( component: " file2.opt.yaml " )
3859+
3860+ try localFileSystem. writeFileContents ( outputFileMap) {
3861+ $0. send ( """
3862+ {
3863+ " \( file1. pathString) " : {
3864+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3865+ " yaml-opt-record " : " \( optRecord1. pathString) "
3866+ },
3867+ " \( file2. pathString) " : {
3868+ " object " : " \( path. appending ( component: " file2.o " ) . pathString) " ,
3869+ " yaml-opt-record " : " \( optRecord2. pathString) "
3870+ }
3871+ }
3872+ """ )
3873+ }
3874+
3875+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3876+ try localFileSystem. writeFileContents ( file2) { $0. send ( " func bar() {} " ) }
3877+
3878+ // Test primary file mode with output file map containing optimization record entries
3879+ var driver = try Driver ( args: [
3880+ " swiftc " , " -save-optimization-record " ,
3881+ " -output-file-map " , outputFileMap. pathString,
3882+ " -c " , file1. pathString, file2. pathString
3883+ ] )
3884+ let plannedJobs = try driver. planBuild ( )
3885+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3886+
3887+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3888+
3889+ for (index, compileJob) in compileJobs. enumerated ( ) {
3890+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3891+ " Compile job \( index) should have -save-optimization-record-path flag " )
3892+
3893+ if let primaryFileIndex = compileJob. commandLine. firstIndex ( of: . flag( " -primary-file " ) ) ,
3894+ primaryFileIndex + 1 < compileJob. commandLine. count {
3895+ let primaryFile = compileJob. commandLine [ primaryFileIndex + 1 ]
3896+
3897+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
3898+ optRecordIndex + 1 < compileJob. commandLine. count {
3899+ let optRecordPath = compileJob. commandLine [ optRecordIndex + 1 ]
3900+
3901+ if case . path( let primaryPath) = primaryFile, case . path( let optPath) = optRecordPath {
3902+ if primaryPath == . absolute( file1) {
3903+ XCTAssertEqual ( optPath, . absolute( optRecord1) ,
3904+ " Compile job with file1.swift as primary should use file1.opt.yaml from output file map " )
3905+ } else if primaryPath == . absolute( file2) {
3906+ XCTAssertEqual ( optPath, . absolute( optRecord2) ,
3907+ " Compile job with file2.swift as primary should use file2.opt.yaml from output file map " )
3908+ }
3909+ }
3910+ }
3911+ }
3912+ }
3913+ }
3914+ }
3915+
3916+ func testOptimizationRecordConflictingOptions( ) throws {
3917+ try withTemporaryDirectory { path in
3918+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3919+ let file1 = path. appending ( component: " file1.swift " )
3920+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3921+ let explicitPath = path. appending ( component: " explicit.opt.yaml " )
3922+
3923+ try localFileSystem. writeFileContents ( outputFileMap) {
3924+ $0. send ( """
3925+ {
3926+ " \( file1. pathString) " : {
3927+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3928+ " yaml-opt-record " : " \( optRecord1. pathString) "
3929+ }
3930+ }
3931+ """ )
3932+ }
3933+
3934+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3935+
3936+ // Test that providing both -save-optimization-record-path and file map entry produces a warning
3937+ try assertDriverDiagnostics ( args: [
3938+ " swiftc " , " -save-optimization-record " ,
3939+ " -save-optimization-record-path " , explicitPath. pathString,
3940+ " -output-file-map " , outputFileMap. pathString,
3941+ " -c " , file1. pathString
3942+ ] ) {
3943+ _ = try ? $0. planBuild ( )
3944+ $1. expect ( . warning( " ignoring -save-optimization-record-path because output file map contains optimization record entries " ) )
3945+ }
3946+ }
3947+ }
3948+
3949+ func testOptimizationRecordPartialFileMapCoverage( ) throws {
3950+ try withTemporaryDirectory { path in
3951+ let outputFileMap = path. appending ( component: " outputFileMap.json " )
3952+ let file1 = path. appending ( component: " file1.swift " )
3953+ let file2 = path. appending ( component: " file2.swift " )
3954+ let optRecord1 = path. appending ( component: " file1.opt.yaml " )
3955+
3956+ try localFileSystem. writeFileContents ( outputFileMap) {
3957+ $0. send ( """
3958+ {
3959+ " \( file1. pathString) " : {
3960+ " object " : " \( path. appending ( component: " file1.o " ) . pathString) " ,
3961+ " yaml-opt-record " : " \( optRecord1. pathString) "
3962+ },
3963+ " \( file2. pathString) " : {
3964+ " object " : " \( path. appending ( component: " file2.o " ) . pathString) "
3965+ }
3966+ }
3967+ """ )
3968+ }
3969+
3970+ try localFileSystem. writeFileContents ( file1) { $0. send ( " func foo() {} " ) }
3971+ try localFileSystem. writeFileContents ( file2) { $0. send ( " func bar() {} " ) }
3972+
3973+ // Test primary file mode with partial file map coverage
3974+ var driver = try Driver ( args: [
3975+ " swiftc " , " -save-optimization-record " ,
3976+ " -output-file-map " , outputFileMap. pathString,
3977+ " -c " , file1. pathString, file2. pathString
3978+ ] )
3979+ let plannedJobs = try driver. planBuild ( )
3980+ let compileJobs = plannedJobs. filter { $0. kind == . compile }
3981+
3982+ XCTAssertEqual ( compileJobs. count, 2 , " Should have two compile jobs in primary file mode " )
3983+
3984+ // file1 should use the path from the file map, file2 should use a derived path
3985+ for compileJob in compileJobs {
3986+ if let primaryFileIndex = compileJob. commandLine. firstIndex ( of: . flag( " -primary-file " ) ) ,
3987+ primaryFileIndex + 1 < compileJob. commandLine. count {
3988+ let primaryFile = compileJob. commandLine [ primaryFileIndex + 1 ]
3989+
3990+ if case . path( let primaryPath) = primaryFile {
3991+ if primaryPath == . absolute( file1) {
3992+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
3993+ " file1 compile job should have -save-optimization-record-path flag " )
3994+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
3995+ optRecordIndex + 1 < compileJob. commandLine. count,
3996+ case . path( let optPath) = compileJob. commandLine [ optRecordIndex + 1 ] {
3997+ XCTAssertEqual ( optPath, . absolute( optRecord1) ,
3998+ " file1 should use the optimization record path from the file map " )
3999+ }
4000+ } else if primaryPath == . absolute( file2) {
4001+ XCTAssertTrue ( compileJob. commandLine. contains ( . flag( " -save-optimization-record-path " ) ) ,
4002+ " file2 compile job should have -save-optimization-record-path flag " )
4003+ if let optRecordIndex = compileJob. commandLine. firstIndex ( of: . flag( " -save-optimization-record-path " ) ) ,
4004+ optRecordIndex + 1 < compileJob. commandLine. count,
4005+ case . path( let optPath) = compileJob. commandLine [ optRecordIndex + 1 ] {
4006+ XCTAssertNotEqual ( optPath, . absolute( optRecord1) ,
4007+ " file2 should NOT use file1's optimization record path " )
4008+ }
4009+ }
4010+ }
4011+ }
4012+ }
4013+ }
4014+ }
4015+
37774016 func testUpdateCode( ) throws {
37784017 do {
37794018 var driver = try Driver ( args: [
0 commit comments