/// <summary>Pops a labelled block from the stack.</summary> public LabelledBlock PopBlock() { // Pop it: LabelledBlock block = BlockStack.Pop(); Instruction blockInstruction = block.Instruction; // Transfer all instructions on the FunctionBody.Root stack // into blockInstruction up to but not // including a match on blockInstruction. CompilerStack <Instruction> stack = FunctionBody.Root; for (int i = 0; i < stack.Count; i++) { if (stack.Peek() == blockInstruction) { break; } // Push it into the block: blockInstruction.PrependInput(stack.Pop()); } return(block); }
public FunctionBody(Reader reader, int index) { // Apply current body: reader.FunctionBody = this; // Clear the block stack: reader.BlockStack.Count = 0; // Get the sig: Signature = reader.Module.FunctionSection.Types[index]; // Sizes: int bodySize = (int)reader.VarUInt32(); // Max (bodySize includes locals); -1 to exclude the final byte: long max = reader.Position + bodySize - 1; // Locals: int localCount = (int)reader.VarUInt32(); List <FunctionLocal> ilLocal = new List <FunctionLocal>(localCount); Locals = ilLocal; for (int i = 0; i < localCount; i++) { // # of this and its type: int count = (int)reader.VarUInt32(); Type type = reader.ValueTypeConverted(); for (int c = 0; c < count; c++) { // Define it: ilLocal.Add(new FunctionLocal(type)); } } // Create the root block instruction (no opcode): Root = new CompilerStack <Instruction>(); // While there is more code.. while (reader.Position < max) { // Opcode: OpCode opcode = OpCodes.Get(reader.ReadByte()); if (opcode == null || opcode.OnOutputIL == null) { throw new Exception("WebAssembly function body went out of alignment (Function " + Signature.Index + ")"); } if (opcode.Ignored) { // Don't create - just load immediates: if (opcode.HasImmediates) { opcode.ReadImmediates(reader); } } else { // Create an instruction: Instruction instruction = new Instruction(); instruction.OpCode = opcode; // Apply default in/out: instruction.InputCount = opcode.InputCount; instruction.ReturnType = opcode.ReturnType; reader.Instruction = instruction; // Add all of its immediates: if (opcode.HasImmediates) { // Load the immediates now: instruction.Immediates = opcode.ReadImmediates(reader); } // Manage the stack now - if it has a fixed number of inputs // we pop those from the stack and add them to the instruction: for (int i = 0; i < instruction.InputCount; i++) { // Add the input to the front of the input set: instruction.PrependInput(Root.Pop()); } if (instruction.ReturnType != typeof(void)) { // Push to Root: Root.Push(instruction); } } } if (reader.ReadByte() != 0x0b) { throw new Exception("A function body did not end correctly."); } }