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