/* * Copyright (C) 2016 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. ``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 * 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. */ "use strict"; class Inst { constructor(opcode, args = []) { this._opcode = opcode; this._args = args; } append(...args) { this._args.push(...args); } clear() { this._opcode = Nop; this._args = []; } get opcode() { return this._opcode; } get args() { return this._args; } visitArg(index, func, ...args) { let replacement = func(this._args[index], ...args); if (replacement) this._args[index] = replacement; } forEachTmpFast(func) { for (let i = 0; i < this._args.length; ++i) { let replacement; if (replacement = this._args[i].forEachTmpFast(func)) this._args[i] = replacement; } } forEachArg(func) { Inst_forEachArg(this, func); } forEachTmp(func) { this.forEachArg((arg, role, type, width) => { return arg.forEachTmp(role, type, width, func); }); } forEach(thing, func) { this.forEachArg((arg, role, type, width) => { return arg.forEach(thing, role, type, width, func); }); } static forEachDef(thing, prevInst, nextInst, func) { if (prevInst) { prevInst.forEach( thing, (value, role, type, width) => { if (Arg.isLateDef(role)) return func(value, role, type, width); }); } if (nextInst) { nextInst.forEach( thing, (value, role, type, width) => { if (Arg.isEarlyDef(role)) return func(value, role, type, width); }); } } static forEachDefWithExtraClobberedRegs(thing, prevInst, nextInst, func) { forEachDef(thing, prevInst, nextInst, func); let regDefRole; let reportReg = reg => { let type = reg.isGPR ? GP : FP; func(thing.fromReg(reg), regDefRole, type, Arg.conservativeWidth(type)); }; if (prevInst && prevInst.opcode == Patch) { regDefRole = Arg.Def; prevInst.extraClobberedRegs.forEach(reportReg); } if (nextInst && nextInst.opcode == Patch) { regDefRole = Arg.EarlyDef; nextInst.extraEarlyClobberedRegs.forEach(reportReg); } } get hasNonArgEffects() { return Inst_hasNonArgEffects(this); } hash() { let result = opcodeCode(this.opcode); for (let arg of this.args) { result += arg.hash(); result |= 0; } return result >>> 0; } toString() { return "" + symbolName(this._opcode) + " " + this._args.join(", "); } }