From d246b1f4c205c4726020b8f028dba9c979f05b99 Mon Sep 17 00:00:00 2001 From: Lehonti Ramos Date: Tue, 31 Oct 2023 13:03:52 +0100 Subject: [PATCH] Used null-coalescing operator for nullable assignments --- .../Extensions/TranslationUnitEx.cs | 7 +- Cesium.CodeGen/Extensions/TypeSystemEx.cs | 17 +- .../CompoundInitializationExpression.cs | 8 +- .../Ir/Expressions/FunctionCallExpression.cs | 7 +- .../Expressions/Values/LValueArrayElement.cs | 7 +- .../Ir/Lowering/BlockItemLowering.cs | 618 +++++++++--------- Cesium.CodeGen/Ir/Types/IType.cs | 7 +- Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs | 24 +- 8 files changed, 325 insertions(+), 370 deletions(-) diff --git a/Cesium.CodeGen/Extensions/TranslationUnitEx.cs b/Cesium.CodeGen/Extensions/TranslationUnitEx.cs index ee90590e..862d84b7 100644 --- a/Cesium.CodeGen/Extensions/TranslationUnitEx.cs +++ b/Cesium.CodeGen/Extensions/TranslationUnitEx.cs @@ -59,13 +59,8 @@ private static IEnumerable GetTopLevelDeclarations(Ast.SymbolDeclara int currentValue = -1; foreach (var enumeratorDeclaration in enumType.Members) { - var enumeratorName = enumeratorDeclaration.Declaration.Identifier; - if (enumeratorName is null) - { - throw new CompilationException( + var enumeratorName = enumeratorDeclaration.Declaration.Identifier ?? throw new CompilationException( $"Enum type {enumType.Identifier} has enumerator without name"); - } - if (enumeratorDeclaration.Initializer is null) { currentValue++; diff --git a/Cesium.CodeGen/Extensions/TypeSystemEx.cs b/Cesium.CodeGen/Extensions/TypeSystemEx.cs index 07a805d8..5b118507 100644 --- a/Cesium.CodeGen/Extensions/TypeSystemEx.cs +++ b/Cesium.CodeGen/Extensions/TypeSystemEx.cs @@ -73,8 +73,8 @@ private static bool Match( { var declParamCount = parameters switch { - {IsVoid: true} => 0, - {IsVarArg: true} => parameters.Parameters.Count + 1, + { IsVoid: true } => 0, + { IsVarArg: true } => parameters.Parameters.Count + 1, _ => parameters.Parameters.Count }; @@ -188,8 +188,8 @@ public static IType GetCommonNumericType(this CTypeSystem ts, IType a, IType b) // Otherwise, if both operands have signed integer types or both have unsigned integer types, // the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank. - var signedTypes = new[] {ts.SignedChar, ts.Short, ts.Int, ts.Long, ts.NativeInt}; - var unsignedTypes = new[] { ts.Char, ts.UnsignedChar, ts.UnsignedShort, ts.UnsignedInt, ts.UnsignedLong, ts.NativeUInt}; + var signedTypes = new[] { ts.SignedChar, ts.Short, ts.Int, ts.Long, ts.NativeInt }; + var unsignedTypes = new[] { ts.Char, ts.UnsignedChar, ts.UnsignedShort, ts.UnsignedInt, ts.UnsignedLong, ts.NativeUInt }; // TODO[#381]: Move NativeInt and NativeUInt accordingly or consider them properly based on the current architecture. var aSignedRank = RankOf(a, signedTypes); @@ -227,7 +227,7 @@ public static IType GetCommonNumericType(this CTypeSystem ts, IType a, IType b) int? RankOf(IType t, IType[] family) { - for(var i = 0; i < family.Length; i++) + for (var i = 0; i < family.Length; i++) if (t.IsEqualTo(family[i])) return i; return null; @@ -243,12 +243,7 @@ public static TypeDefinition GetRuntimeHelperType(this TranslationUnitContext co public static MethodReference GetRuntimeHelperMethod(this TranslationUnitContext context, string helperMethod) { var runtimeHelpersType = context.GetRuntimeHelperType(); - var method = runtimeHelpersType.FindMethod(helperMethod); - if (method == null) - { - throw new AssertException($"RuntimeHelper {helperMethod} cannot be found."); - } - + var method = runtimeHelpersType.FindMethod(helperMethod) ?? throw new AssertException($"RuntimeHelper {helperMethod} cannot be found."); return context.Module.ImportReference(method); } diff --git a/Cesium.CodeGen/Ir/Expressions/CompoundInitializationExpression.cs b/Cesium.CodeGen/Ir/Expressions/CompoundInitializationExpression.cs index cad89c75..bc0fbf2a 100644 --- a/Cesium.CodeGen/Ir/Expressions/CompoundInitializationExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/CompoundInitializationExpression.cs @@ -27,14 +27,10 @@ public void EmitTo(IEmitScope scope) WriteInitializer(stream, i); } - var targetSize = ((InPlaceArrayType)_type).GetSizeInBytes(scope.AssemblyContext.ArchitectureSet); - - if (targetSize is null) - throw new NotImplementedException("Cannot calculate size of target array"); - + int targetSize = ((InPlaceArrayType)_type).GetSizeInBytes(scope.AssemblyContext.ArchitectureSet) ?? throw new NotImplementedException("Cannot calculate size of target array"); if (stream.Position < targetSize) { - stream.Write(new byte[targetSize.Value - (int)stream.Position]); + stream.Write(new byte[targetSize - (int)stream.Position]); } var constantData = stream.ToArray(); diff --git a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs index 0e6f43fb..196966ba 100644 --- a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs @@ -97,12 +97,7 @@ public override IExpression Lower(IDeclarationScope scope) }).ToList()); } - var callee = scope.GetFunctionInfo(functionName); - if (callee is null) - { - throw new CompilationException($"Function \"{functionName}\" was not found."); - } - + var callee = scope.GetFunctionInfo(functionName) ?? throw new CompilationException($"Function \"{functionName}\" was not found."); int firstVarArgArgument = 0; if (callee.Parameters?.IsVarArg == true) { diff --git a/Cesium.CodeGen/Ir/Expressions/Values/LValueArrayElement.cs b/Cesium.CodeGen/Ir/Expressions/Values/LValueArrayElement.cs index b6b0f241..37565ba5 100644 --- a/Cesium.CodeGen/Ir/Expressions/Values/LValueArrayElement.cs +++ b/Cesium.CodeGen/Ir/Expressions/Values/LValueArrayElement.cs @@ -42,12 +42,7 @@ public IType GetValueType() private PrimitiveType GetElementType() { - InPlaceArrayType? type = GetValueType() as InPlaceArrayType; - if (type == null) - { - throw new AssertException("Array type expected."); - } - + InPlaceArrayType? type = GetValueType() as InPlaceArrayType ?? throw new AssertException("Array type expected."); var primitiveType = (PrimitiveType)GetBaseType(type); return primitiveType; } diff --git a/Cesium.CodeGen/Ir/Lowering/BlockItemLowering.cs b/Cesium.CodeGen/Ir/Lowering/BlockItemLowering.cs index 8dbc0599..866be165 100644 --- a/Cesium.CodeGen/Ir/Lowering/BlockItemLowering.cs +++ b/Cesium.CodeGen/Ir/Lowering/BlockItemLowering.cs @@ -32,7 +32,7 @@ private static IBlockItem MakeLoop( testConditionLabel ??= Guid.NewGuid().ToString(); - stmts.Add(new LabelStatement(testConditionLabel, new ExpressionStatement((IExpression?) null))); + stmts.Add(new LabelStatement(testConditionLabel, new ExpressionStatement((IExpression?)null))); if (testExpression != null) { @@ -52,7 +52,7 @@ private static IBlockItem MakeLoop( stmts.Add(updateStmt); stmts.Add(new GoToStatement(testConditionLabel)); - stmts.Add(new LabelStatement(breakLabel, new ExpressionStatement((IExpression?) null))); + stmts.Add(new LabelStatement(breakLabel, new ExpressionStatement((IExpression?)null))); return Lower(scope, new CompoundStatement(stmts, scope)); } @@ -62,396 +62,390 @@ public static IBlockItem Lower(IDeclarationScope scope, IBlockItem blockItem) switch (blockItem) { case AmbiguousBlockItem a: - { - // Check if this can be a valid variable declaration: - var isValidVariableDeclaration = scope.GetVariable(a.Item1) != null; - - // Check if this can be a function call: - var function = scope.GetFunctionInfo(a.Item1); - var isValidFunctionCall = function != null; - - if (!isValidVariableDeclaration && !isValidFunctionCall) - throw new CompilationException( - $"{a.Item1}({a.Item2}) is supposed to be either a variable declaration or a function call," + - " but wasn't resolved to be either."); - - if (isValidVariableDeclaration && isValidFunctionCall) - throw new CompilationException( - $"{a.Item1}({a.Item2}) is supposed to be either a variable declaration or a function call," + - $" but it's ambiguous which it is, since both a function and a type of name {a.Item1} exist."); - - if (!isValidFunctionCall) return a; - - var functionCallExpression = new FunctionCallExpression( - new IdentifierExpression(a.Item1), - null, - ImmutableArray.Create(new IdentifierExpression(a.Item2)) - ); - - return Lower(scope, new ExpressionStatement(functionCallExpression)); - } - case BreakStatement: - { - var breakLabel = scope.GetBreakLabel(); - if (breakLabel is null) - throw new CompilationException("Can't break not from for statement"); + { + // Check if this can be a valid variable declaration: + var isValidVariableDeclaration = scope.GetVariable(a.Item1) != null; - return new GoToStatement(breakLabel); - } - case CaseStatement c: - { - // TODO[#408]: optimize multiple cases at once + // Check if this can be a function call: + var function = scope.GetFunctionInfo(a.Item1); + var isValidFunctionCall = function != null; - if (scope is not BlockScope sws || sws.SwitchCases == null) - throw new AssertException("Cannot use case statement outside of switch"); + if (!isValidVariableDeclaration && !isValidFunctionCall) + throw new CompilationException( + $"{a.Item1}({a.Item2}) is supposed to be either a variable declaration or a function call," + + " but wasn't resolved to be either."); - if (c.Expression != null) - { - var constValue = ConstantEvaluator.GetConstantValue(c.Expression); + if (isValidVariableDeclaration && isValidFunctionCall) + throw new CompilationException( + $"{a.Item1}({a.Item2}) is supposed to be either a variable declaration or a function call," + + $" but it's ambiguous which it is, since both a function and a type of name {a.Item1} exist."); + + if (!isValidFunctionCall) return a; - sws.SwitchCases.Add(new SwitchCase(new ConstantLiteralExpression(constValue), c.Label)); + var functionCallExpression = new FunctionCallExpression( + new IdentifierExpression(a.Item1), + null, + ImmutableArray.Create(new IdentifierExpression(a.Item2)) + ); + + return Lower(scope, new ExpressionStatement(functionCallExpression)); } - else + case BreakStatement: { - sws.SwitchCases.Add(new SwitchCase(null, c.Label)); + var breakLabel = scope.GetBreakLabel() ?? throw new CompilationException("Can't break not from for statement"); + return new GoToStatement(breakLabel); } + case CaseStatement c: + { + // TODO[#408]: optimize multiple cases at once - return Lower(scope, new LabelStatement(c.Label, c.Statement)); - } - case CompoundStatement c: - { - var blockScope = new BlockScope((IEmitScope)scope, null, null); + if (scope is not BlockScope sws || sws.SwitchCases == null) + throw new AssertException("Cannot use case statement outside of switch"); - var newNestedStatements = new List(); - foreach (var stmt in c.Statements) - { - newNestedStatements.Add(Lower(blockScope, stmt)); + if (c.Expression != null) + { + var constValue = ConstantEvaluator.GetConstantValue(c.Expression); + + sws.SwitchCases.Add(new SwitchCase(new ConstantLiteralExpression(constValue), c.Label)); + } + else + { + sws.SwitchCases.Add(new SwitchCase(null, c.Label)); + } + + return Lower(scope, new LabelStatement(c.Label, c.Statement)); } + case CompoundStatement c: + { + var blockScope = new BlockScope((IEmitScope)scope, null, null); - return new CompoundStatement(newNestedStatements, blockScope); - } - case ContinueStatement: - { - var continueLabel = scope.GetContinueLabel(); - if (continueLabel is null) - throw new CompilationException("Can't use continue outside of a loop construct."); + var newNestedStatements = new List(); + foreach (var stmt in c.Statements) + { + newNestedStatements.Add(Lower(blockScope, stmt)); + } - return new GoToStatement(continueLabel); - } + return new CompoundStatement(newNestedStatements, blockScope); + } + case ContinueStatement: + { + var continueLabel = scope.GetContinueLabel() ?? throw new CompilationException("Can't use continue outside of a loop construct."); + return new GoToStatement(continueLabel); + } case DeclarationBlockItem d: - { - var (storageClass, items) = d.Declaration; - var newItems = new List(); - - foreach (var (declaration, initializer) in items) { - var (type, identifier, cliImportMemberName) = declaration; + var (storageClass, items) = d.Declaration; + var newItems = new List(); - // TODO[#91]: A place to register whether {type} is const or not. + foreach (var (declaration, initializer) in items) + { + var (type, identifier, cliImportMemberName) = declaration; - if (identifier == null) - throw new CompilationException("An anonymous local declaration isn't supported."); + // TODO[#91]: A place to register whether {type} is const or not. - if (cliImportMemberName != null) - throw new CompilationException( - $"Local declaration with a CLI import member name {cliImportMemberName} isn't supported."); + if (identifier == null) + throw new CompilationException("An anonymous local declaration isn't supported."); - type = scope.ResolveType(type); - scope.AddVariable(storageClass, identifier, type, null); + if (cliImportMemberName != null) + throw new CompilationException( + $"Local declaration with a CLI import member name {cliImportMemberName} isn't supported."); - var initializerExpression = initializer; - if (initializerExpression != null) - { - var initializerType = initializerExpression.Lower(scope).GetExpressionType(scope); - if (scope.CTypeSystem.IsConversionAvailable(initializerType, type) - && !initializerType.Equals(type)) + type = scope.ResolveType(type); + scope.AddVariable(storageClass, identifier, type, null); + + var initializerExpression = initializer; + if (initializerExpression != null) { - initializerExpression = new TypeCastExpression(type, initializerExpression); + var initializerType = initializerExpression.Lower(scope).GetExpressionType(scope); + if (scope.CTypeSystem.IsConversionAvailable(initializerType, type) + && !initializerType.Equals(type)) + { + initializerExpression = new TypeCastExpression(type, initializerExpression); + } } - } - if (initializerExpression != null) - { - initializerExpression = new AssignmentExpression(new IdentifierExpression(identifier), - AssignmentOperator.Assign, initializerExpression); + if (initializerExpression != null) + { + initializerExpression = new AssignmentExpression(new IdentifierExpression(identifier), + AssignmentOperator.Assign, initializerExpression); + + if (initializerExpression.GetExpressionType(scope) is not PrimitiveType + { + Kind: PrimitiveTypeKind.Void + }) + initializerExpression = new ConsumeExpression(initializerExpression); + } - if (initializerExpression.GetExpressionType(scope) is not PrimitiveType - { - Kind: PrimitiveTypeKind.Void - }) - initializerExpression = new ConsumeExpression(initializerExpression); - } + IExpression? primaryInitializerExpression = null; + if (type is InPlaceArrayType i) + { + primaryInitializerExpression = new ConsumeExpression( + new AssignmentExpression(new IdentifierExpression(identifier), AssignmentOperator.Assign, + new LocalAllocationExpression(i)) + ); + } - IExpression? primaryInitializerExpression = null; - if (type is InPlaceArrayType i) - { - primaryInitializerExpression = new ConsumeExpression( - new AssignmentExpression(new IdentifierExpression(identifier), AssignmentOperator.Assign, - new LocalAllocationExpression(i)) - ); + var initializableDeclaration = new InitializerPart(primaryInitializerExpression?.Lower(scope), + initializerExpression?.Lower(scope)); + newItems.Add(initializableDeclaration); } - var initializableDeclaration = new InitializerPart(primaryInitializerExpression?.Lower(scope), - initializerExpression?.Lower(scope)); - newItems.Add(initializableDeclaration); + return new InitializationBlockItem(newItems); } - - return new InitializationBlockItem(newItems); - } case DoWhileStatement s: - { - var breakLabel = Guid.NewGuid().ToString(); - var continueLabel = Guid.NewGuid().ToString(); - - var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); - - return MakeLoop( - loopScope, - new GoToStatement(continueLabel), - s.TestExpression, - null, - s.Body, - breakLabel, - null, - continueLabel, - null - ); - } + { + var breakLabel = Guid.NewGuid().ToString(); + var continueLabel = Guid.NewGuid().ToString(); + + var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); + + return MakeLoop( + loopScope, + new GoToStatement(continueLabel), + s.TestExpression, + null, + s.Body, + breakLabel, + null, + continueLabel, + null + ); + } case ExpressionStatement s: - { - var loweredExpression = s.Expression?.Lower(scope); + { + var loweredExpression = s.Expression?.Lower(scope); - if (loweredExpression is SetValueExpression setValue) - return new ExpressionStatement(setValue.NoReturn()); + if (loweredExpression is SetValueExpression setValue) + return new ExpressionStatement(setValue.NoReturn()); - if (loweredExpression is not null - && !loweredExpression.GetExpressionType(scope).IsEqualTo(scope.CTypeSystem.Void)) - { - loweredExpression = new ConsumeExpression(loweredExpression); - } + if (loweredExpression is not null + && !loweredExpression.GetExpressionType(scope).IsEqualTo(scope.CTypeSystem.Void)) + { + loweredExpression = new ConsumeExpression(loweredExpression); + } - return new ExpressionStatement(loweredExpression); - } + return new ExpressionStatement(loweredExpression); + } case ForStatement s: - { - var breakLabel = Guid.NewGuid().ToString(); - var continueLabel = Guid.NewGuid().ToString(); - - var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); - - return MakeLoop( - loopScope, - s.InitDeclaration ?? new ExpressionStatement(s.InitExpression), - s.TestExpression, - s.UpdateExpression, - s.Body, - breakLabel, - null, - null, - continueLabel - ); - } + { + var breakLabel = Guid.NewGuid().ToString(); + var continueLabel = Guid.NewGuid().ToString(); + + var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); + + return MakeLoop( + loopScope, + s.InitDeclaration ?? new ExpressionStatement(s.InitExpression), + s.TestExpression, + s.UpdateExpression, + s.Body, + breakLabel, + null, + null, + continueLabel + ); + } case FunctionDeclaration d: - { - var resolvedFunctionType = (FunctionType)scope.ResolveType(d.FunctionType); - var (parametersInfo, returnType) = resolvedFunctionType; - if (d.CliImportMemberName != null) { - if (parametersInfo is null or { Parameters.Count: 0, IsVoid: false }) - throw new CompilationException($"Empty parameter list is not allowed for CLI-imported function {d.Identifier}."); + var resolvedFunctionType = (FunctionType)scope.ResolveType(d.FunctionType); + var (parametersInfo, returnType) = resolvedFunctionType; + if (d.CliImportMemberName != null) + { + if (parametersInfo is null or { Parameters.Count: 0, IsVoid: false }) + throw new CompilationException($"Empty parameter list is not allowed for CLI-imported function {d.Identifier}."); + } + + var cliImportFunctionInfo = new FunctionInfo(parametersInfo, returnType, d.StorageClass, IsDefined: d.CliImportMemberName is not null) + { + CliImportMember = d.CliImportMemberName + }; + scope.DeclareFunction(d.Identifier, cliImportFunctionInfo); + return new FunctionDeclaration(d.Identifier, d.StorageClass, resolvedFunctionType, d.CliImportMemberName); } - var cliImportFunctionInfo = new FunctionInfo(parametersInfo, returnType, d.StorageClass, IsDefined: d.CliImportMemberName is not null) + case FunctionDefinition d: { - CliImportMember = d.CliImportMemberName - }; - scope.DeclareFunction(d.Identifier, cliImportFunctionInfo); - return new FunctionDeclaration(d.Identifier, d.StorageClass, resolvedFunctionType, d.CliImportMemberName); - } + var resolvedFunctionType = (FunctionType)scope.ResolveType(d.FunctionType); + var (parameters, returnType) = resolvedFunctionType; + if (d.IsMain && !returnType.Equals(scope.CTypeSystem.Int)) + throw new CompilationException( + $"Invalid return type for the {d.Name} function: " + + $"int expected, got {returnType}."); - case FunctionDefinition d: - { - var resolvedFunctionType = (FunctionType)scope.ResolveType(d.FunctionType); - var (parameters, returnType) = resolvedFunctionType; - if (d.IsMain && !returnType.Equals(scope.CTypeSystem.Int)) - throw new CompilationException( - $"Invalid return type for the {d.Name} function: " + - $"int expected, got {returnType}."); - - if (d.IsMain && parameters?.IsVarArg == true) - throw new WipException(196, $"Variable arguments for the {d.Name} function aren't supported."); - - var declaration = scope.GetFunctionInfo(d.Name); - if (declaration?.IsDefined == true) - if (declaration.CliImportMember is null) - throw new CompilationException($"Double definition of function {d.Name}."); - else - throw new CompilationException($"Function {d.Name} already defined as immutable."); + if (d.IsMain && parameters?.IsVarArg == true) + throw new WipException(196, $"Variable arguments for the {d.Name} function aren't supported."); - var newDeclaration = new FunctionInfo(parameters, returnType, d.StorageClass, IsDefined: true); - scope.DeclareFunction(d.Name, newDeclaration); + var declaration = scope.GetFunctionInfo(d.Name); + if (declaration?.IsDefined == true) + if (declaration.CliImportMember is null) + throw new CompilationException($"Double definition of function {d.Name}."); + else + throw new CompilationException($"Function {d.Name} already defined as immutable."); - return new FunctionDefinition(d.Name, d.StorageClass, resolvedFunctionType, d.Statement); - } + var newDeclaration = new FunctionInfo(parameters, returnType, d.StorageClass, IsDefined: true); + scope.DeclareFunction(d.Name, newDeclaration); + + return new FunctionDefinition(d.Name, d.StorageClass, resolvedFunctionType, d.Statement); + } case GlobalVariableDefinition d: - { - scope.AddVariable(d.StorageClass, d.Identifier, d.Type, null); + { + scope.AddVariable(d.StorageClass, d.Identifier, d.Type, null); - return d with { Initializer = d.Initializer?.Lower(scope) }; - } + return d with { Initializer = d.Initializer?.Lower(scope) }; + } case EnumConstantDefinition d: - { - scope.AddVariable(StorageClass.Static, d.Identifier, d.Type, d.Value); + { + scope.AddVariable(StorageClass.Static, d.Identifier, d.Type, d.Value); - return d; - } + return d; + } case GoToStatement: - { - // already lowered - return blockItem; - } + { + // already lowered + return blockItem; + } case IfElseStatement s: - { - var falseBranch = s.FalseBranch != null ? Lower(scope, s.FalseBranch) : null; + { + var falseBranch = s.FalseBranch != null ? Lower(scope, s.FalseBranch) : null; - return new IfElseStatement(s.Expression.Lower(scope), Lower(scope, s.TrueBranch), falseBranch); - } + return new IfElseStatement(s.Expression.Lower(scope), Lower(scope, s.TrueBranch), falseBranch); + } case InitializationBlockItem: - { - // already lowered - return blockItem; - } + { + // already lowered + return blockItem; + } case LabelStatement s: - { - // TODO[#201]: Remove side effects from Lower, migrate labels to a separate compilation stage. - if (!s.DidLowered) - scope.AddLabel(s.Identifier); - return new LabelStatement(s.Identifier, Lower(scope, s.Expression), true); - } + { + // TODO[#201]: Remove side effects from Lower, migrate labels to a separate compilation stage. + if (!s.DidLowered) + scope.AddLabel(s.Identifier); + return new LabelStatement(s.Identifier, Lower(scope, s.Expression), true); + } case WhileStatement s: - { - var breakLabel = Guid.NewGuid().ToString(); - var continueLabel = Guid.NewGuid().ToString(); - - var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); - - return MakeLoop( - loopScope, - null, - s.TestExpression, - null, - s.Body, - breakLabel, - continueLabel, - null, - null - ); - } + { + var breakLabel = Guid.NewGuid().ToString(); + var continueLabel = Guid.NewGuid().ToString(); + + var loopScope = new BlockScope((IEmitScope)scope, breakLabel, continueLabel); + + return MakeLoop( + loopScope, + null, + s.TestExpression, + null, + s.Body, + breakLabel, + continueLabel, + null, + null + ); + } case ReturnStatement s: - { - return new ReturnStatement(s.Expression?.Lower(scope)); - } + { + return new ReturnStatement(s.Expression?.Lower(scope)); + } case SwitchStatement s: - { - var switchCases = new List(); - var breakLabel = Guid.NewGuid().ToString(); - var switchScope = new BlockScope((IEmitScope)scope, breakLabel, null, switchCases); + { + var switchCases = new List(); + var breakLabel = Guid.NewGuid().ToString(); + var switchScope = new BlockScope((IEmitScope)scope, breakLabel, null, switchCases); - var loweredBody = Lower(switchScope, s.Body); - var targetStmts = new List(); + var loweredBody = Lower(switchScope, s.Body); + var targetStmts = new List(); - if (switchCases.Count == 0) - { - return Lower(switchScope, new ExpressionStatement(s.Expression)); - } + if (switchCases.Count == 0) + { + return Lower(switchScope, new ExpressionStatement(s.Expression)); + } - var dbi = new DeclarationBlockItem( - new ScopedIdentifierDeclaration( - StorageClass.Auto, - new List - { + var dbi = new DeclarationBlockItem( + new ScopedIdentifierDeclaration( + StorageClass.Auto, + new List + { new(new LocalDeclarationInfo(s.Expression.GetExpressionType(scope), "$switch_tmp", null), s.Expression) - })); + })); - targetStmts.Add(Lower(switchScope, dbi)); + targetStmts.Add(Lower(switchScope, dbi)); - var idExpr = new IdentifierExpression("$switch_tmp"); + var idExpr = new IdentifierExpression("$switch_tmp"); - var hasDefaultCase = false; + var hasDefaultCase = false; - foreach (var matchGroup in switchCases) - { - if (matchGroup.TestExpression != null) - { - targetStmts.Add( - new IfElseStatement( - new BinaryOperatorExpression(idExpr, BinaryOperator.EqualTo, matchGroup.TestExpression).Lower(switchScope), - new GoToStatement(matchGroup.Label), - null - ) - ); - } - else + foreach (var matchGroup in switchCases) { - hasDefaultCase = true; - targetStmts.Add(new GoToStatement(matchGroup.Label)); + if (matchGroup.TestExpression != null) + { + targetStmts.Add( + new IfElseStatement( + new BinaryOperatorExpression(idExpr, BinaryOperator.EqualTo, matchGroup.TestExpression).Lower(switchScope), + new GoToStatement(matchGroup.Label), + null + ) + ); + } + else + { + hasDefaultCase = true; + targetStmts.Add(new GoToStatement(matchGroup.Label)); + } } - } - if (!hasDefaultCase) - targetStmts.Add(new GoToStatement(breakLabel)); + if (!hasDefaultCase) + targetStmts.Add(new GoToStatement(breakLabel)); - targetStmts.Add(loweredBody); - targetStmts.Add(Lower(switchScope, new LabelStatement(breakLabel, new ExpressionStatement((IExpression?) null)))); + targetStmts.Add(loweredBody); + targetStmts.Add(Lower(switchScope, new LabelStatement(breakLabel, new ExpressionStatement((IExpression?)null)))); - // avoiding lowering twice - return new CompoundStatement(targetStmts, switchScope); - } + // avoiding lowering twice + return new CompoundStatement(targetStmts, switchScope); + } case TagBlockItem t: - { - List list = new(); - foreach (var typeDef in t.Types) { - var (type, identifier, cliImportMemberName) = typeDef; - if (identifier == null) - throw new CompilationException($"Anonymous typedef not supported: {type}."); + List list = new(); + foreach (var typeDef in t.Types) + { + var (type, identifier, cliImportMemberName) = typeDef; + if (identifier == null) + throw new CompilationException($"Anonymous typedef not supported: {type}."); - if (cliImportMemberName != null) - throw new CompilationException($"typedef for CLI import not supported: {cliImportMemberName}."); + if (cliImportMemberName != null) + throw new CompilationException($"typedef for CLI import not supported: {cliImportMemberName}."); - type = scope.ResolveType(type); - scope.AddTagDefinition(identifier, type); - list.Add(new LocalDeclarationInfo(type, identifier, cliImportMemberName)); - } + type = scope.ResolveType(type); + scope.AddTagDefinition(identifier, type); + list.Add(new LocalDeclarationInfo(type, identifier, cliImportMemberName)); + } - return new TagBlockItem(list); - } + return new TagBlockItem(list); + } case TypeDefBlockItem t: - { - List list = new(); - foreach (var typeDef in t.Types) { - var (type, identifier, cliImportMemberName) = typeDef; - if (identifier == null) - throw new CompilationException($"Anonymous typedef not supported: {type}."); + List list = new(); + foreach (var typeDef in t.Types) + { + var (type, identifier, cliImportMemberName) = typeDef; + if (identifier == null) + throw new CompilationException($"Anonymous typedef not supported: {type}."); - if (cliImportMemberName != null) - throw new CompilationException($"typedef for CLI import not supported: {cliImportMemberName}."); + if (cliImportMemberName != null) + throw new CompilationException($"typedef for CLI import not supported: {cliImportMemberName}."); - type = scope.ResolveType(type); - scope.AddTypeDefinition(identifier, type); + type = scope.ResolveType(type); + scope.AddTypeDefinition(identifier, type); - if (typeDef.Type is StructType { Identifier: { } tag }) - { - scope.AddTagDefinition(tag, type); + if (typeDef.Type is StructType { Identifier: { } tag }) + { + scope.AddTagDefinition(tag, type); + } + + list.Add(new LocalDeclarationInfo(type, identifier, cliImportMemberName)); } - list.Add(new LocalDeclarationInfo(type, identifier, cliImportMemberName)); + return new TypeDefBlockItem(list); } - - return new TypeDefBlockItem(list); - } default: throw new ArgumentOutOfRangeException(nameof(blockItem)); } diff --git a/Cesium.CodeGen/Ir/Types/IType.cs b/Cesium.CodeGen/Ir/Types/IType.cs index ab8cc112..c0c03b81 100644 --- a/Cesium.CodeGen/Ir/Types/IType.cs +++ b/Cesium.CodeGen/Ir/Types/IType.cs @@ -39,13 +39,10 @@ FieldDefinition CreateFieldOfType(TranslationUnitContext context, TypeDefinition /// For simple types, will emit a constant. IExpression GetSizeInBytesExpression(TargetArchitectureSet arch) { - var size = GetSizeInBytes(arch); - if (size == null) - throw new AssertException( + int size = GetSizeInBytes(arch) ?? throw new AssertException( $"Cannot determine static size of type {this}, " + $"and {nameof(GetSizeInBytesExpression)} method for dynamic calculation is not overridden."); - - return new ConstantLiteralExpression(new IntegerConstant(size.Value)); + return new ConstantLiteralExpression(new IntegerConstant(size)); } } diff --git a/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs b/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs index ca6432bb..9c4d3518 100644 --- a/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs +++ b/Cesium.CodeGen/Ir/Types/InPlaceArrayType.cs @@ -25,14 +25,11 @@ public TypeReference Resolve(TranslationUnitContext context) public FieldDefinition CreateFieldOfType(TranslationUnitContext context, TypeDefinition ownerType, string fieldName) { var arch = context.AssemblyContext.ArchitectureSet; - var size = GetSizeInBytes(arch); - if (size == null) - throw new CompilationException( + int size = GetSizeInBytes(arch) ?? throw new CompilationException( $"Cannot statically determine a size of type {this} for architecture set \"{arch}\". " + $"This size is required to generate a field \"{fieldName}\" inside of a type \"{ownerType}\"."); - var itemType = Base.Resolve(context); - var bufferType = CreateFixedBufferType(context, itemType, fieldName, size.Value); + var bufferType = CreateFixedBufferType(context, itemType, fieldName, size); ownerType.NestedTypes.Add(bufferType); return new FieldDefinition(fieldName, FieldAttributes.Public, bufferType) @@ -43,11 +40,8 @@ public FieldDefinition CreateFieldOfType(TranslationUnitContext context, TypeDef CustomAttribute GenerateCustomFieldAttribute() { var typeType = context.Module.ImportReference(context.AssemblyContext.MscorlibAssembly.GetType("System.Type")); - var fixedBufferAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.FixedBufferAttribute"); - if (fixedBufferAttributeType == null) - throw new AssertException( + var fixedBufferAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.FixedBufferAttribute") ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.FixedBufferAttribute."); - var fixedBufferCtor = new MethodReference(".ctor", context.TypeSystem.Void, fixedBufferAttributeType); fixedBufferCtor.Parameters.Add(new ParameterDefinition(typeType)); fixedBufferCtor.Parameters.Add(new ParameterDefinition(context.TypeSystem.Int32)); @@ -57,7 +51,7 @@ CustomAttribute GenerateCustomFieldAttribute() ConstructorArguments = { new CustomAttributeArgument(typeType, itemType), - new CustomAttributeArgument(context.TypeSystem.Int32, size.Value) + new CustomAttributeArgument(context.TypeSystem.Int32, size) } }; } @@ -112,19 +106,13 @@ private static TypeDefinition CreateFixedBufferType( // } ModuleDefinition module = context.Module; - var compilerGeneratedAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.CompilerGeneratedAttribute"); - if (compilerGeneratedAttributeType == null) - throw new AssertException( + var compilerGeneratedAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.CompilerGeneratedAttribute") ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.CompilerGeneratedAttribute."); - var compilerGeneratedCtor = new MethodReference(".ctor", context.TypeSystem.Void, compilerGeneratedAttributeType); var compilerGeneratedAttribute = new CustomAttribute(module.ImportReference(compilerGeneratedCtor)); - var unsafeValueTypeAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.UnsafeValueTypeAttribute"); - if (unsafeValueTypeAttributeType == null) - throw new AssertException( + var unsafeValueTypeAttributeType = context.AssemblyContext.MscorlibAssembly.GetType("System.Runtime.CompilerServices.UnsafeValueTypeAttribute") ?? throw new AssertException( "Cannot find a type System.Runtime.CompilerServices.UnsafeValueTypeAttribute."); - var unsafeValueTypeCtor = new MethodReference(".ctor", context.TypeSystem.Void, unsafeValueTypeAttributeType); var unsafeValueTypeAttribute = new CustomAttribute(module.ImportReference(unsafeValueTypeCtor));