Commit 261ef74e authored by Nika Layzell's avatar Nika Layzell
Browse files

Bug 1752444 - Part 1: Add {Parent,Child}Impl attributes to ipdl, r=ipc-reviewers,mccr8

These attributes replace the previous direct_call.py table which
specified how to locate the concrete implementation of a protocol and
whether it should use a virtual implementation or not.

They work by specifying the concrete type for an actor, and disabling
the automatic inclusion of the implementation's header file, which can
be included explicitly with an `include "";` statement. This allows
customizing both the name and include path of the concrete
implementation of an interface.

Differential Revision: https://phabricator.services.mozilla.com/D137226
parent 51677d14
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ class Visitor:
    def visitStructDecl(self, struct):
        for f in struct.fields:
            f.accept(self)
        for a in struct.attributes.values():
            a.accept(self)

    def visitStructField(self, field):
        field.typespec.accept(self)
@@ -68,11 +70,12 @@ class Visitor:
    def visitUnionDecl(self, union):
        for t in union.components:
            t.accept(self)
        for a in union.attributes.values():
            a.accept(self)

    def visitUsingStmt(self, using):
        for a in using.attributes.values():
            a.accept(self)
        pass

    def visitProtocol(self, p):
        for namespace in p.namespaces:
@@ -83,6 +86,8 @@ class Visitor:
            managed.accept(self)
        for msgDecl in p.messageDecls:
            msgDecl.accept(self)
        for a in p.attributes.values():
            a.accept(self)

    def visitNamespace(self, ns):
        pass
@@ -98,18 +103,26 @@ class Visitor:
            inParam.accept(self)
        for outParam in md.outParams:
            outParam.accept(self)
        for a in md.attributes.values():
            a.accept(self)

    def visitParam(self, decl):
        pass
        for a in decl.attributes.values():
            a.accept(self)

    def visitTypeSpec(self, ts):
        pass

    def visitAttribute(self, a):
        if isinstance(a.value, Node):
            a.value.accept(self)

    def visitStringLiteral(self, sl):
        pass

    def visitDecl(self, d):
        pass
        for a in d.attributes.values():
            a.accept(self)


class Loc:
@@ -303,6 +316,13 @@ class Protocol(NamespacedNode):

        return NESTED_ATTR_MAP.get(self.attributes["NestedUpTo"].value, NOT_NESTED)

    def implAttribute(self, side):
        assert side in ("parent", "child")
        attr = self.attributes.get(side.capitalize() + "Impl")
        if attr is not None:
            return attr.value
        return None


class StructField(Node):
    def __init__(self, loc, type, name):
@@ -402,6 +422,15 @@ class Attribute(Node):
        self.value = value


class StringLiteral(Node):
    def __init__(self, loc, value):
        Node.__init__(self, loc)
        self.value = value

    def __str__(self):
        return '"%s"' % self.value


class QualifiedId:  # FIXME inherit from node?
    def __init__(self, loc, baseid, quals=[]):
        assert isinstance(baseid, str)

ipc/ipdl/ipdl/direct_call.py

deleted100644 → 0
+0 −763

File deleted.

Preview size limit exceeded, changes collapsed.

+22 −21
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@ import ipdl.ast
import ipdl.builtin
from ipdl.cxx.ast import *
from ipdl.cxx.code import *
from ipdl.direct_call import VIRTUAL_CALL_CLASSES, DIRECT_CALL_OVERRIDES
from ipdl.type import ActorType, UnionType, TypeVisitor, builtinHeaderIncludes
from ipdl.util import hash_str

