From f80be58fed857a3b9e472fee0ed5421b4cad0a3d Mon Sep 17 00:00:00 2001 From: nub31 Date: Mon, 18 Aug 2025 16:56:20 +0200 Subject: [PATCH] ... --- example/makefile | 20 +++-- example/src/main.nub | 49 ---------- src/compiler/NubLang.CLI/GCC.cs | 20 +---- src/compiler/NubLang.CLI/Options.cs | 4 +- src/compiler/NubLang.CLI/Program.cs | 133 +++++++++++----------------- 5 files changed, 73 insertions(+), 153 deletions(-) delete mode 100644 example/src/main.nub diff --git a/example/makefile b/example/makefile index e9f1434..81bd9f9 100644 --- a/example/makefile +++ b/example/makefile @@ -1,11 +1,17 @@ -CFLAGS = -g +NUBC = ../src/compiler/NubLang.CLI/bin/Debug/net9.0/nubc -bin/out: src/main.nub - dotnet build ../src/compiler/NubLang.CLI/NubLang.CLI.csproj -c Release - ../src/compiler/NubLang.CLI/bin/Release/net9.0/nubc src/main.nub +out: $(NUBC) main.nub + $(NUBC) main.nub -run: bin/out - bin/out +$(NUBC): + dotnet build ../src/compiler/NubLang.CLI/NubLang.CLI.csproj + +run: out + out clean: - rm -r bin-int bin + @rm out 2>/dev/null || true + @rm out.a 2>/dev/null || true + @find . -name "*.o" -type f -delete + @find . -name "*.s" -type f -delete + @find . -name "*.ssa" -type f -delete diff --git a/example/src/main.nub b/example/src/main.nub deleted file mode 100644 index 5495540..0000000 --- a/example/src/main.nub +++ /dev/null @@ -1,49 +0,0 @@ -// c -extern func puts(text: cstring) - -// raylib -extern func InitWindow(width: i32, height: i32, title: cstring) -extern func CloseWindow() -extern func WindowShouldClose(): bool -extern func BeginDrawing() -extern func EndDrawing() -extern func ClearBackground(color: Color) -extern func DrawCircle(centerX: i32, centerY: i32, radius: f32, color: Color) - -struct Color -{ - r: u8 - g: u8 - b: u8 - a: u8 -} - -struct Vector2 -{ - x: f32 - y: f32 -} - -struct Vector3 -{ - x: f32 - y: f32 - z: f32 -} - -func main(args: []cstring): i64 -{ - InitWindow(800, 600, "Hello from nub!") - - while !WindowShouldClose() - { - BeginDrawing() - ClearBackground(struct { r = 55 g = 55 b = 55 a = 255 }) - DrawCircle(400, 300, 50, struct { r = 255 g = 255 b = 0 a = 0 }) - EndDrawing() - } - - CloseWindow() - - return 0 -} diff --git a/src/compiler/NubLang.CLI/GCC.cs b/src/compiler/NubLang.CLI/GCC.cs index eb12878..05b0eae 100644 --- a/src/compiler/NubLang.CLI/GCC.cs +++ b/src/compiler/NubLang.CLI/GCC.cs @@ -6,12 +6,6 @@ public static class GCC { public static async Task Assemble(string asmPath, string outPath) { - var dir = Path.GetDirectoryName(outPath); - if (dir != null) - { - Directory.CreateDirectory(dir); - } - using var process = new Process(); process.StartInfo = new ProcessStartInfo("gcc", ["-xassembler", "-c", "-o", outPath, asmPath]) { @@ -22,7 +16,7 @@ public static class GCC }; process.Start(); - + await process.WaitForExitAsync(); var errors = await process.StandardError.ReadToEndAsync(); @@ -33,15 +27,9 @@ public static class GCC return process.ExitCode == 0; } - + public static async Task Link(string executablePath, params IEnumerable objectFiles) { - var dir = Path.GetDirectoryName(executablePath); - if (dir != null) - { - Directory.CreateDirectory(dir); - } - using var process = new Process(); process.StartInfo = new ProcessStartInfo("gcc", ["-nostartfiles", "-o", executablePath, ..objectFiles]) { @@ -52,7 +40,7 @@ public static class GCC }; process.Start(); - + await process.WaitForExitAsync(); var errors = await process.StandardError.ReadToEndAsync(); @@ -63,4 +51,4 @@ public static class GCC return process.ExitCode == 0; } -} +} \ No newline at end of file diff --git a/src/compiler/NubLang.CLI/Options.cs b/src/compiler/NubLang.CLI/Options.cs index d3efdd7..ac3c44e 100644 --- a/src/compiler/NubLang.CLI/Options.cs +++ b/src/compiler/NubLang.CLI/Options.cs @@ -4,8 +4,10 @@ namespace NubLang.CLI; public class Options { - public string? CustomRuntime { get; set; } public string? OutputPath { get; set; } public bool Link { get; set; } = true; public List Files { get; } = []; + public bool EmitSsa { get; set; } = false; + public bool EmitAsm { get; set; } = false; + public bool EmitObj { get; set; } = false; } \ No newline at end of file diff --git a/src/compiler/NubLang.CLI/Program.cs b/src/compiler/NubLang.CLI/Program.cs index 64a0fa5..7bf8359 100644 --- a/src/compiler/NubLang.CLI/Program.cs +++ b/src/compiler/NubLang.CLI/Program.cs @@ -10,41 +10,13 @@ using NubLang.Tokenization; using NubLang.TypeChecking; using NubLang.TypeChecking.Node; -const string BIN_DIR = "bin"; -const string INT_DIR = "bin-int"; -var INT_BUILTIN_DIR = Path.Join(INT_DIR, "builtin"); -var INT_OBJECT_DIR = Path.Join(INT_DIR, "obj"); -var INT_SSA_DIR = Path.Join(INT_DIR, "ssa"); -var INT_ASM_DIR = Path.Join(INT_DIR, "asm"); - -if (Directory.Exists(INT_DIR)) -{ - Directory.Delete(INT_DIR, true); -} - -Directory.CreateDirectory(BIN_DIR); -Directory.CreateDirectory(INT_BUILTIN_DIR); -Directory.CreateDirectory(INT_OBJECT_DIR); -Directory.CreateDirectory(INT_SSA_DIR); -Directory.CreateDirectory(INT_ASM_DIR); - var options = new Options(); for (var i = 0; i < args.Length; i++) { var arg = args[i]; - if (arg == "-r") - { - i++; - if (i >= args.Length - 1) - { - Console.Error.WriteLine($"{arg} must be followed by a value"); - return 1; - } - options.CustomRuntime = args[i]; - } - else if (arg == "-o") + if (arg == "-o") { i++; if (i >= args.Length - 1) @@ -59,6 +31,18 @@ for (var i = 0; i < args.Length; i++) { options.Link = false; } + else if (arg == "-ssa") + { + options.EmitSsa = true; + } + else if (arg == "-asm") + { + options.EmitAsm = true; + } + else if (arg == "-obj") + { + options.EmitObj = true; + } else { options.Files.Add(new SourceFile(arg)); @@ -120,23 +104,35 @@ var objectFiles = new List(); for (var i = 0; i < typedSyntaxTrees.Count; i++) { var syntaxTree = typedSyntaxTrees[i]; - var outFileName = Path.GetFileNameWithoutExtension(options.Files[i].Path); + var outFileName = Path.ChangeExtension(options.Files[i].Path, null); var generator = new QBEGenerator(syntaxTree, typedDefinitionTable); var ssa = generator.Emit(); - var ssaPath = Path.Join(INT_SSA_DIR, $"{outFileName}.ssa"); - File.WriteAllText(ssaPath, ssa); + var ssaFilePath = $"{outFileName}.ssa"; + File.WriteAllText(ssaFilePath, ssa); + + var asmFilePath = $"{outFileName}.s"; + var qbeSuccess = await QBE.Invoke(ssaFilePath, asmFilePath); + + if (!options.EmitSsa) + { + File.Delete(ssaFilePath); + } - var asmFilePath = Path.Join(INT_ASM_DIR, $"{outFileName}.s"); - var qbeSuccess = await QBE.Invoke(ssaPath, asmFilePath); if (!qbeSuccess) { return 1; } - var objFilePath = Path.Join(INT_OBJECT_DIR, $"{outFileName}.o"); + var objFilePath = $"{outFileName}.o"; var asmSuccess = await GCC.Assemble(asmFilePath, objFilePath); + + if (!options.EmitAsm) + { + File.Delete(asmFilePath); + } + if (!asmSuccess) { return 1; @@ -145,32 +141,28 @@ for (var i = 0; i < typedSyntaxTrees.Count; i++) objectFiles.Add(objFilePath); } -if (options.CustomRuntime == null) -{ - try - { - objectFiles.Add(await CreateBuiltinRuntime()); - } - catch (RuntimeCreationException e) - { - Console.Error.WriteLine(e.Message); - return 1; - } -} -else -{ - if (!File.Exists(options.CustomRuntime)) - { - Console.Error.WriteLine($"file '{options.CustomRuntime}' does not exist'"); - return 1; - } +var runtimeFilePath = "libruntime_x64.a"; - objectFiles.Add(options.CustomRuntime); +var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames(); +var runtime = resources.First(r => r.EndsWith(runtimeFilePath)); + +await using var reader = Assembly.GetExecutingAssembly().GetManifestResourceStream(runtime); + +if (reader == null) +{ + Console.Error.WriteLine($"Cannot open stream to '{runtimeFilePath}'"); + return 1; } +await using var writer = new FileStream(runtimeFilePath, FileMode.Create); + +reader.CopyTo(writer); + +objectFiles.Add(runtimeFilePath); + if (options.Link) { - var outPath = options.OutputPath ?? Path.Join(BIN_DIR, "out"); + var outPath = options.OutputPath ?? "out"; var linkResult = await GCC.Link(outPath, objectFiles); if (!linkResult) { @@ -179,7 +171,7 @@ if (options.Link) } else { - var outPath = options.OutputPath ?? Path.Join(BIN_DIR, "out.a"); + var outPath = options.OutputPath ?? "out.a"; var archiveResult = await Archive.Invoke(outPath, objectFiles); if (!archiveResult) { @@ -187,31 +179,12 @@ else } } -return 0; - -async Task CreateBuiltinRuntime() +if (!options.EmitObj) { - const string RUNTIME_NAME = "libruntime_x64.a"; - - var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames(); - var runtime = resources.First(r => r.EndsWith(RUNTIME_NAME)); - - await using var reader = Assembly.GetExecutingAssembly().GetManifestResourceStream(runtime); - - if (reader == null) + foreach (var objectFile in objectFiles) { - throw new RuntimeCreationException($"Cannot open stream to '{RUNTIME_NAME}'"); + File.Delete(objectFile); } - - var runtimePath = Path.Combine(INT_BUILTIN_DIR, RUNTIME_NAME); - await using var writer = new FileStream(runtimePath, FileMode.Create); - - reader.CopyTo(writer); - - return runtimePath; } -namespace NubLang.CLI -{ - internal class RuntimeCreationException(string message) : Exception(message); -} \ No newline at end of file +return 0; \ No newline at end of file