-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[DirectX][NFC] Refactoring DirectX backend to not use llvm::to_underlying
in switch cases.
#151032
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
ea35c41
3c1fc51
591d12a
0d55d28
7841a83
98be089
25ee6d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
|
||
#include "llvm/MC/DXContainerRootSignature.h" | ||
#include "llvm/ADT/SmallString.h" | ||
#include "llvm/BinaryFormat/DXContainer.h" | ||
#include "llvm/Support/EndianStream.h" | ||
|
||
using namespace llvm; | ||
|
@@ -35,20 +36,26 @@ size_t RootSignatureDesc::getSize() const { | |
StaticSamplers.size() * sizeof(dxbc::RTS0::v1::StaticSampler); | ||
|
||
for (const RootParameterInfo &I : ParametersContainer) { | ||
switch (I.Header.ParameterType) { | ||
case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): | ||
if (!dxbc::isValidParameterType(I.Header.ParameterType)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is It seems like a lot of complexity here would go away if we just stored these as the appropriate type, like we do for enums stored in the I suspect it is actually impossible to get to this point in the code with a parameter type that isn't legal (if it isn't impossible it probably should be) or we should be surfacing errors. |
||
continue; | ||
|
||
dxbc::RootParameterType PT = | ||
static_cast<dxbc::RootParameterType>(I.Header.ParameterType); | ||
|
||
switch (PT) { | ||
case dxbc::RootParameterType::Constants32Bit: | ||
Size += sizeof(dxbc::RTS0::v1::RootConstants); | ||
break; | ||
case llvm::to_underlying(dxbc::RootParameterType::CBV): | ||
case llvm::to_underlying(dxbc::RootParameterType::SRV): | ||
case llvm::to_underlying(dxbc::RootParameterType::UAV): | ||
case dxbc::RootParameterType::CBV: | ||
case dxbc::RootParameterType::SRV: | ||
case dxbc::RootParameterType::UAV: | ||
if (Version == 1) | ||
Size += sizeof(dxbc::RTS0::v1::RootDescriptor); | ||
else | ||
Size += sizeof(dxbc::RTS0::v2::RootDescriptor); | ||
|
||
break; | ||
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): | ||
case dxbc::RootParameterType::DescriptorTable: | ||
const DescriptorTable &Table = | ||
ParametersContainer.getDescriptorTable(I.Location); | ||
|
||
|
@@ -97,8 +104,12 @@ void RootSignatureDesc::write(raw_ostream &OS) const { | |
for (size_t I = 0; I < NumParameters; ++I) { | ||
rewriteOffsetToCurrentByte(BOS, ParamsOffsets[I]); | ||
const auto &[Type, Loc] = ParametersContainer.getTypeAndLocForParameter(I); | ||
switch (Type) { | ||
case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { | ||
if (!dxbc::isValidParameterType(Type)) | ||
continue; | ||
dxbc::RootParameterType PT = static_cast<dxbc::RootParameterType>(Type); | ||
|
||
switch (PT) { | ||
case dxbc::RootParameterType::Constants32Bit: { | ||
const dxbc::RTS0::v1::RootConstants &Constants = | ||
ParametersContainer.getConstant(Loc); | ||
support::endian::write(BOS, Constants.ShaderRegister, | ||
|
@@ -109,9 +120,9 @@ void RootSignatureDesc::write(raw_ostream &OS) const { | |
llvm::endianness::little); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::CBV): | ||
case llvm::to_underlying(dxbc::RootParameterType::SRV): | ||
case llvm::to_underlying(dxbc::RootParameterType::UAV): { | ||
case dxbc::RootParameterType::CBV: | ||
case dxbc::RootParameterType::SRV: | ||
case dxbc::RootParameterType::UAV: { | ||
const dxbc::RTS0::v2::RootDescriptor &Descriptor = | ||
ParametersContainer.getRootDescriptor(Loc); | ||
|
||
|
@@ -123,7 +134,7 @@ void RootSignatureDesc::write(raw_ostream &OS) const { | |
support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { | ||
case dxbc::RootParameterType::DescriptorTable: { | ||
const DescriptorTable &Table = | ||
ParametersContainer.getDescriptorTable(Loc); | ||
support::endian::write(BOS, (uint32_t)Table.Ranges.size(), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -278,8 +278,19 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { | |
dxbc::RTS0::v1::RootParameterHeader Header{L.Header.Type, L.Header.Visibility, | ||
L.Header.Offset}; | ||
|
||
switch (L.Header.Type) { | ||
case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { | ||
if (!dxbc::isValidParameterType(L.Header.Type)) { | ||
// Handling invalid parameter type edge case. We intentionally let | ||
// obj2yaml/yaml2obj parse and emit invalid dxcontainer data, in order | ||
// for that to be used as a testing tool more effectively. | ||
RS.ParametersContainer.addInvalidParameter(Header); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I question the utility of this. It doesn't actually enable us to emit a binary that contains potentially well-formed parameters that our implementation doesn't understand. That said, if we're using it for test I guess it is okay, it just has the drawback of forcing the MC code to be resilient to invalid parameter types which wouldn't be necessary if not for this. |
||
continue; | ||
} | ||
|
||
dxbc::RootParameterType ParameterType = | ||
static_cast<dxbc::RootParameterType>(L.Header.Type); | ||
|
||
switch (ParameterType) { | ||
case dxbc::RootParameterType::Constants32Bit: { | ||
const DXContainerYAML::RootConstantsYaml &ConstantYaml = | ||
P.RootSignature->Parameters.getOrInsertConstants(L); | ||
dxbc::RTS0::v1::RootConstants Constants; | ||
|
@@ -289,9 +300,9 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { | |
RS.ParametersContainer.addParameter(Header, Constants); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::CBV): | ||
case llvm::to_underlying(dxbc::RootParameterType::SRV): | ||
case llvm::to_underlying(dxbc::RootParameterType::UAV): { | ||
case dxbc::RootParameterType::CBV: | ||
case dxbc::RootParameterType::SRV: | ||
case dxbc::RootParameterType::UAV: { | ||
const DXContainerYAML::RootDescriptorYaml &DescriptorYaml = | ||
P.RootSignature->Parameters.getOrInsertDescriptor(L); | ||
|
||
|
@@ -303,7 +314,7 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { | |
RS.ParametersContainer.addParameter(Header, Descriptor); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { | ||
case dxbc::RootParameterType::DescriptorTable: { | ||
const DXContainerYAML::DescriptorTableYaml &TableYaml = | ||
P.RootSignature->Parameters.getOrInsertTable(L); | ||
mcdxbc::DescriptorTable Table; | ||
|
@@ -323,11 +334,6 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { | |
RS.ParametersContainer.addParameter(Header, Table); | ||
break; | ||
} | ||
default: | ||
// Handling invalid parameter type edge case. We intentionally let | ||
// obj2yaml/yaml2obj parse and emit invalid dxcontainer data, in order | ||
// for that to be used as a testing tool more effectively. | ||
RS.ParametersContainer.addInvalidParameter(Header); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -424,22 +424,28 @@ void MappingContextTraits<DXContainerYAML::RootParameterLocationYaml, | |
IO.mapRequired("ParameterType", L.Header.Type); | ||
IO.mapRequired("ShaderVisibility", L.Header.Visibility); | ||
|
||
switch (L.Header.Type) { | ||
case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { | ||
if (!dxbc::isValidParameterType(L.Header.Type)) | ||
return; | ||
dxbc::RootParameterType PT = | ||
static_cast<dxbc::RootParameterType>(L.Header.Type); | ||
|
||
// We allow ParameterType to be invalid here. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment doesn't match the implementation. It returns above if the parameter type is invalid. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed the comments to make it clearer what the current behaviour is. |
||
switch (PT) { | ||
case dxbc::RootParameterType::Constants32Bit: { | ||
DXContainerYAML::RootConstantsYaml &Constants = | ||
S.Parameters.getOrInsertConstants(L); | ||
IO.mapRequired("Constants", Constants); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::CBV): | ||
case llvm::to_underlying(dxbc::RootParameterType::SRV): | ||
case llvm::to_underlying(dxbc::RootParameterType::UAV): { | ||
case dxbc::RootParameterType::CBV: | ||
case dxbc::RootParameterType::SRV: | ||
case dxbc::RootParameterType::UAV: { | ||
DXContainerYAML::RootDescriptorYaml &Descriptor = | ||
S.Parameters.getOrInsertDescriptor(L); | ||
IO.mapRequired("Descriptor", Descriptor); | ||
break; | ||
} | ||
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { | ||
case dxbc::RootParameterType::DescriptorTable: { | ||
DXContainerYAML::DescriptorTableYaml &Table = | ||
S.Parameters.getOrInsertTable(L); | ||
IO.mapRequired("Table", Table); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not updating to not use
to_underlying
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This specific case is necessary, to keep using llvm::to_underlying, since that is checking if an uint_32t is valid value for RootParametersType. However, I updated to use the tablegen definition, that way we will always have it covering all possible values.
Or we can change how the check is being done, if folks prefer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to me like we get the same end result by doing the int->enum cast once before the switch and having the switch statement operate on the actual enumerations. I have a strong preference for not using
to_underlying
since it impairs the frontend's ability to generate warnings.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this point, we are not sure
Type
is a validDescriptorRangeType
so the casting here int->enum would cause undefined behaviour.