@@ -3499,19 +3498,19 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):

        self.hdrfile.addthings([traitsdecl, Whitespace.NL] + _includeGuardEnd(hf))

        # make the .cpp file
        if (self.protocol.name, self.side) not in VIRTUAL_CALL_CLASSES:
            if (self.protocol.name, self.side) in DIRECT_CALL_OVERRIDES:
                (_, header_file) = DIRECT_CALL_OVERRIDES[self.protocol.name, self.side]
            else:
        # If the implementation type is not overridden, add an implicit import
        # for the default implementation header file. Explicit implementation
        # types will specify their headers manually with `include`.
        if self.protocol.implAttribute(self.side) is None:
            assert self.protocol.name.startswith("P")
                header_file = "{}/{}{}.h".format(
                    "/".join(n.name for n in self.protocol.namespaces),
                    self.protocol.name[1:],
                    self.side.capitalize(),
            self.externalIncludes.add(
                "".join(n.name + "/" for n in self.protocol.namespaces)
                + self.protocol.name[1:]
                + self.side.capitalize()
                + ".h"
            )
            self.externalIncludes.add(header_file)

        # make the .cpp file
        cf.addthings(
            [
                _DISCLAIMER,
@@ -3723,7 +3722,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
                    defaultRecv = MethodDefn(recvDecl)
                    defaultRecv.addcode("return IPC_OK();\n")
                    self.cls.addstmt(defaultRecv)
                elif (self.protocol.name, self.side) in VIRTUAL_CALL_CLASSES:
                elif self.protocol.implAttribute(self.side) == "virtual":
                    # If we're using virtual calls, we need the methods to be
                    # declared on the base class.
                    recvDecl.methodspec = MethodSpec.PURE
@@ -3731,7 +3730,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):

        # If we're using virtual calls, we need the methods to be declared on
        # the base class.
        if (self.protocol.name, self.side) in VIRTUAL_CALL_CLASSES:
        if self.protocol.implAttribute(self.side) == "virtual":
            for md in p.messageDecls:
                managed = md.decl.type.constructedType()
                if not ptype.isManagerOf(managed) or md.decl.type.isDtor():
@@ -4507,16 +4506,18 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
    ##

    def concreteThis(self):
        if (self.protocol.name, self.side) in VIRTUAL_CALL_CLASSES:
        implAttr = self.protocol.implAttribute(self.side)
        if implAttr == "virtual":
            return ExprVar.THIS

        if (self.protocol.name, self.side) in DIRECT_CALL_OVERRIDES:
            (class_name, _) = DIRECT_CALL_OVERRIDES[self.protocol.name, self.side]
        else:
        if implAttr is None:
            assert self.protocol.name.startswith("P")
            class_name = "{}{}".format(self.protocol.name[1:], self.side.capitalize())
            className = self.protocol.name[1:] + self.side.capitalize()
        else:
            assert isinstance(implAttr, ipdl.ast.StringLiteral)
            className = implAttr.value

        return ExprCode("static_cast<${class_name}*>(this)", class_name=class_name)
        return ExprCode("static_cast<${className}*>(this)", className=className)

    def thisCall(self, function, args):
        return ExprCall(ExprSelect(self.concreteThis(), "->", function), args=args)
+4 −3
Original line number Diff line number Diff line
@@ -177,7 +177,7 @@ def t_ID(t):

def t_STRING(t):
    r'"[^"\n]*"'
    t.value = t.value[1:-1]
    t.value = StringLiteral(Loc(Parser.current.filename, t.lineno), t.value[1:-1])
    return t


@@ -259,7 +259,7 @@ def p_PreambleStmt(p):

def p_CxxIncludeStmt(p):
    """CxxIncludeStmt : INCLUDE STRING"""
    p[0] = CxxInclude(locFromTok(p, 1), p[2])
    p[0] = CxxInclude(locFromTok(p, 1), p[2].value)


def p_IncludeStmt(p):
@@ -298,7 +298,7 @@ def p_UsingStmt(p):
        attributes=p[1],
        kind=p[3],
        cxxTypeSpec=p[4],
        cxxHeader=p[6],
        cxxHeader=p[6].value,
    )


@@ -542,6 +542,7 @@ def p_Attribute(p):

def p_AttributeValue(p):
    """AttributeValue : '=' ID
    | '=' STRING
    |"""
    if 1 == len(p):
        p[0] = None
+12 −3
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ import os
import sys

from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, StructDecl
from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor
from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor, StringLiteral
from ipdl.ast import ASYNC, SYNC, INTR
from ipdl.ast import IN, OUT, INOUT
from ipdl.ast import NOT_NESTED, INSIDE_SYNC_NESTED, INSIDE_CPOW_NESTED
@@ -867,12 +867,19 @@ class GatherDecls(TcheckVisitor):
                        attr.name,
                    )
            elif isinstance(aspec, (list, tuple)):
                if attr.value not in aspec:
                if not any(
                    isinstance(attr.value, s)
                    if isinstance(s, type)
                    else attr.value == s
                    for s in aspec
                ):
                    self.error(
                        attr.loc,
                        "invalid value for attribute `%s', expected one of: %s",
                        attr.name,
                        ", ".join(str(s) for s in aspec),
                        ", ".join(
                            s.__name__ if isinstance(s, type) else str(s) for s in aspec
                        ),
                    )
            elif callable(aspec):
                if not aspec(attr.value):
@@ -919,6 +926,8 @@ class GatherDecls(TcheckVisitor):
                    "RefCounted": None,
                    "NestedUpTo": ("not", "inside_sync", "inside_cpow"),
                    "NeedsOtherPid": None,
                    "ChildImpl": ("virtual", StringLiteral),
                    "ParentImpl": ("virtual", StringLiteral),
                },
            )

Loading