public bool CreateModule(CompilerContext context, ProgramUnit programUnit, out Module module) { bool failed = false; module = new Module(); foreach (MethodDefinition methodDef in programUnit.Methods) { MethodInfo methodInfo = null; TypeDefinition type = null; List<TypeDefinition> parameterTypes = new List<TypeDefinition>(); foreach (var paramDecl in methodDef.Parameters) { TypeDefinition paramType = null; if (!this.TryResolveTypeReference(context, paramDecl.Type, out paramType)) { return false; } foreach (string paramName in paramDecl.ParameterNames) { parameterTypes.Add(paramType); } } if (!context.TryFindMethodAndType( methodDef.MethodNameReference, parameterTypes, out type, out methodInfo)) { string message = string.Format( Properties.Resources.CodeGenerator_UndeclaredMethod, methodDef.MethodNameReference); this.log.Write(new Message( methodDef.Start.Path, methodDef.Start.Line, methodDef.Start.Column, Severity.Error, message)); failed = true; continue; } MethodImpl methodImpl = new MethodImpl(module); methodImpl.Method = methodInfo; if (this.TryImplementMethod(methodImpl, context, methodDef, type)) { module.CodeSegment.Add(methodImpl); } else { failed = true; } } return !failed; }
public MethodImpl(Module module) { this.Module = module; }
public abstract bool Write(Module module);
public override bool Write(Module module) { writer.WriteLine(".model flat,C"); writer.WriteLine(); foreach (MethodInfo method in module.ProtoList) { writer.Write(method.MangledName); writer.WriteLine(" PROTO C"); } foreach (string externSymbol in module.ExternList) { writer.Write(externSymbol); writer.WriteLine(" PROTO C"); } writer.WriteLine(); writer.WriteLine(".data"); foreach (DataEntry dataEntry in module.DataSegment) { if (!string.IsNullOrEmpty(dataEntry.Label)) { writer.Write(dataEntry.Label); } for (int i = 0; i < dataEntry.Value.Length; i++) { writer.Write("\t"); object val = dataEntry.Value[i]; if (val is byte) { writer.Write("db"); } else if (val is ushort) { writer.Write("dw"); } else { writer.Write("dd"); } writer.Write("\t"); writer.WriteLine(val); } writer.WriteLine(); } writer.WriteLine(); writer.WriteLine(".code"); string mainMethod = null; foreach (MethodImpl method in module.CodeSegment) { if (method.Method.IsStatic && string.CompareOrdinal("Main", method.Method.Name) == 0 && method.Method.Parameters.Count == 2 && string.CompareOrdinal(method.Method.Parameters[0].Type.FullName, "integer") == 0 && string.CompareOrdinal(method.Method.Parameters[1].Type.FullName, "#0#0character") == 0) { mainMethod = method.Method.MangledName; } foreach (string symbol in method.Symbols.Keys) { writer.WriteLine("{0}={1}", symbol, method.Symbols[symbol]); } writer.Write(method.Method.MangledName); writer.Write(" PROC C"); if (method.Method.IsProtected || method.Method.IsPublic) { writer.Write(" EXPORT"); } writer.WriteLine(); foreach (var statement in method.Statements) { if (!string.IsNullOrEmpty(statement.Label)) { writer.Write("{0}:", statement.Label); } writer.Write("\t"); writer.WriteLine(statement.Instruction); } writer.Write(method.Method.MangledName); writer.WriteLine(" ENDP"); } if (!string.IsNullOrEmpty(mainMethod)) { string methodText = @"wmain PROC C EXPORT push ebp mov ebp,esp push [ebp+12] push [ebp+8] call {0} add esp,8 mov esp,ebp pop ebp ret wmain ENDP"; writer.WriteLine(methodText, mainMethod); } writer.WriteLine("END"); return true; }