1581 lines
46 KiB
C#
1581 lines
46 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// 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());
|
||
|
}
|
||
|
}
|
||
|
}
|