Changeset 221686 in webkit


Ignore:
Timestamp:
Sep 6, 2017 11:25:55 AM (7 years ago)
Author:
mmaxfield@apple.com
Message:

WSL should correctly handle the interaction between casting operators and complex types
https://bugs.webkit.org/show_bug.cgi?id=176316

Reviewed by Filip Pizlo.

This allows the standard library to include all identity cast operators for all exsting
and yet-to-exist types. The standard library now has a function with the signature:
operator T<><T>(T). This means "for all T, define a cast operator from T to T<>." The
duplicate <>s lets us say things like operator OutputVector<T><T>(InputVector<T> x).

For testing, this patch also adds the ability to cast an arbitrary Equatable type to bool,
by comparing the value to the default value for that type.

  • WebGPUShadingLanguageRI/All.js:
  • WebGPUShadingLanguageRI/CastExpression.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js.

(CastExpression):
(CastExpression.prototype.get functionName):
(CastExpression.prototype.get returnType):
(CastExpression.prototype.toString):

  • WebGPUShadingLanguageRI/Checker.js:
  • WebGPUShadingLanguageRI/Func.js:

(Func.prototype.toDeclString):

  • WebGPUShadingLanguageRI/FuncInstantiator.js:

(FuncInstantiator.prototype.getUnique.Instantiate.prototype.visitNativeFunc):
(FuncInstantiator.prototype.getUnique.Instantiate):
(FuncInstantiator.prototype.getUnique):
(FuncInstantiator):

  • WebGPUShadingLanguageRI/Inliner.js:

(Inliner.prototype.visitCastExpression):
(Inliner):

  • WebGPUShadingLanguageRI/Intrinsics.js:

(Intrinsics):

  • WebGPUShadingLanguageRI/NativeFunc.js:
  • WebGPUShadingLanguageRI/NativeFuncInstance.js:

(NativeFuncInstance):

  • WebGPUShadingLanguageRI/Parse.js:

(parsePossiblePrefix):
(parseFuncDecl):
(parseOperatorFuncDefValues): Deleted.
(parseNonOperatorFuncDefValues): Deleted.
(parseGenericFuncDefValues): Deleted.

  • WebGPUShadingLanguageRI/Prepare.js:

(prepare):

  • WebGPUShadingLanguageRI/Program.js:

(Program.prototype.resolveFuncOverload):

  • WebGPUShadingLanguageRI/ResolveOverloadImpl.js:

(resolveOverloadImpl):

  • WebGPUShadingLanguageRI/Rewriter.js:

(Rewriter.prototype.processDerivedCallData):
(Rewriter.prototype.visitCastExpression):
(Rewriter.prototype.visitCallExpression):

  • WebGPUShadingLanguageRI/StandardLibrary.js: Removed.
  • WebGPUShadingLanguageRI/Test.html:
  • WebGPUShadingLanguageRI/Test.js:
  • WebGPUShadingLanguageRI/TypeDefResolver.js:

(TypeDefResolver):
(TypeDefResolver.prototype.visitFuncDef): Deleted.

  • WebGPUShadingLanguageRI/Visitor.js:

(Visitor.prototype.visitCastExpression):

