Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/jit/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 12 kB image not shown  

Quelle  GenerateMIRFiles.py   Sprache: Python

 
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# This script generates jit/MIROpsGenerated.h (list of MIR instructions)
# from MIROps.yaml, as well as MIR op definitions.

import buildconfig
import six
import yaml
from mozbuild.preprocessor import Preprocessor

HEADER_TEMPLATE = """\
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef %(includeguard)s
#define %(includeguard)s

/* This file is generated by jit/GenerateMIRFiles.py. Do not edit! */

%(contents)s

#endif // %(includeguard)s
"""


def generate_header(c_out, includeguard, contents):
    c_out.write(
        HEADER_TEMPLATE
        % {
            "includeguard": includeguard,
            "contents": contents,
        }
    )


def load_yaml(yaml_path):
    # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in
    # the YAML file.
    pp = Preprocessor()
    pp.context.update(buildconfig.defines["ALLDEFINES"])
    pp.out = six.StringIO()
    pp.do_filter("substitution")
    pp.do_include(yaml_path)
    contents = pp.out.getvalue()
    return yaml.safe_load(contents)


type_policies = {
    "Object""ObjectPolicy",
    "Value""BoxPolicy",
    "Int32""UnboxedInt32Policy",
    "BigInt""BigIntPolicy",
    "IntPtr""IntPtrPolicy",
    "Boolean""BooleanPolicy",
    "Double""DoublePolicy",
    "String""StringPolicy",
    "Symbol""SymbolPolicy",
}


def decide_type_policy(types, no_type_policy):
    if no_type_policy:
        return "public NoTypePolicy::Data"

    if len(types) == 1:
        return "public {}<0>::Data".format(type_policies[types[0]])

    type_num = 0
    mixed_type_policies = []
    for mir_type in types:
        policy = type_policies[mir_type]
        mixed_type_policies.append("{}<{}>".format(policy, type_num))
        type_num += 1

    return "public MixPolicy<{}>::Data".format(", ".join(mixed_type_policies))


mir_base_class = [
    "MNullaryInstruction",
    "MUnaryInstruction",
    "MBinaryInstruction",
    "MTernaryInstruction",
    "MQuaternaryInstruction",
]


gc_pointer_types = [
    "JSObject*",
    "NativeObject*",
    "JSFunction*",
    "BaseScript*",
    "PropertyName*",
    "Shape*",
    "GetterSetter*",
    "JSAtom*",
    "ClassBodyScope*",
    "VarScope*",
    "NamedLambdaObject*",
    "RegExpObject*",
    "JSScript*",
    "LexicalScope*",
]


