strlen
This commit is contained in:
@@ -66,6 +66,26 @@ public class Generator
|
|||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
GenerateFuncDefinition(funcDefinition);
|
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();
|
||||||
_builder.AppendLine("section .data");
|
_builder.AppendLine("section .data");
|
||||||
foreach (var str in _strings)
|
foreach (var str in _strings)
|
||||||
@@ -148,6 +168,9 @@ public class Generator
|
|||||||
case LiteralNode literal:
|
case LiteralNode literal:
|
||||||
GenerateLiteral(literal, func);
|
GenerateLiteral(literal, func);
|
||||||
break;
|
break;
|
||||||
|
case StrlenNode strlen:
|
||||||
|
GenerateStrlen(strlen, func);
|
||||||
|
break;
|
||||||
case SyscallExpressionNode syscallExpression:
|
case SyscallExpressionNode syscallExpression:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
break;
|
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
|
// TODO: Use stack for more than 6 parameters
|
||||||
private void GenerateFuncCall(FuncCall funcCall, Func func)
|
private void GenerateFuncCall(FuncCall funcCall, Func func)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ func main() {
|
|||||||
write("test\n");
|
write("test\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
func write(msg: pointer) {
|
func write(msg: String) {
|
||||||
syscall(SYS_WRITE, STD_OUT, msg, 5);
|
syscall(SYS_WRITE, STD_OUT, msg, strlen(msg));
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,12 @@ public class Parser
|
|||||||
{
|
{
|
||||||
return new SyscallExpressionNode(new Syscall(parameters));
|
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));
|
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);
|
return new DelegateType(typeArguments.Take(typeArguments.Count - 1).ToList(), returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == "pointer")
|
if (name == "String")
|
||||||
{
|
{
|
||||||
return new StringType();
|
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 record StringType : Type
|
||||||
{
|
{
|
||||||
public override string ToString() => "string";
|
public override string ToString() => "String";
|
||||||
}
|
}
|
||||||
|
|
||||||
public record DelegateType : Type
|
public record DelegateType : Type
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ public class ExpressionTyper
|
|||||||
case LiteralNode literal:
|
case LiteralNode literal:
|
||||||
PopulateLiteral(literal);
|
PopulateLiteral(literal);
|
||||||
break;
|
break;
|
||||||
|
case StrlenNode strlen:
|
||||||
|
PopulateStrlen(strlen);
|
||||||
|
break;
|
||||||
case SyscallExpressionNode syscall:
|
case SyscallExpressionNode syscall:
|
||||||
PopulateSyscallExpression(syscall);
|
PopulateSyscallExpression(syscall);
|
||||||
break;
|
break;
|
||||||
@@ -146,6 +149,11 @@ public class ExpressionTyper
|
|||||||
literal.Type = literal.LiteralType;
|
literal.Type = literal.LiteralType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void PopulateStrlen(StrlenNode strlen)
|
||||||
|
{
|
||||||
|
strlen.Type = new PrimitiveType(PrimitiveTypeKind.Int64);
|
||||||
|
}
|
||||||
|
|
||||||
private void PopulateSyscallExpression(SyscallExpressionNode syscall)
|
private void PopulateSyscallExpression(SyscallExpressionNode syscall)
|
||||||
{
|
{
|
||||||
foreach (var parameter in syscall.Syscall.Parameters)
|
foreach (var parameter in syscall.Syscall.Parameters)
|
||||||
|
|||||||
Reference in New Issue
Block a user