Skip to content

Commit

Permalink
Remove unnecessary initialization of variables in generated code (dot…
Browse files Browse the repository at this point in the history
  • Loading branch information
elinor-fung committed Oct 22, 2021
1 parent 24864a9 commit abcee57
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,18 @@ public override (string managed, string native) GetIdentifiers(TypePositionInfo

public BlockSyntax GeneratePInvokeBody(string dllImportName)
{
bool invokeReturnsVoid = _retMarshaller.TypeInfo.ManagedType == SpecialTypeInfo.Void;

// Handle GuaranteedUnmarshal and Cleanup first since whether or not those stages produce statements affects multiple other stages.
var guaranteedUnmarshalStatements = new List<StatementSyntax>();
GenerateStatementsForStage(Stage.GuaranteedUnmarshal, guaranteedUnmarshalStatements);
bool hasGuaranteedUnmarshalStatements = guaranteedUnmarshalStatements.Count > 0;

var cleanupStatements = new List<StatementSyntax>();
GenerateStatementsForStage(Stage.Cleanup, cleanupStatements);

bool shouldInitializeVariables = hasGuaranteedUnmarshalStatements || cleanupStatements.Count > 0;

var setupStatements = new List<StatementSyntax>();

foreach (BoundGenerator marshaller in _paramMarshallers)
Expand All @@ -238,11 +250,9 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName)
}

// Declare variables for parameters
AppendVariableDeclations(setupStatements, info, marshaller.Generator);
AppendVariableDeclations(setupStatements, info, marshaller.Generator, initializeToDefault: shouldInitializeVariables);
}

bool invokeReturnsVoid = _retMarshaller.TypeInfo.ManagedType == SpecialTypeInfo.Void;

// Stub return is not the same as invoke return
if (!_stubReturnsVoid && !_retMarshaller.TypeInfo.IsManagedReturnPosition)
{
Expand All @@ -252,47 +262,41 @@ public BlockSyntax GeneratePInvokeBody(string dllImportName)
(TypePositionInfo stubRetTypeInfo, IMarshallingGenerator stubRetGenerator) = _paramMarshallers.Last();

// Declare variables for stub return value
AppendVariableDeclations(setupStatements, stubRetTypeInfo, stubRetGenerator);
AppendVariableDeclations(setupStatements, stubRetTypeInfo, stubRetGenerator, initializeToDefault: shouldInitializeVariables);
}

if (!invokeReturnsVoid)
{
// Declare variables for invoke return value
AppendVariableDeclations(setupStatements, _retMarshaller.TypeInfo, _retMarshaller.Generator);
AppendVariableDeclations(setupStatements, _retMarshaller.TypeInfo, _retMarshaller.Generator, initializeToDefault: shouldInitializeVariables);
}

// Do not manually handle SetLastError when generating forwarders.
// We want the runtime to handle everything.
if (_setLastError)
{
// Declare variable for last error
setupStatements.Add(MarshallerHelpers.DeclareWithDefault(
setupStatements.Add(MarshallerHelpers.Declare(
PredefinedType(Token(SyntaxKind.IntKeyword)),
LastErrorIdentifier));
LastErrorIdentifier,
initializeToDefault: false));
}

var tryStatements = new List<StatementSyntax>();
var guaranteedUnmarshalStatements = new List<StatementSyntax>();
var cleanupStatements = new List<StatementSyntax>();
InvocationExpressionSyntax invoke = InvocationExpression(IdentifierName(dllImportName));

// Handle GuaranteedUnmarshal first since that stage producing statements affects multiple other stages.
GenerateStatementsForStage(Stage.GuaranteedUnmarshal, guaranteedUnmarshalStatements);
if (guaranteedUnmarshalStatements.Count > 0)
if (hasGuaranteedUnmarshalStatements)
{
setupStatements.Add(MarshallerHelpers.DeclareWithDefault(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier));
setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true));
}

var tryStatements = new List<StatementSyntax>();
InvocationExpressionSyntax invoke = InvocationExpression(IdentifierName(dllImportName));

GenerateStatementsForStage(Stage.Setup, setupStatements);
GenerateStatementsForStage(Stage.Marshal, tryStatements);
GenerateStatementsForInvoke(tryStatements, invoke);
GenerateStatementsForStage(Stage.KeepAlive, tryStatements);
GenerateStatementsForStage(Stage.Unmarshal, tryStatements);
GenerateStatementsForStage(Stage.Cleanup, cleanupStatements);

List<StatementSyntax> allStatements = setupStatements;
List<StatementSyntax> finallyStatements = new List<StatementSyntax>();
if (guaranteedUnmarshalStatements.Count > 0)
if (hasGuaranteedUnmarshalStatements)
{
finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(guaranteedUnmarshalStatements)));
}
Expand Down Expand Up @@ -477,24 +481,26 @@ _retMarshaller.Generator is IAttributedReturnTypeMarshallingGenerator attributed
);
}

private void AppendVariableDeclations(List<StatementSyntax> statementsToUpdate, TypePositionInfo info, IMarshallingGenerator generator)
private void AppendVariableDeclations(List<StatementSyntax> statementsToUpdate, TypePositionInfo info, IMarshallingGenerator generator, bool initializeToDefault)
{
(string managed, string native) = GetIdentifiers(info);

// Declare variable for return value
if (info.IsManagedReturnPosition || info.IsNativeReturnPosition)
{
statementsToUpdate.Add(MarshallerHelpers.DeclareWithDefault(
statementsToUpdate.Add(MarshallerHelpers.Declare(
info.ManagedType.Syntax,
managed));
managed,
false));
}

// Declare variable with native type for parameter or return value
if (generator.UsesNativeIdentifier(info, this))
{
statementsToUpdate.Add(MarshallerHelpers.DeclareWithDefault(
statementsToUpdate.Add(MarshallerHelpers.Declare(
generator.AsNativeType(info),
native));
native,
initializeToDefault));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,23 @@ public static ForStatementSyntax GetForLoop(string collectionIdentifier, string
IdentifierName(indexerIdentifier))));
}

public static LocalDeclarationStatementSyntax DeclareWithDefault(TypeSyntax typeSyntax, string identifier)
public static LocalDeclarationStatementSyntax Declare(TypeSyntax typeSyntax, string identifier, bool initializeToDefault)
{
VariableDeclaratorSyntax decl = VariableDeclarator(identifier);
if (initializeToDefault)
{
decl = decl.WithInitializer(
EqualsValueClause(
LiteralExpression(SyntaxKind.DefaultLiteralExpression)));
}

// <type> <identifier>;
// or
// <type> <identifier> = default;
return LocalDeclarationStatement(
VariableDeclaration(
typeSyntax,
SingletonSeparatedList(
VariableDeclarator(identifier)
.WithInitializer(
EqualsValueClause(
LiteralExpression(SyntaxKind.DefaultLiteralExpression))))));
SingletonSeparatedList(decl)));
}

public static RefKind GetRefKindForByValueContentsKind(this ByValueContentsMarshalKind byValue)
Expand Down

0 comments on commit abcee57

Please sign in to comment.