/* * 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 Arg {
constructor()
{ this._kind = Arg.Invalid;
}
static isAnyUse(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseDef: case Arg.UseZDef: case Arg.LateUse: case Arg.LateColdUse: case Arg.Scratch: returntrue; case Arg.Def: case Arg.ZDef: case Arg.UseAddr: case Arg.EarlyDef: returnfalse; default: thrownew Error("Bad role");
}
}
static isColdUse(role)
{ switch (role) { case Arg.ColdUse: case Arg.LateColdUse: returntrue; case Arg.Use: case Arg.UseDef: case Arg.UseZDef: case Arg.LateUse: case Arg.Def: case Arg.ZDef: case Arg.UseAddr: case Arg.Scratch: case Arg.EarlyDef: returnfalse; default: thrownew Error("Bad role");
}
}
static cooled(role)
{ switch (role) { case Arg.ColdUse: case Arg.LateColdUse: case Arg.UseDef: case Arg.UseZDef: case Arg.Def: case Arg.ZDef: case Arg.UseAddr: case Arg.Scratch: case Arg.EarlyDef: return role; case Arg.Use: return Arg.ColdUse; case Arg.LateUse: return Arg.LateColdUse; default: thrownew Error("Bad role");
}
}
static isEarlyUse(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseDef: case Arg.UseZDef: returntrue; case Arg.Def: case Arg.ZDef: case Arg.UseAddr: case Arg.LateUse: case Arg.LateColdUse: case Arg.Scratch: case Arg.EarlyDef: returnfalse; default: thrownew Error("Bad role");
}
}
static isLateUse(role)
{ switch (role) { case Arg.LateUse: case Arg.LateColdUse: case Arg.Scratch: returntrue; case Arg.ColdUse: case Arg.Use: case Arg.UseDef: case Arg.UseZDef: case Arg.Def: case Arg.ZDef: case Arg.UseAddr: case Arg.EarlyDef: returnfalse; default: thrownew Error("Bad role");
}
}
static isAnyDef(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseAddr: case Arg.LateUse: case Arg.LateColdUse: returnfalse; case Arg.Def: case Arg.UseDef: case Arg.ZDef: case Arg.UseZDef: case Arg.EarlyDef: case Arg.Scratch: returntrue; default: thrownew Error("Bad role");
}
}
static isEarlyDef(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseAddr: case Arg.LateUse: case Arg.Def: case Arg.UseDef: case Arg.ZDef: case Arg.UseZDef: case Arg.LateColdUse: returnfalse; case Arg.EarlyDef: case Arg.Scratch: returntrue; default: thrownew Error("Bad role");
}
}
static isLateDef(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseAddr: case Arg.LateUse: case Arg.EarlyDef: case Arg.Scratch: case Arg.LateColdUse: returnfalse; case Arg.Def: case Arg.UseDef: case Arg.ZDef: case Arg.UseZDef: returntrue; default: thrownew Error("Bad role");
}
}
static isZDef(role)
{ switch (role) { case Arg.Use: case Arg.ColdUse: case Arg.UseAddr: case Arg.LateUse: case Arg.Def: case Arg.UseDef: case Arg.EarlyDef: case Arg.Scratch: case Arg.LateColdUse: returnfalse; case Arg.ZDef: case Arg.UseZDef: returntrue; default: thrownew Error("Bad role");
}
}
static conservativeWidth(type)
{ return type == GP ? Ptr : 64;
}
static minimumWidth(type)
{ return type == GP ? 8 : 32;
}
static bytes(width)
{ return width / 8;
}
static widthForBytes(bytes)
{ switch (bytes) { case 0: case 1: return 8; case 2: return 16; case 3: case 4: return 32; default: if (bytes > 8) thrownew Error("Bad number of bytes"); return 64;
}
}
static createTmp(tmp)
{
let result = new Arg();
result._kind = Arg.Tmp;
result._tmp = tmp; return result;
}
static createRelCond(condition)
{
let result = new Arg();
result._kind = Arg.RelCond;
result._condition = condition; return result;
}
static createResCond(condition)
{
let result = new Arg();
result._kind = Arg.ResCond;
result._condition = condition; return result;
}
static createDoubleCond(condition)
{
let result = new Arg();
result._kind = Arg.DoubleCond;
result._condition = condition; return result;
}
static createWidth(width)
{
let result = new Arg();
result._kind = Arg.Width;
result._width = width; return result;
}
static createSpecial()
{
let result = new Arg();
result._kind = Arg.Special; return result;
}
get kind() { returnthis._kind; }
get isTmp() { returnthis._kind == Arg.Tmp; }
get isImm() { returnthis._kind == Arg.Imm; }
get isBigImm() { returnthis._kind == Arg.BigImm; }
get isBitImm() { returnthis._kind == Arg.BitImm; }
get isBitImm64() { returnthis._kind == Arg.BitImm64; }
get isSomeImm()
{ switch (this._kind) { case Arg.Imm: case Arg.BitImm: returntrue; default: returnfalse;
}
}
get isSomeBigImm()
{ switch (this._kind) { case Arg.BigImm: case Arg.BitImm64: returntrue; default: returnfalse;
}
}
get isAddr() { returnthis._kind == Arg.Addr; }
get isStack() { returnthis._kind == Arg.Stack; }
get isCallArg() { returnthis._kind == Arg.CallArg; }
get isIndex() { returnthis._kind == Arg.Index; }
get isMemory()
{ switch (this._kind) { case Arg.Addr: case Arg.Stack: case Arg.CallArg: case Arg.Index: returntrue; default: returnfalse;
}
}
get isStackMemory()
{ switch (this._kind) { case Arg.Addr: returnthis._base == Reg.callFrameRegister
|| this._base == Reg.stackPointerRegister; case Arg.Stack: case Arg.CallArg: returntrue; default: returnfalse;
}
}
get isRelCond() { returnthis._kind == Arg.RelCond; }
get isResCond() { returnthis._kind == Arg.ResCond; }
get isDoubleCond() { returnthis._kind == Arg.DoubleCond; }
get isCondition()
{ switch (this._kind) { case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: returntrue; default: returnfalse;
}
}
get isWidth() { returnthis._kind == Arg.Width; }
get isSpecial() { returnthis._kind == Arg.Special; }
get isAlive() { returnthis.isTmp || this.isStack; }
get tmp()
{ if (this._kind != Arg.Tmp) thrownew Error("Called .tmp for non-tmp"); returnthis._tmp;
}
get value()
{ if (!this.isSomeImm) thrownew Error("Called .value for non-imm"); returnthis._value;
}
get lowValue()
{ if (!this.isSomeBigImm) thrownew Error("Called .lowValue for non-big-imm"); returnthis._lowValue;
}
get highValue()
{ if (!this.isSomeBigImm) thrownew Error("Called .highValue for non-big-imm"); returnthis._highValue;
}
get base()
{ switch (this._kind) { case Arg.Addr: case Arg.Index: returnthis._base; default: thrownew Error("Called .base for non-address");
}
}
get hasOffset() { returnthis.isMemory; }
get offset()
{ switch (this._kind) { case Arg.Addr: case Arg.Index: case Arg.Stack: case Arg.CallArg: returnthis._offset; default: thrownew Error("Called .offset for non-address");
}
}
get stackSlot()
{ if (this._kind != Arg.Stack) thrownew Error("Called .stackSlot for non-address"); returnthis._slot;
}
get index()
{ if (this._kind != Arg.Index) thrownew Error("Called .index for non-Index"); returnthis._index;
}
get scale()
{ if (this._kind != Arg.Index) thrownew Error("Called .scale for non-Index"); returnthis._scale;
}
get logScale()
{ return Arg.logScale(this.scale);
}
get width()
{ if (this._kind != Arg.Width) thrownew Error("Called .width for non-Width"); returnthis._width;
}
get isGPTmp() { returnthis.isTmp && this.tmp.isGP; }
get isFPTmp() { returnthis.isTmp && this.tmp.isFP; }
get isGP()
{ switch (this._kind) { case Arg.Imm: case Arg.BigImm: case Arg.BitImm: case Arg.BitImm64: case Arg.Addr: case Arg.Index: case Arg.Stack: case Arg.CallArg: case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: case Arg.Width: case Arg.Special: returntrue; case Arg.Tmp: returnthis.isGPTmp; case Arg.Invalid: returnfalse; default: thrownew Error("Bad kind");
}
}
get isFP()
{ switch (this._kind) { case Arg.Imm: case Arg.BitImm: case Arg.BitImm64: case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: case Arg.Width: case Arg.Special: case Arg.Invalid: returnfalse; case Arg.Addr: case Arg.Index: case Arg.Stack: case Arg.CallArg: case Arg.BigImm: returntrue; case Arg.Tmp: returnthis.isFPTmp; default: thrownew Error("Bad kind");
}
}
get hasType()
{ switch (this._kind) { case Arg.Imm: case Arg.BitImm: case Arg.BitImm64: case Arg.Tmp: returntrue; default: returnfalse;
}
}
get type()
{ returnthis.isGP ? GP : FP;
}
isType(type)
{ switch (type) { case Arg.GP: returnthis.isGP; case Arg.FP: returnthis.isFP; default: thrownew Error("Bad type");
}
}
isCompatibleType(other)
{ if (this.hasType) return other.isType(this.type); if (other.hasType) returnthis.isType(other.type); returntrue;
}
get isGPR() { returnthis.isTmp && this.tmp.isGPR; }
get gpr() { returnthis.tmp.gpr; }
get isFPR() { returnthis.isTmp && this.tmp.isFPR; }
get fpr() { returnthis.tmp.fpr; }
get isReg() { returnthis.isTmp && this.tmp.isReg; }
get reg() { returnthis.tmp.reg; }
isValidForm(width)
{ switch (this._kind) { case Arg.Invalid: returnfalse; case Arg.Tmp: returntrue; case Arg.Imm: return Arg.isValidImmForm(this.value); case Arg.BigImm: returntrue; case Arg.BitImm: return Arg.isValidBitImmForm(this.value); case Arg.BitImm64: return Arg.isValidBitImm64Form(this.value); case Arg.Addr: case Arg.Stack: case Arg.CallArg: return Arg.isValidAddrForm(this.offset, width); case Arg.Index: return Arg.isValidIndexForm(this.scale, this.offset, width); case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: case Arg.Width: case Arg.Special: returntrue; default: thrownew Error("Bad kind");
}
}
forEachTmpFast(func)
{ switch (this._kind) { case Arg.Tmp: {
let replacement; if (replacement = func(this._tmp)) return Arg.createTmp(replacement); break;
} case Arg.Addr: {
let replacement; if (replacement = func(this._base)) return Arg.createAddr(replacement, this._offset); break;
} case Arg.Index: {
let baseReplacement = func(this._base);
let indexReplacement = func(this._index); if (baseReplacement || indexReplacement) { return Arg.createIndex(
baseReplacement ? baseReplacement : this._base,
indexReplacement ? indexReplacement : this._index, this._scale, this._offset);
} break;
} default: break;
}
}
get condition()
{ switch (this._kind) { case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: returnthis._condition; default: thrownew Error("Called .condition for non-condition");
}
}
get isInvertible()
{ switch (this._kind) { case Arg.RelCond: case Arg.DoubleCold: returntrue; case Arg.ResCond: switch (this._condition) { case Zero: case NonZero: case Signed: case PositiveOrZero: returntrue; default: returnfalse;
} default: returnfalse;
}
}
static kindCode(kind)
{ switch (kind) { case Arg.Invalid: return 0; case Arg.Tmp: return 1; case Arg.Imm: return 2; case Arg.BigImm: return 3; case Arg.BitImm: return 4; case Arg.BitImm64: return 5; case Arg.Addr: return 6; case Arg.Stack: return 7; case Arg.CallArg: return 8; case Arg.Index: return 9; case Arg.RelCond: return 10; case Arg.ResCond: return 11; case Arg.DoubleCond: return 12; case Arg.Special: return 13; case Arg.WidthArg: return 14; default: thrownew Error("Bad kind");
}
}
hash()
{
let result = Arg.kindCode(this._kind);
switch (this._kind) { case Arg.Invalid: case Arg.Special: break; case Arg.Tmp:
result += this._tmp.hash();
result |= 0; break; case Arg.Imm: case Arg.BitImm:
result += this._value;
result |= 0; break; case Arg.BigImm: case Arg.BitImm64:
result += this._lowValue;
result |= 0;
result += this._highValue;
result |= 0; break; case Arg.CallArg:
result += this._offset;
result |= 0; break; case Arg.RelCond:
result += relCondCode(this._condition);
result |= 0; break; case Arg.ResCond:
result += resCondCode(this._condition);
result |= 0; break; case Arg.DoubleCond:
result += doubleCondCode(this._condition);
result |= 0; break; case Arg.WidthArg:
result += this._width;
result |= 0; break; case Arg.Addr:
result += this._offset;
result |= 0;
result += this._base.hash();
result |= 0; break; case Arg.Index:
result += this._offset;
result |= 0;
result += this._scale;
result |= 0;
result += this._base.hash();
result |= 0;
result += this._index.hash();
result |= 0; break; case Arg.Stack:
result += this._offset;
result |= 0;
result += this.stackSlot.index;
result |= 0; break;
}
return result >>> 0;
}
toString()
{ switch (this._kind) { case Arg.Invalid: return""; case Arg.Tmp: returnthis._tmp.toString(); case Arg.Imm: return"$" + this._value; case Arg.BigImm: case Arg.BitImm64: return"$0x" + this._highValue.toString(16) + ":" + this._lowValue.toString(16); case Arg.Addr: return"" + (this._offset ? this._offset : "") + "(" + this._base + ")"; case Arg.Index: return"" + (this._offset ? this._offset : "") + "(" + this._base + "," + this._index + (this._scale == 1 ? "" : "," + this._scale) + ")"; case Arg.Stack: return"" + (this._offset ? this._offset : "") + "(" + this._slot + ")"; case Arg.CallArg: return"" + (this._offset ? this._offset : "") + "(callArg)"; case Arg.RelCond: case Arg.ResCond: case Arg.DoubleCond: return symbolName(this._condition); case Arg.Special: return"special"; case Arg.Width: return"" + this._value; default: thrownew Error("Bad kind");
}
}
}
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.