diff --git a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs index a0e239c3..fa9f16ac 100644 --- a/Cesium.CodeGen.Tests/CodeGenMethodTests.cs +++ b/Cesium.CodeGen.Tests/CodeGenMethodTests.cs @@ -425,6 +425,18 @@ int main() return fooptr(123); }", "Attempted to call non-function pointer"); + [Fact] + public Task StructParameters() => DoTest(@" +struct struct1 { + int x; +}; + +int console_read(struct struct1* __s); + +int console_read(struct struct1* s) { + return s->x; +}"); + // TODO [#196] /* [Fact] public Task VarargFunctionPointerCallTest() => DoTest(@"int foo(int a, ...) { return a; } diff --git a/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.StructParameters.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.StructParameters.verified.txt new file mode 100644 index 00000000..4b86e693 --- /dev/null +++ b/Cesium.CodeGen.Tests/verified/CodeGenMethodTests.StructParameters.verified.txt @@ -0,0 +1,4 @@ +System.Int32 ::console_read(struct1* __s) + IL_0000: ldarg.0 + IL_0001: ldfld System.Int32 struct1::x + IL_0006: ret diff --git a/Cesium.CodeGen/Contexts/BlockScope.cs b/Cesium.CodeGen/Contexts/BlockScope.cs index d7e8bd0f..58b5f7bf 100644 --- a/Cesium.CodeGen/Contexts/BlockScope.cs +++ b/Cesium.CodeGen/Contexts/BlockScope.cs @@ -74,7 +74,7 @@ public VariableDefinition ResolveVariable(string identifier) return variableDefinition; } - public ParameterDefinition ResolveParameter(string name) => Parent.ResolveParameter(name); + public ParameterDefinition ResolveParameter(int index) => Parent.ResolveParameter(index); public ParameterInfo? GetParameterInfo(string name) => ((IDeclarationScope)Parent).GetParameterInfo(name); /// diff --git a/Cesium.CodeGen/Contexts/FunctionScope.cs b/Cesium.CodeGen/Contexts/FunctionScope.cs index e916384a..38baa1e4 100644 --- a/Cesium.CodeGen/Contexts/FunctionScope.cs +++ b/Cesium.CodeGen/Contexts/FunctionScope.cs @@ -64,15 +64,9 @@ public VariableDefinition ResolveVariable(string identifier) } public ParameterInfo? GetParameterInfo(string name) => FunctionInfo.Parameters?.Parameters.FirstOrDefault(p => p.Name == name); - private readonly Dictionary _parameterCache = new(); - public ParameterDefinition ResolveParameter(string name) + public ParameterDefinition ResolveParameter(int index) { - if (_parameterCache.TryGetValue(name, out var parameter)) - return parameter; - - parameter = Method.Parameters.FirstOrDefault(p => p.Name == name) ?? throw new AssertException($"Cannot resolve parameter with name name {name}"); - _parameterCache.Add(name, parameter); - return parameter; + return Method.Parameters[index]; } /// public IType ResolveType(IType type) => Context.ResolveType(type); diff --git a/Cesium.CodeGen/Contexts/GlobalConstructorScope.cs b/Cesium.CodeGen/Contexts/GlobalConstructorScope.cs index 625d69ae..5dbebb78 100644 --- a/Cesium.CodeGen/Contexts/GlobalConstructorScope.cs +++ b/Cesium.CodeGen/Contexts/GlobalConstructorScope.cs @@ -51,7 +51,7 @@ public VariableDefinition ResolveVariable(string identifier) => throw new AssertException("Cannot add a variable into a global constructor scope"); public ParameterInfo? GetParameterInfo(string name) => null; - public ParameterDefinition ResolveParameter(string name) => + public ParameterDefinition ResolveParameter(int index) => throw new AssertException("Cannot resolve parameter from the global constructor scope"); /// diff --git a/Cesium.CodeGen/Contexts/IEmitScope.cs b/Cesium.CodeGen/Contexts/IEmitScope.cs index 92414950..151ee860 100644 --- a/Cesium.CodeGen/Contexts/IEmitScope.cs +++ b/Cesium.CodeGen/Contexts/IEmitScope.cs @@ -13,7 +13,7 @@ internal interface IEmitScope ModuleDefinition Module { get; } TranslationUnitContext Context { get; } VariableDefinition ResolveVariable(string identifier); - ParameterDefinition ResolveParameter(string name); + ParameterDefinition ResolveParameter(int index); /// /// Resolves instruction to which label pointed. diff --git a/Cesium.CodeGen/Contexts/Meta/FunctionInfo.cs b/Cesium.CodeGen/Contexts/Meta/FunctionInfo.cs index 2807a26f..3c0dc9b4 100644 --- a/Cesium.CodeGen/Contexts/Meta/FunctionInfo.cs +++ b/Cesium.CodeGen/Contexts/Meta/FunctionInfo.cs @@ -13,6 +13,9 @@ internal record FunctionInfo( StorageClass StorageClass, bool IsDefined) { + public ParametersInfo? Parameters { get; set; } = Parameters; + public StorageClass StorageClass { get; set; } = StorageClass; + public bool IsDefined { get; set; } = IsDefined; public MethodReference? MethodReference { get; set; } public string? CliImportMember { get; set; } diff --git a/Cesium.CodeGen/Contexts/TranslationUnitContext.cs b/Cesium.CodeGen/Contexts/TranslationUnitContext.cs index a6a18409..ede5ac43 100644 --- a/Cesium.CodeGen/Contexts/TranslationUnitContext.cs +++ b/Cesium.CodeGen/Contexts/TranslationUnitContext.cs @@ -53,9 +53,10 @@ internal void DeclareFunction(string identifier, FunctionInfo functionInfo) if (functionInfo.CliImportMember is not null && existingDeclaration.CliImportMember is not null) { var method = this.MethodLookup(functionInfo.CliImportMember, functionInfo.Parameters!, functionInfo.ReturnType); - if (!method.FullName.Equals(existingDeclaration.MethodReference!.FullName)) + var methodReference = existingDeclaration.MethodReference!; + if (!method.FullName.Equals(methodReference.FullName)) { - throw new CompilationException($"Function {identifier} already defined as as CLI-import with {existingDeclaration.MethodReference.FullName}."); + throw new CompilationException($"Function {identifier} already defined as as CLI-import with {methodReference.FullName}."); } } @@ -63,7 +64,9 @@ internal void DeclareFunction(string identifier, FunctionInfo functionInfo) ? existingDeclaration.StorageClass : functionInfo.StorageClass; var mergedIsDefined = existingDeclaration.IsDefined || functionInfo.IsDefined; - Functions[identifier] = existingDeclaration with { StorageClass = mergedStorageClass, IsDefined = mergedIsDefined }; + existingDeclaration.Parameters = functionInfo.Parameters; + existingDeclaration.IsDefined = mergedIsDefined; + existingDeclaration.StorageClass = mergedStorageClass; } } @@ -73,16 +76,16 @@ internal MethodDefinition DefineMethod( IType returnType, ParametersInfo? parameters) { - var owningType = storageClass == StorageClass.Auto ? GlobalType : GetOrCreateTranslationUnitType(); - var method = owningType.DefineMethod( - this, - name, - returnType.Resolve(this), - parameters); + var owningType = storageClass == StorageClass.Auto ? GlobalType : GetOrCreateTranslationUnitType(); + var method = owningType.DefineMethod( + this, + name, + returnType.Resolve(this), + parameters); var existingDeclaration = Functions.GetValueOrDefault(name); Debug.Assert(existingDeclaration is not null, $"Attempt to define method for undeclared function {name}"); Functions[name] = existingDeclaration with { MethodReference = method }; - return method; + return method; } private readonly Dictionary _generatedTypes = new(); diff --git a/Cesium.CodeGen/Extensions/TypeDefinitionEx.cs b/Cesium.CodeGen/Extensions/TypeDefinitionEx.cs index 6755f957..27ad5095 100644 --- a/Cesium.CodeGen/Extensions/TypeDefinitionEx.cs +++ b/Cesium.CodeGen/Extensions/TypeDefinitionEx.cs @@ -38,7 +38,7 @@ private static void AddParameters( foreach (var parameter in parameters) { - var (type, name) = parameter; + var (type, name, _) = parameter; var parameterDefinition = new ParameterDefinition(type.Resolve(context)) { Name = name diff --git a/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs b/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs index b94f7bbc..1fd42d43 100644 --- a/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs +++ b/Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs @@ -10,6 +10,7 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; +using System.Diagnostics; using PointerType = Cesium.CodeGen.Ir.Types.PointerType; namespace Cesium.CodeGen.Ir.BlockItems; @@ -65,6 +66,7 @@ public void EmitCode(IEmitScope scope) var (parameters, returnType) = FunctionType; var declaration = context.GetFunctionInfo(Name); + Debug.Assert(declaration != null, $"Function {Name} does not declared."); var method = declaration switch { diff --git a/Cesium.CodeGen/Ir/Expressions/Values/LValueParameter.cs b/Cesium.CodeGen/Ir/Expressions/Values/LValueParameter.cs index 5b0650bd..3b6cbecb 100644 --- a/Cesium.CodeGen/Ir/Expressions/Values/LValueParameter.cs +++ b/Cesium.CodeGen/Ir/Expressions/Values/LValueParameter.cs @@ -53,8 +53,7 @@ private ParameterDefinition GetParameterDefinition(IEmitScope scope) return _definition; } - var parameterName = _parameterInfo.Name ?? throw new AssertException("Name of parameter does not specified"); - _definition = scope.ResolveParameter(parameterName); + _definition = scope.ResolveParameter(_parameterInfo.Index); return _definition; } diff --git a/Cesium.CodeGen/Ir/ParametersInfo.cs b/Cesium.CodeGen/Ir/ParametersInfo.cs index 35dcd0c9..fc059c5a 100644 --- a/Cesium.CodeGen/Ir/ParametersInfo.cs +++ b/Cesium.CodeGen/Ir/ParametersInfo.cs @@ -39,9 +39,9 @@ internal record ParametersInfo(IList Parameters, bool IsVoid, boo } } -internal record ParameterInfo(IType Type, string? Name) +internal record ParameterInfo(IType Type, string? Name, int Index) { - public static ParameterInfo Of(ParameterDeclaration declaration) + public static ParameterInfo Of(ParameterDeclaration declaration, int index) { var (specifiers, declarator, abstractDeclarator) = declaration; var (type, identifier, cliImportMemberName) = (declarator, abstractDeclarator) switch @@ -55,6 +55,6 @@ public static ParameterInfo Of(ParameterDeclaration declaration) if (cliImportMemberName != null) throw new CompilationException("CLI import specifier isn't supported for a parameter."); - return new ParameterInfo(type, identifier); + return new ParameterInfo(type, identifier, index); } } diff --git a/Cesium.CodeGen/Ir/Types/FunctionType.cs b/Cesium.CodeGen/Ir/Types/FunctionType.cs index fb187889..0aa4f053 100644 --- a/Cesium.CodeGen/Ir/Types/FunctionType.cs +++ b/Cesium.CodeGen/Ir/Types/FunctionType.cs @@ -26,7 +26,7 @@ public TypeReference ResolvePointer(TranslationUnitContext context) if (isVarArg) throw new WipException(196, $"A pointer to a vararg function is not implemented, yet: {this}."); - foreach (var (type, name) in parameterInfos) + foreach (var (type, name, index) in parameterInfos) { pointer.Parameters.Add(new ParameterDefinition(type.Resolve(context)) {