Realisation v1
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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')
|
||||
|
||||
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."
|
||||
Reference in New Issue
Block a user