This commit is contained in:
nub31
2025-01-26 20:22:22 +01:00
parent 59effadc19
commit 84b3636e75
6 changed files with 54 additions and 5 deletions

View File

@@ -66,6 +66,26 @@ public class Generator
_builder.AppendLine();
GenerateFuncDefinition(funcDefinition);
}
_builder.AppendLine("""
; https://tuttlem.github.io/2013/01/08/strlen-implementation-in-nasm.html
strlen:
push rcx ; save and clear out counter
xor rcx, rcx
.strlen_next:
cmp [rdi], byte 0 ; null byte yet?
jz .strlen_null ; yes, get out
inc rcx ; char is ok, count it
inc rdi ; move to next char
jmp .strlen_next ; process again
.strlen_null:
mov rax, rcx ; rcx = the length (put in rax)
pop rcx ; restore rcx
ret ; get out
""");
_builder.AppendLine();
_builder.AppendLine("section .data");
foreach (var str in _strings)
@@ -148,6 +168,9 @@ public class Generator
case LiteralNode literal:
GenerateLiteral(literal, func);
break;
case StrlenNode strlen:
GenerateStrlen(strlen, func);
break;
case SyscallExpressionNode syscallExpression:
throw new NotImplementedException();
break;
@@ -232,6 +255,13 @@ public class Generator
}
}
private void GenerateStrlen(StrlenNode strlen, Func func)
{
GenerateExpression(strlen.String, func);
_builder.AppendLine(" mov rdi, rax");
_builder.AppendLine(" call strlen");
}
// TODO: Use stack for more than 6 parameters
private void GenerateFuncCall(FuncCall funcCall, Func func)
{

View File

@@ -7,6 +7,6 @@ func main() {
write("test\n");
}
func write(msg: pointer) {
syscall(SYS_WRITE, STD_OUT, msg, 5);
func write(msg: String) {
syscall(SYS_WRITE, STD_OUT, msg, strlen(msg));
}

View File

@@ -144,7 +144,12 @@ public class Parser
{
return new SyscallExpressionNode(new Syscall(parameters));
}
if (identifier.Value == "strlen" && parameters.Count == 1)
{
return new StrlenNode(parameters[0]);
}
return new FuncCallExpressionNode(new FuncCall(identifier.Value, parameters));
}
@@ -184,7 +189,7 @@ public class Parser
return new DelegateType(typeArguments.Take(typeArguments.Count - 1).ToList(), returnType);
}
if (name == "pointer")
if (name == "String")
{
return new StringType();
}

View File

@@ -0,0 +1,6 @@
namespace Nub.Lang.Parsing;
public class StrlenNode(ExpressionNode @string) : ExpressionNode
{
public ExpressionNode String { get; } = @string;
}

View File

@@ -56,7 +56,7 @@ public enum PrimitiveTypeKind
public record StringType : Type
{
public override string ToString() => "string";
public override string ToString() => "String";
}
public record DelegateType : Type

View File

@@ -104,6 +104,9 @@ public class ExpressionTyper
case LiteralNode literal:
PopulateLiteral(literal);
break;
case StrlenNode strlen:
PopulateStrlen(strlen);
break;
case SyscallExpressionNode syscall:
PopulateSyscallExpression(syscall);
break;
@@ -146,6 +149,11 @@ public class ExpressionTyper
literal.Type = literal.LiteralType;
}
private static void PopulateStrlen(StrlenNode strlen)
{
strlen.Type = new PrimitiveType(PrimitiveTypeKind.Int64);
}
private void PopulateSyscallExpression(SyscallExpressionNode syscall)
{
foreach (var parameter in syscall.Syscall.Parameters)