From 9babcd0b41284ea6453c5130aa8ff1a78899885c Mon Sep 17 00:00:00 2001 From: nub31 Date: Thu, 3 Jul 2025 18:29:33 +0200 Subject: [PATCH] ... --- example/src/main.nub | 14 +++- src/compiler/Generation/QBE/QBEGenerator.cs | 74 +++++++++++---------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/example/src/main.nub b/example/src/main.nub index 29e5532..a7a5d44 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -1,8 +1,13 @@ namespace main +struct Name { + first: cstring + last: cstring +} + struct Human { - name: cstring + name: Name age: i64 } @@ -11,11 +16,14 @@ export func main(args: []cstring): i64 let x: Human x = alloc Human { - name = "john" + name = alloc Name { + first = "john" + last = "doe" + } age = 23 } - c::puts(x.name) + c::puts(x.name.last) return 0 } diff --git a/src/compiler/Generation/QBE/QBEGenerator.cs b/src/compiler/Generation/QBE/QBEGenerator.cs index a2dd1af..64b7b1a 100644 --- a/src/compiler/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/Generation/QBE/QBEGenerator.cs @@ -195,17 +195,43 @@ public static class QBEGenerator return size; } - private static void EmitCopyInto(NubType type, string source, string destinationPointer) + private static bool EmitTryMoveInto(BoundExpressionNode source, string destinationPointer) { - switch (type) + switch (source) + { + case BoundArrayInitializerNode arrayInitializer: + { + EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer); + return true; + } + case BoundStructInitializerNode structInitializer: + { + EmitStructInitializer(structInitializer, destinationPointer); + return true; + } + } + + return false; + } + + private static void EmitCopyOrMoveInto(BoundExpressionNode source, string destinationPointer) + { + if (EmitTryMoveInto(source, destinationPointer)) + { + return; + } + + var value = EmitUnwrap(EmitExpression(source)); + + switch (source.Type) { case NubComplexType complexType: { var size = complexType switch { - NubArrayType nubArrayType => EmitArraySizeInBytes(nubArrayType, source), - NubCStringType => EmitCStringSizeInBytes(source), - NubStringType => EmitStringSizeInBytes(source), + NubArrayType nubArrayType => EmitArraySizeInBytes(nubArrayType, value), + NubCStringType => EmitCStringSizeInBytes(value), + NubStringType => EmitStringSizeInBytes(value), NubStructType nubStructType => SizeOf(nubStructType).ToString(), _ => throw new ArgumentOutOfRangeException(nameof(complexType)) }; @@ -218,13 +244,13 @@ public static class QBEGenerator { var buffer = VarName(); _builder.AppendLine($" {buffer} =l alloc8 {size}"); - EmitMemcpy(source, buffer, size); - EmitStore(type, buffer, destinationPointer); + EmitMemcpy(value, buffer, size); + EmitStore(source.Type, buffer, destinationPointer); return; } case NubStructType: { - EmitMemcpy(source, destinationPointer, size); + EmitMemcpy(value, destinationPointer, size); return; } default: @@ -235,12 +261,12 @@ public static class QBEGenerator } case NubSimpleType simpleType: { - EmitStore(simpleType, source, destinationPointer); + EmitStore(simpleType, value, destinationPointer); return; } default: { - throw new ArgumentOutOfRangeException(nameof(type)); + throw new ArgumentOutOfRangeException(nameof(source.Type)); } } } @@ -570,28 +596,7 @@ public static class QBEGenerator { var destination = EmitExpression(assignment.Expression); Debug.Assert(destination.Kind == ValKind.Pointer); - - // Initializers will be created in place to prevent a - switch (assignment.Value) - { - case BoundArrayInitializerNode arrayInitializer: - { - var value = EmitUnwrap(EmitArrayInitializer(arrayInitializer)); - EmitStore(assignment.Value.Type, value, destination.Name); - break; - } - case BoundStructInitializerNode structInitializer: - { - EmitStructInitializer(structInitializer, destination.Name); - break; - } - default: - { - var value = EmitUnwrap(EmitExpression(assignment.Value)); - EmitCopyInto(assignment.Value.Type, value, destination.Name); - break; - } - } + EmitCopyOrMoveInto(assignment.Value, destination.Name); } private static void EmitBlock(BoundBlockNode block, List? variables = null) @@ -1017,7 +1022,7 @@ public static class QBEGenerator var size = SizeOf(structInitializer.StructType); _builder.AppendLine($" {destination} =l alloc8 {size}"); } - + foreach (var field in structDefinition.Fields) { if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression)) @@ -1029,8 +1034,7 @@ public static class QBEGenerator var offset = VarName(); _builder.AppendLine($" {offset} =l add {destination}, {OffsetOf(structDefinition, field.Name)}"); - var source = EmitUnwrap(EmitExpression(valueExpression)); - EmitCopyInto(valueExpression.Type, source, offset); + EmitCopyOrMoveInto(valueExpression, offset); } return new Val(destination, structInitializer.StructType, ValKind.Direct);