improve addressof
This commit is contained in:
@@ -5,15 +5,19 @@ struct Human {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export func main(args: []^string): i64 {
|
export func main(args: []^string): i64 {
|
||||||
let x = [3]f64
|
let age: u64 = 23
|
||||||
|
|
||||||
x[0] = 1
|
let me = alloc Human {
|
||||||
x[1] = 2
|
age = &age
|
||||||
x[2] = 3
|
}
|
||||||
|
|
||||||
c::printf("%f\n", x[0])
|
me.age^ = 24.5
|
||||||
c::printf("%f\n", x[1])
|
|
||||||
c::printf("%f\n", x[2])
|
test(me.age^)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func test(me: u64) {
|
||||||
|
c::printf("%d\n", me)
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ error = error || typeCheckResult.HasErrors;
|
|||||||
|
|
||||||
if (error) return 1;
|
if (error) return 1;
|
||||||
|
|
||||||
var generator = new Generator();
|
var generator = new QBEGenerator();
|
||||||
var result = generator.Generate(files);
|
var result = generator.Generate(files);
|
||||||
|
|
||||||
Console.Out.Write(result);
|
Console.Out.Write(result);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using Nub.Lang.Frontend.Typing;
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Generation;
|
namespace Nub.Lang.Frontend.Generation;
|
||||||
|
|
||||||
public class Generator
|
public class QBEGenerator
|
||||||
{
|
{
|
||||||
private const string OutOfBoundsMessage = "Index is out of bounds\\n";
|
private const string OutOfBoundsMessage = "Index is out of bounds\\n";
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ public class Generator
|
|||||||
|
|
||||||
foreach (var parameter in node.Parameters)
|
foreach (var parameter in node.Parameters)
|
||||||
{
|
{
|
||||||
var parameterName = parameter.Name;
|
var parameterName = "%" + parameter.Name;
|
||||||
|
|
||||||
if (parameter.Type is NubPrimitiveType primitiveType)
|
if (parameter.Type is NubPrimitiveType primitiveType)
|
||||||
{
|
{
|
||||||
@@ -319,24 +319,18 @@ public class Generator
|
|||||||
parameterName = GenVarName();
|
parameterName = GenVarName();
|
||||||
_builder.AppendLine($" {parameterName} =w extub %{parameter.Name}");
|
_builder.AppendLine($" {parameterName} =w extub %{parameter.Name}");
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_variables[parameter.Name] = parameterName;
|
_variables[parameter.Name] = parameterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
_builder.AppendLine();
|
|
||||||
|
|
||||||
GenerateBlock(node.Body);
|
GenerateBlock(node.Body);
|
||||||
|
|
||||||
if (node.Body.Statements.LastOrDefault() is not ReturnNode)
|
if (node.Body.Statements.LastOrDefault() is not ReturnNode)
|
||||||
{
|
{
|
||||||
if (node.ReturnType is NubVoidType)
|
if (node.ReturnType is NubVoidType)
|
||||||
{
|
{
|
||||||
_builder.AppendLine();
|
|
||||||
_builder.AppendLine(" # Implicit return");
|
|
||||||
_builder.AppendLine(" ret");
|
_builder.AppendLine(" ret");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,17 +430,10 @@ public class Generator
|
|||||||
var adjustedIndex = GenVarName();
|
var adjustedIndex = GenVarName();
|
||||||
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||||
|
|
||||||
var offsetName = GenVarName();
|
var pointer = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
|
_builder.AppendLine($" {pointer} =l add {startName}, {adjustedIndex}");
|
||||||
|
|
||||||
if (IsLargeType(arrayType.ElementType))
|
GenerateCopy(arrayType.ElementType, value, pointer);
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(arrayType.ElementType)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(arrayType.ElementType)} {value}, {offsetName}");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NubFixedArrayType fixedArrayType:
|
case NubFixedArrayType fixedArrayType:
|
||||||
@@ -457,17 +444,10 @@ public class Generator
|
|||||||
var adjustedIndex = GenVarName();
|
var adjustedIndex = GenVarName();
|
||||||
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
||||||
|
|
||||||
var offsetName = GenVarName();
|
var pointer = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
|
_builder.AppendLine($" {pointer} =l add {startName}, {adjustedIndex}");
|
||||||
|
|
||||||
if (IsLargeType(fixedArrayType.ElementType))
|
GenerateCopy(fixedArrayType.ElementType, value, pointer);
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(fixedArrayType.ElementType)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(fixedArrayType.ElementType)} {value}, {offsetName}");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -501,17 +481,9 @@ public class Generator
|
|||||||
|
|
||||||
private void GenerateDereferenceAssignment(DereferenceAssignmentNode dereferenceAssignment)
|
private void GenerateDereferenceAssignment(DereferenceAssignmentNode dereferenceAssignment)
|
||||||
{
|
{
|
||||||
var location = GenerateExpression(dereferenceAssignment.Dereference.Expression);
|
var pointer = GenerateExpression(dereferenceAssignment.Dereference.Expression);
|
||||||
var value = GenerateExpression(dereferenceAssignment.Value);
|
var value = GenerateExpression(dereferenceAssignment.Value);
|
||||||
|
GenerateCopy(dereferenceAssignment.Value.Type, value, pointer);
|
||||||
if (IsLargeType(dereferenceAssignment.Value.Type))
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {value}, {location}, {SizeOf(dereferenceAssignment.Value.Type)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(dereferenceAssignment.Value.Type)} {value}, {location}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateIf(IfNode ifStatement)
|
private void GenerateIf(IfNode ifStatement)
|
||||||
@@ -547,20 +519,13 @@ public class Generator
|
|||||||
var offset = LookupMemberOffset(structDefinition, memberAssignment.MemberAccess.Member);
|
var offset = LookupMemberOffset(structDefinition, memberAssignment.MemberAccess.Member);
|
||||||
|
|
||||||
var item = GenerateExpression(memberAssignment.MemberAccess.Expression);
|
var item = GenerateExpression(memberAssignment.MemberAccess.Expression);
|
||||||
var offsetName = GenVarName();
|
var pointer = GenVarName();
|
||||||
|
|
||||||
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
|
_builder.AppendLine($" {pointer} =l add {item}, {offset}");
|
||||||
|
|
||||||
var value = GenerateExpression(memberAssignment.Value);
|
var value = GenerateExpression(memberAssignment.Value);
|
||||||
|
|
||||||
if (IsLargeType(memberAssignment.Value.Type))
|
GenerateCopy(memberAssignment.Value.Type, value, pointer);
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(memberAssignment.Value.Type)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(memberAssignment.Value.Type)} {value}, {offsetName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateReturn(ReturnNode @return)
|
private void GenerateReturn(ReturnNode @return)
|
||||||
@@ -578,45 +543,29 @@ public class Generator
|
|||||||
|
|
||||||
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(variableAssignment.Value);
|
var value = GenerateExpression(variableAssignment.Value);
|
||||||
_builder.AppendLine($" storel {result}, {_variables[variableAssignment.Identifier.Identifier]}");
|
var pointer = _variables[variableAssignment.Identifier.Identifier];
|
||||||
|
GenerateCopy(variableAssignment.Value.Type, value, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
private void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
||||||
{
|
{
|
||||||
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value?.Type!;
|
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value!.Type;
|
||||||
|
var pointer = GenVarName();
|
||||||
string pointerName;
|
_builder.AppendLine($" {pointer} =l alloc8 {SizeOf(type)}");
|
||||||
|
|
||||||
if (variableDeclaration.Value.HasValue)
|
if (variableDeclaration.Value.HasValue)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(variableDeclaration.Value.Value);
|
var value = GenerateExpression(variableDeclaration.Value.Value);
|
||||||
if (IsLargeType(type))
|
GenerateCopy(variableDeclaration.Value.Value.Type, value, pointer);
|
||||||
{
|
|
||||||
pointerName = result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pointerName = GenVarName();
|
|
||||||
_builder.AppendLine($" {pointerName} =l alloc8 {SizeOf(type)}");
|
|
||||||
_builder.AppendLine($" {QBEStore(type)} {result}, {pointerName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pointerName = GenVarName();
|
var pointerName = GenVarName();
|
||||||
_builder.AppendLine($" {pointerName} =l alloc8 {SizeOf(type)}");
|
_variables[variableDeclaration.Name] = pointerName;
|
||||||
if (IsLargeType(type))
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" call $nub_memset(l {pointerName}, ub 0, l {SizeOf(type)})");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(type)} 0, {pointerName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_variables[variableDeclaration.Name] = pointerName;
|
_variables[variableDeclaration.Name] = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateWhile(WhileNode whileStatement)
|
private void GenerateWhile(WhileNode whileStatement)
|
||||||
@@ -645,10 +594,9 @@ public class Generator
|
|||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||||
ArrayIndexAccessNode arrayIndex => GenerateArrayIndex(arrayIndex),
|
ArrayIndexAccessNode arrayIndex => GenerateArrayAccessIndex(arrayIndex),
|
||||||
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
|
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
|
||||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||||
// CastNode cast => GenerateCast(cast),
|
|
||||||
DereferenceNode dereference => GenerateDereference(dereference),
|
DereferenceNode dereference => GenerateDereference(dereference),
|
||||||
FixedArrayInitializerNode fixedArrayInitializer => GenerateFixedArrayInitializer(fixedArrayInitializer),
|
FixedArrayInitializerNode fixedArrayInitializer => GenerateFixedArrayInitializer(fixedArrayInitializer),
|
||||||
FuncCallNode funcCallExpression => GenerateFuncCall(funcCallExpression),
|
FuncCallNode funcCallExpression => GenerateFuncCall(funcCallExpression),
|
||||||
@@ -661,7 +609,7 @@ public class Generator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
|
private string GenerateArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var array = GenerateExpression(arrayIndexAccess.Array);
|
var array = GenerateExpression(arrayIndexAccess.Array);
|
||||||
var index = GenerateExpression(arrayIndexAccess.Index);
|
var index = GenerateExpression(arrayIndexAccess.Index);
|
||||||
@@ -677,17 +625,7 @@ public class Generator
|
|||||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||||
var resultPointerName = GenVarName();
|
var resultPointerName = GenVarName();
|
||||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||||
|
return resultPointerName;
|
||||||
if (IsLargeType(arrayType.ElementType))
|
|
||||||
{
|
|
||||||
return resultPointerName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var outputName = GenVarName();
|
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(arrayType.ElementType)} {QBELoad(arrayType.ElementType)} {resultPointerName}");
|
|
||||||
return outputName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case NubFixedArrayType fixedArrayType:
|
case NubFixedArrayType fixedArrayType:
|
||||||
{
|
{
|
||||||
@@ -697,17 +635,7 @@ public class Generator
|
|||||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
||||||
var resultPointerName = GenVarName();
|
var resultPointerName = GenVarName();
|
||||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||||
|
return resultPointerName;
|
||||||
if (IsLargeType(fixedArrayType.ElementType))
|
|
||||||
{
|
|
||||||
return resultPointerName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var outputName = GenVarName();
|
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(fixedArrayType.ElementType)} {QBELoad(fixedArrayType.ElementType)} {resultPointerName}");
|
|
||||||
return outputName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -716,6 +644,22 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateArrayAccessIndex(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
|
{
|
||||||
|
var pointerName = GenerateArrayIndexPointer(arrayIndexAccess);
|
||||||
|
|
||||||
|
if (IsLargeType(arrayIndexAccess.Type))
|
||||||
|
{
|
||||||
|
return pointerName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var outputName = GenVarName();
|
||||||
|
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointerName}");
|
||||||
|
return outputName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateArrayBoundsCheck(string array, string index)
|
private void GenerateArrayBoundsCheck(string array, string index)
|
||||||
{
|
{
|
||||||
var countName = GenVarName();
|
var countName = GenVarName();
|
||||||
@@ -768,30 +712,18 @@ public class Generator
|
|||||||
|
|
||||||
private string GenerateAddressOf(AddressOfNode addressOf)
|
private string GenerateAddressOf(AddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(addressOf.Expression);
|
switch (addressOf.Expression)
|
||||||
var outputName = GenVarName();
|
|
||||||
switch (addressOf.Expression.Type)
|
|
||||||
{
|
{
|
||||||
case NubPointerType:
|
case ArrayIndexAccessNode arrayIndexAccess:
|
||||||
case NubStructType:
|
return GenerateArrayIndexPointer(arrayIndexAccess);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
case DereferenceNode dereference:
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
return GenerateExpression(dereference.Expression);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
|
case IdentifierNode identifier:
|
||||||
_builder.AppendLine($" {outputName} =l alloc8 8");
|
return _variables[identifier.Identifier];
|
||||||
_builder.AppendLine($" storel {result}, {outputName}");
|
case MemberAccessNode memberAccess:
|
||||||
return outputName;
|
return GenerateMemberAccessPointer(memberAccess);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
|
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
|
||||||
_builder.AppendLine($" {outputName} =l alloc8 4");
|
|
||||||
_builder.AppendLine($" storew {result}, {outputName}");
|
|
||||||
return outputName;
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new UnreachableException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,462 +953,9 @@ public class Generator
|
|||||||
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// private string GenerateCast(CastNode cast)
|
|
||||||
// {
|
|
||||||
// var input = GenerateExpression(cast.Expression);
|
|
||||||
// var outputType = cast.TargetType;
|
|
||||||
// var inputType = cast.Expression.Type;
|
|
||||||
//
|
|
||||||
// if (inputType.Equals(outputType))
|
|
||||||
// {
|
|
||||||
// return input;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (outputType is not NubPrimitiveType primitiveOutputType || inputType is not NubPrimitiveType primitiveInputType)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException("Casting is only supported for primitive types");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var outputName = GenVarName();
|
|
||||||
//
|
|
||||||
// switch (primitiveInputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// _builder.AppendLine($" {outputName} =d sltof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// _builder.AppendLine($" {outputName} =s sltof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_i64_to_string(l {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extsw {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extsw {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d sltof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// _builder.AppendLine($" {outputName} =s swtof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// var extAnyName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extAnyName} =l extsw {input}");
|
|
||||||
// return extAnyName;
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extsh {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// _builder.AppendLine($" {outputName} =w extsh {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extsh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d sltof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extsh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =s swtof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extsh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {extName})");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extsh {input}");
|
|
||||||
// return extName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extsb {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// _builder.AppendLine($" {outputName} =w extsb {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extsb {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d sltof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extsb {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =s swtof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extsb {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {extName})");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extsb {input}");
|
|
||||||
// return extName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// _builder.AppendLine($" {outputName} =d ultof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// _builder.AppendLine($" {outputName} =s ultof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_u64_to_string(l {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extuw {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extuw {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d ultof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// _builder.AppendLine($" {outputName} =s uwtof {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// var extAnyName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extAnyName} =l extuw {input}");
|
|
||||||
// return extAnyName;
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extuh {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// _builder.AppendLine($" {outputName} =w extuh {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extuh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d ultof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extuh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =s uwtof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extuh {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {extName})");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extuh {input}");
|
|
||||||
// return extName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extub {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// _builder.AppendLine($" {outputName} =w extub {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extub {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =d ultof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extub {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =s uwtof {extName}");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =w extub {input}");
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {extName})");
|
|
||||||
// return outputName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// {
|
|
||||||
// var extName = GenVarName();
|
|
||||||
// _builder.AppendLine($" {extName} =l extub {input}");
|
|
||||||
// return extName;
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// _builder.AppendLine($" {outputName} =s dtos {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l dtosi {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// _builder.AppendLine($" {outputName} =w dtosi {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l dtoui {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// _builder.AppendLine($" {outputName} =w dtoui {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_f64_to_string(d {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// _builder.AppendLine($" {outputName} =d stod {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l stosi {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// _builder.AppendLine($" {outputName} =w stosi {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// _builder.AppendLine($" {outputName} =l stoui {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// _builder.AppendLine($" {outputName} =w stoui {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_f32_to_string(s {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// _builder.AppendLine($" {outputName} =l extsw {input}");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// _builder.AppendLine($" {outputName} =l call $nub_bool_to_string(s {input})");
|
|
||||||
// return outputName;
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// switch (primitiveOutputType.Kind)
|
|
||||||
// {
|
|
||||||
// case PrimitiveTypeKind.String:
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// return input;
|
|
||||||
// case PrimitiveTypeKind.I64:
|
|
||||||
// case PrimitiveTypeKind.I32:
|
|
||||||
// case PrimitiveTypeKind.I16:
|
|
||||||
// case PrimitiveTypeKind.I8:
|
|
||||||
// case PrimitiveTypeKind.U64:
|
|
||||||
// case PrimitiveTypeKind.U32:
|
|
||||||
// case PrimitiveTypeKind.U16:
|
|
||||||
// case PrimitiveTypeKind.U8:
|
|
||||||
// case PrimitiveTypeKind.F64:
|
|
||||||
// case PrimitiveTypeKind.F32:
|
|
||||||
// case PrimitiveTypeKind.Bool:
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// case PrimitiveTypeKind.Any:
|
|
||||||
// return input;
|
|
||||||
// default:
|
|
||||||
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private string GenerateIdentifier(IdentifierNode identifier)
|
private string GenerateIdentifier(IdentifierNode identifier)
|
||||||
{
|
{
|
||||||
var variable = _variables[identifier.Identifier];
|
return _variables[identifier.Identifier];
|
||||||
if (IsLargeType(identifier.Type))
|
|
||||||
{
|
|
||||||
return variable;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var outputName = GenVarName();
|
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(identifier.Type)} {QBELoad(identifier.Type)} {variable}");
|
|
||||||
return outputName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateLiteral(LiteralNode literal)
|
private string GenerateLiteral(LiteralNode literal)
|
||||||
@@ -1534,33 +1013,17 @@ public class Generator
|
|||||||
|
|
||||||
if (structInitializer.Initializers.TryGetValue(field.Name, out var fieldValue))
|
if (structInitializer.Initializers.TryGetValue(field.Name, out var fieldValue))
|
||||||
{
|
{
|
||||||
var var = GenerateExpression(fieldValue);
|
var value = GenerateExpression(fieldValue);
|
||||||
var offsetName = GenVarName();
|
var pointer = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {structVar}, {offset}");
|
_builder.AppendLine($" {pointer} =l add {structVar}, {offset}");
|
||||||
|
GenerateCopy(field.Type, value, pointer);
|
||||||
if (IsLargeType(field.Type))
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(field.Type)} {var}, {offsetName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (field.Value.HasValue)
|
else if (field.Value.HasValue)
|
||||||
{
|
{
|
||||||
var var = GenerateExpression(field.Value.Value);
|
var value = GenerateExpression(field.Value.Value);
|
||||||
var offsetName = GenVarName();
|
var pointer = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {structVar}, {offset}");
|
_builder.AppendLine($" {pointer} =l add {structVar}, {offset}");
|
||||||
|
GenerateCopy(field.Type, value, pointer);
|
||||||
if (IsLargeType(field.Type))
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_builder.AppendLine($" {QBEStore(field.Type)} {var}, {offsetName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1618,22 +1081,19 @@ public class Generator
|
|||||||
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateMemberAccess(MemberAccessNode memberAccess)
|
private string GenerateMemberAccessPointer(MemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var item = GenerateExpression(memberAccess.Expression);
|
var item = GenerateExpression(memberAccess.Expression);
|
||||||
|
|
||||||
switch (memberAccess.Expression.Type)
|
switch (memberAccess.Expression.Type)
|
||||||
{
|
{
|
||||||
case NubArrayType:
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
if (memberAccess.Member == "count")
|
if (memberAccess.Member == "count")
|
||||||
{
|
{
|
||||||
var outputName = GenVarName();
|
return item;
|
||||||
_builder.AppendLine($" {outputName} =l loadl {item}");
|
|
||||||
return outputName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(memberAccess.Member));
|
throw new UnreachableException(nameof(memberAccess.Member));
|
||||||
}
|
}
|
||||||
case NubStructType structType:
|
case NubStructType structType:
|
||||||
{
|
{
|
||||||
@@ -1642,26 +1102,31 @@ public class Generator
|
|||||||
|
|
||||||
var offsetName = GenVarName();
|
var offsetName = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
|
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
|
||||||
|
return offsetName;
|
||||||
if (IsLargeType(memberAccess.Type))
|
|
||||||
{
|
|
||||||
return offsetName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var outputName = GenVarName();
|
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {offsetName}");
|
|
||||||
|
|
||||||
return outputName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(memberAccess.Expression.Type));
|
throw new UnreachableException(nameof(memberAccess.Expression.Type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateMemberAccess(MemberAccessNode memberAccess)
|
||||||
|
{
|
||||||
|
var pointer = GenerateMemberAccessPointer(memberAccess);
|
||||||
|
|
||||||
|
if (IsLargeType(memberAccess.Type))
|
||||||
|
{
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var outputName = GenVarName();
|
||||||
|
_builder.AppendLine($" {outputName} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {pointer}");
|
||||||
|
return outputName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GenerateFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
private string GenerateFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
||||||
{
|
{
|
||||||
var capacityInBytes = SizeOf(fixedArrayInitializer.Type);
|
var capacityInBytes = SizeOf(fixedArrayInitializer.Type);
|
||||||
@@ -1737,6 +1202,18 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenerateCopy(NubType type, string value, string destinationPointer)
|
||||||
|
{
|
||||||
|
if (IsLargeType(type))
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" blit {value}, {destinationPointer}, {SizeOf(type)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" {QBEStore(type)} {value}, {destinationPointer}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GenVarName()
|
private string GenVarName()
|
||||||
{
|
{
|
||||||
return $"%v{++_variableIndex}";
|
return $"%v{++_variableIndex}";
|
||||||
@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||||
|
|
||||||
public class AddressOfNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : ExpressionNode(tokens)
|
public class AddressOfNode(IReadOnlyList<Token> tokens, LValueNode expression) : ExpressionNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public LValueNode Expression { get; } = expression;
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||||
|
|
||||||
public class ArrayIndexAccessNode(IReadOnlyList<Token> tokens, ExpressionNode array, ExpressionNode index) : ExpressionNode(tokens)
|
public class ArrayIndexAccessNode(IReadOnlyList<Token> tokens, ExpressionNode array, ExpressionNode index) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Array { get; } = array;
|
public ExpressionNode Array { get; } = array;
|
||||||
public ExpressionNode Index { get; } = index;
|
public ExpressionNode Index { get; } = index;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// using Nub.Lang.Frontend.Lexing;
|
|
||||||
// using Nub.Lang.Frontend.Typing;
|
|
||||||
//
|
|
||||||
// namespace Nub.Lang.Frontend.Parsing.Expressions;
|
|
||||||
//
|
|
||||||
// public class CastNode(IReadOnlyList<Token> tokens, NubType targetType, ExpressionNode expression) : ExpressionNode(tokens)
|
|
||||||
// {
|
|
||||||
// public NubType TargetType { get; } = targetType;
|
|
||||||
// public ExpressionNode Expression { get; } = expression;
|
|
||||||
// }
|
|
||||||
@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||||
|
|
||||||
public class DereferenceNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : ExpressionNode(tokens)
|
public class DereferenceNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public ExpressionNode Expression { get; } = expression;
|
||||||
}
|
}
|
||||||
@@ -12,3 +12,5 @@ public abstract class ExpressionNode(IReadOnlyList<Token> tokens) : Node(tokens)
|
|||||||
set => _type = value;
|
set => _type = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class LValueNode(IReadOnlyList<Token> tokens) : ExpressionNode(tokens);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||||
|
|
||||||
public class IdentifierNode(IReadOnlyList<Token> tokens, string identifier) : ExpressionNode(tokens)
|
public class IdentifierNode(IReadOnlyList<Token> tokens, string identifier) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public string Identifier { get; } = identifier;
|
public string Identifier { get; } = identifier;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
namespace Nub.Lang.Frontend.Parsing.Expressions;
|
||||||
|
|
||||||
public class MemberAccessNode(IReadOnlyList<Token> tokens, ExpressionNode expression, string member) : ExpressionNode(tokens)
|
public class MemberAccessNode(IReadOnlyList<Token> tokens, ExpressionNode expression, string member) : LValueNode(tokens)
|
||||||
{
|
{
|
||||||
public ExpressionNode Expression { get; } = expression;
|
public ExpressionNode Expression { get; } = expression;
|
||||||
public string Member { get; } = member;
|
public string Member { get; } = member;
|
||||||
|
|||||||
@@ -495,20 +495,18 @@ public class Parser
|
|||||||
expr = expression;
|
expr = expression;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// case Symbol.LessThan:
|
|
||||||
// {
|
|
||||||
// var type = ParseType();
|
|
||||||
// ExpectSymbol(Symbol.GreaterThan);
|
|
||||||
// ExpectSymbol(Symbol.OpenParen);
|
|
||||||
// var expressionToCast = ParseExpression();
|
|
||||||
// ExpectSymbol(Symbol.CloseParen);
|
|
||||||
// expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
case Symbol.Ampersand:
|
case Symbol.Ampersand:
|
||||||
{
|
{
|
||||||
var expression = ParsePrimaryExpression();
|
var expression = ParsePrimaryExpression();
|
||||||
expr = new AddressOfNode(GetTokensForNode(startIndex), expression);
|
if (expression is not LValueNode lValue)
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("& symbol can only be used on lvalues")
|
||||||
|
.At(expression)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
expr = new AddressOfNode(GetTokensForNode(startIndex), lValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.Minus:
|
case Symbol.Minus:
|
||||||
|
|||||||
@@ -362,7 +362,6 @@ public class TypeChecker
|
|||||||
LiteralNode literal => TypeCheckLiteral(literal, expectedType),
|
LiteralNode literal => TypeCheckLiteral(literal, expectedType),
|
||||||
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||||
// CastNode cast => TypeCheckCast(cast),
|
|
||||||
DereferenceNode dereference => TypeCheckDereference(dereference),
|
DereferenceNode dereference => TypeCheckDereference(dereference),
|
||||||
FixedArrayInitializerNode fixedArray => TypeCheckFixedInitializerArray(fixedArray),
|
FixedArrayInitializerNode fixedArray => TypeCheckFixedInitializerArray(fixedArray),
|
||||||
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
|
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
|
||||||
@@ -394,7 +393,7 @@ public class TypeChecker
|
|||||||
{
|
{
|
||||||
if (literal.Kind == LiteralKind.Float)
|
if (literal.Kind == LiteralKind.Float)
|
||||||
{
|
{
|
||||||
ReportWarning("Possible loss of precision when using float in integer context", literal);
|
ReportWarning("Float used in integer context. Everything after the '.' will be ignored", literal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,13 +516,6 @@ public class TypeChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private NubType? TypeCheckCast(CastNode cast)
|
|
||||||
// {
|
|
||||||
// TypeCheckExpression(cast.Expression, cast.TargetType);
|
|
||||||
// // TODO: Check if castable
|
|
||||||
// return cast.TargetType;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private NubType? TypeCheckStructInitializer(StructInitializerNode structInit)
|
private NubType? TypeCheckStructInitializer(StructInitializerNode structInit)
|
||||||
{
|
{
|
||||||
var initialized = new HashSet<string>();
|
var initialized = new HashSet<string>();
|
||||||
|
|||||||
Reference in New Issue
Block a user