...
This commit is contained in:
@@ -28,8 +28,6 @@ var moduleRepository = new ModuleRepository(syntaxTrees);
|
|||||||
|
|
||||||
var definitions = new List<DefinitionNode>();
|
var definitions = new List<DefinitionNode>();
|
||||||
|
|
||||||
var referencedStructTypes = new HashSet<NubStructType>();
|
|
||||||
|
|
||||||
foreach (var syntaxTree in syntaxTrees)
|
foreach (var syntaxTree in syntaxTrees)
|
||||||
{
|
{
|
||||||
var typeChecker = new TypeChecker(syntaxTree, moduleRepository);
|
var typeChecker = new TypeChecker(syntaxTree, moduleRepository);
|
||||||
@@ -37,11 +35,6 @@ foreach (var syntaxTree in syntaxTrees)
|
|||||||
|
|
||||||
definitions.AddRange(typeChecker.Definitions);
|
definitions.AddRange(typeChecker.Definitions);
|
||||||
diagnostics.AddRange(typeChecker.Diagnostics);
|
diagnostics.AddRange(typeChecker.Diagnostics);
|
||||||
|
|
||||||
foreach (var structType in typeChecker.ReferencedStructTypes)
|
|
||||||
{
|
|
||||||
referencedStructTypes.Add(structType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var diagnostic in diagnostics)
|
foreach (var diagnostic in diagnostics)
|
||||||
@@ -56,7 +49,7 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
|
|||||||
|
|
||||||
Directory.CreateDirectory(".build");
|
Directory.CreateDirectory(".build");
|
||||||
|
|
||||||
var generator = new Generator(definitions, referencedStructTypes);
|
var generator = new Generator(definitions);
|
||||||
var c = generator.Emit();
|
var c = generator.Emit();
|
||||||
var cFilePath = Path.Combine(".build", "out.c");
|
var cFilePath = Path.Combine(".build", "out.c");
|
||||||
|
|
||||||
@@ -91,7 +84,7 @@ if (moduleRepository.Modules().TryGetValue("main", out var mainModule))
|
|||||||
.text
|
.text
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
mov rdi, [rsp + 8] # Pass stack pointer to main (argv-like)
|
mov rdi, rsp # Pass stack pointer to main (length + cstring pointers)
|
||||||
call {mainFunction.ExternSymbol}
|
call {mainFunction.ExternSymbol}
|
||||||
mov rdi, rax # Move return value into rdi
|
mov rdi, rax # Move return value into rdi
|
||||||
mov rax, 60 # syscall: exit
|
mov rax, 60 # syscall: exit
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ public record StructFuncNode(List<Token> Tokens, string Name, FuncSignatureNode
|
|||||||
|
|
||||||
public record StructNode(List<Token> Tokens, string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Tokens, Module, Name);
|
public record StructNode(List<Token> Tokens, string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Tokens, Module, Name);
|
||||||
|
|
||||||
public record GlobalVariableNode(List<Token> Tokens, string Module, string Name, ExpressionNode Value) : DefinitionNode(Tokens, Module, Name);
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Statements
|
#region Statements
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
public List<DefinitionNode> Definitions { get; } = [];
|
public List<DefinitionNode> Definitions { get; } = [];
|
||||||
public List<Diagnostic> Diagnostics { get; } = [];
|
public List<Diagnostic> Diagnostics { get; } = [];
|
||||||
public List<NubStructType> ReferencedStructTypes { get; } = [];
|
|
||||||
|
|
||||||
public void Check()
|
public void Check()
|
||||||
{
|
{
|
||||||
@@ -41,7 +40,6 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
Diagnostics.Clear();
|
Diagnostics.Clear();
|
||||||
Definitions.Clear();
|
Definitions.Clear();
|
||||||
ReferencedStructTypes.Clear();
|
|
||||||
|
|
||||||
using (BeginRootScope(_syntaxTree.Metadata.ModuleName))
|
using (BeginRootScope(_syntaxTree.Metadata.ModuleName))
|
||||||
{
|
{
|
||||||
@@ -57,9 +55,6 @@ public sealed class TypeChecker
|
|||||||
case StructSyntax structSyntax:
|
case StructSyntax structSyntax:
|
||||||
Definitions.Add(CheckStructDefinition(structSyntax));
|
Definitions.Add(CheckStructDefinition(structSyntax));
|
||||||
break;
|
break;
|
||||||
case GlobalVariableSyntax globalVariableSyntax:
|
|
||||||
Definitions.Add(CheckGlobalVariable(globalVariableSyntax));
|
|
||||||
break;
|
|
||||||
case StructTemplateSyntax:
|
case StructTemplateSyntax:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -90,39 +85,7 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private ScopeDisposer BeginRootScope(string moduleName)
|
private ScopeDisposer BeginRootScope(string moduleName)
|
||||||
{
|
{
|
||||||
if (!_visibleModules.TryGetValue(moduleName, out var moduleScope))
|
_scopes.Push(new Scope(moduleName));
|
||||||
{
|
|
||||||
throw new TypeCheckerException(Diagnostic.Error($"Module with name {moduleName} not found").Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
var scope = new Scope(moduleName);
|
|
||||||
_scopes.Push(scope);
|
|
||||||
|
|
||||||
foreach (var globalVariable in moduleScope.GlobalVariables(true))
|
|
||||||
{
|
|
||||||
NubType? type;
|
|
||||||
|
|
||||||
if (globalVariable.ExplicitType != null)
|
|
||||||
{
|
|
||||||
type = ResolveType(globalVariable.ExplicitType);
|
|
||||||
var valueExpression = CheckExpression(globalVariable.Value, type);
|
|
||||||
|
|
||||||
if (valueExpression.Type != ResolveType(globalVariable.ExplicitType))
|
|
||||||
{
|
|
||||||
throw new TypeCheckerException(Diagnostic
|
|
||||||
.Error("Value does not match explicit type of global variable")
|
|
||||||
.At(globalVariable.Value)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
type = CheckExpression(globalVariable.Value).Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.DeclareVariable(new Variable(globalVariable.Name, type, VariableKind.LValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ScopeDisposer(this);
|
return new ScopeDisposer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,11 +187,6 @@ public sealed class TypeChecker
|
|||||||
return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GlobalVariableNode CheckGlobalVariable(GlobalVariableSyntax node)
|
|
||||||
{
|
|
||||||
return new GlobalVariableNode(node.Tokens, CurrentScope.Module, node.Name, CheckExpression(node.Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private AssignmentNode CheckAssignment(AssignmentSyntax statement)
|
private AssignmentNode CheckAssignment(AssignmentSyntax statement)
|
||||||
{
|
{
|
||||||
var target = CheckExpression(statement.Target);
|
var target = CheckExpression(statement.Target);
|
||||||
@@ -702,7 +660,6 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression)
|
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression)
|
||||||
{
|
{
|
||||||
// First, look in the current scope for a matching identifier
|
|
||||||
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
|
var scopeIdent = CurrentScope.LookupVariable(expression.Name);
|
||||||
if (scopeIdent != null)
|
if (scopeIdent != null)
|
||||||
{
|
{
|
||||||
@@ -714,7 +671,6 @@ public sealed class TypeChecker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, look in the current module for a function matching the identifier
|
|
||||||
var module = _visibleModules[CurrentScope.Module];
|
var module = _visibleModules[CurrentScope.Module];
|
||||||
var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name);
|
var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name);
|
||||||
|
|
||||||
@@ -741,20 +697,6 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
var includePrivate = expression.Module == CurrentScope.Module;
|
var includePrivate = expression.Module == CurrentScope.Module;
|
||||||
|
|
||||||
var globalVariable = module.GlobalVariables(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
|
||||||
if (globalVariable != null)
|
|
||||||
{
|
|
||||||
// todo(nub31): This should be done in the global scope
|
|
||||||
NubType? type = null;
|
|
||||||
if (globalVariable.ExplicitType != null)
|
|
||||||
{
|
|
||||||
type = ResolveType(globalVariable.ExplicitType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CheckExpression(globalVariable.Value, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, look for the exported function in the specified module
|
|
||||||
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name);
|
||||||
if (function != null)
|
if (function != null)
|
||||||
{
|
{
|
||||||
@@ -1069,8 +1011,6 @@ public sealed class TypeChecker
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
result.Functions.AddRange(functions);
|
result.Functions.AddRange(functions);
|
||||||
|
|
||||||
ReferencedStructTypes.Add(result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,8 +1086,6 @@ public sealed class TypeChecker
|
|||||||
_checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}");
|
_checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
ReferencedStructTypes.Add(structType);
|
|
||||||
|
|
||||||
return structType;
|
return structType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Text;
|
||||||
using NubLang.Ast;
|
using NubLang.Ast;
|
||||||
using NubLang.Syntax;
|
using NubLang.Syntax;
|
||||||
|
|
||||||
@@ -6,17 +7,16 @@ namespace NubLang.Generation;
|
|||||||
public class Generator
|
public class Generator
|
||||||
{
|
{
|
||||||
private readonly List<DefinitionNode> _definitions;
|
private readonly List<DefinitionNode> _definitions;
|
||||||
private readonly HashSet<NubStructType> _structTypes;
|
|
||||||
private readonly IndentedTextWriter _writer;
|
private readonly IndentedTextWriter _writer;
|
||||||
private readonly Stack<List<DeferNode>> _deferStack = [];
|
private readonly Stack<List<DeferNode>> _deferStack = [];
|
||||||
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
||||||
|
private readonly List<NubStructType> _structTypes = [];
|
||||||
private int _tmpIndex;
|
private int _tmpIndex;
|
||||||
private int _funcDefIndex;
|
private int _funcDefIndex;
|
||||||
|
|
||||||
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
|
public Generator(List<DefinitionNode> definitions)
|
||||||
{
|
{
|
||||||
_definitions = definitions;
|
_definitions = definitions;
|
||||||
_structTypes = structTypes;
|
|
||||||
_writer = new IndentedTextWriter();
|
_writer = new IndentedTextWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,12 +55,18 @@ public class Generator
|
|||||||
},
|
},
|
||||||
NubPointerType pointerType => MapType(pointerType.BaseType),
|
NubPointerType pointerType => MapType(pointerType.BaseType),
|
||||||
NubStringType => throw new NotImplementedException(),
|
NubStringType => throw new NotImplementedException(),
|
||||||
NubStructType structType => StructName(structType.Module, structType.Name),
|
NubStructType structType => MapStructType(structType),
|
||||||
NubVoidType => "void",
|
NubVoidType => "void",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string MapStructType(NubStructType structType)
|
||||||
|
{
|
||||||
|
_structTypes.Add(structType);
|
||||||
|
return StructName(structType.Module, structType.Name);
|
||||||
|
}
|
||||||
|
|
||||||
private string MapFuncType(NubFuncType funcType)
|
private string MapFuncType(NubFuncType funcType)
|
||||||
{
|
{
|
||||||
var name = $"_func_type_def{++_funcDefIndex}";
|
var name = $"_func_type_def{++_funcDefIndex}";
|
||||||
@@ -146,21 +152,7 @@ public class Generator
|
|||||||
#define U64_C(x) x##ULL
|
#define U64_C(x) x##ULL
|
||||||
""";
|
""";
|
||||||
|
|
||||||
foreach (var structType in _structTypes)
|
|
||||||
{
|
|
||||||
_writer.WriteLine("typedef struct");
|
|
||||||
_writer.WriteLine("{");
|
|
||||||
using (_writer.Indent())
|
|
||||||
{
|
|
||||||
foreach (var field in structType.Fields)
|
|
||||||
{
|
|
||||||
_writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};");
|
|
||||||
_writer.WriteLine();
|
_writer.WriteLine();
|
||||||
}
|
|
||||||
|
|
||||||
var appendNewLine = false;
|
var appendNewLine = false;
|
||||||
|
|
||||||
@@ -231,7 +223,21 @@ public class Generator
|
|||||||
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
||||||
}
|
}
|
||||||
|
|
||||||
return header + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
var structDefSb = new StringBuilder();
|
||||||
|
foreach (var structType in _structTypes)
|
||||||
|
{
|
||||||
|
structDefSb.AppendLine("typedef struct");
|
||||||
|
structDefSb.AppendLine("{");
|
||||||
|
foreach (var field in structType.Fields)
|
||||||
|
{
|
||||||
|
structDefSb.AppendLine($" {MapNameWithType(field.Type, field.Name)};");
|
||||||
|
}
|
||||||
|
|
||||||
|
structDefSb.AppendLine($"}} {StructName(structType.Module, structType.Name)};");
|
||||||
|
structDefSb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return header + structDefSb + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitStatement(StatementNode statementNode)
|
private void EmitStatement(StatementNode statementNode)
|
||||||
|
|||||||
@@ -34,12 +34,4 @@ public class Module
|
|||||||
.Where(x => x.Exported || includePrivate)
|
.Where(x => x.Exported || includePrivate)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GlobalVariableSyntax> GlobalVariables(bool includePrivate)
|
|
||||||
{
|
|
||||||
return _definitions
|
|
||||||
.OfType<GlobalVariableSyntax>()
|
|
||||||
.Where(x => x.Exported || includePrivate)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,6 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
Symbol.Func => ParseFunc(startIndex, exported, null),
|
Symbol.Func => ParseFunc(startIndex, exported, null),
|
||||||
Symbol.Struct => ParseStruct(startIndex, exported),
|
Symbol.Struct => ParseStruct(startIndex, exported),
|
||||||
Symbol.Let => ParseGlobalVariable(startIndex, exported),
|
|
||||||
_ => throw new ParseException(Diagnostic
|
_ => throw new ParseException(Diagnostic
|
||||||
.Error($"Expected 'func' or 'struct' but found '{keyword.Symbol}'")
|
.Error($"Expected 'func' or 'struct' but found '{keyword.Symbol}'")
|
||||||
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
||||||
@@ -112,22 +111,6 @@ public sealed class Parser
|
|||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GlobalVariableSyntax ParseGlobalVariable(int startIndex, bool exported)
|
|
||||||
{
|
|
||||||
var name = ExpectIdentifier();
|
|
||||||
|
|
||||||
TypeSyntax? type = null;
|
|
||||||
if (TryExpectSymbol(Symbol.Colon))
|
|
||||||
{
|
|
||||||
type = ParseType();
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectSymbol(Symbol.Assign);
|
|
||||||
var value = ParseExpression();
|
|
||||||
|
|
||||||
return new GlobalVariableSyntax(GetTokens(startIndex), name.Value, exported, type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FuncSignatureSyntax ParseFuncSignature()
|
private FuncSignatureSyntax ParseFuncSignature()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
var startIndex = _tokenIndex;
|
||||||
@@ -924,21 +907,6 @@ public sealed class Parser
|
|||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntLiteralToken ExpectIntLiteral()
|
|
||||||
{
|
|
||||||
var token = ExpectToken();
|
|
||||||
if (token is not IntLiteralToken identifier)
|
|
||||||
{
|
|
||||||
throw new ParseException(Diagnostic
|
|
||||||
.Error($"Expected int literal, but found {token.GetType().Name}")
|
|
||||||
.WithHelp("Provide a valid int literal")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryExpectIntLiteral([NotNullWhen(true)] out IntLiteralToken? stringLiteral)
|
private bool TryExpectIntLiteral([NotNullWhen(true)] out IntLiteralToken? stringLiteral)
|
||||||
{
|
{
|
||||||
if (CurrentToken is IntLiteralToken token)
|
if (CurrentToken is IntLiteralToken token)
|
||||||
@@ -952,36 +920,6 @@ public sealed class Parser
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FloatLiteralToken ExpectFloatLiteral()
|
|
||||||
{
|
|
||||||
var token = ExpectToken();
|
|
||||||
if (token is not FloatLiteralToken identifier)
|
|
||||||
{
|
|
||||||
throw new ParseException(Diagnostic
|
|
||||||
.Error($"Expected float literal, but found {token.GetType().Name}")
|
|
||||||
.WithHelp("Provide a valid float literal")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BoolLiteralToken ExpectBoolLiteral()
|
|
||||||
{
|
|
||||||
var token = ExpectToken();
|
|
||||||
if (token is not BoolLiteralToken identifier)
|
|
||||||
{
|
|
||||||
throw new ParseException(Diagnostic
|
|
||||||
.Error($"Expected bool literal, but found {token.GetType().Name}")
|
|
||||||
.WithHelp("Provide a valid bool literal")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringLiteralToken ExpectStringLiteral()
|
private StringLiteralToken ExpectStringLiteral()
|
||||||
{
|
{
|
||||||
var token = ExpectToken();
|
var token = ExpectToken();
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<
|
|||||||
|
|
||||||
public record StructTemplateSyntax(List<Token> Tokens, List<string> TemplateArguments, string Name, bool Exported, List<StructFieldSyntax> Fields, List<StructFuncSyntax> Functions) : DefinitionSyntax(Tokens, Name, Exported);
|
public record StructTemplateSyntax(List<Token> Tokens, List<string> TemplateArguments, string Name, bool Exported, List<StructFieldSyntax> Fields, List<StructFuncSyntax> Functions) : DefinitionSyntax(Tokens, Name, Exported);
|
||||||
|
|
||||||
public record GlobalVariableSyntax(List<Token> Tokens, string Name, bool Exported, TypeSyntax? ExplicitType, ExpressionSyntax Value) : DefinitionSyntax(Tokens, Name, Exported);
|
|
||||||
|
|
||||||
public enum UnaryOperatorSyntax
|
public enum UnaryOperatorSyntax
|
||||||
{
|
{
|
||||||
Negate,
|
Negate,
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
out: .build/out.o
|
.build/out: main.nub
|
||||||
gcc -nostartfiles -lm -o out x86_64.s .build/out.o
|
|
||||||
|
|
||||||
.build/out.o: main.nub
|
|
||||||
nubc main.nub
|
nubc main.nub
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -r .build 2>/dev/null || true
|
@rm -r .build 2>/dev/null || true
|
||||||
@rm out 2>/dev/null || true
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
.intel_syntax noprefix
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _start
|
|
||||||
_start:
|
|
||||||
mov rdi, rsp
|
|
||||||
call main
|
|
||||||
mov rdi, rax
|
|
||||||
mov rax, 60
|
|
||||||
syscall
|
|
||||||
3
examples/raylib/.gitignore
vendored
3
examples/raylib/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
.build
|
|
||||||
out.a
|
|
||||||
out
|
|
||||||
Reference in New Issue
Block a user