public (Scope root, TypeChecker tc) Compile(CompilerOptionsBuild options) { CompilerOptionsBuild._i.lib_path.Add(Path.GetFullPath(Program.RelDir("..\\lib"))); CompilerOptionsBuild._i.include_dirs.Add(Path.GetFullPath(Program.RelDir("..\\include"))); Platform platform; if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { platform = Platform.WindowsX64; CompilerOptionsBuild._i.libs.Add("kernel32.lib"); } else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) { platform = Platform.LinuxX64; } else { throw new Exception("Platform not supported"); } var filename = options.inputFilename; var buildExecuteable = options.buildExecuteable; var timer = new Stopwatch(); Program.CompilerMessage("parsing...", CompilerMessageType.Info); timer.Start(); Queue <(string, Token)> toImport = new Queue <(string, Token)>(); HashSet <string> imported = new HashSet <string>(); Stack <Token[]> toCompile = new Stack <Token[]>(); var ffn = filename; if (!Path.IsPathRooted(filename)) { ffn = Path.GetFullPath(filename); } toImport.Enqueue((ffn, Token.Undefined)); imported.Add(ffn); var scope = AST.MakeRootScope(); var rootToken = Token.UndefinedRoot(ffn); var root = new AST.ProgramRoot(rootToken, scope); while (toImport.Count > 0) { var(fn, import_token) = toImport.Dequeue(); string text; try { if (GetFileText != null) { text = GetFileText(fn); } else { text = File.ReadAllText(fn); } } catch (Exception) { throw new CompilerError($"Could not read import file", import_token); } if (string.IsNullOrWhiteSpace(text)) { throw new CompilerError($"Empty import file!", import_token); } text = Preprocessor.Preprocess(text, platform); var tokens = Tokenize(text, fn); AST.ParseState ps = new ParseState(); ps.pos = 0; ps.tokens = tokens; List <(string, Token)> imports = null; imports = AST.ParseImports(ref ps, scope); toCompile.Push(tokens); foreach (var(import, token) in imports) { var dir = Path.GetDirectoryName(fn); var importPath = ResolveImportPath(import, dir, options.include_dirs); if (!imported.Contains(importPath)) { toImport.Enqueue((importPath, token)); imported.Add(importPath); } } } foreach (var tokens in toCompile) { AST.ParseState ps = new ParseState(); ps.pos = 0; ps.tokens = tokens; // Log($"parsing {ps.tokens[0].filename}..."); var fileRoot = AST.ParseFileRoot(ref ps, scope) as FileRoot; root.files.Add(fileRoot); } var entry = CompilerOptionsBuild._i.entry; if (entry != null) { SetEntryPoint(entry); } timer.Stop(); Program.CompilerMessage($"{timer.ElapsedMilliseconds}ms", CompilerMessageType.Timing); Program.CompilerMessage("type checking...", CompilerMessageType.Info); timer.Reset(); timer.Start(); var tc = new TypeChecker(); tc.CheckTypes(root); timer.Stop(); Program.CompilerMessage($"{timer.ElapsedMilliseconds}ms", CompilerMessageType.Timing); Program.CompilerMessage("de-sugar...", CompilerMessageType.Info); timer.Reset(); timer.Start(); ParseTreeTransformations.Init(root); ParseTreeTransformations.Desugar(tc.embeddings, tc); ParseTreeTransformations.Desugar(tc.namespaceAccesses, tc); timer.Stop(); Program.CompilerMessage($"{timer.ElapsedMilliseconds}ms", CompilerMessageType.Timing); Program.CompilerMessage("backend...", CompilerMessageType.Info); timer.Reset(); timer.Start(); var backend = new Backend(tc, platform); if (buildExecuteable && entry == null) { throw new CompilerError("No entry point defined", root.token); } backend.Visit(root, entry); timer.Stop(); Program.CompilerMessage($"{timer.ElapsedMilliseconds}ms", CompilerMessageType.Timing); if (buildExecuteable) { backend.AOT(); } return(scope, tc); }
int GetDICompileUnit(AST.ProgramRoot root) { if (!debugInfoScopeLookup.TryGetValue(root, out int compileUnitIdx)) { string emptyArray = "!{}"; var emptyArrayIdx = AddDebugInfoNode(emptyArray); // HACK: TODO(pragma): remove var placeholder = System.Guid.NewGuid().ToString(); var debugGlobalVariableArrayIdx = AddDebugInfoNode(placeholder); debugGlobalVariableArrayPlaceholder = placeholder; string producer = "\"pragma version 0.2 (build 8)\""; string nodeString = $"distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !{GetDIFile(root)}, producer: {producer}, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !{emptyArrayIdx}, enums: !{emptyArrayIdx}, globals: !{debugGlobalVariableArrayIdx}, imports: !{emptyArrayIdx})"; compileUnitIdx = AddDebugInfoNode(nodeString); debugInfoScopeLookup.Add(root, compileUnitIdx); debugInfoCompileUnitIdx = compileUnitIdx; if (platform == Platform.WindowsX64) { string debugInfoVersion = "!{i32 2, !\"Debug Info Version\", i32 3}"; var debugInfoVersionIdx = AddDebugInfoNode(debugInfoVersion); debugInfoModuleFlags.Add(debugInfoVersionIdx); string codeViewVersion = "!{i32 2, !\"CodeView\", i32 1}"; var codeViewVersionIdx = AddDebugInfoNode(codeViewVersion); debugInfoModuleFlags.Add(codeViewVersionIdx); string wcharSize = "!{i32 1, !\"wchar_size\", i32 2}"; var wcharSizeIdx = AddDebugInfoNode(wcharSize); debugInfoModuleFlags.Add(wcharSizeIdx); string picLevel = "!{i32 7, !\"PIC Level\", i32 2}"; var picLevelIdx = AddDebugInfoNode(picLevel); debugInfoModuleFlags.Add(picLevelIdx); } else if (platform == Platform.LinuxX64) { string debugInfoVersion = "!{i32 2, !\"Debug Info Version\", i32 3}"; var debugInfoVersionIdx = AddDebugInfoNode(debugInfoVersion); debugInfoModuleFlags.Add(debugInfoVersionIdx); string codeViewVersion = "!{i32 7, !\"Dwarf Version\", i32 4}"; var codeViewVersionIdx = AddDebugInfoNode(codeViewVersion); debugInfoModuleFlags.Add(codeViewVersionIdx); string wcharSize = "!{i32 1, !\"wchar_size\", i32 2}"; var wcharSizeIdx = AddDebugInfoNode(wcharSize); debugInfoModuleFlags.Add(wcharSizeIdx); } // TODO(pragma): versions?? string ident = $"!{{!{producer}}}"; debugInfoIdentFlag = AddDebugInfoNode(ident); debugRootNode = root; } return(compileUnitIdx); }
public static void Init(AST.ProgramRoot root) { fixupParents(null, root); }