def gen_mir_class(
    name,
    operands,
    arguments,
    no_type_policy,
    result,
    guard,
    movable,
    folds_to,
    congruent_to,
    alias_set,
    might_alias,
    possibly_calls,
    compute_range,
    can_recover,
    clone,
    can_consume_float32,
):
    """Generates class definition for a single MIR opcode."""

    # Generate a MIR opcode class definition.
    # For example:
    # class MGuardIndexIsValidUpdateOrAdd
    #     : public MBinaryInstruction,
    #       public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>>::Data {
    #  explicit MGuardIndexIsValidUpdateOrAdd(MDefinition* object,
    #                                         MDefinition* index)
    #     : MBinaryInstruction(classOpcode, object, index) {
    #   setGuard();
    #   setMovable();
    #   setResultType(MIRType::Int32);
    #  }
    # public:
    #  INSTRUCTION_HEADER(GetFrameArgument)
    #  TRIVIAL_NEW_WRAPPERS
    #  NAMED_OPERANDS((0, object), (1, index))
    #  AliasSet getAliasSet() const override { return AliasSet::None(); }
    #  bool congruentTo(const MDefinition* ins) const override {
    #    return congruentIfOperandsEqual(ins); }
    #  };
    #

    type_policy = ""
    # MIR op constructor operands.
    mir_operands = []
    # MIR op base class constructor operands.
    mir_base_class_operands = []
    # Types of each constructor operand.
    mir_types = []
    # Items for NAMED_OPERANDS.
    named_operands = []
    if operands:
        current_oper_num = 0
        for oper_name in operands:
            oper = "MDefinition* " + oper_name
            mir_operands.append(oper)
            mir_base_class_operands.append(", " + oper_name)
            # Collect all the MIR argument types to use for determining the
            # ops type policy.
            mir_types.append(operands[oper_name])
            # Collecting named operands for defining accessors.
            named_operands.append("({}, {})".format(current_oper_num, oper_name))
            current_oper_num += 1
        type_policy = decide_type_policy(mir_types, no_type_policy)

    class_name = "M" + name

    assert len(mir_operands) < 5
    base_class = mir_base_class[len(mir_operands)]
    assert base_class
    if base_class != "MNullaryInstruction":
        assert type_policy
        type_policy = ", " + type_policy
    code = "class {} : public {}{} {{\\\n".format(class_name, base_class, type_policy)

    # Arguments to class constructor that require accessors.
    mir_args = []
    if arguments:
        for arg_name in arguments:
            arg_type_sig = arguments[arg_name]
            mir_args.append(arg_type_sig + " " + arg_name)
            if arg_type_sig in gc_pointer_types:
                code += " CompilerGCPointer<" + arg_type_sig + ">"
            else:
                code += " " + arg_type_sig
            code += " " + arg_name + "_;\\\n"

    code += " explicit {}({}) : {}(classOpcode{})".format(
        class_name,
        ", ".join(mir_operands + mir_args),
        base_class,
        "".join(mir_base_class_operands),
    )
    if arguments:
        for arg_name in arguments:
            code += ", " + arg_name + "_(" + arg_name + ")"
    code += " {\\\n"
    if guard:
        code += " setGuard();\\\n"
    if movable:
        code += " setMovable();\\\n"
    if result:
        code += " setResultType(MIRType::{});\\\n".format(result)
    code += " }\\\n public:\\\n"
    if arguments:
        for arg_name in arguments:
            code += " " + arguments[arg_name] + " " + arg_name + "() const { "
            code += "return " + arg_name + "_; }\\\n"
    code += " INSTRUCTION_HEADER({})\\\n".format(name)
    code += " TRIVIAL_NEW_WRAPPERS\\\n"
    if named_operands:
        code += " NAMED_OPERANDS({})\\\n".format(", ".join(named_operands))
    if alias_set:
        if alias_set == "custom":
            code += " AliasSet getAliasSet() const override;\\\n"
        else:
            assert alias_set == "none"
            code += (
                " AliasSet getAliasSet() const override { "
                "return AliasSet::None(); }\\\n"
            )
    if might_alias:
        code += " AliasType mightAlias(const MDefinition* store) const override;\\\n"
    if folds_to:
        code += " MDefinition* foldsTo(TempAllocator& alloc) override;\\\n"
    if congruent_to:
        if congruent_to == "custom":
            code += " bool congruentTo(const MDefinition* ins) const override;\\\n"
        else:
            assert congruent_to == "if_operands_equal"
            code += (
                " bool congruentTo(const MDefinition* ins) const override { "
                "return congruentIfOperandsEqual(ins); }\\\n"
            )
    if possibly_calls:
        if possibly_calls == "custom":
            code += " bool possiblyCalls() const override;\\\n"
        else:
            code += " bool possiblyCalls() const override { return true; }\\\n"
    if compute_range:
        code += " void computeRange(TempAllocator& alloc) override;\\\n"
    if can_recover:
        code += " [[nodiscard]] bool writeRecoverData(\\\n"
        code += " CompactBufferWriter& writer) const override;\\\n"
        if can_recover == "custom":
            code += " bool canRecoverOnBailout() const override;\\\n"
        else:
            code += " bool canRecoverOnBailout() const override { return true; }\\\n"
    if clone:
        code += " ALLOW_CLONE(" + class_name + ")\\\n"
    if can_consume_float32:
        code += (
            " bool canConsumeFloat32(MUse* use) const override { return true; }\\\n"
        )
    code += "};\\\n"
    return code


