128 lines
5.2 KiB
PowerShell
128 lines
5.2 KiB
PowerShell
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateSet('scalar', 'baseline', 'avx2')]
|
|
[string]$Profile
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$build = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\out\build\msvc-$Profile"))
|
|
$targets = @('uc_demo', 'uc_tests', 'uc_bench', 'uc_focused_bench')
|
|
|
|
function Require-Flag(
|
|
[string]$Command,
|
|
[string]$Pattern,
|
|
[string]$Description,
|
|
[string]$Context
|
|
) {
|
|
if ($Command -notmatch $Pattern) {
|
|
throw "${Profile}/${Context}: missing $Description"
|
|
}
|
|
}
|
|
|
|
function Reject-Flag(
|
|
[string]$Command,
|
|
[string]$Pattern,
|
|
[string]$Description,
|
|
[string]$Context
|
|
) {
|
|
if ($Command -match $Pattern) {
|
|
throw "${Profile}/${Context}: unexpected $Description"
|
|
}
|
|
}
|
|
|
|
function Assert-ProfileCommand(
|
|
[string]$Command,
|
|
[string]$Context
|
|
) {
|
|
$optimizationFlags = @([regex]::Matches(
|
|
$Command,
|
|
'(?i)(?:^|\s)/(?:O1|O2|Od|Ox)(?=\s|$)'
|
|
) | ForEach-Object { $_.Value.Trim() })
|
|
if ($optimizationFlags.Count -ne 1 -or $optimizationFlags[0] -ine '/O2') {
|
|
$actual = if ($optimizationFlags.Count -eq 0) { 'none' } else { $optimizationFlags -join ', ' }
|
|
throw "${Profile}/${Context}: expected exactly /O2, found $actual"
|
|
}
|
|
|
|
$runtimeFlags = @([regex]::Matches(
|
|
$Command,
|
|
'(?i)(?:^|\s)/(?:MDd?|MTd?)(?=\s|$)'
|
|
) | ForEach-Object { $_.Value.Trim() })
|
|
if ($runtimeFlags.Count -ne 1 -or $runtimeFlags[0] -ine '/MT') {
|
|
$actual = if ($runtimeFlags.Count -eq 0) { 'none' } else { $runtimeFlags -join ', ' }
|
|
throw "${Profile}/${Context}: expected exactly /MT, found $actual"
|
|
}
|
|
|
|
Reject-Flag $Command '(?i)(?:^|\s)/GL(?=\s|$)' '/GL (IPO/LTO must be off)' $Context
|
|
|
|
switch ($Profile) {
|
|
'scalar' {
|
|
Require-Flag $Command '(?i)(?:^|\s)/d2Qvec-(?=\s|$)' '/d2Qvec-' $Context
|
|
Require-Flag $Command '(?i)(?:^|\s)/Qvec-report:1(?=\s|$)' '/Qvec-report:1' $Context
|
|
Require-Flag $Command '(?i)(?:^|\s)/Oi-(?=\s|$)' '/Oi-' $Context
|
|
Require-Flag $Command '(?i)UC_SIMD_PROFILE_SCALAR=1' 'UC_SIMD_PROFILE_SCALAR=1' $Context
|
|
Require-Flag $Command '(?i)_USE_STD_VECTOR_ALGORITHMS=0' '_USE_STD_VECTOR_ALGORITHMS=0' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/arch:AVX\S*' '/arch:AVX*' $Context
|
|
Reject-Flag $Command '(?i)UC_SIMD_PROFILE_(?:BASELINE|AVX2)=1' 'a foreign SIMD profile definition' $Context
|
|
}
|
|
'baseline' {
|
|
Require-Flag $Command '(?i)UC_SIMD_PROFILE_BASELINE=1' 'UC_SIMD_PROFILE_BASELINE=1' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/(?:d2Qvec-|Qvec-)(?=\s|$)' 'vectorizer-disable flag' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/Oi-(?=\s|$)' '/Oi-' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/arch:AVX\S*' '/arch:AVX*' $Context
|
|
Reject-Flag $Command '(?i)_USE_STD_VECTOR_ALGORITHMS=0|UC_SIMD_PROFILE_(?:SCALAR|AVX2)=1' 'a foreign SIMD profile definition' $Context
|
|
}
|
|
'avx2' {
|
|
Require-Flag $Command '(?i)UC_SIMD_PROFILE_AVX2=1' 'UC_SIMD_PROFILE_AVX2=1' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/(?:d2Qvec-|Qvec-)(?=\s|$)' 'vectorizer-disable flag' $Context
|
|
Reject-Flag $Command '(?i)(?:^|\s)/Oi-(?=\s|$)' '/Oi-' $Context
|
|
Reject-Flag $Command '(?i)_USE_STD_VECTOR_ALGORITHMS=0|UC_SIMD_PROFILE_(?:SCALAR|BASELINE)=1' 'a foreign SIMD profile definition' $Context
|
|
|
|
$architectureFlags = @([regex]::Matches(
|
|
$Command,
|
|
'(?i)(?:^|\s)/arch:\S+'
|
|
) | ForEach-Object { $_.Value.Trim() })
|
|
if ($architectureFlags.Count -ne 1 -or $architectureFlags[0] -ine '/arch:AVX2') {
|
|
$actual = if ($architectureFlags.Count -eq 0) {
|
|
'none'
|
|
} else {
|
|
$architectureFlags -join ', '
|
|
}
|
|
throw "${Profile}/${Context}: expected exactly /arch:AVX2, found $actual"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$validatedCommands = 0
|
|
foreach ($target in $targets) {
|
|
$releaseDirectory = Join-Path $build "$target.dir\Release"
|
|
if (-not (Test-Path -LiteralPath $releaseDirectory -PathType Container)) {
|
|
throw "${Profile}/${target}: missing Release build directory $releaseDirectory"
|
|
}
|
|
|
|
$logs = @(Get-ChildItem -LiteralPath $releaseDirectory -Recurse `
|
|
-Filter 'CL.command.1.tlog' -File)
|
|
if ($logs.Count -ne 1) {
|
|
throw "${Profile}/${target}: expected one compiler command log, found $($logs.Count)"
|
|
}
|
|
|
|
# MSBuild writes command tlogs as UTF-16LE without a reliable BOM.
|
|
$commandLines = @(Get-Content -LiteralPath $logs[0].FullName -Encoding Unicode |
|
|
Where-Object { $_ -and -not $_.StartsWith('^') })
|
|
if ($commandLines.Count -eq 0) {
|
|
throw "${Profile}/${target}: compiler command log contains no commands"
|
|
}
|
|
|
|
for ($index = 0; $index -lt $commandLines.Count; ++$index) {
|
|
$context = if ($commandLines.Count -eq 1) {
|
|
$target
|
|
} else {
|
|
"$target command $($index + 1)"
|
|
}
|
|
Assert-ProfileCommand $commandLines[$index] $context
|
|
++$validatedCommands
|
|
}
|
|
}
|
|
|
|
Write-Host "Build flag audit passed for ${Profile}: $validatedCommands Release compiler command(s) across $($targets.Count) targets."
|