Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix codegen with forward declaration. #481

Merged
merged 2 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cesium.CodeGen.Tests/CodeGenMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
System.Int32 <Module>::console_read(struct1* __s)
IL_0000: ldarg.0
IL_0001: ldfld System.Int32 struct1::x
IL_0006: ret
2 changes: 1 addition & 1 deletion Cesium.CodeGen/Contexts/BlockScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <inheritdoc />
Expand Down
10 changes: 2 additions & 8 deletions Cesium.CodeGen/Contexts/FunctionScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, ParameterDefinition> _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];
}
/// <inheritdoc />
public IType ResolveType(IType type) => Context.ResolveType(type);
Expand Down
2 changes: 1 addition & 1 deletion Cesium.CodeGen/Contexts/GlobalConstructorScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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");

/// <inheritdoc />
Expand Down
2 changes: 1 addition & 1 deletion Cesium.CodeGen/Contexts/IEmitScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <summary>
/// Resolves instruction to which label pointed.
Expand Down
3 changes: 3 additions & 0 deletions Cesium.CodeGen/Contexts/Meta/FunctionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
23 changes: 13 additions & 10 deletions Cesium.CodeGen/Contexts/TranslationUnitContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,20 @@ 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}.");
}
}

var mergedStorageClass = existingDeclaration.StorageClass != StorageClass.Auto
? 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;
}
}

Expand All @@ -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<IGeneratedType, TypeReference> _generatedTypes = new();
Expand Down
2 changes: 1 addition & 1 deletion Cesium.CodeGen/Extensions/TypeDefinitionEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Cesium.CodeGen/Ir/BlockItems/FunctionDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
{
Expand Down
3 changes: 1 addition & 2 deletions Cesium.CodeGen/Ir/Expressions/Values/LValueParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 3 additions & 3 deletions Cesium.CodeGen/Ir/ParametersInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ internal record ParametersInfo(IList<ParameterInfo> 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
Expand All @@ -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);
}
}
2 changes: 1 addition & 1 deletion Cesium.CodeGen/Ir/Types/FunctionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down
Loading