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

mono struct return temporary variable not inlined #1555

Closed
arbruijn opened this issue Jun 30, 2019 · 1 comment
Closed

mono struct return temporary variable not inlined #1555

arbruijn opened this issue Jun 30, 2019 · 1 comment
Labels
C# Decompiler The decompiler engine itself Enhancement Areas for improvement mcs Problems with assemblies generated by the Mono compiler

Comments

@arbruijn
Copy link

Mono mcs seems to create a temporary variable when accessing fields in structs returned from calls (e.g. getStruct().x). This temporary variable is not inlined with recent ILSpy versions. It used to be inlined with ILSpy 2, but the current IsGeneratedValueTypeTemporary check prevents this.

The variable is inlined when I add the following code at the top of IsGeneratedValueTypeTemporary, I don't know if that's a proper fix:

if (loadInst.Parent.OpCode == OpCode.LdFlda)
	return true;

For example for the following the class:

class Structret {
    struct S { public int x; }
    static S getS() { return new S(); }
    void Do(int x) { Do(getS().x); }
}

The Do method is compiled with mono to:

IL_0000: ldarg.0
IL_0001: call valuetype testvar/S testvar::getS()
IL_0006: stloc.0
IL_0007: ldloca.s 0
IL_0009: ldfld int32 testvar/S::x
IL_000e: call instance void testvar::Do(int32)

And this is currently decompiled to:

private void Do(int x)
{
	S s = getS();
	Do(s.x);
}

monostructret.zip

@siegfriedpammer siegfriedpammer added C# Decompiler The decompiler engine itself mcs Problems with assemblies generated by the Mono compiler Enhancement Areas for improvement labels Jul 13, 2019
@tamlin-mike
Copy link

While that fixes the current scenario, I it could produce incorrect decompilation if the data in slot 0 is used (read) again later in scope.

Probably DFA - even if trivially simple - needs to be used, together with some heuristics to not generate excessively long expressions (in case access would be something like getS().foo.bar.longname.baz.x).
I believe this example could be a good starting point, to only inline 1st level of such chains.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 7, 2020
ElektroKill added a commit to dnSpyEx/ILSpy that referenced this issue Aug 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C# Decompiler The decompiler engine itself Enhancement Areas for improvement mcs Problems with assemblies generated by the Mono compiler
Projects
None yet
Development

No branches or pull requests

3 participants