2 // driver.cs: The compiler command line driver.
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2002, 2003, 2004 Rafael Teixeira
12 namespace Mono.Languages {
15 using System.Collections;
18 using System.Globalization;
19 using System.Reflection;
20 using System.Reflection.Emit;
22 using Mono.GetOptions;
23 using Mono.GetOptions.Useful;
28 CompilerOptions options;
30 private void InitializeRootContextAndOthersFromOptions()
32 Report.Stacktrace = options.Stacktrace;
33 Report.WarningsAreErrors = options.WarningsAreErrors;
34 // TODO: change Report to receive the whole array
35 for(int i = 0; i < options.WarningsToIgnore.Length; i++)
36 Report.SetIgnoreWarning(options.WarningsToIgnore[i]);
37 Report.Fatal = options.MakeErrorsFatal;
39 RootContext.WarningLevel = options.WarningLevel;
40 RootContext.Checked = options.CheckedContext;
41 RootContext.MainClass = options.MainClassName;
42 RootContext.StdLib = !options.NoStandardLibraries;
43 RootContext.Unsafe = options.AllowUnsafeCode;
44 if (options.RootNamespace != null)
45 RootContext.RootNamespace = options.RootNamespace;
47 // TODO: semantics are different and should be adjusted
48 GenericParser.yacc_verbose_flag = options.Verbose ? 1 : 0;
50 Mono.MonoBASIC.Parser.InitialOptionExplicit = options.OptionExplicit;
51 Mono.MonoBASIC.Parser.InitialOptionStrict = options.OptionStrict;
52 Mono.MonoBASIC.Parser.InitialOptionCompareBinary = options.OptionCompareBinary;
53 Mono.MonoBASIC.Parser.ImportsList = options.Imports;
56 bool ParseAllSourceFiles()
58 options.StartTime("Parsing Source Files");
59 foreach(FileToCompile file in options.SourceFilesToCompile)
60 GenericParser.Parse(file.Filename, file.Encoding);
61 options.ShowTime(" Done");
62 return (Report.Errors == 0);
65 private bool InitializeDebuggingSupport()
67 string[] debug_args = new string [options.DebugListOfArguments.Count];
68 options.DebugListOfArguments.CopyTo(debug_args);
69 CodeGen.Init(options.OutputFileName, options.OutputFileName, options.WantDebuggingSupport, debug_args);
70 TypeManager.AddModule(CodeGen.ModuleBuilder);
74 private bool LoadReferencedAssemblies()
77 options.LoadReferencedAssemblies(
78 new Mono.GetOptions.Useful.AssemblyAdder(TypeManager.AddAssembly));
81 private bool AdjustCodegenWhenTargetIsNetModule()
83 options.AdjustCodegenWhenTargetIsNetModule(CodeGen.AssemblyBuilder);
87 private bool LoadAddedNetModules()
90 options.LoadAddedNetModules(
91 CodeGen.AssemblyBuilder,
92 new Mono.GetOptions.Useful.ModuleAdder(TypeManager.AddModule));
95 private bool InitializeCoreTypes()
98 // Before emitting, we need to get the core
99 // types emitted from the user defined types
100 // or from the system ones.
102 options.StartTime("Initializing Core Types");
104 if (!RootContext.StdLib)
105 RootContext.ResolveCore ();
106 if (Report.Errors > 0)
109 TypeManager.InitCoreTypes();
111 options.ShowTime("Core Types Done");
112 return Report.Errors == 0;
115 private bool ResolveTree()
117 options.StartTime("Resolving tree");
118 RootContext.ResolveTree (); // The second pass of the compiler
119 options.ShowTime("Tree resolved");
120 return Report.Errors == 0;
123 private bool PopulateCoreTypes()
125 if (!RootContext.StdLib) {
126 options.StartTime("Populate core types");
127 RootContext.BootCorlib_PopulateCoreTypes();
128 options.ShowTime(" Done");
130 return Report.Errors == 0;
133 private bool PopulateTypes()
135 options.StartTime("Populate types");
136 RootContext.PopulateTypes();
137 options.ShowTime(" Done");
138 return Report.Errors == 0;
141 private bool InitCodeHelpers()
143 options.StartTime("Initialize code helpers");
144 TypeManager.InitCodeHelpers();
145 options.ShowTime(" Done");
146 return Report.Errors == 0;
149 void CookUpEntryPointForWinFormsApplication(Type t)
151 Type SystemWindowsFormsFormType = TypeManager.LookupType ("System.Windows.Forms.Form");
152 if (SystemWindowsFormsFormType == null || !t.IsSubclassOf (SystemWindowsFormsFormType))
155 TypeBuilder tb = t as TypeBuilder;
156 MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
157 typeof(void), new Type[0]);
159 Type SystemWindowsFormsApplicationType = TypeManager.LookupType ("System.Windows.Forms.Application");
160 MethodInfo mi = SystemWindowsFormsApplicationType.GetMethod ("Run", new Type[] { SystemWindowsFormsFormType } );
161 ILGenerator ig = mb.GetILGenerator();
162 ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
164 ig.Emit (OpCodes.Newobj, ci);
165 ig.Emit (OpCodes.Call, mi);
166 ig.Emit (OpCodes.Ret);
168 RootContext.EntryPoint = mb as MethodInfo;
173 if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
174 if (RootContext.EntryPoint == null && RootContext.MainClass != null) {
175 // If we don't have a valid entry point yet AND if System.Windows.Forms is included
176 // among the dependencies, we have to build a new entry point on-the-fly for the specified
178 // Otherwise we won't be able to compile SWF code out of the box.
179 Type t = TypeManager.LookupType(RootContext.MainClass);
181 Report.Error(-1, string.Format("Specified main class {0} doesn't exist", RootContext.MainClass));
183 CookUpEntryPointForWinFormsApplication (t);
188 private bool EmitCode()
190 options.StartTime("Emitting code");
191 RootContext.EmitCode();
193 options.ShowTime(" Done");
194 return Report.Errors == 0;
197 private bool CloseTypes()
199 options.StartTime("Closing types");
200 RootContext.CloseTypes ();
201 options.ShowTime(" Done");
202 return Report.Errors == 0;
205 private bool SetEntryPoint()
207 if (options.TargetFileType == TargetType.Exe || options.TargetFileType == TargetType.WinExe) {
208 options.StartTime("Setting entry point");
209 MethodInfo ep = RootContext.EntryPoint;
212 Report.Error (30737, "Program " + options.OutputFileName + " does not have an entry point defined");
216 CodeGen.AssemblyBuilder.SetEntryPoint (ep,
217 (options.TargetFileType == TargetType.Exe)?PEFileKinds.ConsoleApplication:PEFileKinds.WindowApplication);
218 options.ShowTime(" Done");
220 return Report.Errors == 0;
223 private bool EmbedResources()
225 options.StartTime("Embedding resources");
226 options.EmbedResources(CodeGen.AssemblyBuilder);
227 options.ShowTime(" Done");
228 return Report.Errors == 0;
231 private bool SaveOutput()
233 options.StartTime("Saving Output");
234 CodeGen.Save(options.OutputFileName);
235 options.ShowTime(" Done");
236 return Report.Errors == 0;
240 private bool SaveDebugSymbols()
242 if (options.WantDebuggingSupport) {
243 options.StartTime("Saving Debug Symbols");
244 CodeGen.SaveSymbols ();
245 options.ShowTime (" Done");
250 delegate bool CompilerStep();
252 private CompilerStep[] Steps {
254 return new CompilerStep[] {
255 new CompilerStep(ParseAllSourceFiles),
256 new CompilerStep(InitializeDebuggingSupport),
257 new CompilerStep(LoadReferencedAssemblies),
258 new CompilerStep(AdjustCodegenWhenTargetIsNetModule),
259 new CompilerStep(LoadAddedNetModules),
260 new CompilerStep(InitializeCoreTypes),
261 new CompilerStep(ResolveTree),
262 new CompilerStep(PopulateCoreTypes),
263 new CompilerStep(PopulateTypes),
264 new CompilerStep(InitCodeHelpers),
265 new CompilerStep(EmitCode),
266 new CompilerStep(CloseTypes),
267 new CompilerStep(SetEntryPoint),
268 new CompilerStep(SaveOutput),
269 new CompilerStep(SaveDebugSymbols) } ;
274 /// Parses the arguments, and calls the compilation process.
276 int Execute(string [] args)
278 options = new CompilerOptions(args, new ErrorReporter(Report.Error));
279 if (options.NothingToCompile)
282 InitializeRootContextAndOthersFromOptions();
284 foreach(CompilerStep step in Steps)
288 } catch (Exception ex) {
289 Report.Error(0, "Exception: " + ex.ToString());
291 return Report.ProcessResults(options.BeQuiet);
294 public static int Main (string[] args)
296 Driver driver = new Driver();
298 return driver.Execute(args);