/// <summary>Reads a set of func_types.</summary> public FuncType[] FuncTypes(int count, int globalOffset) { // Create FuncType[] set = new FuncType[count]; // Load each one: for (int i = 0; i < set.Length; i++) { // Load it: set[i] = new FuncType(this, i + globalOffset); } return(set); }
/// <summary>Get the imported method.</summary> public MethodInfo Get(Module module, out int paramCount, out Type returnType) { if (Signature == null) { // Get the signature: Signature = module.FunctionSection.Types[(int)Type]; } paramCount = Signature.ParameterCount; returnType = Signature.GetReturnType(); // If we're importing a compiling JS function then we // can potentially generate an overload which specifically // matches our given signature. if (ImportedMethod == null) { ImportedMethod = MapImport(module) as MethodInfo; } return(ImportedMethod); }
/// <summary>Compiles all the methods in this code section.</summary> public void Compile() { if (Bodies == null) { return; } for (int b = 0; b < Bodies.Length; b++) { // Get the body: FunctionBody body = Bodies[b]; // Get the function signature: FuncType sig = body.Signature; // Create the builder: ILGenerator gen = sig.GetGenerator(Module); // Define the locals now: body.DefineLocals(gen); // Set body to the generator: gen.FunctionBody = body; // For each instruction in the input set, output it now: for (int i = 0; i < body.Root.Count; i++) { // Get the instruction: Instruction instruction = body.Root[i]; // Emit it: instruction.Output(gen); } // Complete it: gen.Complete(sig.Name, sig.GetParameters(), sig.GetReturnType(), true); } }
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."); } }