using System.Collections; using System.Collections.Generic; using System.Diagnostics; namespace dnlib.IR { public class IRBasicBlock { public IRBasicBlock nextIrbb; public BasicBlock ilbb; private readonly List _insts = new List(); private readonly List _inboundVars = new List(); private readonly List _outboundVars = new List(); private readonly List _inboundBbs = new List(); private readonly List _outboundBbs = new List(); public List Instructions => _insts; public IList InboundVariables => _inboundVars; public IList OutboundVariables => _outboundVars; public IList InboundBasicBlocks => _inboundBbs; public IList OutboundBasicBlocks => _outboundBbs; public int IROffset { get; set; } = -1; public void AddInstruction(IRInstruction inst) { VerifyInstruction(inst); _insts.Add(inst); } private void VerifyInstruction(IRInstruction inst) { var meta = InstructionMeta.Get(inst.opcode); if (meta.args.Count != inst.args.Count) { Debug.Fail($"Instruction {inst.opcode} has {inst.args.Count} arguments, but {meta.args.Count} are expected."); } for (int i = 0; i < inst.args.Count; i++) { var arg = inst.args[i]; var argMeta = meta.args[i]; if ((argMeta.flag & ArgumentMetaFlag.Constant) != 0) { if (!(arg is InstructionArgumentConstant)) { Debug.Fail($"Argument {i} of instruction {inst.opcode} should be constant."); } } else if ((argMeta.flag & ArgumentMetaFlag.Variadic) != 0) { if (!(arg is InstructionArgumentMultiVariable)) { Debug.Fail($"Argument {i} of instruction {inst.opcode} should be variable."); } } else { if (arg != null && !(arg is InstructionArgumentVariable)) { Debug.Fail($"Argument {i} of instruction {inst.opcode} should be variable."); } } } if ((meta.flag & (InstructionFlag.InlineToken | InstructionFlag.InlineOffset)) != 0) { Debug.Assert(inst.inlineOperand != null, "inline operand should be null"); } } //public void PushEvalStack(VariableInfo v) { // _inboundVars.Add(v); //} //public void PushEvalStack(IList vs) { // _inboundVars.AddRange(vs); //} public void SetInboundVariable(VariableInfo variable) { SetInboundVariables(new VariableInfo[] { variable }); } public void SetInboundVariables(IList vs) { if (_inboundVars.Count == 0) { _inboundVars.AddRange(vs); } else { Debug.Assert(_inboundVars.Count == vs.Count); } } public void SetOutboundVariables(IList vs) { _outboundVars.Clear(); _outboundVars.AddRange(vs); } public void AddOutboundBasicBlock(IRBasicBlock target) { if (target != this && !_outboundBbs.Contains(target)) { _outboundBbs.Add(target); target._inboundBbs.Add(this); } } } }