Repository navigation
64ビット整数のリテラルと定数を無効な型として断つ - #248
Conversation
PRレビュー / PR review変更 7 ファイル、コミット 5 件。 / 7 files, 5 commits. 検証の要否 / Verification required以下を走らせ、失敗した試験の名前と失敗の様子を変更前と突き合わせてください。総数だけで判断しないでください。 dotnet build ComputeWeave.sln -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.SourceGenerators/ComputeWeave.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.Internals/ComputeWeave.Tests.Internals.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests/ComputeWeave.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.DeviceLost/ComputeWeave.Tests.DeviceLost.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.SourceGenerators/ComputeWeave.D2D1.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests/ComputeWeave.D2D1.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes.csproj -c Release -p:Platform=x64ビルドエラーを出す診断を変えた場合は、アナライザーの試験に加えて解全体の検証が要ります。 慎重を要する箇所 / Guarded areas touched
寿命の追跡と危険の追跡は別々の保証です。一方を保っても他方が保たれるとは限りません。 公開APIまたは生成される記述子を変えた場合は、該当部分の互換性、生成の決定性、基準データの検査を走らせてください。 確認できた点 / Confirmed
これは自動の確認で、査読の代わりにはなりません。指摘は判断の材料であって、従う義務はありません。 |
Summary / 概要
64ビット整数のリテラルと定数を、型集合の外の型として断ちます。
longとulongのリテラルは接尾辞のまま、定数は桁だけで生成 HLSL へ出ており、同梱のシェーダーコンパイラはそれを32ビットの値として読んでいました。負のリテラルを左辺に置いた符号なしとの比較は符号なしで解かれ、32ビットを越える値は切り詰められ、生成器の診断もシェーダーコンパイラの誤りも出ません。被演算子の広がりを断つCMPW0125は左辺の変換だけを読むので、変換を伴わないリテラルと定数を左辺に置いた形は素通りしていました。判定は型で行います。リテラルの型が型集合の外にあるとき、また定数の値を HLSL のリテラルとして書き出せないとき、その型を発見された型として追跡します。
longの局所変数と明示的な変換が既にCMPW0050で断られているのと同じ経路なので、新しい診断は足していません。定数を定義へ書き出す3箇所は1つの補助メソッドへ集め、書き出せない値をその失敗の経路で断ちます。文字列の定数はこれまで識別子のまま残され、シェーダーコンパイラが生成物の行を名指して落ちていましたが、同じ経路で断られるようになります。Linked issue / 関連する課題
Closes #242
Kind / 種別
Behavior change / 挙動の変更
64ビット整数のリテラルか定数、または文字列の定数を持つシェーダーは、ビルドが止まるようになります。既定の重大度はエラーです。次の表は、土台の
main(887d5851)とこの枝で計算側の生成器を直に動かして測ったものです。式のうちリテラルと定数以外の値は定数バッファから読んでいます。5L < this.unsignedCMPW0050(float)(5UL + this.unsigned)CMPW0050const longを名前で読むCMPW0050const longをメンバーアクセスで読むCMPW0050const longCMPW0050const longに単項の負号を付けるCMPW0050long.MaxValueCMPW0050const longCMPW0050const stringどうしの比較CMPW0046CMPW0050const stringと文字列リテラルの比較CMPW0036CMPW0036とCMPW0050(float)1.5mCMPW0046CMPW00505Lとconst longCMPW0125CMPW0125とCMPW0050(long)this.signedを左辺に置いた演算CMPW0125とCMPW0050longの局所変数CMPW0050const int、const uint、const short、const byte、const decimal、intのリテラル、int.MaxValueDirect2D の生成器では同じ経路が
CMPWD2D0041を報告します。リテラルと定数を1つずつ試験にしてあります。このリポジトリのシェーダーにはこの形が1つもありません。土台と
ca8735fcで11のプロジェクトをビルドし直し、生成器が書くファイルを突き合わせました。違う2件は
ShaderWithOverriddenOptionsとShaderWithOverriddenProfileAndOptionsで、同じコミットを2回ビルドしても動く DXBC の検査値です。公開 API は変わりません。触れたのは共有の書き換え器の
internalな型だけで、記述子と README は動いていません。Verification / 検証
9本をビルド済みの dll から走らせました。判定は失敗した試験の名前で行い、失敗は0件です。生成器の2スイートは
cd6b8ab6で、他の7本は文字列の定数の試験を書き直す前のca8735fcで走らせています。その後の2コミットは広がりの報告の注記の1文と台帳の引用で、生成器の符号は変わりません。枝の最後のコミットbf32530eの CI は4本とも通っています。ComputeWeave.Tests.GlobalStatementsは終了状態0です。土台側の値は 2026-09-13 にab003f50で測った記録で、そこから887d5851までの13コミットはsrcとtestsを触っていません。生成器の2本は 557 と 232 で、増えた10件と2件が足した回帰試験です。他の7本は同じ値です。ComputeWeave.Testsは1度目にTransition_ReadWriteTexture3Dの2変種が 75 MB の確保のE_OUTOFMEMORYで落ちました。並列のビルドで機械のメモリが尽きていたときの回で、所要も 352 秒と長く、同じ dll を単独で走らせ直した2度目が上の値です。変異
実装をコミットしてから3通りに壊し、足した試験だけを両方の生成器で回しました。対照は変異なしで失敗0件です。
longとulongを外す断たない側の4行はどの変異でも落ちません。断ちすぎる向きの変異は行っていません。判定は型集合の有無をそのまま読んでおり、逆へ倒すと型集合の中の型を持つリテラル全部が断たれ、既存の試験が軒並み落ちるためです。
Adapter and driver tested / 試したアダプターとドライバー: Intel(R) Iris(R) Xe Graphics, 32.0.101.7085、および WARP
なぜ型の追跡で断つのか
書き出す側が知らない型を、書き出す側で見分ける形にしました。
longの局所変数と明示的な変換は、型を追跡する既存の経路がCMPW0050で断っています。リテラルと定数は型の追跡を通らないので、その2箇所だけが型集合の外の型を持ち込めていました。追跡へ載せると、局所変数、変換、リテラル、定数のどれから入っても同じ判定に届きます。CMPW0125の判定を右辺へ広げる形は退けました。その報告は被演算子の変換を読むもので、リテラルと定数は変換を持ちません。左辺に置かれた5Lとconst longを捉えるには変換ではなく型を読む判定が要り、それを演算の側に置くと、演算の中に現れないlongの定数を取り落とします。問題を所有しているのは型の側です。新しい診断は足しませんでした。
longの局所変数を書いた著者が今日受け取るのと同じ報告を、リテラルと定数を書いた著者も受け取ります。識別子を計算側と Direct2D 側に1つずつ増やすと README の6箇所と解析器のリリース記録の2箇所が動き、既存の報告と意味が重なります。文字列の定数は同じ補助メソッドの失敗の経路に入るので、そのまま断つ形にしました。
TryGetConstantLiteralが偽を返す値は、どの型であれ HLSL の定義へ書き出せないので、分ける理由がありません。decimalの定数は触っていません。浮動小数点の綴りへ書き出す既存の扱いが在り、その値は C# と同じです。decimalのリテラルは型集合の外なので追跡へ載りますが、(float)1.5mの形はこれまでもシェーダーコンパイラが落としており、届く診断が生成物の行から著者の型へ移るだけです。(long)の明示的な変換を伴う演算は、これまでどおりCMPW0050とCMPW0125の両方を受けます。1つの原因に2つの報告が並ぶ形ですが、この変更が新しく作ったものではなく、変換の側の既存の形です。測っていないこと
Direct2D 側で FXC が
Lの接尾辞をどう読むかは確かめていません。ulongは DXC の DXIL までで、装置では読んでいません。Direct2D 側の文字列の定数は試していません。利用者のシェーダーにこの形がどれだけ在るかは分かりません。走らせていないスイート
ComputeWeave.Tests.NativeLibrariesResolverだけ走らせていません。出荷経路のワークフローが回すもので、この変更が触れるファイルを取り込みません。Checklist / 確認
If this touches a guarded area / 慎重を要する箇所に触れる場合
Notes for the reviewer / 査読者への注記
コミットは5つです。断りを足すもの、試験を足すもの、台帳の行を足すもの、広がりの報告の注記へ左辺のリテラルと定数の扱いを足すもの、台帳の行にそのコミットを引くものの順です。
3箇所にあった定数の書き出しの4行を1つの補助メソッドへ集めたのは、書き出せない値の扱いを3箇所へ書かないためです。集めた補助メソッドの成功の経路は元の4行と同じ文で、生成物は変わりません。
解全体のビルドは、この機械では資源で落ちるのでプロジェクトを1本ずつビルドしています。11のプロジェクトすべてが警告0、誤り0でビルドできました。
PR #243 の枝とは
HlslSourceRewriter.csのVisitIdentifierNameで衝突します。PR #243 は定数の条件を1つのifへ戻して初期化子の環の報告を歩きへ置き換え、この PR は同じifの中で補助メソッドを呼ぶためです。解決は、そのifの最後の条件をTryGetConstantLiteralの呼び出しからTryRewriteConstantReference(operation.Field, out IdentifierNameSyntax? constantName)へ替え、本体をreturn constantName;の1行にする形です。PR #243 の最後のコミットへこの枝を併合してそのように解いた木で、生成器の2スイートは 587 件と 236 件で失敗0件、警告0で建ちました。先に入った方の後に、残った方がmainを取り込んで同じ形に解きます。