singrdk/base/Kernel/Singularity.Hal.Acpi/AmlInterpreter/AmlStackIR.cs

1581 lines
46 KiB
C#
Raw Normal View History

2008-11-17 18:29:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Microsoft Research Singularity
//
// The AML stack IR is a proprietary linearized representation of an AML method.
// By converting the AML to a linearized IR, we can deal with cooperative
// multithreading more easily, because it's easier to represent and explicitly
// store the current state of the interpreter. This transformation also provides
// an opportunity to eliminate redundancies in the original representation.
using System;
using System.Collections;
using System.Diagnostics;
using Node = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.Node;
using NodePath = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.NodePath;
using AbsoluteNodePath = Microsoft.Singularity.Hal.Acpi.AcpiNamespace.AbsoluteNodePath;
using Microsoft.Singularity.Hal.Acpi.AcpiObject;
using Microsoft.Singularity.Hal.Acpi.StackIR;
using Microsoft.Singularity.Hal.Acpi.AmlParserUnions;
namespace Microsoft.Singularity.Hal.Acpi.StackIR
{
public abstract class StackIRNode
{
public abstract void Accept(StackIRNodeVisitor v);
}
public class Jump : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
int target;
public int Target {
get
{
return target;
}
set
{
target = value;
}
}
}
public class JumpIfNonZero : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
int thenTarget;
public int ThenTarget {
get
{
return thenTarget;
}
set
{
thenTarget = value;
}
}
}
public class PushArgObj : StackIRNode
{
int argNum;
public PushArgObj(int argNum)
{
this.argNum = argNum;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public int ArgNum
{
get
{
return argNum;
}
}
}
public class PushLocalObj : StackIRNode
{
int localNum;
public PushLocalObj(int localNum)
{
this.localNum = localNum;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public int LocalNum
{
get
{
return localNum;
}
}
}
public class PushDebugObj : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class PushNodePath : StackIRNode
{
NodePath value;
public PushNodePath(NodePath value)
{
this.value = value;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public NodePath Value
{
get
{
return value;
}
}
}
public class PushConst : StackIRNode
{
AcpiObject.AcpiObject value;
public PushConst(AcpiObject.AcpiObject value)
{
this.value = value;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public AcpiObject.AcpiObject Value
{
get
{
return value;
}
}
}
public class Discard : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
// Store a value in a location *and* push it on the stack
public class Store : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class MethodCall : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Index : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class ShiftLeft : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class ShiftRight : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Concatenate : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Add : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Subtract : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Multiply : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Divide : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Remainder : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class FindSetLeftBit : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class FindSetRightBit : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class SizeOf : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class LogicalOp : StackIRNode
{
public enum Op
{
Less,
LessEq,
Equal,
Greater,
GreaterEq,
And,
Or,
Not
}
Op op;
public LogicalOp(Op op)
{
this.op = op;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public Op Operator
{
get
{
return op;
}
}
}
public class BitOp : StackIRNode
{
public enum Op
{
And,
Or,
NAnd,
NOr,
Not,
XOr
}
Op op;
public BitOp(Op op)
{
this.op = op;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public Op Operator
{
get
{
return op;
}
}
}
public class Return : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class CreateField : StackIRNode
{
NodePath nodePath;
public CreateField(NodePath nodePath)
{
this.nodePath = nodePath;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
}
public class DefBuffer : StackIRNode
{
byte[] initializer;
public DefBuffer(byte[] initializer)
{
this.initializer = initializer;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public byte[] Initializer
{
get
{
return (byte[])initializer.Clone();
}
}
}
public class DefName : StackIRNode
{
NodePath nodePath;
public DefName(NodePath nodePath)
{
this.nodePath = nodePath;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
}
public class Load : StackIRNode
{
NodePath nodePath;
public Load(NodePath nodePath)
{
this.nodePath = nodePath;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
}
public class Stall : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Match : StackIRNode
{
AmlParser.MatchOpcode matchOp1, matchOp2;
public Match(AmlParser.MatchOpcode matchOp1, AmlParser.MatchOpcode matchOp2)
{
this.matchOp1 = matchOp1;
this.matchOp2 = matchOp2;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class DerefOf : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Package : StackIRNode
{
int numElements;
public Package(int numElements)
{
this.numElements = numElements;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Notify : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Sleep : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class RefOf : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class JumpIfNodePathExists : StackIRNode
{
private NodePath nodePath;
public JumpIfNodePathExists(NodePath nodePath)
{
this.nodePath = nodePath;
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
int thenTarget;
public int ThenTarget {
get
{
return thenTarget;
}
set
{
thenTarget = value;
}
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class OperationRegion : StackIRNode
{
RegionSpace operationSpace;
NodePath nodePath;
public OperationRegion(RegionSpace operationSpace, NodePath nodePath)
{
this.operationSpace = operationSpace;
this.nodePath = nodePath;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public RegionSpace OperationSpace
{
get
{
return operationSpace;
}
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
}
public class Field : StackIRNode
{
AmlParser.FieldFlags fieldFlags;
NodePath nodePath;
FieldElement[] fieldElements;
public Field(AmlParser.FieldFlags fieldFlags, NodePath nodePath, FieldElement[] fieldElements)
{
this.fieldFlags = fieldFlags;
this.nodePath = nodePath;
this.fieldElements = fieldElements;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
public AmlParser.FieldFlags FieldFlags
{
get
{
return fieldFlags;
}
}
public NodePath NodePath
{
get
{
return nodePath;
}
}
public FieldElement[] FieldElements
{
get
{
return fieldElements;
}
}
}
public class Acquire : StackIRNode
{
ushort timeout;
public Acquire(ushort timeout)
{
this.timeout = timeout;
}
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class Release : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class ToBuffer : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class ToInteger : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public class ToString : StackIRNode
{
public override void Accept(StackIRNodeVisitor v)
{
v.Visit(this);
}
}
public abstract class StackIRNodeVisitor
{
public abstract void Visit(Jump node);
public abstract void Visit(JumpIfNonZero node);
public abstract void Visit(JumpIfNodePathExists node);
public abstract void Visit(PushArgObj node);
public abstract void Visit(PushLocalObj node);
public abstract void Visit(PushDebugObj node);
public abstract void Visit(PushNodePath node);
public abstract void Visit(PushConst node);
public abstract void Visit(Discard node);
public abstract void Visit(Store node);
public abstract void Visit(MethodCall node);
public abstract void Visit(Index node);
public abstract void Visit(Add node);
public abstract void Visit(Subtract node);
public abstract void Visit(Multiply node);
public abstract void Visit(Divide node);
public abstract void Visit(Remainder node);
public abstract void Visit(ShiftLeft node);
public abstract void Visit(ShiftRight node);
public abstract void Visit(Concatenate node);
public abstract void Visit(LogicalOp node);
public abstract void Visit(BitOp node);
public abstract void Visit(Return node);
public abstract void Visit(CreateField node);
public abstract void Visit(FindSetLeftBit node);
public abstract void Visit(FindSetRightBit node);
public abstract void Visit(SizeOf node);
public abstract void Visit(DefName node);
public abstract void Visit(Load node);
public abstract void Visit(Stall node);
public abstract void Visit(Match node);
public abstract void Visit(DerefOf node);
public abstract void Visit(Package node);
public abstract void Visit(DefBuffer node);
public abstract void Visit(Notify node);
public abstract void Visit(Sleep node);
public abstract void Visit(RefOf node);
public abstract void Visit(OperationRegion node);
public abstract void Visit(Field node);
public abstract void Visit(Acquire node);
public abstract void Visit(Release node);
public abstract void Visit(ToBuffer node);
public abstract void Visit(ToInteger node);
public abstract void Visit(ToString node);
}
}
namespace Microsoft.Singularity.Hal.Acpi
{
public class AmlToStackIRException : Exception
{
// TODO
}
public class AmlToStackIRVisitor : AmlParserNodeVisitor
{
private class StackIRNodeList
{
ArrayList list = new ArrayList();
public void Add(StackIRNode node) {
list.Add(node);
}
public StackIRNode[] ToArray() {
return (StackIRNode[])list.ToArray(typeof(StackIRNode));
}
public StackIRNode Last
{
get
{
return (StackIRNode)list[list.Count - 1];
}
}
public int Count
{
get
{
return list.Count;
}
}
}
StackIRNodeList result = new StackIRNodeList();
public StackIRNode[] Result
{
get
{
// Tack on a return of an uninitialized object at the end
// so it doesn't run off the end.
result.Add(new PushConst(new UninitializedObject()));
result.Add(new Return());
return result.ToArray();
}
}
public override void UnhandledNodeType(string nodeTypeName)
{
throw new AmlToStackIRException();
}
public void VisitSequence(AmlParserNode[] nodeSequence)
{
if (nodeSequence == null) {
return;
}
foreach (AmlParserNode node in nodeSequence) {
node.Accept(this);
DiscardResults();
}
}
public void DiscardResults()
{
// Certain operations produce results in contexts where we
// don't need them. This throws them away if so.
if (result.Count > 0 && result.Last is Store) {
result.Add(new Discard());
}
}
public void VisitSequenceReverse(AmlParserNode[] nodeSequence)
{
for(int i = nodeSequence.Length - 1; i >= 0; i--) {
nodeSequence[i].Accept(this);
}
}
public override void Visit(AmlParser.DefIfElse defIfElse)
{
// We create a sequence like this:
// (push predicate)
// jump if nonzero to thenBranch
// (else branch instructions)
// jump to end
// elseBranch:
// (then branch instructions)
// end:
defIfElse.predicate.Accept(this);
JumpIfNonZero thenJump = new JumpIfNonZero();
result.Add(thenJump);
defIfElse.defElse.Accept(this);
Jump jumpOverThenBrach = new Jump();
result.Add(jumpOverThenBrach);
thenJump.ThenTarget = result.Count;
VisitSequence(defIfElse.termList);
jumpOverThenBrach.Target = result.Count;
}
public override void Visit(AmlParser.Predicate predicate)
{
predicate.integer.Accept(this);
}
public override void Visit(AmlParser.DefElse defElse)
{
VisitSequence(defElse.termList);
}
public override void Visit(AmlParser.ArgObj argObj)
{
result.Add(new PushArgObj(argObj.op));
}
public override void Visit(AmlParser.LocalObj localObj)
{
result.Add(new PushLocalObj(localObj.op));
}
public override void Visit(AmlParser.IndexValue indexValue)
{
indexValue.integer.Accept(this);
}
public override void Visit(AmlParser.ShiftCount shiftCount)
{
shiftCount.integer.Accept(this);
}
public override void Visit(AmlParser.BuffPkgStrObj buffPkgStrObj)
{
buffPkgStrObj.termArg.Accept(this);
}
public override void Visit(AmlParser.Target target)
{
target.superName.Accept(this);
}
public override void Visit(AmlParser.Operand operand)
{
operand.integer.Accept(this);
}
public override void Visit(AmlParser.ArgObject argObject)
{
argObject.dataRefObject.Accept(this);
}
public override void Visit(AmlParser.BitIndex bitIndex)
{
bitIndex.integer.Accept(this);
}
public override void Visit(AmlParser.ByteIndex byteIndex)
{
byteIndex.integer.Accept(this);
}
public override void Visit(AmlParser.SourceBuff sourceBuff)
{
sourceBuff.buffer.Accept(this);
}
public override void Visit(AmlParser.StartIndex startIndex)
{
startIndex.integer.Accept(this);
}
public override void Visit(AmlParser.ObjReference objReference)
{
objReference.termArg.Accept(this);
}
public override void Visit(AmlParser.SearchPkg searchPkg)
{
searchPkg.package.Accept(this);
}
public override void Visit(AmlParser.NumBits numBits)
{
numBits.integer.Accept(this);
}
public override void Visit(AmlParser.NotifyValue notifyValue)
{
notifyValue.integer.Accept(this);
}
public override void Visit(AmlParser.NotifyObject notifyObject)
{
notifyObject.superName.Accept(this);
}
public override void Visit(AmlParser.MsecTime msecTime)
{
msecTime.integer.Accept(this);
}
public override void Visit(AmlParser.RegionLen regionLen)
{
regionLen.integer.Accept(this);
}
public override void Visit(AmlParser.RegionOffset regionOffset)
{
regionOffset.integer.Accept(this);
}
public override void Visit(AmlParser.MutexObject mutexObject)
{
mutexObject.superName.Accept(this);
}
public override void Visit(AmlParser.LengthArg lengthArg)
{
lengthArg.integer.Accept(this);
}
public override void Visit(AmlParser.DDBHandleObject ddbHandleObject)
{
ddbHandleObject.superName.Accept(this);
}
public override void Visit(AmlParser.UsecTime usecTime)
{
usecTime.byteData.Accept(this);
}
public override void Visit(AmlParser.Dividend dividend)
{
dividend.integer.Accept(this);
}
public override void Visit(AmlParser.Divisor divisor)
{
divisor.integer.Accept(this);
}
public override void Visit(AmlParser.Remainder remainder)
{
remainder.target.Accept(this);
}
public override void Visit(AmlParser.Quotient quotient)
{
quotient.target.Accept(this);
}
public override void Visit(AmlParser.Data data)
{
data.computationalData.Accept(this);
}
public override void Visit(AmlParser.DefStore defStore)
{
defStore.superName.Accept(this);
defStore.termArg.Accept(this);
result.Add(new Store());
}
public override void Visit(AmlParser.NameString nameString)
{
result.Add(new PushNodePath(nameString.nodePath));
}
public override void Visit(ComputationalData computationalData)
{
switch (computationalData.Tag) {
case ComputationalData.TagValue.ByteConst:
byte byteConst = computationalData.GetAsByteConst();
result.Add(new PushConst(new AcpiObject.Integer(byteConst)));
break;
case ComputationalData.TagValue.WordConst:
UInt16 wordConst = computationalData.GetAsWordConst();
result.Add(new PushConst(new AcpiObject.Integer(wordConst)));
break;
case ComputationalData.TagValue.DWordConst:
UInt32 dWordConst = computationalData.GetAsDWordConst();
result.Add(new PushConst(new AcpiObject.Integer(dWordConst)));
break;
case ComputationalData.TagValue.QWordConst:
UInt64 qWordConst = computationalData.GetAsQWordConst();
result.Add(new PushConst(new AcpiObject.Integer(qWordConst)));
break;
case ComputationalData.TagValue.StringConst:
string stringConst = computationalData.GetAsStringConst();
result.Add(new PushConst(new AcpiObject.String(stringConst)));
break;
case ComputationalData.TagValue.ConstObj:
AmlParser.ConstObj constObj = computationalData.GetAsConstObj();
switch (constObj.op) {
case AmlParser.ZeroOp:
result.Add(new PushConst(AcpiObject.IntegerConstant.Zero));
break;
case AmlParser.OneOp:
result.Add(new PushConst(AcpiObject.IntegerConstant.One));
break;
case AmlParser.OnesOp:
result.Add(new PushConst(AcpiObject.IntegerConstant.Ones));
break;
}
break;
case ComputationalData.TagValue.RevisionOp:
result.Add(new PushConst(AcpiObject.IntegerConstant.Revision));
break;
case ComputationalData.TagValue.DefBuffer:
AmlParser.DefBuffer defBuffer = computationalData.GetAsDefBuffer();
defBuffer.Accept(this);
break;
default:
Debug.Assert(false, "Unhandled alternative in switch over 'ComputationalData'");
break;
}
}
public override void Visit(AmlParser.DefName defName)
{
defName.dataRefObject.Accept(this);
result.Add(new DefName(defName.nameString.nodePath));
}
public override void Visit(AmlParser.UserTermObj userTermObj)
{
if (userTermObj.termArgList.Length > 0) {
VisitSequenceReverse(userTermObj.termArgList);
result.Add(new PushNodePath(userTermObj.nameString.nodePath));
result.Add(new MethodCall());
}
else {
// The interpreter will determine at runtime if this is a method or not
result.Add(new PushNodePath(userTermObj.nameString.nodePath));
}
}
public override void Visit(AmlParser.DefCreateField defCreateField)
{
defCreateField.numBits.Accept(this);
defCreateField.bitIndex.Accept(this);
defCreateField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateField.nameString.nodePath));
}
public override void Visit(AmlParser.DefCreateBitField defCreateBitField)
{
result.Add(new PushConst(new AcpiObject.Integer(1))); // number of bits
defCreateBitField.bitIndex.Accept(this);
defCreateBitField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateBitField.nameString.nodePath));
}
public override void Visit(AmlParser.DefCreateByteField defCreateByteField)
{
result.Add(new PushConst(new AcpiObject.Integer(8))); // number of bits
// Multiply byte index by 8 to get bit index
defCreateByteField.byteIndex.Accept(this);
result.Add(new PushConst(new AcpiObject.Integer(8)));
result.Add(new Multiply());
defCreateByteField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateByteField.nameString.nodePath));
}
public override void Visit(AmlParser.DefCreateWordField defCreateWordField)
{
result.Add(new PushConst(new AcpiObject.Integer(16))); // number of bits
// Multiply byte index by 8 to get bit index
defCreateWordField.byteIndex.Accept(this);
result.Add(new PushConst(new AcpiObject.Integer(8)));
result.Add(new Multiply());
defCreateWordField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateWordField.nameString.nodePath));
}
public override void Visit(AmlParser.DefCreateDWordField defCreateDWordField)
{
result.Add(new PushConst(new AcpiObject.Integer(32))); // number of bits
// Multiply byte index by 8 to get bit index
defCreateDWordField.byteIndex.Accept(this);
result.Add(new PushConst(new AcpiObject.Integer(8)));
result.Add(new Multiply());
defCreateDWordField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateDWordField.nameString.nodePath));
}
public override void Visit(AmlParser.DefCreateQWordField defCreateQWordField)
{
result.Add(new PushConst(new AcpiObject.Integer(64))); // number of bits
// Multiply byte index by 8 to get bit index
defCreateQWordField.byteIndex.Accept(this);
result.Add(new PushConst(new AcpiObject.Integer(8)));
result.Add(new Multiply());
defCreateQWordField.sourceBuff.Accept(this);
result.Add(new CreateField(defCreateQWordField.nameString.nodePath));
}
public override void Visit(AmlParser.DefBuffer defBuffer)
{
defBuffer.bufferSize.integer.Accept(this);
result.Add(new DefBuffer(defBuffer.byteList));
}
public override void Visit(AmlParser.DefDecrement defDecrement)
{
defDecrement.superName.Accept(this); // target
result.Add(new PushConst(new AcpiObject.Integer(1)));
defDecrement.superName.Accept(this); // left
result.Add(new Subtract());
result.Add(new Store());
}
public override void Visit(AmlParser.DefIncrement defIncrement)
{
defIncrement.superName.Accept(this); // target
result.Add(new PushConst(new AcpiObject.Integer(1)));
defIncrement.superName.Accept(this); // left
result.Add(new Add());
result.Add(new Store());
}
public override void Visit(AmlParser.DefPackage defPackage)
{
VisitSequenceReverse(defPackage.packageElementList);
result.Add(new Microsoft.Singularity.Hal.Acpi.StackIR.Package(
defPackage.numElements.byteData));
}
public override void Visit(AmlParser.DefFindSetLeftBit defFindSetLeftBit)
{
VisitUnaryOperator(defFindSetLeftBit.operand, defFindSetLeftBit.target, new FindSetLeftBit());
}
public override void Visit(AmlParser.DefFindSetRightBit defFindSetRightBit)
{
VisitUnaryOperator(defFindSetRightBit.operand, defFindSetRightBit.target, new FindSetRightBit());
}
public override void Visit(AmlParser.DefSizeOf defSizeOf)
{
defSizeOf.superName.Accept(this);
result.Add(new SizeOf());
}
public override void Visit(AmlParser.DefIndex defIndex)
{
VisitBinaryOperator(defIndex.buffPkgStrObj, defIndex.indexValue, defIndex.target, new Index());
}
public override void Visit(AmlParser.DefAdd defAdd)
{
VisitBinaryOperator(defAdd.leftOperand, defAdd.rightOperand, defAdd.target, new Add());
}
public override void Visit(AmlParser.DefSubtract defSubtract)
{
VisitBinaryOperator(defSubtract.leftOperand, defSubtract.rightOperand, defSubtract.target, new Subtract());
}
public override void Visit(AmlParser.DefMultiply defMultiply)
{
VisitBinaryOperator(defMultiply.leftOperand, defMultiply.rightOperand, defMultiply.target, new Multiply());
}
public override void Visit(AmlParser.DefDivide defDivide)
{
const int divisorLocal = AmlStackFrame.FirstReservedLocal;
const int dividendLocal = divisorLocal + 1;
// Push all operands on stack first, since subexpressions may use the reserved locals
if (!IsNullTarget(defDivide.remainder.target)) {
defDivide.remainder.target.Accept(this);
}
if (!IsNullTarget(defDivide.quotient.target)) {
defDivide.quotient.target.Accept(this);
}
result.Add(new PushLocalObj(divisorLocal));
defDivide.divisor.Accept(this);
result.Add(new PushLocalObj(dividendLocal));
defDivide.dividend.Accept(this);
result.Add(new Store()); // Store dividend expression in dividendLocal
result.Add(new Store()); // store divisor expression in divisorLocal
if (!IsNullTarget(defDivide.quotient.target)) {
result.Add(new PushLocalObj(divisorLocal));
result.Add(new PushLocalObj(dividendLocal));
result.Add(new Divide());
result.Add(new Store()); // Store quotient in quotient.target
}
if (!IsNullTarget(defDivide.remainder.target)) {
result.Add(new PushLocalObj(divisorLocal));
result.Add(new PushLocalObj(dividendLocal));
result.Add(new Remainder());
result.Add(new Store()); // Store remainder in remainder.target
}
}
public override void Visit(AmlParser.DefShiftLeft defShiftLeft)
{
VisitBinaryOperator(defShiftLeft.operand, defShiftLeft.shiftCount, defShiftLeft.target, new ShiftLeft());
}
public override void Visit(AmlParser.DefShiftRight defShiftRight)
{
VisitBinaryOperator(defShiftRight.operand, defShiftRight.shiftCount, defShiftRight.target, new ShiftRight());
}
public override void Visit(AmlParser.DefConcat defConcat)
{
VisitBinaryOperator(defConcat.leftData, defConcat.rightData, defConcat.target, new Concatenate());
}
public override void Visit(AmlParser.DebugObj debugObj)
{
result.Add(new PushDebugObj());
}
public override void Visit(AmlParser.DefDerefOf defDerefOf)
{
defDerefOf.objReference.Accept(this);
result.Add(new DerefOf());
}
public override void Visit(AmlParser.DefMatch defMatch)
{
defMatch.startIndex.Accept(this);
defMatch.operand2.Accept(this);
defMatch.operand1.Accept(this);
defMatch.searchPkg.Accept(this);
result.Add(new Match(defMatch.matchOpcode1, defMatch.matchOpcode2));
}
public override void Visit(AmlParser.DefLEqual defLEqual)
{
defLEqual.rightOperand.Accept(this);
defLEqual.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.Equal));
}
public override void Visit(AmlParser.DefLLess defLLess)
{
defLLess.rightOperand.Accept(this);
defLLess.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.Less));
}
public override void Visit(AmlParser.DefLLessEqual defLLessEqual)
{
defLLessEqual.rightOperand.Accept(this);
defLLessEqual.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.LessEq));
}
public override void Visit(AmlParser.DefLGreater defLGreater)
{
defLGreater.rightOperand.Accept(this);
defLGreater.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.Greater));
}
public override void Visit(AmlParser.DefLGreaterEqual defLGreaterEqual)
{
defLGreaterEqual.rightOperand.Accept(this);
defLGreaterEqual.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.GreaterEq));
}
public override void Visit(AmlParser.DefLAnd defLAnd)
{
defLAnd.rightOperand.Accept(this);
defLAnd.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.And));
}
public override void Visit(AmlParser.DefLOr defLOr)
{
defLOr.rightOperand.Accept(this);
defLOr.leftOperand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.Or));
}
public override void Visit(AmlParser.DefLNot defLNot)
{
defLNot.operand.Accept(this);
result.Add(new LogicalOp(LogicalOp.Op.Not));
}
public override void Visit(AmlParser.DefAnd defAnd)
{
VisitBinaryOperator(defAnd.leftOperand, defAnd.rightOperand, defAnd.target,
new BitOp(BitOp.Op.And));
}
public override void Visit(AmlParser.DefOr defOr)
{
VisitBinaryOperator(defOr.leftOperand, defOr.rightOperand, defOr.target,
new BitOp(BitOp.Op.Or));
}
public override void Visit(AmlParser.DefNAnd defNAnd)
{
VisitBinaryOperator(defNAnd.leftOperand, defNAnd.rightOperand, defNAnd.target,
new BitOp(BitOp.Op.NAnd));
}
public override void Visit(AmlParser.DefNOr defNOr)
{
VisitBinaryOperator(defNOr.leftOperand, defNOr.rightOperand, defNOr.target,
new BitOp(BitOp.Op.NOr));
}
public override void Visit(AmlParser.DefNot defNot)
{
VisitUnaryOperator(defNot.operand, defNot.target,
new BitOp(BitOp.Op.Not));
}
public override void Visit(AmlParser.DefXOr defXOr)
{
VisitBinaryOperator(defXOr.leftOperand, defXOr.rightOperand, defXOr.target,
new BitOp(BitOp.Op.XOr));
}
private void VisitBinaryOperator(AmlParserNode left, AmlParserNode right,
AmlParser.Target target, StackIRNode stackNode)
{
if (IsNullTarget(target)) {
right.Accept(this);
left.Accept(this);
result.Add(stackNode);
}
else {
target.Accept(this);
right.Accept(this);
left.Accept(this);
result.Add(stackNode);
result.Add(new Store());
}
}
private void VisitUnaryOperator(AmlParserNode operand,
AmlParser.Target target, StackIRNode stackNode)
{
if (IsNullTarget(target)) {
operand.Accept(this);
result.Add(stackNode);
}
else {
target.Accept(this);
operand.Accept(this);
result.Add(stackNode);
result.Add(new Store());
}
}
public bool IsNullTarget(AmlParser.Target target)
{
SuperName superName = target.superName;
if (superName.Tag != SuperName.TagValue.SimpleName) {
return false;
}
SimpleName simpleName = superName.GetAsSimpleName();
if (simpleName.Tag != SimpleName.TagValue.NameString) {
return false;
}
NodePath nodePath = simpleName.GetAsNameString().nodePath;
return (!nodePath.IsAbsolute &&
nodePath.NumParentPrefixes == 0 &&
nodePath.NameSegments.Length == 0);
}
public override void Visit(AmlParser.DefReturn defReturn)
{
defReturn.argObject.Accept(this);
result.Add(new Return());
}
public override void Visit(AmlParser.DefWhile defWhile)
{
// We create a sequence like this:
// jump to pushPredicate
// loopback:
// (body instructions)
// pushPredicate:
// (push predicate)
// jump if not zero to loopback
Jump jumpToPushPredicate = new Jump();
JumpIfNonZero jumpLoopBack = new JumpIfNonZero();
result.Add(jumpToPushPredicate);
jumpLoopBack.ThenTarget = result.Count;
VisitSequence(defWhile.termList);
jumpToPushPredicate.Target = result.Count;
defWhile.predicate.Accept(this);
result.Add(jumpLoopBack);
}
public override void Visit(AmlParser.DefNotify defNotify)
{
defNotify.notifyValue.Accept(this);
defNotify.notifyObject.Accept(this);
result.Add(new Notify());
}
public override void Visit(AmlParser.DefSleep defSleep)
{
defSleep.msecTime.Accept(this);
result.Add(new Sleep());
}
public override void Visit(AmlParser.DefCondRefOf defCondRefOf)
{
// We create a sequence like this:
// jump if node path exists to existsBranch
// (push 0)
// jump to end
// existsBranch:
// (execute RefOf instruction and store to target)
// (push 1)
// end:
// The only SuperName that can fail to exist is a node path
if (defCondRefOf.superName.Tag == SuperName.TagValue.SimpleName &&
defCondRefOf.superName.GetAsSimpleName().Tag == SimpleName.TagValue.NameString) {
JumpIfNodePathExists existsJump = new JumpIfNodePathExists(
defCondRefOf.superName.GetAsSimpleName().GetAsNameString().nodePath);
result.Add(existsJump);
result.Add(new PushConst(new Integer(0)));
Jump jumpOverExistsBranch = new Jump();
result.Add(jumpOverExistsBranch);
existsJump.ThenTarget = result.Count;
defCondRefOf.target.Accept(this);
defCondRefOf.superName.Accept(this);
result.Add(new RefOf());
result.Add(new Store());
result.Add(new Discard());
result.Add(new PushConst(new Integer(1)));
jumpOverExistsBranch.Target = result.Count;
}
else {
defCondRefOf.target.Accept(this);
defCondRefOf.superName.Accept(this);
result.Add(new RefOf());
result.Add(new Store());
result.Add(new Discard());
result.Add(new PushConst(new Integer(1)));
}
}
public override void Visit(AmlParser.DefOpRegion defOpRegion)
{
defOpRegion.regionLen.Accept(this);
defOpRegion.regionOffset.Accept(this);
result.Add(new StackIR.OperationRegion((RegionSpace)defOpRegion.regionSpace.byteData,
defOpRegion.nameString.nodePath));
}
public override void Visit(AmlParser.DefField defField)
{
result.Add(new Field(defField.fieldFlags, defField.nameString.nodePath, defField.fieldList));
}
public override void Visit(AmlParser.DefAcquire defAcquire)
{
defAcquire.mutexObject.Accept(this);
result.Add(new Acquire(defAcquire.timeOut.wordData));
}
public override void Visit(AmlParser.DefRelease defRelease)
{
defRelease.mutexObject.Accept(this);
result.Add(new Release());
}
public override void Visit(AmlParser.DefToBuffer defToBuffer)
{
defToBuffer.target.Accept(this);
defToBuffer.operand.Accept(this);
result.Add(new ToBuffer());
}
public override void Visit(AmlParser.DefToInteger defToInteger)
{
defToInteger.target.Accept(this);
defToInteger.operand.Accept(this);
result.Add(new ToInteger());
}
public override void Visit(AmlParser.DefToString defToString)
{
defToString.target.Accept(this);
defToString.lengthArg.Accept(this);
defToString.termArg.Accept(this);
result.Add(new ToString());
}
public override void Visit(AmlParser.DefNoop defNoop)
{
// Do nothing
}
public override void Visit(AmlParser.DefLoad defLoad)
{
defLoad.ddbHandleObject.Accept(this);
result.Add(new Load(defLoad.nameString.nodePath));
}
public override void Visit(AmlParser.DefStall defStall)
{
defStall.usecTime.Accept(this);
result.Add(new Stall());
}
}
}