This commit is contained in:
nub31
2025-07-03 18:29:33 +02:00
parent 792afd0442
commit 9babcd0b41
2 changed files with 50 additions and 38 deletions

View File

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

View File

@@ -195,17 +195,43 @@ public static class QBEGenerator
return size; 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: case NubComplexType complexType:
{ {
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))
}; };
@@ -218,13 +244,13 @@ public static class QBEGenerator
{ {
var buffer = VarName(); var buffer = VarName();
_builder.AppendLine($" {buffer} =l alloc8 {size}"); _builder.AppendLine($" {buffer} =l alloc8 {size}");
EmitMemcpy(source, buffer, size); EmitMemcpy(value, buffer, size);
EmitStore(type, buffer, destinationPointer); EmitStore(source.Type, buffer, destinationPointer);
return; return;
} }
case NubStructType: case NubStructType:
{ {
EmitMemcpy(source, destinationPointer, size); EmitMemcpy(value, destinationPointer, size);
return; return;
} }
default: default:
@@ -235,12 +261,12 @@ public static class QBEGenerator
} }
case NubSimpleType simpleType: case NubSimpleType simpleType:
{ {
EmitStore(simpleType, source, destinationPointer); EmitStore(simpleType, value, destinationPointer);
return; return;
} }
default: 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); var destination = EmitExpression(assignment.Expression);
Debug.Assert(destination.Kind == ValKind.Pointer); Debug.Assert(destination.Kind == ValKind.Pointer);
EmitCopyOrMoveInto(assignment.Value, destination.Name);
// 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;
}
}
} }
private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null) private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null)
@@ -1017,7 +1022,7 @@ public static class QBEGenerator
var size = SizeOf(structInitializer.StructType); var size = SizeOf(structInitializer.StructType);
_builder.AppendLine($" {destination} =l alloc8 {size}"); _builder.AppendLine($" {destination} =l alloc8 {size}");
} }
foreach (var field in structDefinition.Fields) foreach (var field in structDefinition.Fields)
{ {
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression)) if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
@@ -1029,8 +1034,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)}");
var source = EmitUnwrap(EmitExpression(valueExpression)); EmitCopyOrMoveInto(valueExpression, offset);
EmitCopyInto(valueExpression.Type, source, offset);
} }
return new Val(destination, structInitializer.StructType, ValKind.Direct); return new Val(destination, structInitializer.StructType, ValKind.Direct);