This commit is contained in:
nub31
2025-06-29 17:06:57 +02:00
parent 7657085243
commit 7617ddae73
7 changed files with 138 additions and 9 deletions

View File

@@ -1,9 +1,12 @@
CFLAGS = -Wall -Werror -Wextra -g CFLAGS = -g
example: bin/out: src/main.nub src/c.nub
dotnet run --project ../src/compiler/CLI/CLI.csproj src/main.nub src/c.nub dotnet run --project ../src/compiler/CLI/CLI.csproj src/main.nub src/c.nub
mkdir -p bin mkdir -p bin
gcc $(CFLAGS) -o bin/out lib/libruntime_x64.a bin-int/out.a gcc $(CFLAGS) -o bin/out bin-int/out/out.a
run: bin/out
bin/out
clean: clean:
rm -r bin-int bin rm -r bin-int bin

View File

@@ -3,4 +3,5 @@ namespace main
export func main(args: []cstring): i64 { export func main(args: []cstring): i64 {
c::puts("test") c::puts("test")
return 0 return 0
} }

View File

@@ -18,4 +18,9 @@
<None Remove="runtime\libruntime_x64.a" /> <None Remove="runtime\libruntime_x64.a" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Remove="assets\libruntime_x64.a" />
<EmbeddedResource Include="assets\libruntime_x64.a" />
</ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,38 @@
namespace CLI;
internal static class HexString
{
private static readonly HashSet<string> _used = [];
private static readonly char[] StringChars = "0123456789abcdef".ToArray();
public static string CreateUnique(int length)
{
string hex;
while (true)
{
hex = Create(length);
if (_used.Add(hex))
{
break;
}
}
return hex;
}
public static string Create(int length)
{
var rand = new Random();
var hexString = "";
for (var i = 0; i < length; i++)
{
var randIndex = rand.Next(0, StringChars.Length);
hexString += StringChars[randIndex];
}
return hexString;
}
}

View File

@@ -0,0 +1,6 @@
namespace CLI;
public class Options
{
public string? CustomRuntime { get; set; }
}

View File

@@ -1,20 +1,49 @@
using CLI; using System.Reflection;
using CLI;
using Generation.QBE; using Generation.QBE;
using Syntax; using Syntax;
using Syntax.Diagnostics; using Syntax.Diagnostics;
using Syntax.Parsing; using Syntax.Parsing;
using Syntax.Tokenization; using Syntax.Tokenization;
using Syntax.Typing; using Syntax.Typing;
using Binder = Syntax.Typing.Binder;
const string OUT_DIR = "bin-int"; const string INT_DIR = "bin-int";
var BUILTIN_DIR = Path.Join(INT_DIR, "builtin");
var OBJECT_DIR = Path.Join(INT_DIR, "obj");
var OUT_DIR = Path.Join(INT_DIR, "out");
if (Directory.Exists(INT_DIR))
{
Directory.Delete(INT_DIR, true);
}
Directory.CreateDirectory(BUILTIN_DIR);
Directory.CreateDirectory(OBJECT_DIR);
Directory.CreateDirectory(OUT_DIR); Directory.CreateDirectory(OUT_DIR);
var options = new Options();
var files = new List<string>(); var files = new List<string>();
foreach (var arg in args) for (var i = 0; i < args.Length; i++)
{ {
var arg = args[i];
if (arg.StartsWith("-r") || arg.StartsWith("--runtime"))
{
i++;
if (i >= args.Length - 1)
{
Console.Error.WriteLine($"{arg} must be followed by a value");
return 1;
}
options.CustomRuntime = args[i];
}
else
{
files.Add(arg); files.Add(arg);
}
} }
var diagnostics = new List<Diagnostic>(); var diagnostics = new List<Diagnostic>();
@@ -80,7 +109,7 @@ foreach (var file in files)
return 1; return 1;
} }
var fileName = Path.GetTempFileName(); var fileName = Path.Join(OBJECT_DIR, $"{HexString.CreateUnique(8)}_{Path.GetFileNameWithoutExtension(file)}.o");
var asmSuccess = await GCC.Assemble(asm, fileName); var asmSuccess = await GCC.Assemble(asm, fileName);
if (!asmSuccess) if (!asmSuccess)
{ {
@@ -90,6 +119,29 @@ foreach (var file in files)
objectFiles.Add(fileName); objectFiles.Add(fileName);
} }
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;
}
objectFiles.Add(options.CustomRuntime);
}
var archiveResult = await Archive.Invoke(Path.Join(OUT_DIR, "out.a"), objectFiles); var archiveResult = await Archive.Invoke(Path.Join(OUT_DIR, "out.a"), objectFiles);
if (!archiveResult) if (!archiveResult)
{ {
@@ -97,3 +149,27 @@ if (!archiveResult)
} }
return 0; return 0;
async Task<string> CreateBuiltinRuntime()
{
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)
{
throw new RuntimeCreationException($"Cannot open stream to '{RUNTIME_NAME}'");
}
var runtimePath = Path.Combine(BUILTIN_DIR, RUNTIME_NAME);
await using var writer = new FileStream(runtimePath, FileMode.Create);
reader.CopyTo(writer);
return runtimePath;
}
class RuntimeCreationException(string message) : Exception(message);