Location:
trunk/Tools
Files:
1 deleted
18 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r221679 r221686  
     12017-09-06  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        WSL should correctly handle the interaction between casting operators and complex types
     4        https://bugs.webkit.org/show_bug.cgi?id=176316
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This allows the standard library to include all identity cast operators for all exsting
     9        and yet-to-exist types. The standard library now has a function with the signature:
     10        operator T<><T>(T). This means "for all T, define a cast operator from T to T<>." The
     11        duplicate <>s lets us say things like operator OutputVector<T><T>(InputVector<T> x).
     12
     13        For testing, this patch also adds the ability to cast an arbitrary Equatable type to bool,
     14        by comparing the value to the default value for that type.
     15
     16        * WebGPUShadingLanguageRI/All.js:
     17        * WebGPUShadingLanguageRI/CastExpression.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js.
     18        (CastExpression):
     19        (CastExpression.prototype.get functionName):
     20        (CastExpression.prototype.get returnType):
     21        (CastExpression.prototype.toString):
     22        * WebGPUShadingLanguageRI/Checker.js:
     23        * WebGPUShadingLanguageRI/Func.js:
     24        (Func.prototype.toDeclString):
     25        * WebGPUShadingLanguageRI/FuncInstantiator.js:
     26        (FuncInstantiator.prototype.getUnique.Instantiate.prototype.visitNativeFunc):
     27        (FuncInstantiator.prototype.getUnique.Instantiate):
     28        (FuncInstantiator.prototype.getUnique):
     29        (FuncInstantiator):
     30        * WebGPUShadingLanguageRI/Inliner.js:
     31        (Inliner.prototype.visitCastExpression):
     32        (Inliner):
     33        * WebGPUShadingLanguageRI/Intrinsics.js:
     34        (Intrinsics):
     35        * WebGPUShadingLanguageRI/NativeFunc.js:
     36        * WebGPUShadingLanguageRI/NativeFuncInstance.js:
     37        (NativeFuncInstance):
     38        * WebGPUShadingLanguageRI/Parse.js:
     39        (parsePossiblePrefix):
     40        (parseFuncDecl):
     41        (parseOperatorFuncDefValues): Deleted.
     42        (parseNonOperatorFuncDefValues): Deleted.
     43        (parseGenericFuncDefValues): Deleted.
     44        * WebGPUShadingLanguageRI/Prepare.js:
     45        (prepare):
     46        * WebGPUShadingLanguageRI/Program.js:
     47        (Program.prototype.resolveFuncOverload):
     48        * WebGPUShadingLanguageRI/ResolveOverloadImpl.js:
     49        (resolveOverloadImpl):
     50        * WebGPUShadingLanguageRI/Rewriter.js:
     51        (Rewriter.prototype.processDerivedCallData):
     52        (Rewriter.prototype.visitCastExpression):
     53        (Rewriter.prototype.visitCallExpression):
     54        * WebGPUShadingLanguageRI/StandardLibrary.js: Removed.
     55        * WebGPUShadingLanguageRI/Test.html:
     56        * WebGPUShadingLanguageRI/Test.js:
     57        * WebGPUShadingLanguageRI/TypeDefResolver.js:
     58        (TypeDefResolver):
     59        (TypeDefResolver.prototype.visitFuncDef): Deleted.
     60        * WebGPUShadingLanguageRI/Visitor.js:
     61        (Visitor.prototype.visitCastExpression):
     62
    1632017-09-06  Daniel Bates  <dabates@apple.com>
    264
  • trunk/Tools/WebGPUShadingLanguageRI/All.js

    r221634 r221686  
    4242load("CallExpression.js");
    4343load("CallFunction.js");
     44load("CastExpression.js");
    4445load("Check.js");
    4546load("CheckLiteralTypes.js");
     
    9798load("ReturnChecker.js");
    9899load("ReturnException.js");
    99 load("StandardLibrary.js");
     100load("StandardLibraryEpilogue.js");
     101load("StandardLibraryPrologue.js");
    100102load("StructLayoutBuilder.js");
    101103load("StructType.js");
  • trunk/Tools/WebGPUShadingLanguageRI/CastExpression.js

    r221684 r221686  
    2525"use strict";
    2626
    27 class NativeFuncInstance extends Func {
    28     constructor(func, returnType, parameters)
     27// This is a bit of a misnomer, as this represents casts as well as constructors.
     28// Syntactically they are identical; a cast just takes one argument whereas a
     29// constructor takes 0-n.
     30class CastExpression extends CallExpression {
     31    constructor(origin, returnType, typeArguments, argumentList)
    2932    {
    30         super(func.origin, func.name, returnType, [], parameters);
     33        super(origin, CastExpression.functionName, typeArguments, argumentList);
     34        this._returnType = returnType;
    3135    }
     36
     37    static get functionName() { return "operator cast"; }
    3238   
    33     get func() { return this._func; }
    34     get isNative() { return true; }
    35 
    36     toDeclString()
     39    get returnType() { return this._returnType; }
     40   
     41    toString()
    3742    {
    38         return "native " + super.toDeclString();
     43        return this.returnType + "<" + this.typeArguments + ">(" + this.argumentList + ")";
    3944    }
    4045}
  • trunk/Tools/WebGPUShadingLanguageRI/Checker.js

    r221634 r221686  
    234234        return result;
    235235    }
    236    
    237     visitCallExpression(node)
     236
     237    checkCastOrCallExpression(node, returnType)
    238238    {
    239239        for (let typeArgument of node.typeArguments)
     
    246246        });
    247247        node.argumentTypes = argumentTypes;
     248        if (returnType)
     249            returnType.visit(this);
    248250       
    249251        let overload = null;
     
    258260            if (!signatures)
    259261                continue;
    260             overload = resolveOverloadImpl(signatures, node.typeArguments, argumentTypes);
     262            overload = resolveOverloadImpl(signatures, node.typeArguments, argumentTypes, returnType);
    261263            if (overload.func)
    262264                break;
     
    266268        if (!overload) {
    267269            overload = this._program.resolveFuncOverload(
    268                 node.name, node.typeArguments, argumentTypes);
     270                node.name, node.typeArguments, argumentTypes, returnType);
    269271            if (!overload.func) {
    270272                failures.push(...overload.failures);
     
    285287        return node.resolve(overload);
    286288    }
     289
     290    visitCastExpression(node)
     291    {
     292        return this.checkCastOrCallExpression(node, node.returnType);
     293    }
     294   
     295    visitCallExpression(node)
     296    {
     297        return this.checkCastOrCallExpression(node, undefined);
     298    }
    287299}
    288300
  • trunk/Tools/WebGPUShadingLanguageRI/Func.js

    r221634 r221686  
    4949    toDeclString()
    5050    {
    51         return (this.isCast ? "" : this.returnType + " ") + this.name + "<" + this.typeParameters + ">(" + this.parameters + ")";
     51        return (this.isCast ? "operator " + this.returnType : this.returnType + " " + this.name) + "<" + this.typeParameters + ">(" + this.parameters + ")";
    5252    }
    5353   
  • trunk/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js

    r221592 r221686  
    9393                    func,
    9494                    func.returnType.visit(substitution),
    95                     func.parameters.map(parameter => parameter.visit(substitution)));
     95                    func.parameters.map(parameter => parameter.visit(substitution)),
     96                    func.isCast);
    9697            }
    9798        }
  • trunk/Tools/WebGPUShadingLanguageRI/Inliner.js

    r221550 r221686  
    5959        });
    6060    }
     61
     62    visitCastExpression(node)
     63    {
     64        return this.visitCallExpression(node);
     65    }
    6166}
    6267
  • trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js

    r221634 r221686  
    3535
    3636        // NOTE: Intrinsic resolution happens before type name resolution, so the strings we use here
    37         // to catch the intrinsics must be based on the type names that StandardLibrary.js uses. For
    38         // example, if a native function is declared using "int" rather than "int32", then we must use
    39         // "int" here, since we don't yet know that they are the same type.
     37        // to catch the intrinsics must be based on the type names that StandardLibraryPrologue.js uses.
     38        // For example, if a native function is declared using "int" rather than "int32", then we must
     39        // use "int" here, since we don't yet know that they are the same type.
    4040       
    4141        this._map.set(
     
    179179            });
    180180       
    181         this._map.set(
    182             "native operator int<>(int)",
    183             func => {
    184                 func.implementation = ([value]) =>
    185                     EPtr.box(value.loadValue());
    186             });
    187        
    188         this._map.set(
    189             "native operator uint<>(uint)",
    190             func => {
    191                 func.implementation = ([value]) =>
    192                     EPtr.box(value.loadValue());
    193             });
    194        
    195         this._map.set(
    196             "native operator bool<>(bool)",
    197             func => {
    198                 func.implementation = ([value]) =>
    199                     EPtr.box(value.loadValue());
    200             });
    201        
    202181        let arrayElementPtr = func => {
    203182            func.implementation = ([ref, index], node) => {
  • trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js

    r221634 r221686  
    2626
    2727class NativeFunc extends Func {
    28     constructor(origin, name, returnType, typeParameters, parameters, isCast = false)
     28    constructor(origin, name, returnType, typeParameters, parameters, isCast)
    2929    {
    3030        super(origin, name, returnType, typeParameters, parameters, isCast);
  • trunk/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js

    r221549 r221686  
    2626
    2727class NativeFuncInstance extends Func {
    28     constructor(func, returnType, parameters)
     28    constructor(func, returnType, parameters, isCast)
    2929    {
    30         super(func.origin, func.name, returnType, [], parameters);
     30        super(func.origin, func.name, returnType, [], parameters, isCast);
    3131    }
    3232   
  • trunk/Tools/WebGPUShadingLanguageRI/Parse.js

    r221634 r221686  
    381381        if (token = tryConsume("@"))
    382382            return new MakeArrayRefExpression(token, parsePossiblePrefix());
    383         if (token = tryConsume("!"))
    384             return new LogicalNot(token, new CallExpression(token, "operator bool", [], [parsePossiblePrefix()]));
     383        if (token = tryConsume("!")) {
     384            let remainder = parsePossiblePrefix();
     385            return new LogicalNot(token, new CastExpression(remainder.origin, new TypeRef(remainder.origin, "bool", []), [], [remainder]));
     386        }
    385387        return parsePossibleSuffix();
    386388    }
     
    621623    }
    622624
    623     function parseOperatorFuncDefValues()
    624     {
    625         let result = {};
    626         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176316 Correctly handle the interaction between casting operators and complex types
    627         let castType = consumeKind("identifier").text;
    628         result.returnType = new TypeRef(name, castType, []);
    629         result.name = "operator " + castType;
    630         result.isCast = true;
    631         return result;
    632     }
    633 
    634     function parseNonOperatorFuncDefValues()
    635     {
    636         let result = {};
    637         result.returnType = parseType();
    638         result.origin = result.returnType.origin;
    639         result.name = parseFuncName();
    640         result.isCast = false;
    641         return result;
    642     }
    643 
    644     function parseGenericFuncDefValues()
    645     {
     625    function parseFuncDecl()
     626    {
     627        let origin;
     628        let returnType;
     629        let name;
     630        let isCast;
    646631        let operatorToken = tryConsume("operator");
    647632        if (operatorToken) {
    648             let result = parseOperatorFuncDefValues();
    649             result.origin = operatorToken.origin;
    650             return result;
    651         }
    652         return parseNonOperatorFuncDefValues();
    653     }
    654 
    655     function parseFuncDecl()
    656     {
    657         let values = parseGenericFuncDefValues();
     633            origin = operatorToken;
     634            returnType = parseType();
     635            name = CastExpression.functionName;
     636            isCast = true;
     637        } else {
     638            returnType = parseType();
     639            origin = returnType.origin;
     640            name = parseFuncName();
     641            isCast = false;
     642        }
    658643        let typeParameters = parseTypeParameters();
    659644        let parameters = parseParameters();
    660         return new Func(values.origin, values.name, values.returnType, typeParameters, parameters, values.isCast);
     645        return new Func(origin, name, returnType, typeParameters, parameters, isCast);
    661646    }
    662647
  • trunk/Tools/WebGPUShadingLanguageRI/Prepare.js

    r221593 r221686  
    2828{
    2929    let program = new Program();
    30     parse(program, "/internal/stdlib", 28, standardLibrary);
     30    parse(program, "/internal/stdlib/prologue", 28, standardLibraryPrologue);
    3131    parse(program, origin, lineNumberOffset, text);
     32    parse(program, "/internal/stdlib/epilogue", 28, standardLibraryEpilogue);
    3233    resolveNames(program);
    3334    resolveTypeDefs(program);
  • trunk/Tools/WebGPUShadingLanguageRI/Program.js

    r221496 r221686  
    5959    }
    6060   
    61     resolveFuncOverload(name, typeArguments, argumentTypes)
     61    resolveFuncOverload(name, typeArguments, argumentTypes, returnType)
    6262    {
    6363        let functions = this.functions.get(name);
     
    6565            return {failures: []};
    6666       
    67         return resolveOverloadImpl(functions, typeArguments, argumentTypes);
     67        return resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType);
    6868    }
    6969   
  • trunk/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js

    r221550 r221686  
    2525"use strict";
    2626
    27 function resolveOverloadImpl(functions, typeArguments, argumentTypes)
     27function resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType)
    2828{
    2929    let failures = [];
     
    4343            let parameter = func.typeParameters[i];
    4444            if (!argument.unify(unificationContext, parameter)) {
    45                 failures.push(new OverloadResolutionFailure(func, "Type argument #" + (i + 1) + " for parameter " + func.typeParameters.name + " does not match (passed " + argument + ", require " + parameter + ")"));
     45                failures.push(new OverloadResolutionFailure(func, "Type argument #" + (i + 1) + " for parameter " + parameter.name + " does not match (passed " + argument + ", require " + parameter + ")"));
    4646                ok = false;
    4747                break;
     
    6161        if (!ok)
    6262            continue;
     63        if (returnType) {
     64            if (!returnType.unify(unificationContext, func.returnType)) {
     65                failures.push(new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType));
     66                continue;
     67            }
     68        }
    6369        if (!unificationContext.verify()) {
    6470            failures.push(new OverloadResolutionFailure(func, "Violates type variable constraints"));
  • trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js

    r221634 r221686  
    236236        return result;
    237237    }
    238    
    239     visitCallExpression(node)
    240     {
    241         let result = new CallExpression(
    242             node.origin, node.name,
    243             node.typeArguments.map(typeArgument => typeArgument.visit(this)),
    244             node.argumentList.map(argument => argument.visit(this)));
     238
     239    processDerivedCallData(node, result)
     240    {
    245241        let actualTypeArguments = node.actualTypeArguments;
    246242        if (actualTypeArguments) {
     
    255251        return result;
    256252    }
     253
     254    visitCastExpression(node)
     255    {
     256        let result = new CastExpression(
     257            node.origin, node.returnType.visit(this),
     258            node.typeArguments.map(typeArgument => typeArgument.visit(this)),
     259            node.argumentList.map(argument => argument.visit(this)));
     260        return this.processDerivedCallData(node, result);
     261    }
     262   
     263    visitCallExpression(node)
     264    {
     265        let result = new CallExpression(
     266            node.origin, node.name,
     267            node.typeArguments.map(typeArgument => typeArgument.visit(this)),
     268            node.argumentList.map(argument => argument.visit(this)));
     269        return this.processDerivedCallData(node, result);
     270    }
    257271   
    258272    visitFunctionLikeBlock(node)
  • trunk/Tools/WebGPUShadingLanguageRI/Test.html

    r221634 r221686  
    1818<script src="CallExpression.js"></script>
    1919<script src="CallFunction.js"></script>
     20<script src="CastExpression.js"></script>
    2021<script src="Check.js"></script>
    2122<script src="CheckLiteralTypes.js"></script>
     
    7374<script src="ReturnChecker.js"></script>
    7475<script src="ReturnException.js"></script>
    75 <script src="StandardLibrary.js"></script>
     76<script src="StandardLibraryEpilogue.js"></script>
     77<script src="StandardLibraryPrologue.js"></script>
    7678<script src="StructLayoutBuilder.js"></script>
    7779<script src="StructType.js"></script>
  • trunk/Tools/WebGPUShadingLanguageRI/Test.js

    r221634 r221686  
    202202}
    203203
     204function TEST_generalNegation()
     205{
     206    let program = doPrep("bool foo(int x) { return !x; }");
     207    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7)]), false);
     208    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 0)]), true);
     209}
     210
    204211function TEST_add1() {
    205212    let program = doPrep("int foo(int x) { return x + 1; }");
  • trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js

    r221634 r221686  
    3131        this._visiting = new VisitingSet();
    3232    }
    33 
    34     visitFuncDef(node)
    35     {
    36         if (node.isCast && node.returnType.type instanceof TypeDef) {
    37             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176316 Correctly handle the interaction between casting operators and complex types
    38             throw new Error("Casting operators don't work with typedefs.");
    39         }
    40         super.visitFuncDef(node);
    41     }
    4233   
    4334    visitTypeRef(node)
  • trunk/Tools/WebGPUShadingLanguageRI/Visitor.js

    r221634 r221686  
    256256        }
    257257    }
     258   
     259    visitCastExpression(node)
     260    {
     261        this.visitCallExpression(node);
     262        node.returnType.visit(this);
     263    }
    258264
    259265    visitLogicalNot(node)
Note: See TracChangeset for help on using the changeset viewer.