This commit is contained in:
nub31
2025-07-03 18:57:37 +02:00
parent 8889f984d6
commit 66d47b9100
2 changed files with 57 additions and 28 deletions

View File

@@ -1,29 +1,31 @@
namespace main namespace main
struct Name { // struct Name {
first: cstring // first: cstring
last: cstring // last: cstring
} // }
struct Human // struct Human
{ // {
name: Name // name: Name
age: i64 // age: i64
} // }
export func main(args: []cstring): i64 export func main(args: []cstring): i64
{ {
let x: Human // let x: Human
x = alloc Human { // x = alloc Human {
name = alloc Name { // name = alloc Name {
first = "john" // first = "john"
last = "doe" // last = "doe"
} // }
age = 23 // age = 23
} // }
c::puts(x.name.last) // c::puts(x.name.last)
c::puts("test")
return 0 return 0
} }

View File

@@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
using Syntax; using Syntax;
@@ -219,8 +220,9 @@ public static class QBEGenerator
return false; return false;
} }
private static void EmitCopyOrMoveInto(BoundExpressionNode source, string destinationPointer) private static void EmitCopyIntoOrInitialize(BoundExpressionNode source, string destinationPointer)
{ {
// If the source is a value which is not used yet such as an array/struct initializer or literal, we can skip copying
if (EmitTryMoveInto(source, destinationPointer)) if (EmitTryMoveInto(source, destinationPointer))
{ {
return; return;
@@ -276,8 +278,33 @@ public static class QBEGenerator
} }
} }
private static string EmitCopy(NubType type, string source) private static bool EmitTryCreateWithoutCopy(BoundExpressionNode source, [NotNullWhen(true)] out string? destination)
{ {
switch (source)
{
case BoundArrayInitializerNode:
case BoundStructInitializerNode:
case BoundLiteralNode { Kind: LiteralKind.String }:
{
destination = EmitUnwrap(EmitExpression(source));
return true;
}
}
destination = null;
return false;
}
private static string EmitCreateCopyOrInitialize(NubType type, BoundExpressionNode source)
{
// If the source is a value which is not used yet such as an array/struct initializer or literal, we can skip copying
if (EmitTryCreateWithoutCopy(source, out var uncopiedValue))
{
return uncopiedValue;
}
var value = EmitUnwrap(EmitExpression(source));
switch (type) switch (type)
{ {
case NubComplexType complexType: case NubComplexType complexType:
@@ -286,20 +313,20 @@ public static class QBEGenerator
var size = complexType switch var size = complexType switch
{ {
NubArrayType nubArrayType => EmitArraySizeInBytes(nubArrayType, source), NubArrayType nubArrayType => EmitArraySizeInBytes(nubArrayType, value),
NubCStringType => EmitCStringSizeInBytes(source), NubCStringType => EmitCStringSizeInBytes(value),
NubStringType => EmitStringSizeInBytes(source), NubStringType => EmitStringSizeInBytes(value),
NubStructType nubStructType => SizeOf(nubStructType).ToString(), NubStructType nubStructType => SizeOf(nubStructType).ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(complexType)) _ => throw new ArgumentOutOfRangeException(nameof(complexType))
}; };
_builder.AppendLine($" {destination} =l alloc8 {size}"); _builder.AppendLine($" {destination} =l alloc8 {size}");
EmitMemcpy(source, destination, size); EmitMemcpy(value, destination, size);
return destination; return destination;
} }
case NubSimpleType: case NubSimpleType:
{ {
return source; return value;
} }
default: default:
{ {
@@ -601,7 +628,7 @@ public static class QBEGenerator
{ {
var destination = EmitExpression(assignment.Expression); var destination = EmitExpression(assignment.Expression);
Debug.Assert(destination.Kind == ValKind.Pointer); Debug.Assert(destination.Kind == ValKind.Pointer);
EmitCopyOrMoveInto(assignment.Value, destination.Name); EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
} }
private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null) private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null)
@@ -1039,7 +1066,7 @@ public static class QBEGenerator
var offset = VarName(); var offset = VarName();
_builder.AppendLine($" {offset} =l add {destination}, {OffsetOf(structDefinition, field.Name)}"); _builder.AppendLine($" {offset} =l add {destination}, {OffsetOf(structDefinition, field.Name)}");
EmitCopyOrMoveInto(valueExpression, offset); EmitCopyIntoOrInitialize(valueExpression, offset);
} }
return new Val(destination, structInitializer.StructType, ValKind.Direct); return new Val(destination, structInitializer.StructType, ValKind.Direct);
@@ -1169,7 +1196,7 @@ public static class QBEGenerator
_ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used in function calls") _ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used in function calls")
}; };
var copy = EmitCopy(parameter.Type, EmitUnwrap(EmitExpression(parameter))); var copy = EmitCreateCopyOrInitialize(parameter.Type, parameter);
parameterStrings.Add($"{qbeType} {copy}"); parameterStrings.Add($"{qbeType} {copy}");
} }