def gen_non_gc_pointer_type_assertions(seen_types):
    """Generates a list of static assertions used to ensure that all argument
    types seen are not derived from gc::Cell, ensuring that gc pointer arguments
    are added to the gc_pointer_types list.
    """
    assertions = []

    for seen_type in sorted(seen_types):
        assertions.append(
            "static_assert(!std::is_base_of_v + seen_type.strip("*") + ">, "
            '"Ensure that '
            + seen_type.strip("*")
            + ' is added to the gc_pointer_types list in GenerateMIRFiles.py."'
            ");"
        )

    return assertions


def generate_mir_header(c_out, yaml_path):
    """Generate MIROpsGenerated.h from MIROps.yaml. The generated file
    has a list of MIR ops and boilerplate for MIR op definitions.
    """

    data = load_yaml(yaml_path)

    # MIR_OPCODE_LIST items. Stores the name of each MIR op.
    ops_items = []

    # Generated MIR op class definitions.
    mir_op_classes = []

    # Unique and non gc pointer types seen for arguments to the MIR constructor.
    seen_non_gc_pointer_argument_types = set()

    for op in data:
        name = op["name"]

        ops_items.append("_({})".format(name))

        gen_boilerplate = op.get("gen_boilerplate"True)
        assert isinstance(gen_boilerplate, bool)

        if gen_boilerplate:
            operands = op.get("operands"None)
            assert operands is None or isinstance(operands, dict)

            arguments = op.get("arguments"None)
            assert arguments is None or isinstance(arguments, dict)

            no_type_policy = op.get("type_policy"None)
            assert no_type_policy in (None"none")

            result = op.get("result_type"None)
            assert result is None or isinstance(result, str)

            guard = op.get("guard"None)
            assert guard in (NoneTrueFalse)

            movable = op.get("movable"None)
            assert movable in (NoneTrueFalse)

            folds_to = op.get("folds_to"None)
            assert folds_to in (None"custom")

            congruent_to = op.get("congruent_to"None)
            assert congruent_to in (None"if_operands_equal""custom")

            alias_set = op.get("alias_set"None)
            assert alias_set in (None"none""custom")

            might_alias = op.get("might_alias"None)
            assert might_alias in (None"custom")

            possibly_calls = op.get("possibly_calls"None)
            assert possibly_calls in (NoneTrue"custom")

            compute_range = op.get("compute_range"None)
            assert compute_range in (None"custom")

            can_recover = op.get("can_recover"None)
            assert can_recover in (NoneTrueFalse"custom")

            clone = op.get("clone"None)
            assert clone in (NoneTrueFalse)

            can_consume_float32 = op.get("can_consume_float32"None)
            assert can_consume_float32 in (NoneTrueFalse)

            code = gen_mir_class(
                name,
                operands,
                arguments,
                no_type_policy,
                result,
                guard,
                movable,
                folds_to,
                congruent_to,
                alias_set,
                might_alias,
                possibly_calls,
                compute_range,
                can_recover,
                clone,
                can_consume_float32,
            )
            mir_op_classes.append(code)

            if arguments:
                for argument in arguments:
                    arg_type = arguments[argument]
                    if arg_type not in gc_pointer_types:
                        seen_non_gc_pointer_argument_types.add(arg_type)

    contents = "#define MIR_OPCODE_LIST(_)\\\n"
    contents += "\\\n".join(ops_items)
    contents += "\n\n"

    contents += "#define MIR_OPCODE_CLASS_GENERATED \\\n"
    contents += "\\\n".join(mir_op_classes)
    contents += "\n\n"

    contents += "#define NON_GC_POINTER_TYPE_ASSERTIONS_GENERATED \\\n"
    contents += "\\\n".join(
        gen_non_gc_pointer_type_assertions(seen_non_gc_pointer_argument_types)
    )
    contents += "\n\n"

    generate_header(c_out, "jit_MIROpsGenerated_h", contents)

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.