| // Copyright 2021 The Tint Authors. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #include "src/tint/transform/renamer.h" | 
 |  | 
 | #include <memory> | 
 | #include <unordered_set> | 
 | #include <utility> | 
 |  | 
 | #include "src/tint/program_builder.h" | 
 | #include "src/tint/sem/call.h" | 
 | #include "src/tint/sem/member_accessor_expression.h" | 
 | #include "src/tint/sem/type_conversion.h" | 
 | #include "src/tint/sem/type_initializer.h" | 
 | #include "src/tint/text/unicode.h" | 
 | #include "src/tint/type/short_name.h" | 
 |  | 
 | TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer); | 
 | TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer::Data); | 
 | TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer::Config); | 
 |  | 
 | namespace tint::transform { | 
 |  | 
 | namespace { | 
 |  | 
 | // This list is used for a binary search and must be kept in sorted order. | 
 | const char* kReservedKeywordsGLSL[] = { | 
 |     "abs", | 
 |     "acos", | 
 |     "acosh", | 
 |     "active", | 
 |     "all", | 
 |     "any", | 
 |     "asin", | 
 |     "asinh", | 
 |     "asm", | 
 |     "atan", | 
 |     "atanh", | 
 |     "atomicAdd", | 
 |     "atomicAnd", | 
 |     "atomicCompSwap", | 
 |     "atomicCounter", | 
 |     "atomicCounterDecrement", | 
 |     "atomicCounterIncrement", | 
 |     "atomicExchange", | 
 |     "atomicMax", | 
 |     "atomicMin", | 
 |     "atomicOr", | 
 |     "atomicXor", | 
 |     "atomic_uint", | 
 |     "attribute", | 
 |     "barrier", | 
 |     "bitCount", | 
 |     "bitfieldExtract", | 
 |     "bitfieldInsert", | 
 |     "bitfieldReverse", | 
 |     "bool", | 
 |     "break", | 
 |     "buffer", | 
 |     "bvec2", | 
 |     "bvec3", | 
 |     "bvec4", | 
 |     "case", | 
 |     "cast", | 
 |     "ceil", | 
 |     "centroid", | 
 |     "clamp", | 
 |     "class", | 
 |     "coherent", | 
 |     "common", | 
 |     "const", | 
 |     "continue", | 
 |     "cos", | 
 |     "cosh", | 
 |     "cross", | 
 |     "dFdx", | 
 |     "dFdy", | 
 |     "default", | 
 |     "degrees", | 
 |     "determinant", | 
 |     "discard", | 
 |     "distance", | 
 |     "dmat2", | 
 |     "dmat2x2", | 
 |     "dmat2x3", | 
 |     "dmat2x4", | 
 |     "dmat3", | 
 |     "dmat3x2", | 
 |     "dmat3x3", | 
 |     "dmat3x4", | 
 |     "dmat4", | 
 |     "dmat4x2", | 
 |     "dmat4x3", | 
 |     "dmat4x4", | 
 |     "do", | 
 |     "dot", | 
 |     "double", | 
 |     "dvec2", | 
 |     "dvec3", | 
 |     "dvec4", | 
 |     "else", | 
 |     "enum", | 
 |     "equal", | 
 |     "exp", | 
 |     "exp2", | 
 |     "extern", | 
 |     "external", | 
 |     "faceforward", | 
 |     "false", | 
 |     "filter", | 
 |     "findLSB", | 
 |     "findMSB", | 
 |     "fixed", | 
 |     "flat", | 
 |     "float", | 
 |     "floatBitsToInt", | 
 |     "floatBitsToUint", | 
 |     "floor", | 
 |     "for", | 
 |     "fract", | 
 |     "frexp", | 
 |     "fvec2", | 
 |     "fvec3", | 
 |     "fvec4", | 
 |     "fwidth", | 
 |     "gl_BaseInstance", | 
 |     "gl_BaseVertex", | 
 |     "gl_ClipDistance", | 
 |     "gl_DepthRangeParameters", | 
 |     "gl_DrawID", | 
 |     "gl_FragCoord", | 
 |     "gl_FragDepth", | 
 |     "gl_FrontFacing", | 
 |     "gl_GlobalInvocationID", | 
 |     "gl_InstanceID", | 
 |     "gl_LocalInvocationID", | 
 |     "gl_LocalInvocationIndex", | 
 |     "gl_NumSamples", | 
 |     "gl_NumWorkGroups", | 
 |     "gl_PerVertex", | 
 |     "gl_PointCoord", | 
 |     "gl_PointSize", | 
 |     "gl_Position", | 
 |     "gl_PrimitiveID", | 
 |     "gl_SampleID", | 
 |     "gl_SampleMask", | 
 |     "gl_SampleMaskIn", | 
 |     "gl_SamplePosition", | 
 |     "gl_VertexID", | 
 |     "gl_WorkGroupID", | 
 |     "gl_WorkGroupSize", | 
 |     "goto", | 
 |     "greaterThan", | 
 |     "greaterThanEqual", | 
 |     "groupMemoryBarrier", | 
 |     "half", | 
 |     "highp", | 
 |     "hvec2", | 
 |     "hvec3", | 
 |     "hvec4", | 
 |     "if", | 
 |     "iimage1D", | 
 |     "iimage1DArray", | 
 |     "iimage2D", | 
 |     "iimage2DArray", | 
 |     "iimage2DMS", | 
 |     "iimage2DMSArray", | 
 |     "iimage2DRect", | 
 |     "iimage3D", | 
 |     "iimageBuffer", | 
 |     "iimageCube", | 
 |     "iimageCubeArray", | 
 |     "image1D", | 
 |     "image1DArray", | 
 |     "image2D", | 
 |     "image2DArray", | 
 |     "image2DMS", | 
 |     "image2DMSArray", | 
 |     "image2DRect", | 
 |     "image3D", | 
 |     "imageBuffer", | 
 |     "imageCube", | 
 |     "imageCubeArray", | 
 |     "imageLoad", | 
 |     "imageSize", | 
 |     "imageStore", | 
 |     "imulExtended", | 
 |     "in", | 
 |     "inline", | 
 |     "inout", | 
 |     "input", | 
 |     "int", | 
 |     "intBitsToFloat", | 
 |     "interface", | 
 |     "invariant", | 
 |     "inverse", | 
 |     "inversesqrt", | 
 |     "isampler1D", | 
 |     "isampler1DArray", | 
 |     "isampler2D", | 
 |     "isampler2DArray", | 
 |     "isampler2DMS", | 
 |     "isampler2DMSArray", | 
 |     "isampler2DRect", | 
 |     "isampler3D", | 
 |     "isamplerBuffer", | 
 |     "isamplerCube", | 
 |     "isamplerCubeArray", | 
 |     "isinf", | 
 |     "isnan", | 
 |     "ivec2", | 
 |     "ivec3", | 
 |     "ivec4", | 
 |     "layout", | 
 |     "ldexp", | 
 |     "length", | 
 |     "lessThan", | 
 |     "lessThanEqual", | 
 |     "log", | 
 |     "log2", | 
 |     "long", | 
 |     "lowp", | 
 |     "main", | 
 |     "mat2", | 
 |     "mat2x2", | 
 |     "mat2x3", | 
 |     "mat2x4", | 
 |     "mat3", | 
 |     "mat3x2", | 
 |     "mat3x3", | 
 |     "mat3x4", | 
 |     "mat4", | 
 |     "mat4x2", | 
 |     "mat4x3", | 
 |     "mat4x4", | 
 |     "matrixCompMult", | 
 |     "max", | 
 |     "mediump", | 
 |     "memoryBarrier", | 
 |     "memoryBarrierAtomicCounter", | 
 |     "memoryBarrierBuffer", | 
 |     "memoryBarrierImage", | 
 |     "memoryBarrierShared", | 
 |     "min", | 
 |     "mix", | 
 |     "mod", | 
 |     "modf", | 
 |     "namespace", | 
 |     "noinline", | 
 |     "noperspective", | 
 |     "normalize", | 
 |     "not", | 
 |     "notEqual", | 
 |     "out", | 
 |     "outerProduct", | 
 |     "output", | 
 |     "packHalf2x16", | 
 |     "packSnorm2x16", | 
 |     "packSnorm4x8", | 
 |     "packUnorm2x16", | 
 |     "packUnorm4x8", | 
 |     "partition", | 
 |     "patch", | 
 |     "pow", | 
 |     "precise", | 
 |     "precision", | 
 |     "public", | 
 |     "radians", | 
 |     "readonly", | 
 |     "reflect", | 
 |     "refract", | 
 |     "resource", | 
 |     "restrict", | 
 |     "return", | 
 |     "round", | 
 |     "roundEven", | 
 |     "sample", | 
 |     "sampler1D", | 
 |     "sampler1DArray", | 
 |     "sampler1DArrayShadow", | 
 |     "sampler1DShadow", | 
 |     "sampler2D", | 
 |     "sampler2DArray", | 
 |     "sampler2DArrayShadow", | 
 |     "sampler2DMS", | 
 |     "sampler2DMSArray", | 
 |     "sampler2DRect", | 
 |     "sampler2DRectShadow", | 
 |     "sampler2DShadow", | 
 |     "sampler3D", | 
 |     "sampler3DRect", | 
 |     "samplerBuffer", | 
 |     "samplerCube", | 
 |     "samplerCubeArray", | 
 |     "samplerCubeArrayShadow", | 
 |     "samplerCubeShadow", | 
 |     "shared", | 
 |     "short", | 
 |     "sign", | 
 |     "sin", | 
 |     "sinh", | 
 |     "sizeof", | 
 |     "smooth", | 
 |     "smoothstep", | 
 |     "sqrt", | 
 |     "static", | 
 |     "step", | 
 |     "struct", | 
 |     "subroutine", | 
 |     "superp", | 
 |     "switch", | 
 |     "tan", | 
 |     "tanh", | 
 |     "template", | 
 |     "texelFetch", | 
 |     "texelFetchOffset", | 
 |     "texture", | 
 |     "textureGather", | 
 |     "textureGatherOffset", | 
 |     "textureGrad", | 
 |     "textureGradOffset", | 
 |     "textureLod", | 
 |     "textureLodOffset", | 
 |     "textureOffset", | 
 |     "textureProj", | 
 |     "textureProjGrad", | 
 |     "textureProjGradOffset", | 
 |     "textureProjLod", | 
 |     "textureProjLodOffset", | 
 |     "textureProjOffset", | 
 |     "textureSize", | 
 |     "this", | 
 |     "transpose", | 
 |     "true", | 
 |     "trunc", | 
 |     "typedef", | 
 |     "uaddCarry", | 
 |     "uimage1D", | 
 |     "uimage1DArray", | 
 |     "uimage2D", | 
 |     "uimage2DArray", | 
 |     "uimage2DMS", | 
 |     "uimage2DMSArray", | 
 |     "uimage2DRect", | 
 |     "uimage3D", | 
 |     "uimageBuffer", | 
 |     "uimageCube", | 
 |     "uimageCubeArray", | 
 |     "uint", | 
 |     "uintBitsToFloat", | 
 |     "umulExtended", | 
 |     "uniform", | 
 |     "union", | 
 |     "unpackHalf2x16", | 
 |     "unpackSnorm2x16", | 
 |     "unpackSnorm4x8", | 
 |     "unpackUnorm2x16", | 
 |     "unpackUnorm4x8", | 
 |     "unsigned", | 
 |     "usampler1D", | 
 |     "usampler1DArray", | 
 |     "usampler2D", | 
 |     "usampler2DArray", | 
 |     "usampler2DMS", | 
 |     "usampler2DMSArray", | 
 |     "usampler2DRect", | 
 |     "usampler3D", | 
 |     "usamplerBuffer", | 
 |     "usamplerCube", | 
 |     "usamplerCubeArray", | 
 |     "using", | 
 |     "usubBorrow", | 
 |     "uvec2", | 
 |     "uvec3", | 
 |     "uvec4", | 
 |     "varying", | 
 |     "vec2", | 
 |     "vec3", | 
 |     "vec4", | 
 |     "void", | 
 |     "volatile", | 
 |     "while", | 
 |     "writeonly", | 
 | }; | 
 |  | 
 | // This list is used for a binary search and must be kept in sorted order. | 
 | const char* kReservedKeywordsHLSL[] = { | 
 |     "AddressU", | 
 |     "AddressV", | 
 |     "AddressW", | 
 |     "AllMemoryBarrier", | 
 |     "AllMemoryBarrierWithGroupSync", | 
 |     "AppendStructuredBuffer", | 
 |     "BINORMAL", | 
 |     "BLENDINDICES", | 
 |     "BLENDWEIGHT", | 
 |     "BlendState", | 
 |     "BorderColor", | 
 |     "Buffer", | 
 |     "ByteAddressBuffer", | 
 |     "COLOR", | 
 |     "CheckAccessFullyMapped", | 
 |     "ComparisonFunc", | 
 |     "CompileShader", | 
 |     "ComputeShader", | 
 |     "ConsumeStructuredBuffer", | 
 |     "D3DCOLORtoUBYTE4", | 
 |     "DEPTH", | 
 |     "DepthStencilState", | 
 |     "DepthStencilView", | 
 |     "DeviceMemoryBarrier", | 
 |     "DeviceMemroyBarrierWithGroupSync", | 
 |     "DomainShader", | 
 |     "EvaluateAttributeAtCentroid", | 
 |     "EvaluateAttributeAtSample", | 
 |     "EvaluateAttributeSnapped", | 
 |     "FOG", | 
 |     "Filter", | 
 |     "GeometryShader", | 
 |     "GetRenderTargetSampleCount", | 
 |     "GetRenderTargetSamplePosition", | 
 |     "GroupMemoryBarrier", | 
 |     "GroupMemroyBarrierWithGroupSync", | 
 |     "Hullshader", | 
 |     "InputPatch", | 
 |     "InterlockedAdd", | 
 |     "InterlockedAnd", | 
 |     "InterlockedCompareExchange", | 
 |     "InterlockedCompareStore", | 
 |     "InterlockedExchange", | 
 |     "InterlockedMax", | 
 |     "InterlockedMin", | 
 |     "InterlockedOr", | 
 |     "InterlockedXor", | 
 |     "LineStream", | 
 |     "MaxAnisotropy", | 
 |     "MaxLOD", | 
 |     "MinLOD", | 
 |     "MipLODBias", | 
 |     "NORMAL", | 
 |     "NULL", | 
 |     "Normal", | 
 |     "OutputPatch", | 
 |     "POSITION", | 
 |     "POSITIONT", | 
 |     "PSIZE", | 
 |     "PixelShader", | 
 |     "PointStream", | 
 |     "Process2DQuadTessFactorsAvg", | 
 |     "Process2DQuadTessFactorsMax", | 
 |     "Process2DQuadTessFactorsMin", | 
 |     "ProcessIsolineTessFactors", | 
 |     "ProcessQuadTessFactorsAvg", | 
 |     "ProcessQuadTessFactorsMax", | 
 |     "ProcessQuadTessFactorsMin", | 
 |     "ProcessTriTessFactorsAvg", | 
 |     "ProcessTriTessFactorsMax", | 
 |     "ProcessTriTessFactorsMin", | 
 |     "RWBuffer", | 
 |     "RWByteAddressBuffer", | 
 |     "RWStructuredBuffer", | 
 |     "RWTexture1D", | 
 |     "RWTexture1DArray", | 
 |     "RWTexture2D", | 
 |     "RWTexture2DArray", | 
 |     "RWTexture3D", | 
 |     "RasterizerState", | 
 |     "RenderTargetView", | 
 |     "SV_ClipDistance", | 
 |     "SV_Coverage", | 
 |     "SV_CullDistance", | 
 |     "SV_Depth", | 
 |     "SV_DepthGreaterEqual", | 
 |     "SV_DepthLessEqual", | 
 |     "SV_DispatchThreadID", | 
 |     "SV_DomainLocation", | 
 |     "SV_GSInstanceID", | 
 |     "SV_GroupID", | 
 |     "SV_GroupIndex", | 
 |     "SV_GroupThreadID", | 
 |     "SV_InnerCoverage", | 
 |     "SV_InsideTessFactor", | 
 |     "SV_InstanceID", | 
 |     "SV_IsFrontFace", | 
 |     "SV_OutputControlPointID", | 
 |     "SV_Position", | 
 |     "SV_PrimitiveID", | 
 |     "SV_RenderTargetArrayIndex", | 
 |     "SV_SampleIndex", | 
 |     "SV_StencilRef", | 
 |     "SV_Target", | 
 |     "SV_TessFactor", | 
 |     "SV_VertexArrayIndex", | 
 |     "SV_VertexID", | 
 |     "Sampler", | 
 |     "Sampler1D", | 
 |     "Sampler2D", | 
 |     "Sampler3D", | 
 |     "SamplerCUBE", | 
 |     "SamplerComparisonState", | 
 |     "SamplerState", | 
 |     "StructuredBuffer", | 
 |     "TANGENT", | 
 |     "TESSFACTOR", | 
 |     "TEXCOORD", | 
 |     "Texcoord", | 
 |     "Texture", | 
 |     "Texture1D", | 
 |     "Texture1DArray", | 
 |     "Texture2D", | 
 |     "Texture2DArray", | 
 |     "Texture2DMS", | 
 |     "Texture2DMSArray", | 
 |     "Texture3D", | 
 |     "TextureCube", | 
 |     "TextureCubeArray", | 
 |     "TriangleStream", | 
 |     "VFACE", | 
 |     "VPOS", | 
 |     "VertexShader", | 
 |     "abort", | 
 |     "allow_uav_condition", | 
 |     "asdouble", | 
 |     "asfloat", | 
 |     "asint", | 
 |     "asm", | 
 |     "asm_fragment", | 
 |     "asuint", | 
 |     "auto", | 
 |     "bool", | 
 |     "bool1", | 
 |     "bool1x1", | 
 |     "bool1x2", | 
 |     "bool1x3", | 
 |     "bool1x4", | 
 |     "bool2", | 
 |     "bool2x1", | 
 |     "bool2x2", | 
 |     "bool2x3", | 
 |     "bool2x4", | 
 |     "bool3", | 
 |     "bool3x1", | 
 |     "bool3x2", | 
 |     "bool3x3", | 
 |     "bool3x4", | 
 |     "bool4", | 
 |     "bool4x1", | 
 |     "bool4x2", | 
 |     "bool4x3", | 
 |     "bool4x4", | 
 |     "branch", | 
 |     "break", | 
 |     "call", | 
 |     "case", | 
 |     "catch", | 
 |     "cbuffer", | 
 |     "centroid", | 
 |     "char", | 
 |     "class", | 
 |     "clip", | 
 |     "column_major", | 
 |     "compile", | 
 |     "compile_fragment", | 
 |     "const", | 
 |     "const_cast", | 
 |     "continue", | 
 |     "countbits", | 
 |     "ddx", | 
 |     "ddx_coarse", | 
 |     "ddx_fine", | 
 |     "ddy", | 
 |     "ddy_coarse", | 
 |     "ddy_fine", | 
 |     "default", | 
 |     "degrees", | 
 |     "delete", | 
 |     "discard", | 
 |     "do", | 
 |     "double", | 
 |     "double1", | 
 |     "double1x1", | 
 |     "double1x2", | 
 |     "double1x3", | 
 |     "double1x4", | 
 |     "double2", | 
 |     "double2x1", | 
 |     "double2x2", | 
 |     "double2x3", | 
 |     "double2x4", | 
 |     "double3", | 
 |     "double3x1", | 
 |     "double3x2", | 
 |     "double3x3", | 
 |     "double3x4", | 
 |     "double4", | 
 |     "double4x1", | 
 |     "double4x2", | 
 |     "double4x3", | 
 |     "double4x4", | 
 |     "dst", | 
 |     "dword", | 
 |     "dword1", | 
 |     "dword1x1", | 
 |     "dword1x2", | 
 |     "dword1x3", | 
 |     "dword1x4", | 
 |     "dword2", | 
 |     "dword2x1", | 
 |     "dword2x2", | 
 |     "dword2x3", | 
 |     "dword2x4", | 
 |     "dword3", | 
 |     "dword3x1", | 
 |     "dword3x2", | 
 |     "dword3x3", | 
 |     "dword3x4", | 
 |     "dword4", | 
 |     "dword4x1", | 
 |     "dword4x2", | 
 |     "dword4x3", | 
 |     "dword4x4", | 
 |     "dynamic_cast", | 
 |     "else", | 
 |     "enum", | 
 |     "errorf", | 
 |     "explicit", | 
 |     "export", | 
 |     "extern", | 
 |     "f16to32", | 
 |     "f32tof16", | 
 |     "false", | 
 |     "fastopt", | 
 |     "firstbithigh", | 
 |     "firstbitlow", | 
 |     "flatten", | 
 |     "float", | 
 |     "float1", | 
 |     "float1x1", | 
 |     "float1x2", | 
 |     "float1x3", | 
 |     "float1x4", | 
 |     "float2", | 
 |     "float2x1", | 
 |     "float2x2", | 
 |     "float2x3", | 
 |     "float2x4", | 
 |     "float3", | 
 |     "float3x1", | 
 |     "float3x2", | 
 |     "float3x3", | 
 |     "float3x4", | 
 |     "float4", | 
 |     "float4x1", | 
 |     "float4x2", | 
 |     "float4x3", | 
 |     "float4x4", | 
 |     "fmod", | 
 |     "for", | 
 |     "forcecase", | 
 |     "frac", | 
 |     "friend", | 
 |     "fxgroup", | 
 |     "goto", | 
 |     "groupshared", | 
 |     "half", | 
 |     "half1", | 
 |     "half1x1", | 
 |     "half1x2", | 
 |     "half1x3", | 
 |     "half1x4", | 
 |     "half2", | 
 |     "half2x1", | 
 |     "half2x2", | 
 |     "half2x3", | 
 |     "half2x4", | 
 |     "half3", | 
 |     "half3x1", | 
 |     "half3x2", | 
 |     "half3x3", | 
 |     "half3x4", | 
 |     "half4", | 
 |     "half4x1", | 
 |     "half4x2", | 
 |     "half4x3", | 
 |     "half4x4", | 
 |     "if", | 
 |     "in", | 
 |     "inline", | 
 |     "inout", | 
 |     "int", | 
 |     "int1", | 
 |     "int1x1", | 
 |     "int1x2", | 
 |     "int1x3", | 
 |     "int1x4", | 
 |     "int2", | 
 |     "int2x1", | 
 |     "int2x2", | 
 |     "int2x3", | 
 |     "int2x4", | 
 |     "int3", | 
 |     "int3x1", | 
 |     "int3x2", | 
 |     "int3x3", | 
 |     "int3x4", | 
 |     "int4", | 
 |     "int4x1", | 
 |     "int4x2", | 
 |     "int4x3", | 
 |     "int4x4", | 
 |     "interface", | 
 |     "isfinite", | 
 |     "isinf", | 
 |     "isnan", | 
 |     "lerp", | 
 |     "line", | 
 |     "lineadj", | 
 |     "linear", | 
 |     "lit", | 
 |     "log10", | 
 |     "long", | 
 |     "loop", | 
 |     "mad", | 
 |     "matrix", | 
 |     "min10float", | 
 |     "min10float1", | 
 |     "min10float1x1", | 
 |     "min10float1x2", | 
 |     "min10float1x3", | 
 |     "min10float1x4", | 
 |     "min10float2", | 
 |     "min10float2x1", | 
 |     "min10float2x2", | 
 |     "min10float2x3", | 
 |     "min10float2x4", | 
 |     "min10float3", | 
 |     "min10float3x1", | 
 |     "min10float3x2", | 
 |     "min10float3x3", | 
 |     "min10float3x4", | 
 |     "min10float4", | 
 |     "min10float4x1", | 
 |     "min10float4x2", | 
 |     "min10float4x3", | 
 |     "min10float4x4", | 
 |     "min12int", | 
 |     "min12int1", | 
 |     "min12int1x1", | 
 |     "min12int1x2", | 
 |     "min12int1x3", | 
 |     "min12int1x4", | 
 |     "min12int2", | 
 |     "min12int2x1", | 
 |     "min12int2x2", | 
 |     "min12int2x3", | 
 |     "min12int2x4", | 
 |     "min12int3", | 
 |     "min12int3x1", | 
 |     "min12int3x2", | 
 |     "min12int3x3", | 
 |     "min12int3x4", | 
 |     "min12int4", | 
 |     "min12int4x1", | 
 |     "min12int4x2", | 
 |     "min12int4x3", | 
 |     "min12int4x4", | 
 |     "min16float", | 
 |     "min16float1", | 
 |     "min16float1x1", | 
 |     "min16float1x2", | 
 |     "min16float1x3", | 
 |     "min16float1x4", | 
 |     "min16float2", | 
 |     "min16float2x1", | 
 |     "min16float2x2", | 
 |     "min16float2x3", | 
 |     "min16float2x4", | 
 |     "min16float3", | 
 |     "min16float3x1", | 
 |     "min16float3x2", | 
 |     "min16float3x3", | 
 |     "min16float3x4", | 
 |     "min16float4", | 
 |     "min16float4x1", | 
 |     "min16float4x2", | 
 |     "min16float4x3", | 
 |     "min16float4x4", | 
 |     "min16int", | 
 |     "min16int1", | 
 |     "min16int1x1", | 
 |     "min16int1x2", | 
 |     "min16int1x3", | 
 |     "min16int1x4", | 
 |     "min16int2", | 
 |     "min16int2x1", | 
 |     "min16int2x2", | 
 |     "min16int2x3", | 
 |     "min16int2x4", | 
 |     "min16int3", | 
 |     "min16int3x1", | 
 |     "min16int3x2", | 
 |     "min16int3x3", | 
 |     "min16int3x4", | 
 |     "min16int4", | 
 |     "min16int4x1", | 
 |     "min16int4x2", | 
 |     "min16int4x3", | 
 |     "min16int4x4", | 
 |     "min16uint", | 
 |     "min16uint1", | 
 |     "min16uint1x1", | 
 |     "min16uint1x2", | 
 |     "min16uint1x3", | 
 |     "min16uint1x4", | 
 |     "min16uint2", | 
 |     "min16uint2x1", | 
 |     "min16uint2x2", | 
 |     "min16uint2x3", | 
 |     "min16uint2x4", | 
 |     "min16uint3", | 
 |     "min16uint3x1", | 
 |     "min16uint3x2", | 
 |     "min16uint3x3", | 
 |     "min16uint3x4", | 
 |     "min16uint4", | 
 |     "min16uint4x1", | 
 |     "min16uint4x2", | 
 |     "min16uint4x3", | 
 |     "min16uint4x4", | 
 |     "msad4", | 
 |     "mul", | 
 |     "mutable", | 
 |     "namespace", | 
 |     "new", | 
 |     "nointerpolation", | 
 |     "noise", | 
 |     "noperspective", | 
 |     "numthreads", | 
 |     "operator", | 
 |     "out", | 
 |     "packoffset", | 
 |     "pass", | 
 |     "pixelfragment", | 
 |     "pixelshader", | 
 |     "point", | 
 |     "precise", | 
 |     "printf", | 
 |     "private", | 
 |     "protected", | 
 |     "public", | 
 |     "radians", | 
 |     "rcp", | 
 |     "refract", | 
 |     "register", | 
 |     "reinterpret_cast", | 
 |     "return", | 
 |     "row_major", | 
 |     "rsqrt", | 
 |     "sample", | 
 |     "sampler", | 
 |     "sampler1D", | 
 |     "sampler2D", | 
 |     "sampler3D", | 
 |     "samplerCUBE", | 
 |     "sampler_state", | 
 |     "saturate", | 
 |     "shared", | 
 |     "short", | 
 |     "signed", | 
 |     "sincos", | 
 |     "sizeof", | 
 |     "snorm", | 
 |     "stateblock", | 
 |     "stateblock_state", | 
 |     "static", | 
 |     "static_cast", | 
 |     "string", | 
 |     "struct", | 
 |     "switch", | 
 |     "tbuffer", | 
 |     "technique", | 
 |     "technique10", | 
 |     "technique11", | 
 |     "template", | 
 |     "tex1D", | 
 |     "tex1Dbias", | 
 |     "tex1Dgrad", | 
 |     "tex1Dlod", | 
 |     "tex1Dproj", | 
 |     "tex2D", | 
 |     "tex2Dbias", | 
 |     "tex2Dgrad", | 
 |     "tex2Dlod", | 
 |     "tex2Dproj", | 
 |     "tex3D", | 
 |     "tex3Dbias", | 
 |     "tex3Dgrad", | 
 |     "tex3Dlod", | 
 |     "tex3Dproj", | 
 |     "texCUBE", | 
 |     "texCUBEbias", | 
 |     "texCUBEgrad", | 
 |     "texCUBElod", | 
 |     "texCUBEproj", | 
 |     "texture", | 
 |     "texture1D", | 
 |     "texture1DArray", | 
 |     "texture2D", | 
 |     "texture2DArray", | 
 |     "texture2DMS", | 
 |     "texture2DMSArray", | 
 |     "texture3D", | 
 |     "textureCube", | 
 |     "textureCubeArray", | 
 |     "this", | 
 |     "throw", | 
 |     "transpose", | 
 |     "triangle", | 
 |     "triangleadj", | 
 |     "true", | 
 |     "try", | 
 |     "typedef", | 
 |     "typename", | 
 |     "uint", | 
 |     "uint1", | 
 |     "uint1x1", | 
 |     "uint1x2", | 
 |     "uint1x3", | 
 |     "uint1x4", | 
 |     "uint2", | 
 |     "uint2x1", | 
 |     "uint2x2", | 
 |     "uint2x3", | 
 |     "uint2x4", | 
 |     "uint3", | 
 |     "uint3x1", | 
 |     "uint3x2", | 
 |     "uint3x3", | 
 |     "uint3x4", | 
 |     "uint4", | 
 |     "uint4x1", | 
 |     "uint4x2", | 
 |     "uint4x3", | 
 |     "uint4x4", | 
 |     "uniform", | 
 |     "union", | 
 |     "unorm", | 
 |     "unroll", | 
 |     "unsigned", | 
 |     "using", | 
 |     "vector", | 
 |     "vertexfragment", | 
 |     "vertexshader", | 
 |     "virtual", | 
 |     "void", | 
 |     "volatile", | 
 |     "while", | 
 | }; | 
 |  | 
 | // This list is used for a binary search and must be kept in sorted order. | 
 | const char* kReservedKeywordsMSL[] = { | 
 |     "HUGE_VALF", | 
 |     "HUGE_VALH", | 
 |     "INFINITY", | 
 |     "MAXFLOAT", | 
 |     "MAXHALF", | 
 |     "M_1_PI_F", | 
 |     "M_1_PI_H", | 
 |     "M_2_PI_F", | 
 |     "M_2_PI_H", | 
 |     "M_2_SQRTPI_F", | 
 |     "M_2_SQRTPI_H", | 
 |     "M_E_F", | 
 |     "M_E_H", | 
 |     "M_LN10_F", | 
 |     "M_LN10_H", | 
 |     "M_LN2_F", | 
 |     "M_LN2_H", | 
 |     "M_LOG10E_F", | 
 |     "M_LOG10E_H", | 
 |     "M_LOG2E_F", | 
 |     "M_LOG2E_H", | 
 |     "M_PI_2_F", | 
 |     "M_PI_2_H", | 
 |     "M_PI_4_F", | 
 |     "M_PI_4_H", | 
 |     "M_PI_F", | 
 |     "M_PI_H", | 
 |     "M_SQRT1_2_F", | 
 |     "M_SQRT1_2_H", | 
 |     "M_SQRT2_F", | 
 |     "M_SQRT2_H", | 
 |     "NAN", | 
 |     "access", | 
 |     "alignas", | 
 |     "alignof", | 
 |     "and", | 
 |     "and_eq", | 
 |     "array", | 
 |     "array_ref", | 
 |     "as_type", | 
 |     "asm", | 
 |     "atomic", | 
 |     "atomic_bool", | 
 |     "atomic_int", | 
 |     "atomic_uint", | 
 |     "auto", | 
 |     "bitand", | 
 |     "bitor", | 
 |     "bool", | 
 |     "bool2", | 
 |     "bool3", | 
 |     "bool4", | 
 |     "break", | 
 |     "buffer", | 
 |     "case", | 
 |     "catch", | 
 |     "char", | 
 |     "char16_t", | 
 |     "char2", | 
 |     "char3", | 
 |     "char32_t", | 
 |     "char4", | 
 |     "class", | 
 |     "compl", | 
 |     "const", | 
 |     "const_cast", | 
 |     "const_reference", | 
 |     "constant", | 
 |     "constexpr", | 
 |     "continue", | 
 |     "decltype", | 
 |     "default", | 
 |     "delete", | 
 |     "depth2d", | 
 |     "depth2d_array", | 
 |     "depth2d_ms", | 
 |     "depth2d_ms_array", | 
 |     "depthcube", | 
 |     "depthcube_array", | 
 |     "device", | 
 |     "discard_fragment", | 
 |     "do", | 
 |     "double", | 
 |     "dynamic_cast", | 
 |     "else", | 
 |     "enum", | 
 |     "explicit", | 
 |     "extern", | 
 |     "false", | 
 |     "final", | 
 |     "float", | 
 |     "float2", | 
 |     "float2x2", | 
 |     "float2x3", | 
 |     "float2x4", | 
 |     "float3", | 
 |     "float3x2", | 
 |     "float3x3", | 
 |     "float3x4", | 
 |     "float4", | 
 |     "float4x2", | 
 |     "float4x3", | 
 |     "float4x4", | 
 |     "for", | 
 |     "fragment", | 
 |     "friend", | 
 |     "goto", | 
 |     "half", | 
 |     "half2", | 
 |     "half2x2", | 
 |     "half2x3", | 
 |     "half2x4", | 
 |     "half3", | 
 |     "half3x2", | 
 |     "half3x3", | 
 |     "half3x4", | 
 |     "half4", | 
 |     "half4x2", | 
 |     "half4x3", | 
 |     "half4x4", | 
 |     "if", | 
 |     "imageblock", | 
 |     "infinity", | 
 |     "inline", | 
 |     "int", | 
 |     "int16_t", | 
 |     "int2", | 
 |     "int3", | 
 |     "int32_t", | 
 |     "int4", | 
 |     "int64_t", | 
 |     "int8_t", | 
 |     "kernel", | 
 |     "long", | 
 |     "long2", | 
 |     "long3", | 
 |     "long4", | 
 |     "main", | 
 |     "matrix", | 
 |     "metal", | 
 |     "mutable", | 
 |     "namespace", | 
 |     "new", | 
 |     "noexcept", | 
 |     "not", | 
 |     "not_eq", | 
 |     "nullptr", | 
 |     "operator", | 
 |     "or", | 
 |     "or_eq", | 
 |     "override", | 
 |     "packed_bool2", | 
 |     "packed_bool3", | 
 |     "packed_bool4", | 
 |     "packed_char2", | 
 |     "packed_char3", | 
 |     "packed_char4", | 
 |     "packed_float2", | 
 |     "packed_float3", | 
 |     "packed_float4", | 
 |     "packed_half2", | 
 |     "packed_half3", | 
 |     "packed_half4", | 
 |     "packed_int2", | 
 |     "packed_int3", | 
 |     "packed_int4", | 
 |     "packed_short2", | 
 |     "packed_short3", | 
 |     "packed_short4", | 
 |     "packed_uchar2", | 
 |     "packed_uchar3", | 
 |     "packed_uchar4", | 
 |     "packed_uint2", | 
 |     "packed_uint3", | 
 |     "packed_uint4", | 
 |     "packed_ushort2", | 
 |     "packed_ushort3", | 
 |     "packed_ushort4", | 
 |     "patch_control_point", | 
 |     "private", | 
 |     "protected", | 
 |     "ptrdiff_t", | 
 |     "public", | 
 |     "r16snorm", | 
 |     "r16unorm", | 
 |     "r8unorm", | 
 |     "reference", | 
 |     "register", | 
 |     "reinterpret_cast", | 
 |     "return", | 
 |     "rg11b10f", | 
 |     "rg16snorm", | 
 |     "rg16unorm", | 
 |     "rg8snorm", | 
 |     "rg8unorm", | 
 |     "rgb10a2", | 
 |     "rgb9e5", | 
 |     "rgba16snorm", | 
 |     "rgba16unorm", | 
 |     "rgba8snorm", | 
 |     "rgba8unorm", | 
 |     "sampler", | 
 |     "short", | 
 |     "short2", | 
 |     "short3", | 
 |     "short4", | 
 |     "signed", | 
 |     "size_t", | 
 |     "sizeof", | 
 |     "srgba8unorm", | 
 |     "static", | 
 |     "static_assert", | 
 |     "static_cast", | 
 |     "struct", | 
 |     "switch", | 
 |     "template", | 
 |     "texture", | 
 |     "texture1d", | 
 |     "texture1d_array", | 
 |     "texture2d", | 
 |     "texture2d_array", | 
 |     "texture2d_ms", | 
 |     "texture2d_ms_array", | 
 |     "texture3d", | 
 |     "texture_buffer", | 
 |     "texturecube", | 
 |     "texturecube_array", | 
 |     "this", | 
 |     "thread", | 
 |     "thread_local", | 
 |     "threadgroup", | 
 |     "threadgroup_imageblock", | 
 |     "throw", | 
 |     "true", | 
 |     "try", | 
 |     "typedef", | 
 |     "typeid", | 
 |     "typename", | 
 |     "uchar", | 
 |     "uchar2", | 
 |     "uchar3", | 
 |     "uchar4", | 
 |     "uint", | 
 |     "uint16_t", | 
 |     "uint2", | 
 |     "uint3", | 
 |     "uint32_t", | 
 |     "uint4", | 
 |     "uint64_t", | 
 |     "uint8_t", | 
 |     "ulong2", | 
 |     "ulong3", | 
 |     "ulong4", | 
 |     "uniform", | 
 |     "union", | 
 |     "unsigned", | 
 |     "ushort", | 
 |     "ushort2", | 
 |     "ushort3", | 
 |     "ushort4", | 
 |     "using", | 
 |     "vec", | 
 |     "vertex", | 
 |     "virtual", | 
 |     "void", | 
 |     "volatile", | 
 |     "wchar_t", | 
 |     "while", | 
 |     "xor", | 
 |     "xor_eq", | 
 | }; | 
 |  | 
 | }  // namespace | 
 |  | 
 | Renamer::Data::Data(Remappings&& r) : remappings(std::move(r)) {} | 
 | Renamer::Data::Data(const Data&) = default; | 
 | Renamer::Data::~Data() = default; | 
 |  | 
 | Renamer::Config::Config(Target t, bool pu) : target(t), preserve_unicode(pu) {} | 
 | Renamer::Config::Config(const Config&) = default; | 
 | Renamer::Config::~Config() = default; | 
 |  | 
 | Renamer::Renamer() = default; | 
 | Renamer::~Renamer() = default; | 
 |  | 
 | Transform::ApplyResult Renamer::Apply(const Program* src, | 
 |                                       const DataMap& inputs, | 
 |                                       DataMap& outputs) const { | 
 |     ProgramBuilder b; | 
 |     CloneContext ctx{&b, src, /* auto_clone_symbols */ false}; | 
 |  | 
 |     // Identifiers that need to keep their symbols preserved. | 
 |     utils::Hashset<const ast::IdentifierExpression*, 8> preserved_identifiers; | 
 |     // Type names that need to keep their symbols preserved. | 
 |     utils::Hashset<const ast::TypeName*, 8> preserved_type_names; | 
 |  | 
 |     auto is_type_short_name = [&](const Symbol& symbol) { | 
 |         auto name = src->Symbols().NameFor(symbol); | 
 |         if (type::ParseShortName(name) != type::ShortName::kUndefined) { | 
 |             // Identifier *looks* like a builtin short-name, but check the using actually | 
 |             // shadowing a short-name with a type alias. | 
 |             for (auto* decl : src->AST().TypeDecls()) { | 
 |                 if (decl->name == symbol) { | 
 |                     return false; | 
 |                 } | 
 |             } | 
 |             return true; | 
 |         } | 
 |         return false; | 
 |     }; | 
 |  | 
 |     for (auto* node : src->ASTNodes().Objects()) { | 
 |         Switch( | 
 |             node, | 
 |             [&](const ast::MemberAccessorExpression* accessor) { | 
 |                 auto* sem = src->Sem().Get(accessor)->UnwrapLoad(); | 
 |                 if (sem->Is<sem::Swizzle>()) { | 
 |                     preserved_identifiers.Add(accessor->member); | 
 |                 } else if (auto* str_expr = src->Sem().Get(accessor->structure)) { | 
 |                     if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) { | 
 |                         if (ty->Declaration() == nullptr) {  // Builtin structure | 
 |                             preserved_identifiers.Add(accessor->member); | 
 |                         } | 
 |                     } | 
 |                 } | 
 |             }, | 
 |             [&](const ast::CallExpression* call) { | 
 |                 if (auto* ident = call->target.name) { | 
 |                     Switch( | 
 |                         src->Sem().Get(call)->UnwrapMaterialize()->As<sem::Call>()->Target(), | 
 |                         [&](const sem::Builtin*) { preserved_identifiers.Add(ident); }, | 
 |                         [&](const sem::TypeConversion*) { | 
 |                             if (is_type_short_name(ident->symbol)) { | 
 |                                 preserved_identifiers.Add(ident); | 
 |                             } | 
 |                         }, | 
 |                         [&](const sem::TypeInitializer*) { | 
 |                             if (is_type_short_name(ident->symbol)) { | 
 |                                 preserved_identifiers.Add(ident); | 
 |                             } | 
 |                         }); | 
 |                 } | 
 |             }, | 
 |             [&](const ast::TypeName* type_name) { | 
 |                 if (is_type_short_name(type_name->name)) { | 
 |                     preserved_type_names.Add(type_name); | 
 |                 } | 
 |             }); | 
 |     } | 
 |  | 
 |     Data::Remappings remappings; | 
 |  | 
 |     Target target = Target::kAll; | 
 |     bool preserve_unicode = false; | 
 |  | 
 |     if (auto* cfg = inputs.Get<Config>()) { | 
 |         target = cfg->target; | 
 |         preserve_unicode = cfg->preserve_unicode; | 
 |     } | 
 |  | 
 |     ctx.ReplaceAll([&](Symbol sym_in) { | 
 |         auto name_in = src->Symbols().NameFor(sym_in); | 
 |         if (preserve_unicode || text::utf8::IsASCII(name_in)) { | 
 |             switch (target) { | 
 |                 case Target::kAll: | 
 |                     // Always rename. | 
 |                     break; | 
 |                 case Target::kGlslKeywords: | 
 |                     if (!std::binary_search(kReservedKeywordsGLSL, | 
 |                                             kReservedKeywordsGLSL + | 
 |                                                 sizeof(kReservedKeywordsGLSL) / sizeof(const char*), | 
 |                                             name_in) && | 
 |                         name_in.compare(0, 3, "gl_")) { | 
 |                         // No match, just reuse the original name. | 
 |                         return ctx.dst->Symbols().New(name_in); | 
 |                     } | 
 |                     break; | 
 |                 case Target::kHlslKeywords: | 
 |                     if (!std::binary_search(kReservedKeywordsHLSL, | 
 |                                             kReservedKeywordsHLSL + | 
 |                                                 sizeof(kReservedKeywordsHLSL) / sizeof(const char*), | 
 |                                             name_in)) { | 
 |                         // No match, just reuse the original name. | 
 |                         return ctx.dst->Symbols().New(name_in); | 
 |                     } | 
 |                     break; | 
 |                 case Target::kMslKeywords: | 
 |                     if (!std::binary_search(kReservedKeywordsMSL, | 
 |                                             kReservedKeywordsMSL + | 
 |                                                 sizeof(kReservedKeywordsMSL) / sizeof(const char*), | 
 |                                             name_in)) { | 
 |                         // No match, just reuse the original name. | 
 |                         return ctx.dst->Symbols().New(name_in); | 
 |                     } | 
 |                     break; | 
 |             } | 
 |         } | 
 |  | 
 |         auto sym_out = ctx.dst->Sym(); | 
 |         remappings.emplace(name_in, ctx.dst->Symbols().NameFor(sym_out)); | 
 |         return sym_out; | 
 |     }); | 
 |  | 
 |     ctx.ReplaceAll([&](const ast::IdentifierExpression* ident) -> const ast::IdentifierExpression* { | 
 |         if (preserved_identifiers.Contains(ident)) { | 
 |             auto sym_in = ident->symbol; | 
 |             auto str = src->Symbols().NameFor(sym_in); | 
 |             auto sym_out = b.Symbols().Register(str); | 
 |             return ctx.dst->create<ast::IdentifierExpression>(ctx.Clone(ident->source), sym_out); | 
 |         } | 
 |         return nullptr;  // Clone ident. Uses the symbol remapping above. | 
 |     }); | 
 |  | 
 |     ctx.ReplaceAll([&](const ast::TypeName* type_name) -> const ast::TypeName* { | 
 |         if (preserved_type_names.Contains(type_name)) { | 
 |             auto sym_in = type_name->name; | 
 |             auto str = src->Symbols().NameFor(sym_in); | 
 |             auto sym_out = b.Symbols().Register(str); | 
 |             return ctx.dst->create<ast::TypeName>(ctx.Clone(type_name->source), sym_out); | 
 |         } | 
 |         return nullptr;  // Clone ident. Uses the symbol remapping above. | 
 |     }); | 
 |  | 
 |     ctx.Clone();  // Must come before the std::move() | 
 |  | 
 |     outputs.Add<Data>(std::move(remappings)); | 
 |  | 
 |     return Program(std::move(b)); | 
 | } | 
 |  | 
 | }  // namespace tint::transform |