strlen
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
6
Nub.Lang/Nub.Lang/Parsing/StrlenNode.cs
Normal file
6
Nub.Lang/Nub.Lang/Parsing/StrlenNode.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Nub.Lang.Parsing;
|
||||
|
||||
public class StrlenNode(ExpressionNode @string) : ExpressionNode
|
||||
{
|
||||
public ExpressionNode String { get; } = @string;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user