private VariableLocation GetLocation(Variable variable) { VariableLocation location; if (!locals.TryGetValue(variable, out location)) { var localIndex = cil.DeclareLocal(variable.StaticRepr.CliType, variable.Name); location = VariableLocation.Local(localIndex); locals.Add(variable, location); } return(location); }
internal FunctionEmitter(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup) { Contract.Requires(function != null); Contract.Requires(methodFactory != null); Contract.Requires(functionLookup != null); this.declaration = function; this.functionLookup = functionLookup; var signature = new FunctionSignature(function.Inputs.Select(i => i.StaticRepr), function.Outputs.Select(o => o.StaticRepr)); // Determine the method signature var parameterDescriptors = new List <ParameterDescriptor>(); foreach (var input in function.Inputs) { locals.Add(input, VariableLocation.Parameter(parameterDescriptors.Count)); parameterDescriptors.Add(new ParameterDescriptor(input.StaticCliType, ParameterAttributes.None, input.Name)); } Type returnType = typeof(void); if (function.Outputs.Length == 1) { returnType = function.Outputs[0].StaticCliType; // 1 output, use return value } else if (function.Outputs.Length >= 2) { // 2 or more outputs, use 'out' parameters foreach (var output in function.Outputs) { string name = output.Name; if (locals.ContainsKey(output)) { // inout parameter, rename not to clash with input name += "$out"; } else { locals.Add(output, VariableLocation.Parameter(parameterDescriptors.Count)); } var parameterType = output.StaticCliType.MakeByRefType(); parameterDescriptors.Add(new ParameterDescriptor(parameterType, ParameterAttributes.Out, name)); } } // Create the method and get its IL generator ILGenerator ilGenerator; var methodInfo = methodFactory(function.Name, parameterDescriptors, returnType, out ilGenerator); this.method = new FunctionMethod(methodInfo, signature); cil = new ILGeneratorMethodBodyWriter(ilGenerator); cil = new MethodBodyVerifier(new MethodBodyVerificationContext { Method = methodInfo, ParameterTypes = parameterDescriptors.Select(p => p.Type).ToArray(), ReturnType = returnType, HasInitLocals = true, MaxStackSize = ushort.MaxValue }, cil); temporaryPool = new TemporaryLocalPool(cil, "$temp"); if (function.Outputs.Length == 1) { // Declare a local variable for the return value var output = function.Outputs[0]; var localIndex = cil.DeclareLocal(output.StaticCliType, output.Name); if (!function.Inputs.Contains(output)) { locals.Add(output, VariableLocation.Local(localIndex)); } } }