Skip to content

Commit c190dc7

Browse files
committed
Revered half-baked byref support for legacy function emit strategy.
1 parent d6ffc9c commit c190dc7

File tree

3 files changed

+19
-108
lines changed

3 files changed

+19
-108
lines changed

Biohazrd.CSharp/CSharpGenerationOptions.cs

-8
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,6 @@ public TargetLanguageVersion TargetLanguageVersion
9292
}
9393
}
9494

95-
/// <summary>Controls how C++ reference types are translated to C#.</summary>
96-
/// <remarks>
97-
/// By default, references are emitted according to <see cref="ReferenceTypeOutputBehavior.AsRefOrByValue"/>.
98-
///
99-
/// This setting can be overriden for individual parameters using <see cref="Metadata.OverrideReferenceTypeOutputBehavior"/>
100-
/// </remarks>
101-
public ReferenceTypeOutputBehavior ReferenceTypeOutputBehavior { get; init; } = ReferenceTypeOutputBehavior.AsRefOrByValue;
102-
10395
public bool SuppressDefaultParameterValuesOnNonPublicMethods { get; init; } = true;
10496

10597
public CSharpGenerationOptions()

Biohazrd.CSharp/CSharpLibraryGenerator.Functions.cs

+18-99
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using Biohazrd.CSharp.Metadata;
22
using Biohazrd.CSharp.Trampolines;
3-
using Biohazrd.OutputGeneration;
43
using ClangSharp.Pathogen;
54
using System;
6-
using System.Collections.Immutable;
75
using System.Diagnostics;
86
using System.Runtime.CompilerServices;
97
using System.Runtime.InteropServices;
@@ -13,47 +11,19 @@ namespace Biohazrd.CSharp
1311
{
1412
partial class CSharpLibraryGenerator
1513
{
16-
private struct ParameterEmitStrategy
17-
{
18-
public TranslatedParameter Declaration { get; init; }
19-
public ParameterOutputMode OutputMode { get; init; }
20-
public string FixedName => $"__{Declaration.Name}P";
21-
}
22-
2314
private ref struct EmitFunctionContext
2415
{
2516
public bool NeedsTrampoline { get; }
2617
public string DllImportName { get; }
2718
public TypeReference? ThisType { get; }
2819
public string ThisParameterName => "this";
2920
public string ReturnBufferParameterName => "__returnBuffer";
30-
public ImmutableArray<ParameterEmitStrategy> Parameters { get; }
31-
public VisitorContext ParameterContext { get; }
3221

33-
public EmitFunctionContext(VisitorContext context, TranslatedFunction declaration, CSharpGenerationOptions options)
22+
public EmitFunctionContext(VisitorContext context, TranslatedFunction declaration)
3423
{
3524
// We emit a trampoline for functions which are instance methods or return via reference to hide those ABI semantics
3625
NeedsTrampoline = declaration.IsInstanceMethod || declaration.ReturnByReference;
3726

38-
// Determine how parameters will be written
39-
ImmutableArray<ParameterEmitStrategy>.Builder parameters = ImmutableArray.CreateBuilder<ParameterEmitStrategy>(declaration.Parameters.Length);
40-
foreach (TranslatedParameter parameter in declaration.Parameters)
41-
{
42-
ParameterEmitStrategy strategy = new()
43-
{
44-
Declaration = parameter,
45-
OutputMode = parameter.GetParameterOutputMode(options.ReferenceTypeOutputBehavior)
46-
};
47-
48-
// References emitted as anything other than pointers need a trampoline
49-
if (strategy.OutputMode != ParameterOutputMode.Normal)
50-
{ NeedsTrampoline = true; }
51-
52-
parameters.Add(strategy);
53-
}
54-
Parameters = parameters.MoveToImmutable();
55-
ParameterContext = context.Add(declaration);
56-
5727
// When this function is uses a trampoline, we add a suffix to the P/Invoke method to ensure they don't conflict with other methods.
5828
// (For instance, when there's a SomeClass::Method() method in addition to a SomeClass::Method(SomeClass*) method.)
5929
DllImportName = NeedsTrampoline ? $"{declaration.Name}_PInvoke" : declaration.Name;
@@ -100,7 +70,7 @@ protected override void VisitFunction(VisitorContext context, TranslatedFunction
10070
return;
10171
}
10272

103-
EmitFunctionContext emitContext = new(context, declaration, Options);
73+
EmitFunctionContext emitContext = new(context, declaration);
10474

10575
// Emit the DllImport
10676
if (!declaration.IsVirtual)
@@ -283,31 +253,20 @@ private void EmitFunctionTrampoline(VisitorContext context, EmitFunctionContext
283253
// Emit the dispatch
284254
using (Writer.Block())
285255
{
286-
bool hasFixedBlocks = false;
287-
288-
// Fix the this pointer if necessary
256+
bool hasThis;
289257
if (emitContext.ThisType is not null)
290258
{
259+
hasThis = true;
291260
Debug.Assert(declaration.IsInstanceMethod);
292261

293262
Writer.Write($"fixed (");
294263
WriteType(context, declaration, emitContext.ThisType!);
295264
Writer.WriteLine($" {SanitizeIdentifier(emitContext.ThisParameterName)} = &this)");
296-
hasFixedBlocks = true;
297265
}
298266
else
299-
{ Debug.Assert(!declaration.IsInstanceMethod); }
300-
301-
// Fix the parameters if necessary
302-
foreach (ParameterEmitStrategy parameter in emitContext.Parameters)
303267
{
304-
if (parameter.OutputMode != ParameterOutputMode.RefByRef && parameter.OutputMode != ParameterOutputMode.RefByReadonlyRef)
305-
{ continue; }
306-
307-
Writer.Write("fixed (");
308-
WriteType(emitContext.ParameterContext, parameter.Declaration, parameter.Declaration.Type);
309-
Writer.WriteLine($" {SanitizeIdentifier(parameter.FixedName)} = &{SanitizeIdentifier(parameter.Declaration.Name)})");
310-
hasFixedBlocks = true;
268+
hasThis = false;
269+
Debug.Assert(!declaration.IsInstanceMethod);
311270
}
312271

313272
bool hasReturnValue = declaration.ReturnType is not VoidTypeReference;
@@ -326,7 +285,7 @@ void EmitFunctionBodyWithReturnByReference(EmitFunctionContext emitContext)
326285
Writer.WriteLine($"return {SanitizeIdentifier(emitContext.ReturnBufferParameterName)};");
327286
}
328287

329-
if (hasFixedBlocks)
288+
if (hasThis)
330289
{
331290
// If we have a fixed statement for the this pointer, wrap the return buffer logic with a block
332291
using (Writer.Block())
@@ -338,7 +297,7 @@ void EmitFunctionBodyWithReturnByReference(EmitFunctionContext emitContext)
338297
else
339298
{
340299
// If we have a fixed statement for the this pointer, write out the curly braces for it
341-
if (hasFixedBlocks)
300+
if (hasThis)
342301
{ Writer.Write("{ "); }
343302

344303
if (hasReturnValue)
@@ -348,7 +307,7 @@ void EmitFunctionBodyWithReturnByReference(EmitFunctionContext emitContext)
348307
EmitFunctionParameterList(context, emitContext, declaration, EmitParameterListMode.TrampolineArguments);
349308
Writer.Write(");");
350309

351-
if (hasFixedBlocks)
310+
if (hasThis)
352311
{ Writer.WriteLine(" }"); }
353312
}
354313
}
@@ -411,6 +370,8 @@ private void EmitFunctionParameterList(VisitorContext context, EmitFunctionConte
411370
_ => false
412371
};
413372

373+
VisitorContext parameterContext = context.Add(declaration);
374+
414375
// Write out the this/retbuf parameters
415376
if (writeImplicitParameters)
416377
{
@@ -466,80 +427,38 @@ void WriteOutReturnBuffer(EmitFunctionContext emitContext)
466427
}
467428

468429
// Write out parameters
469-
foreach (ParameterEmitStrategy strategy in emitContext.Parameters)
430+
foreach (TranslatedParameter parameter in declaration.Parameters)
470431
{
471-
TranslatedParameter parameter = strategy.Declaration;
472-
473432
if (first)
474433
{ first = false; }
475434
else
476435
{ Writer.Write(", "); }
477436

478437
if (writeTypes)
479438
{
480-
if (mode == EmitParameterListMode.TrampolineParameters && strategy.OutputMode != ParameterOutputMode.Normal)
481-
{
482-
Debug.Assert(writeNames);
483-
Debug.Assert(!parameter.ImplicitlyPassedByReference);
484-
PointerTypeReference? pointerType = parameter.Type as PointerTypeReference;
485-
Debug.Assert(pointerType is not null); // EffectiveReferenceTypeOutputBehavior should not return a byref mode when the type isn't a pointer
486-
Debug.Assert(pointerType.WasReference);
487-
488-
switch (strategy.OutputMode)
489-
{
490-
case ParameterOutputMode.RefByReadonlyRef:
491-
Writer.Write("in ");
492-
break;
493-
case ParameterOutputMode.RefByRef:
494-
Writer.Write("ref ");
495-
break;
496-
}
497-
498-
WriteTypeForTrampoline(emitContext.ParameterContext, parameter, pointerType.Inner);
499-
}
500-
else if (parameter.ImplicitlyPassedByReference)
501-
{ WriteTypeAsReference(emitContext.ParameterContext, parameter, parameter.Type); }
439+
if (parameter.ImplicitlyPassedByReference)
440+
{ WriteTypeAsReference(parameterContext, parameter, parameter.Type); }
502441
else
503442
{
504443
// Write MarshalAs for booleans at pinvoke boundaries
505444
if (mode == EmitParameterListMode.DllImportParameters && parameter.Type.IsCSharpType(context.Library, CSharpBuiltinType.Bool))
506445
{ Writer.Write("[MarshalAs(UnmanagedType.I1)] "); }
507446

508447
if (mode == EmitParameterListMode.TrampolineParameters)
509-
{ WriteTypeForTrampoline(emitContext.ParameterContext, parameter, parameter.Type); }
448+
{ WriteTypeForTrampoline(parameterContext, parameter, parameter.Type); }
510449
else
511-
{ WriteType(emitContext.ParameterContext, parameter, parameter.Type); }
450+
{ WriteType(parameterContext, parameter, parameter.Type); }
512451
}
513452

514453
if (writeNames)
515454
{ Writer.Write(' '); }
516455
}
517456

518457
if (writeNames)
519-
{
520-
if (mode == EmitParameterListMode.TrampolineArguments && strategy.OutputMode != ParameterOutputMode.Normal)
521-
{
522-
switch (strategy.OutputMode)
523-
{
524-
case ParameterOutputMode.RefByReadonlyRef:
525-
case ParameterOutputMode.RefByRef:
526-
Writer.WriteIdentifier(strategy.FixedName);
527-
break;
528-
case ParameterOutputMode.RefByValue:
529-
Writer.Write('&');
530-
Writer.WriteIdentifier(parameter.Name);
531-
break;
532-
default:
533-
FatalContext(emitContext.ParameterContext, parameter, $"Invalid parameter output mode '{strategy.OutputMode}'");
534-
break;
535-
}
536-
}
537-
else
538-
{ Writer.WriteIdentifier(parameter.Name); }
539-
}
458+
{ Writer.WriteIdentifier(parameter.Name); }
540459

541460
if (writeDefautValues && parameter.DefaultValue is not null)
542-
{ Writer.Write($" = {GetConstantAsString(emitContext.ParameterContext, parameter, parameter.DefaultValue, parameter.Type)}"); }
461+
{ Writer.Write($" = {GetConstantAsString(parameterContext, parameter, parameter.DefaultValue, parameter.Type)}"); }
543462
}
544463
}
545464

Biohazrd.CSharp/CSharpLibraryGenerator.Records.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private void EmitVTable(VisitorContext context, TranslatedVTableField field, Tra
8989

9090
if (entry.IsFunctionPointer && entry.MethodReference?.TryResolve(context.Library) is TranslatedFunction associatedFunction)
9191
{
92-
EmitFunctionContext emitContext = new(context, associatedFunction, Options);
92+
EmitFunctionContext emitContext = new(context, associatedFunction);
9393
EmitFunctionPointerForVTable(context, emitContext, associatedFunction);
9494
}
9595
else

0 commit comments

Comments
 (0)