WebKit Bugzilla
Attachment 370289 Details for
Bug 198059
: WHLSL: Add an AST dumper
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
b-backup.diff (text/plain), 39.14 KB, created by
Saam Barati
on 2019-05-20 18:36:00 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-05-20 18:36:00 PDT
Size:
39.14 KB
patch
obsolete
>Index: Source/WebCore/Sources.txt >=================================================================== >--- Source/WebCore/Sources.txt (revision 245539) >+++ Source/WebCore/Sources.txt (working copy) >@@ -306,6 +306,7 @@ Modules/websockets/WorkerThreadableWebSo > > Modules/webgpu/GPUCanvasContext.cpp > Modules/webgpu/NavigatorGPU.cpp >+Modules/webgpu/WHLSL/WHLSLASTDumper.cpp > Modules/webgpu/WHLSL/WHLSLInferTypes.cpp > Modules/webgpu/WHLSL/WHLSLLexer.cpp > Modules/webgpu/WHLSL/WHLSLParser.cpp >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp (nonexistent) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp (working copy) >@@ -0,0 +1,590 @@ >+#include "config.h" >+#include "WHLSLASTDumper.h" >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLAST.h" >+#include "WHLSLProgram.h" >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+void ASTDumper::visit(Program& program) >+{ >+ m_out.println("\\start PROGRAM"); >+ Base::visit(program); >+ m_out.println("\n\\end PROGRAM"); >+} >+ >+void ASTDumper::visit(AST::UnnamedType& unnamedType) >+{ >+ Base::visit(unnamedType); >+ /* >+ if (is<AST::TypeReference>(unnamedType)) >+ checkErrorAndVisit(downcast<AST::TypeReference>(unnamedType)); >+ else if (is<AST::PointerType>(unnamedType)) >+ checkErrorAndVisit(downcast<AST::PointerType>(unnamedType)); >+ else if (is<AST::ArrayReferenceType>(unnamedType)) >+ checkErrorAndVisit(downcast<AST::ArrayReferenceType>(unnamedType)); >+ else { >+ ASSERT(is<AST::ArrayType>(unnamedType)); >+ checkErrorAndVisit(downcast<AST::ArrayType>(unnamedType)); >+ } >+ */ >+} >+ >+void ASTDumper::visit(AST::NamedType& namedType) >+{ >+ Base::visit(namedType); >+ /* >+ if (is<AST::TypeDefinition>(namedType)) >+ checkErrorAndVisit(downcast<AST::TypeDefinition>(namedType)); >+ else if (is<AST::StructureDefinition>(namedType)) >+ checkErrorAndVisit(downcast<AST::StructureDefinition>(namedType)); >+ else if (is<AST::EnumerationDefinition>(namedType)) >+ checkErrorAndVisit(downcast<AST::EnumerationDefinition>(namedType)); >+ else { >+ ASSERT(is<AST::NativeTypeDeclaration>(namedType)); >+ checkErrorAndVisit(downcast<AST::NativeTypeDeclaration>(namedType)); >+ } >+ */ >+} >+ >+void ASTDumper::visit(AST::TypeDefinition& typeDefinition) >+{ >+ Base::visit(typeDefinition); >+ //checkErrorAndVisit(typeDefinition.type()); >+} >+ >+void ASTDumper::visit(AST::StructureDefinition& structureDefinition) >+{ >+ m_out.println(m_indent, "struct ", structureDefinition.name(), " {"); >+ { >+ auto indent = bumpIndent(); >+ for (auto& structureElement : structureDefinition.structureElements()) >+ visit(structureElement); >+ } >+ m_out.println(m_indent, "}"); >+} >+ >+void ASTDumper::visit(AST::EnumerationDefinition& enumerationDefinition) >+{ >+ checkErrorAndVisit(enumerationDefinition.type()); >+ for (auto& enumerationMember : enumerationDefinition.enumerationMembers()) >+ checkErrorAndVisit(enumerationMember); >+} >+ >+void ASTDumper::visit(AST::FunctionDefinition& functionDefinition) >+{ >+ checkErrorAndVisit(static_cast<AST::FunctionDeclaration&>(functionDefinition)); >+ checkErrorAndVisit(functionDefinition.block()); >+} >+ >+void ASTDumper::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration) >+{ >+ checkErrorAndVisit(static_cast<AST::FunctionDeclaration&>(nativeFunctionDeclaration)); >+} >+ >+void ASTDumper::visit(AST::NativeTypeDeclaration& nativeTypeDeclaration) >+{ >+ dataLogLn("native type declaration!"); >+ m_out.print(nativeTypeDeclaration.name()); >+ //for (auto& typeArgument : nativeTypeDeclaration.typeArguments()) >+ // checkErrorAndVisit(typeArgument); >+} >+ >+void ASTDumper::visit(AST::TypeReference& typeReference) >+{ >+ m_out.print(typeReference.name()); >+ >+ for (auto& typeArgument : typeReference.typeArguments()) >+ checkErrorAndVisit(typeArgument); >+ if (typeReference.resolvedType() && is<AST::TypeDefinition>(*typeReference.resolvedType())) { >+ auto& typeDefinition = downcast<AST::TypeDefinition>(*typeReference.resolvedType()); >+ checkErrorAndVisit(typeDefinition.type()); >+ } >+} >+ >+void ASTDumper::visit(AST::PointerType& pointerType) >+{ >+ checkErrorAndVisit(static_cast<AST::ReferenceType&>(pointerType)); >+} >+ >+void ASTDumper::visit(AST::ArrayReferenceType& arrayReferenceType) >+{ >+ checkErrorAndVisit(static_cast<AST::ReferenceType&>(arrayReferenceType)); >+} >+ >+void ASTDumper::visit(AST::ArrayType& arrayType) >+{ >+ checkErrorAndVisit(arrayType.type()); >+} >+ >+void ASTDumper::visit(AST::StructureElement& structureElement) >+{ >+ m_out.print(m_indent); >+ visit(structureElement.type()); >+ m_out.print(" ", structureElement.name()); >+ if (structureElement.semantic()) >+ visit(*structureElement.semantic()); >+ m_out.println(";"); >+} >+ >+void ASTDumper::visit(AST::EnumerationMember& enumerationMember) >+{ >+ if (enumerationMember.value()) >+ checkErrorAndVisit(*enumerationMember.value()); >+} >+ >+void ASTDumper::visit(AST::FunctionDeclaration& functionDeclaration) >+{ >+ //checkErrorAndVisit(functionDeclaration.attributeBlock()); >+ m_out.print(m_indent); >+ visit(functionDeclaration.type()); >+ m_out.print(" ", functionDeclaration.name(), "("); >+ bool hadPrevious = false; >+ for (auto& parameter : functionDeclaration.parameters()) { >+ if (hadPrevious) >+ m_out.print(", "); >+ hadPrevious = true; >+ visit(parameter); >+ } >+ m_out.print(") "); >+ if (functionDeclaration.semantic()) { >+ visit(*functionDeclaration.semantic()); >+ m_out.print(" "); >+ } >+} >+ >+void ASTDumper::visit(AST::TypeArgument& typeArgument) >+{ >+ WTF::visit(WTF::makeVisitor([&](AST::ConstantExpression& constantExpression) { >+ checkErrorAndVisit(constantExpression); >+ }, [&](UniqueRef<AST::TypeReference>& typeReference) { >+ checkErrorAndVisit(typeReference); >+ }), typeArgument); >+} >+ >+void ASTDumper::visit(AST::ReferenceType& referenceType) >+{ >+ checkErrorAndVisit(referenceType.elementType()); >+} >+ >+void ASTDumper::visit(AST::Semantic& semantic) >+{ >+ m_out.print(" : "); >+ WTF::visit(WTF::makeVisitor([&](AST::BuiltInSemantic& builtInSemantic) { >+ visit(builtInSemantic); >+ }, [&](AST::ResourceSemantic& resourceSemantic) { >+ visit(resourceSemantic); >+ }, [&](AST::SpecializationConstantSemantic& specializationConstantSemantic) { >+ visit(specializationConstantSemantic); >+ }, [&](AST::StageInOutSemantic& stageInOutSemantic) { >+ visit(stageInOutSemantic); >+ }), semantic); >+} >+ >+void ASTDumper::visit(AST::ConstantExpression& constantExpression) >+{ >+ constantExpression.visit(WTF::makeVisitor([&](AST::IntegerLiteral& integerLiteral) { >+ visit(integerLiteral); >+ }, [&](AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) { >+ visit(unsignedIntegerLiteral); >+ }, [&](AST::FloatLiteral& floatLiteral) { >+ visit(floatLiteral); >+ }, [&](AST::NullLiteral& nullLiteral) { >+ visit(nullLiteral); >+ }, [&](AST::BooleanLiteral& booleanLiteral) { >+ visit(booleanLiteral); >+ }, [&](AST::EnumerationMemberLiteral& enumerationMemberLiteral) { >+ visit(enumerationMemberLiteral); >+ })); >+} >+ >+void ASTDumper::visit(AST::AttributeBlock& attributeBlock) >+{ >+ for (auto& functionAttribute : attributeBlock) >+ checkErrorAndVisit(functionAttribute); >+} >+ >+void ASTDumper::visit(AST::BuiltInSemantic& builtInSemantic) >+{ >+ m_out.print(builtInSemantic.toString()); >+} >+ >+void ASTDumper::visit(AST::ResourceSemantic& resourceSemantic) >+{ >+ m_out.print(resourceSemantic.toString()); >+} >+ >+void ASTDumper::visit(AST::SpecializationConstantSemantic&) >+{ >+ // OOPS! >+} >+ >+void ASTDumper::visit(AST::StageInOutSemantic&) >+{ >+ // OOPS! >+} >+ >+void ASTDumper::visit(AST::IntegerLiteral& integerLiteral) >+{ >+ m_out.print(integerLiteral.value()); >+ //checkErrorAndVisit(integerLiteral.type()); >+} >+ >+void ASTDumper::visit(AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) >+{ >+ m_out.print(unsignedIntegerLiteral.value()); >+ //checkErrorAndVisit(unsignedIntegerLiteral.type()); >+} >+ >+void ASTDumper::visit(AST::FloatLiteral& floatLiteral) >+{ >+ m_out.print(floatLiteral.value()); >+ //checkErrorAndVisit(floatLiteral.type()); >+} >+ >+void ASTDumper::visit(AST::NullLiteral& nullLiteral) >+{ >+ m_out.print("null"); >+ checkErrorAndVisit(nullLiteral.type()); >+} >+ >+void ASTDumper::visit(AST::BooleanLiteral&) >+{ >+} >+ >+void ASTDumper::visit(AST::IntegerLiteralType& integerLiteralType) >+{ >+ dataLogLn("integer literal type!"); >+ if (integerLiteralType.resolvedType()) >+ checkErrorAndVisit(*integerLiteralType.resolvedType()); >+ checkErrorAndVisit(integerLiteralType.preferredType()); >+} >+ >+void ASTDumper::visit(AST::UnsignedIntegerLiteralType& unsignedIntegerLiteralType) >+{ >+ if (unsignedIntegerLiteralType.resolvedType()) >+ checkErrorAndVisit(*unsignedIntegerLiteralType.resolvedType()); >+ checkErrorAndVisit(unsignedIntegerLiteralType.preferredType()); >+} >+ >+void ASTDumper::visit(AST::FloatLiteralType& floatLiteralType) >+{ >+ if (floatLiteralType.resolvedType()) >+ checkErrorAndVisit(*floatLiteralType.resolvedType()); >+ checkErrorAndVisit(floatLiteralType.preferredType()); >+} >+ >+void ASTDumper::visit(AST::NullLiteralType& nullLiteralType) >+{ >+ if (nullLiteralType.resolvedType()) >+ checkErrorAndVisit(*nullLiteralType.resolvedType()); >+} >+ >+void ASTDumper::visit(AST::EnumerationMemberLiteral&) >+{ >+} >+ >+void ASTDumper::visit(AST::FunctionAttribute& functionAttribute) >+{ >+ WTF::visit(WTF::makeVisitor([&](AST::NumThreadsFunctionAttribute& numThreadsFunctionAttribute) { >+ checkErrorAndVisit(numThreadsFunctionAttribute); >+ }), functionAttribute); >+} >+ >+void ASTDumper::visit(AST::NumThreadsFunctionAttribute&) >+{ >+} >+ >+void ASTDumper::visit(AST::Block& block) >+{ >+ m_out.println("{"); >+ { >+ auto indent = bumpIndent(); >+ for (auto& statement : block.statements()) { >+ checkErrorAndVisit(statement); >+ } >+ } >+ m_out.print(m_indent, "}"); >+} >+ >+void ASTDumper::visit(AST::Statement& statement) >+{ >+ m_out.print(m_indent); >+ Base::visit(statement); >+ m_out.println(";"); >+ /* >+ if (is<AST::Block>(statement)) >+ checkErrorAndVisit(downcast<AST::Block>(statement)); >+ else if (is<AST::Break>(statement)) >+ checkErrorAndVisit(downcast<AST::Break>(statement)); >+ else if (is<AST::Continue>(statement)) >+ checkErrorAndVisit(downcast<AST::Continue>(statement)); >+ else if (is<AST::DoWhileLoop>(statement)) >+ checkErrorAndVisit(downcast<AST::DoWhileLoop>(statement)); >+ else if (is<AST::EffectfulExpressionStatement>(statement)) >+ checkErrorAndVisit(downcast<AST::EffectfulExpressionStatement>(statement)); >+ else if (is<AST::Fallthrough>(statement)) >+ checkErrorAndVisit(downcast<AST::Fallthrough>(statement)); >+ else if (is<AST::ForLoop>(statement)) >+ checkErrorAndVisit(downcast<AST::ForLoop>(statement)); >+ else if (is<AST::IfStatement>(statement)) >+ checkErrorAndVisit(downcast<AST::IfStatement>(statement)); >+ else if (is<AST::Return>(statement)) >+ checkErrorAndVisit(downcast<AST::Return>(statement)); >+ else if (is<AST::SwitchCase>(statement)) >+ checkErrorAndVisit(downcast<AST::SwitchCase>(statement)); >+ else if (is<AST::SwitchStatement>(statement)) >+ checkErrorAndVisit(downcast<AST::SwitchStatement>(statement)); >+ else if (is<AST::Trap>(statement)) >+ checkErrorAndVisit(downcast<AST::Trap>(statement)); >+ else if (is<AST::VariableDeclarationsStatement>(statement)) >+ checkErrorAndVisit(downcast<AST::VariableDeclarationsStatement>(statement)); >+ else { >+ ASSERT(is<AST::WhileLoop>(statement)); >+ checkErrorAndVisit(downcast<AST::WhileLoop>(statement)); >+ } >+ */ >+} >+ >+void ASTDumper::visit(AST::Break&) >+{ >+ m_out.print("break"); >+} >+ >+void ASTDumper::visit(AST::Continue&) >+{ >+ m_out.print("continue"); >+} >+ >+void ASTDumper::visit(AST::DoWhileLoop& doWhileLoop) >+{ >+ checkErrorAndVisit(doWhileLoop.body()); >+ checkErrorAndVisit(doWhileLoop.conditional()); >+} >+ >+void ASTDumper::visit(AST::Expression& expression) >+{ >+ Base::visit(expression); >+ /* >+ if (is<AST::AssignmentExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::AssignmentExpression>(expression)); >+ else if (is<AST::BooleanLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::BooleanLiteral>(expression)); >+ else if (is<AST::CallExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::CallExpression>(expression)); >+ else if (is<AST::CommaExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::CommaExpression>(expression)); >+ else if (is<AST::DereferenceExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::DereferenceExpression>(expression)); >+ else if (is<AST::FloatLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::FloatLiteral>(expression)); >+ else if (is<AST::IntegerLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::IntegerLiteral>(expression)); >+ else if (is<AST::LogicalExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::LogicalExpression>(expression)); >+ else if (is<AST::LogicalNotExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::LogicalNotExpression>(expression)); >+ else if (is<AST::MakeArrayReferenceExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::MakeArrayReferenceExpression>(expression)); >+ else if (is<AST::MakePointerExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::MakePointerExpression>(expression)); >+ else if (is<AST::NullLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::NullLiteral>(expression)); >+ else if (is<AST::DotExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::DotExpression>(expression)); >+ else if (is<AST::IndexExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::IndexExpression>(expression)); >+ else if (is<AST::ReadModifyWriteExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::ReadModifyWriteExpression>(expression)); >+ else if (is<AST::TernaryExpression>(expression)) >+ checkErrorAndVisit(downcast<AST::TernaryExpression>(expression)); >+ else if (is<AST::UnsignedIntegerLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::UnsignedIntegerLiteral>(expression)); >+ else if (is<AST::EnumerationMemberLiteral>(expression)) >+ checkErrorAndVisit(downcast<AST::EnumerationMemberLiteral>(expression)); >+ else { >+ ASSERT(is<AST::VariableReference>(expression)); >+ checkErrorAndVisit(downcast<AST::VariableReference>(expression)); >+ } >+ */ >+} >+ >+void ASTDumper::visit(AST::DotExpression& dotExpression) >+{ >+ checkErrorAndVisit(static_cast<AST::PropertyAccessExpression&>(dotExpression)); >+} >+ >+void ASTDumper::visit(AST::IndexExpression& indexExpression) >+{ >+ checkErrorAndVisit(indexExpression.indexExpression()); >+ checkErrorAndVisit(static_cast<AST::PropertyAccessExpression&>(indexExpression)); >+} >+ >+void ASTDumper::visit(AST::PropertyAccessExpression& expression) >+{ >+ checkErrorAndVisit(expression.base()); >+} >+ >+void ASTDumper::visit(AST::EffectfulExpressionStatement& effectfulExpressionStatement) >+{ >+ checkErrorAndVisit(effectfulExpressionStatement.effectfulExpression()); >+} >+ >+void ASTDumper::visit(AST::Fallthrough&) >+{ >+} >+ >+void ASTDumper::visit(AST::ForLoop& forLoop) >+{ >+ WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >+ checkErrorAndVisit(variableDeclarationsStatement); >+ }, [&](UniqueRef<AST::Expression>& expression) { >+ checkErrorAndVisit(expression); >+ }), forLoop.initialization()); >+ if (forLoop.condition()) >+ checkErrorAndVisit(*forLoop.condition()); >+ if (forLoop.increment()) >+ checkErrorAndVisit(*forLoop.increment()); >+ checkErrorAndVisit(forLoop.body()); >+} >+ >+void ASTDumper::visit(AST::IfStatement& ifStatement) >+{ >+ checkErrorAndVisit(ifStatement.conditional()); >+ checkErrorAndVisit(ifStatement.body()); >+ if (ifStatement.elseBody()) >+ checkErrorAndVisit(*ifStatement.elseBody()); >+} >+ >+void ASTDumper::visit(AST::Return& returnStatement) >+{ >+ m_out.print("return"); >+ if (returnStatement.value()) { >+ m_out.print(" "); >+ checkErrorAndVisit(*returnStatement.value()); >+ } >+} >+ >+void ASTDumper::visit(AST::SwitchCase& switchCase) >+{ >+ if (switchCase.value()) >+ checkErrorAndVisit(*switchCase.value()); >+ checkErrorAndVisit(switchCase.block()); >+} >+ >+void ASTDumper::visit(AST::SwitchStatement& switchStatement) >+{ >+ checkErrorAndVisit(switchStatement.value()); >+ for (auto& switchCase : switchStatement.switchCases()) >+ checkErrorAndVisit(switchCase); >+} >+ >+void ASTDumper::visit(AST::Trap&) >+{ >+} >+ >+void ASTDumper::visit(AST::VariableDeclarationsStatement& variableDeclarationsStatement) >+{ >+ for (auto& variableDeclaration : variableDeclarationsStatement.variableDeclarations()) >+ checkErrorAndVisit(variableDeclaration); >+} >+ >+void ASTDumper::visit(AST::WhileLoop& whileLoop) >+{ >+ checkErrorAndVisit(whileLoop.conditional()); >+ checkErrorAndVisit(whileLoop.body()); >+} >+ >+void ASTDumper::visit(AST::VariableDeclaration& variableDeclaration) >+{ >+ if (variableDeclaration.type()) { >+ checkErrorAndVisit(*variableDeclaration.type()); >+ m_out.print(" "); >+ } >+ m_out.print(variableDeclaration.name()); >+ if (variableDeclaration.semantic()) >+ visit(*variableDeclaration.semantic()); >+ if (variableDeclaration.initializer()) { >+ m_out.print(" = "); >+ checkErrorAndVisit(*variableDeclaration.initializer()); >+ } >+} >+ >+void ASTDumper::visit(AST::AssignmentExpression& assignmentExpression) >+{ >+ checkErrorAndVisit(assignmentExpression.left()); >+ checkErrorAndVisit(assignmentExpression.right()); >+} >+ >+void ASTDumper::visit(AST::CallExpression& callExpression) >+{ >+ for (auto& argument : callExpression.arguments()) >+ checkErrorAndVisit(argument); >+ if (callExpression.castReturnType()) >+ checkErrorAndVisit(*callExpression.castReturnType()); >+} >+ >+void ASTDumper::visit(AST::CommaExpression& commaExpression) >+{ >+ for (auto& expression : commaExpression.list()) >+ checkErrorAndVisit(expression); >+} >+ >+void ASTDumper::visit(AST::DereferenceExpression& dereferenceExpression) >+{ >+ checkErrorAndVisit(dereferenceExpression.pointer()); >+} >+ >+void ASTDumper::visit(AST::LogicalExpression& logicalExpression) >+{ >+ checkErrorAndVisit(logicalExpression.left()); >+ checkErrorAndVisit(logicalExpression.right()); >+} >+ >+void ASTDumper::visit(AST::LogicalNotExpression& logicalNotExpression) >+{ >+ checkErrorAndVisit(logicalNotExpression.operand()); >+} >+ >+void ASTDumper::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) >+{ >+ checkErrorAndVisit(makeArrayReferenceExpression.lValue()); >+} >+ >+void ASTDumper::visit(AST::MakePointerExpression& makePointerExpression) >+{ >+ checkErrorAndVisit(makePointerExpression.lValue()); >+} >+ >+void ASTDumper::visit(AST::ReadModifyWriteExpression& readModifyWriteExpression) >+{ >+ checkErrorAndVisit(readModifyWriteExpression.lValue()); >+ checkErrorAndVisit(readModifyWriteExpression.oldValue()); >+ checkErrorAndVisit(readModifyWriteExpression.newValue()); >+ if (readModifyWriteExpression.newValueExpression()) >+ checkErrorAndVisit(*readModifyWriteExpression.newValueExpression()); >+ if (readModifyWriteExpression.resultExpression()) >+ checkErrorAndVisit(*readModifyWriteExpression.resultExpression()); >+} >+ >+void ASTDumper::visit(AST::TernaryExpression& ternaryExpression) >+{ >+ checkErrorAndVisit(ternaryExpression.predicate()); >+ checkErrorAndVisit(ternaryExpression.bodyExpression()); >+ checkErrorAndVisit(ternaryExpression.elseExpression()); >+} >+ >+void ASTDumper::visit(AST::VariableReference& variableReference) >+{ >+ m_out.print(variableReference.name()); >+} >+ >+} // namespace WHLSL >+ >+} // namespace WebCore >+ >+#endif >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h (nonexistent) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h (working copy) >@@ -0,0 +1,133 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLVisitor.h" >+ >+#include <wtf/SetForScope.h> >+#include <wtf/StringPrintStream.h> >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class ASTDumper : Visitor { >+ using Base = Visitor; >+public: >+ void visit(Program&) override; >+ void visit(AST::UnnamedType&) override; >+ void visit(AST::NamedType&) override; >+ void visit(AST::TypeDefinition&) override; >+ void visit(AST::StructureDefinition&) override; >+ void visit(AST::EnumerationDefinition&) override; >+ void visit(AST::FunctionDefinition&) override; >+ void visit(AST::NativeFunctionDeclaration&) override; >+ void visit(AST::NativeTypeDeclaration&) override; >+ void visit(AST::TypeReference&) override; >+ void visit(AST::PointerType&) override; >+ void visit(AST::ArrayReferenceType&) override; >+ void visit(AST::ArrayType&) override; >+ void visit(AST::StructureElement&) override; >+ void visit(AST::EnumerationMember&) override; >+ void visit(AST::FunctionDeclaration&) override; >+ void visit(AST::TypeArgument&) override; >+ void visit(AST::ReferenceType&) override; >+ void visit(AST::Semantic&) override; >+ void visit(AST::ConstantExpression&) override; >+ void visit(AST::AttributeBlock&) override; >+ void visit(AST::BuiltInSemantic&) override; >+ void visit(AST::ResourceSemantic&) override; >+ void visit(AST::SpecializationConstantSemantic&) override; >+ void visit(AST::StageInOutSemantic&) override; >+ void visit(AST::IntegerLiteral&) override; >+ void visit(AST::UnsignedIntegerLiteral&) override; >+ void visit(AST::FloatLiteral&) override; >+ void visit(AST::NullLiteral&) override; >+ void visit(AST::BooleanLiteral&) override; >+ void visit(AST::IntegerLiteralType&) override; >+ void visit(AST::UnsignedIntegerLiteralType&) override; >+ void visit(AST::FloatLiteralType&) override; >+ void visit(AST::NullLiteralType&) override; >+ void visit(AST::EnumerationMemberLiteral&) override; >+ void visit(AST::FunctionAttribute&) override; >+ void visit(AST::NumThreadsFunctionAttribute&) override; >+ void visit(AST::Block&) override; >+ void visit(AST::Statement&) override; >+ void visit(AST::Break&) override; >+ void visit(AST::Continue&) override; >+ void visit(AST::DoWhileLoop&) override; >+ void visit(AST::Expression&) override; >+ void visit(AST::DotExpression&) override; >+ void visit(AST::IndexExpression&) override; >+ void visit(AST::PropertyAccessExpression&) override; >+ void visit(AST::EffectfulExpressionStatement&) override; >+ void visit(AST::Fallthrough&) override; >+ void visit(AST::ForLoop&) override; >+ void visit(AST::IfStatement&) override; >+ void visit(AST::Return&) override; >+ void visit(AST::SwitchCase&) override; >+ void visit(AST::SwitchStatement&) override; >+ void visit(AST::Trap&) override; >+ void visit(AST::VariableDeclarationsStatement&) override; >+ void visit(AST::WhileLoop&) override; >+ void visit(AST::VariableDeclaration&) override; >+ void visit(AST::AssignmentExpression&) override; >+ void visit(AST::CallExpression&) override; >+ void visit(AST::CommaExpression&) override; >+ void visit(AST::DereferenceExpression&) override; >+ void visit(AST::LogicalExpression&) override; >+ void visit(AST::LogicalNotExpression&) override; >+ void visit(AST::MakeArrayReferenceExpression&) override; >+ void visit(AST::MakePointerExpression&) override; >+ void visit(AST::ReadModifyWriteExpression&) override; >+ void visit(AST::TernaryExpression&) override; >+ void visit(AST::VariableReference&) override; >+ >+ String toString() { return m_out.toString(); } >+ >+private: >+ struct Indent { >+ Indent(ASTDumper& dumper) >+ : m_scope(dumper.m_indent, dumper.m_indent + " ") >+ { } >+ SetForScope<String> m_scope; >+ }; >+ >+ Indent bumpIndent() { return Indent(*this); } >+ >+ friend struct Indent; >+ >+ StringPrintStream m_out; >+ String m_indent; >+}; >+ >+} // namespace WHLSL >+ >+} // namespace WebCore >+ >+#endif // ENABLE(WEBGPU) >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (revision 245539) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (working copy) >@@ -46,8 +46,11 @@ > #include "WHLSLSynthesizeConstructors.h" > #include "WHLSLSynthesizeEnumerationFunctions.h" > #include "WHLSLSynthesizeStructureAccessors.h" >+#include <wtf/DataLog.h> > #include <wtf/Optional.h> > >+#include "WHLSLASTDumper.h" >+ > namespace WebCore { > > namespace WHLSL { >@@ -56,11 +59,17 @@ static Optional<Program> prepareShared(S > { > Program program; > Parser parser; >- auto standardLibrary = String::fromUTF8(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary)); >- auto failure = static_cast<bool>(parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary)); >- ASSERT_UNUSED(failure, !failure); >+ //auto standardLibrary = String::fromUTF8(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary)); >+ //auto failure = static_cast<bool>(parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary)); >+ //ASSERT_UNUSED(failure, !failure); > if (parser.parse(program, whlslSource, Parser::Mode::User)) > return WTF::nullopt; >+ >+ ASTDumper dumper; >+ dumper.visit(program); >+ dataLogLn(dumper.toString()); >+ return WTF::nullopt; >+ > NameResolver nameResolver(program.nameContext()); > if (!resolveNamesInTypes(program, nameResolver)) > return WTF::nullopt; >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp (revision 245539) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp (working copy) >@@ -28,73 +28,7 @@ > > #if ENABLE(WEBGPU) > >-#include "WHLSLArrayReferenceType.h" >-#include "WHLSLArrayType.h" >-#include "WHLSLAssignmentExpression.h" >-#include "WHLSLBaseFunctionAttribute.h" >-#include "WHLSLBaseSemantic.h" >-#include "WHLSLBlock.h" >-#include "WHLSLBooleanLiteral.h" >-#include "WHLSLBreak.h" >-#include "WHLSLBuiltInSemantic.h" >-#include "WHLSLCallExpression.h" >-#include "WHLSLCommaExpression.h" >-#include "WHLSLConstantExpression.h" >-#include "WHLSLContinue.h" >-#include "WHLSLDereferenceExpression.h" >-#include "WHLSLDoWhileLoop.h" >-#include "WHLSLDotExpression.h" >-#include "WHLSLEffectfulExpressionStatement.h" >-#include "WHLSLEnumerationDefinition.h" >-#include "WHLSLEnumerationMember.h" >-#include "WHLSLEnumerationMemberLiteral.h" >-#include "WHLSLExpression.h" >-#include "WHLSLFallthrough.h" >-#include "WHLSLFloatLiteral.h" >-#include "WHLSLForLoop.h" >-#include "WHLSLFunctionAttribute.h" >-#include "WHLSLFunctionDeclaration.h" >-#include "WHLSLFunctionDefinition.h" >-#include "WHLSLIfStatement.h" >-#include "WHLSLIndexExpression.h" >-#include "WHLSLIntegerLiteral.h" >-#include "WHLSLLogicalExpression.h" >-#include "WHLSLLogicalNotExpression.h" >-#include "WHLSLMakeArrayReferenceExpression.h" >-#include "WHLSLMakePointerExpression.h" >-#include "WHLSLNativeFunctionDeclaration.h" >-#include "WHLSLNativeTypeDeclaration.h" >-#include "WHLSLNode.h" >-#include "WHLSLNullLiteral.h" >-#include "WHLSLNumThreadsFunctionAttribute.h" >-#include "WHLSLPointerType.h" >-#include "WHLSLProgram.h" >-#include "WHLSLPropertyAccessExpression.h" >-#include "WHLSLQualifier.h" >-#include "WHLSLReadModifyWriteExpression.h" >-#include "WHLSLReferenceType.h" >-#include "WHLSLResourceSemantic.h" >-#include "WHLSLReturn.h" >-#include "WHLSLSemantic.h" >-#include "WHLSLSpecializationConstantSemantic.h" >-#include "WHLSLStageInOutSemantic.h" >-#include "WHLSLStatement.h" >-#include "WHLSLStructureDefinition.h" >-#include "WHLSLStructureElement.h" >-#include "WHLSLSwitchCase.h" >-#include "WHLSLSwitchStatement.h" >-#include "WHLSLTernaryExpression.h" >-#include "WHLSLTrap.h" >-#include "WHLSLType.h" >-#include "WHLSLTypeArgument.h" >-#include "WHLSLTypeDefinition.h" >-#include "WHLSLTypeReference.h" >-#include "WHLSLUnsignedIntegerLiteral.h" >-#include "WHLSLValue.h" >-#include "WHLSLVariableDeclaration.h" >-#include "WHLSLVariableDeclarationsStatement.h" >-#include "WHLSLVariableReference.h" >-#include "WHLSLWhileLoop.h" >+#include "WHLSLAST.h" > > namespace WebCore { > >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h (nonexistent) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h (working copy) >@@ -0,0 +1,106 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLAddressSpace.h" >+#include "WHLSLArrayReferenceType.h" >+#include "WHLSLArrayType.h" >+#include "WHLSLAssignmentExpression.h" >+#include "WHLSLBaseFunctionAttribute.h" >+#include "WHLSLBaseSemantic.h" >+#include "WHLSLBlock.h" >+#include "WHLSLBooleanLiteral.h" >+#include "WHLSLBreak.h" >+#include "WHLSLBuiltInSemantic.h" >+#include "WHLSLCallExpression.h" >+#include "WHLSLCommaExpression.h" >+#include "WHLSLConstantExpression.h" >+#include "WHLSLContinue.h" >+#include "WHLSLDereferenceExpression.h" >+#include "WHLSLDotExpression.h" >+#include "WHLSLDoWhileLoop.h" >+#include "WHLSLEffectfulExpressionStatement.h" >+#include "WHLSLEntryPointType.h" >+#include "WHLSLEnumerationDefinition.h" >+#include "WHLSLEnumerationMember.h" >+#include "WHLSLEnumerationMemberLiteral.h" >+#include "WHLSLExpression.h" >+#include "WHLSLFallthrough.h" >+#include "WHLSLFloatLiteral.h" >+#include "WHLSLFloatLiteralType.h" >+#include "WHLSLForLoop.h" >+#include "WHLSLFunctionAttribute.h" >+#include "WHLSLFunctionDeclaration.h" >+#include "WHLSLFunctionDefinition.h" >+#include "WHLSLIfStatement.h" >+#include "WHLSLIndexExpression.h" >+#include "WHLSLIntegerLiteral.h" >+#include "WHLSLIntegerLiteralType.h" >+#include "WHLSLLogicalExpression.h" >+#include "WHLSLLogicalNotExpression.h" >+#include "WHLSLMakeArrayReferenceExpression.h" >+#include "WHLSLMakePointerExpression.h" >+#include "WHLSLNamedType.h" >+#include "WHLSLNativeFunctionDeclaration.h" >+#include "WHLSLNativeTypeDeclaration.h" >+#include "WHLSLNode.h" >+#include "WHLSLNullLiteral.h" >+#include "WHLSLNullLiteralType.h" >+#include "WHLSLNumThreadsFunctionAttribute.h" >+#include "WHLSLPointerType.h" >+#include "WHLSLPropertyAccessExpression.h" >+#include "WHLSLQualifier.h" >+#include "WHLSLReadModifyWriteExpression.h" >+#include "WHLSLReferenceType.h" >+#include "WHLSLResolvableType.h" >+#include "WHLSLResourceSemantic.h" >+#include "WHLSLReturn.h" >+#include "WHLSLSemantic.h" >+#include "WHLSLSpecializationConstantSemantic.h" >+#include "WHLSLStageInOutSemantic.h" >+#include "WHLSLStatement.h" >+#include "WHLSLStructureDefinition.h" >+#include "WHLSLStructureElement.h" >+#include "WHLSLSwitchCase.h" >+#include "WHLSLSwitchStatement.h" >+#include "WHLSLTernaryExpression.h" >+#include "WHLSLTrap.h" >+#include "WHLSLType.h" >+#include "WHLSLTypeArgument.h" >+#include "WHLSLTypeDefinition.h" >+#include "WHLSLTypeReference.h" >+#include "WHLSLUnnamedType.h" >+#include "WHLSLUnsignedIntegerLiteral.h" >+#include "WHLSLUnsignedIntegerLiteralType.h" >+#include "WHLSLValue.h" >+#include "WHLSLVariableDeclaration.h" >+#include "WHLSLVariableDeclarationsStatement.h" >+#include "WHLSLVariableReference.h" >+#include "WHLSLWhileLoop.h" >+ >+#endif >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLBuiltInSemantic.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLBuiltInSemantic.h (revision 245539) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLBuiltInSemantic.h (working copy) >@@ -81,6 +81,40 @@ public: > return !(*this == other); > } > >+ String toString() const >+ { >+ switch (m_variable) { >+ case Variable::SVInstanceID: >+ return "SVInstanceID"; >+ case Variable::SVVertexID: >+ return "SVVertexID"; >+ case Variable::PSize: >+ return "PSize"; >+ case Variable::SVPosition: >+ return "SVPosition"; >+ case Variable::SVIsFrontFace: >+ return "SVIsFrontFace"; >+ case Variable::SVSampleIndex: >+ return "SVSampleIndex"; >+ case Variable::SVInnerCoverage: >+ return "SVInnerCoverage"; >+ case Variable::SVTarget: >+ return "SVTarget"; >+ case Variable::SVDepth: >+ return "SVDepth"; >+ case Variable::SVCoverage: >+ return "SVCoverage"; >+ case Variable::SVDispatchThreadID: >+ return "SVDispatchThreadID"; >+ case Variable::SVGroupID: >+ return "SVGroupID"; >+ case Variable::SVGroupIndex: >+ return "SVGroupIndex"; >+ case Variable::SVGroupThreadID: >+ return "SVGroupThreadID"; >+ } >+ } >+ > bool isAcceptableType(const UnnamedType&, const Intrinsics&) const override; > bool isAcceptableForShaderItemDirection(ShaderItemDirection, const Optional<EntryPointType>&) const override; > >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.h (revision 245539) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.h (working copy) >@@ -58,6 +58,20 @@ public: > ResourceSemantic(const ResourceSemantic&) = delete; > ResourceSemantic(ResourceSemantic&&) = default; > >+ String toString() >+ { >+ switch (m_mode) { >+ case Mode::UnorderedAccessView: >+ return "UnorderedAccessView"; >+ case Mode::Texture: >+ return "Texture"; >+ case Mode::Buffer: >+ return "Buffer"; >+ case Mode::Sampler: >+ return "Sampler"; >+ } >+ } >+ > Mode mode() const { return m_mode; } > unsigned index() const { return m_index; } > unsigned space() const { return m_space; } >Index: Source/WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebCore/WebCore.xcodeproj/project.pbxproj (revision 245539) >+++ Source/WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -8314,6 +8314,7 @@ > 51FB67D91AE6B5E400D06C5A /* ContentExtensionStyleSheet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionStyleSheet.cpp; sourceTree = "<group>"; }; > 51FB67DA1AE6B5E400D06C5A /* ContentExtensionStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionStyleSheet.h; sourceTree = "<group>"; }; > 52131E5A1C4F15610033F802 /* VideoFullscreenInterfaceMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = VideoFullscreenInterfaceMac.mm; sourceTree = "<group>"; }; >+ 5215862C229377B7005925EF /* WHLSLAST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLAST.h; sourceTree = "<group>"; }; > 526724F11CB2FDF60075974D /* TextTrackRepresentationCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextTrackRepresentationCocoa.mm; sourceTree = "<group>"; }; > 526724F21CB2FDF60075974D /* TextTrackRepresentationCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackRepresentationCocoa.h; sourceTree = "<group>"; }; > 52B0D4BD1C57FD1E0077CE53 /* PlatformView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformView.h; sourceTree = "<group>"; }; >@@ -16997,6 +16998,7 @@ > 1CA0C2F621EEDAD200A11860 /* AST */ = { > isa = PBXGroup; > children = ( >+ 5215862C229377B7005925EF /* WHLSLAST.h */, > 1C840B9021EC30F900D0500D /* WHLSLAddressSpace.h */, > C21BF72521CD89E200227979 /* WHLSLArrayReferenceType.h */, > C21BF70921CD89CA00227979 /* WHLSLArrayType.h */, >Index: LayoutTests/webgpu/whlsl.html >=================================================================== >--- LayoutTests/webgpu/whlsl.html (revision 245539) >+++ LayoutTests/webgpu/whlsl.html (working copy) >@@ -6,12 +6,15 @@ > <canvas id="canvas" width="400" height="400"></canvas> > <script> > const shaderSource = ` >-vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position { >- return position; >+struct M { >+ int a; >+ int b; >+ float c; > } > >-fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 { >- return position; >+float foo(int a, int b) { >+ float result = 42; >+ return result; > } > `; > async function start() {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198059
:
370289
|
370295
|
370362
|
370373
|
370374