question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mixing C# and IL locals

See original GitHub issue

Hello Lucas!

I tried to use InlineIL for a painful case of working with ref locals, and found some limitations. A simplified sample below. I want to mix locals defined normally and via InlineIL. For ref locals, I really miss reference to reference similar to pointer to pointer and C# does not allow to initialize ref local in efficient way in my case. But after initialization, I would rather continue to use C#, not IL. The type under question if a struct with objects, so using Unsafe.AsPointer is dangerous and questionable.

Here we define baz in C# and then add two additional locals via IL. The output locals will be merged as expected. I want to have access to baz from IL.

        public int UseLocalVariables(int value)
        {
#pragma warning disable 219
            var baz = 10;
#pragma warning restore 219
            IL.DeclareLocals(
                new LocalVar("foo", typeof(int)),
                new LocalVar("bar", typeof(int))
            );

            IL.Push(value);
            Stloc("foo");

            Ldc_I4(42);
            Stloc("bar");

            IncrBaz();

            Ldloc("foo");

            // We want to be able to load baz, which is defined normally in C#
            // Ldloc("baz"); -- will not work, and local names are not available in Mono.Cecil: https://groups.google.com/g/mono-cecil/c/GwDG0bQ8TXk/m/mIr6QtXTQNsJ
            // But we could use an index. There is one auto local for local function IncrBaz,
            // so the baz has index 1. Or we could look the index in actual IL after weaving.
            Ldloc_1();
            Add();
            return IL.Return<int>();

            void IncrBaz()
            {
                baz++;
            }
        }

Looking into MethodLocals implementation I think the fix could be simple. Even though Mono.Cecil does not support names of locals (or technically there are no names in IL), we could use indices.

A potential fix is to add this: image

This will create some complexity with indexing, because the required index will be the one from combined locals, not from IL-defined locals. And in the presence of local functions, like in the sample, there could be autogenerated locals. To get the right indices one will have to look into generated IL. Thankfully, in Rider, IL View is one click away and it shows IL after weaving. So this indexing behavior could be left as “by design”.

But since it’s the first time I look into this source code, I don’t know if something else could break after the proposed change.


The real use case looks like this: image

This is one of the hottest methods, and GetLoadRef2 is not trivial. But it’s still faster to have it as AggressivelyInlined. However, this generates twice as much of the assembly code. So the idea is to initialize ref locals in a loop to have the GetLoadRef2 inlined once.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
buybackoffcommented, Nov 28, 2020

Good luck with that! 😄

Thanks! It’s already faster than C on SciMark benchmark. But absolutely meaningless timing of the benchmark is 1095, and you could guess what my obsession is and what a round number is the goal 😂

I have implemented kind of JIT, or an optimization phase, that rewrites instructions from stack-based to virtual-registers based ones. Could eliminate more than 25% of all instructions. Without that the timing is at 1460. I should probably continue with this direction, and not IL rewrite.

Very fun experience overall.

1reaction
ltrzesniewskicommented, Nov 28, 2020

Yeah, the for loop won’t work, as you need to have a well-defined evaluation stack state for each basic block.

But I think you probably have a GC hole here since you’re going through a void* local… I guess it depends on the way this is going to get JITted. 😕

I think I’ll have to provide some kind of PopRef method or add something similar which would let you reassign a ref.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mixing C and C++ Code in the Same Program
The C++ language provides mechanisms for mixing code that is compiled by compatible C and C++ compilers in the same program. You can...
Read more >
Is it okay to mix C and C++?
Yes, it is possible to mix C and C++ code in a single program. C++ is a superset of C, which means that...
Read more >
How to mix C and C++, C++ FAQ
What do I need to know when mixing C and C++ code? How do I call a C function from C++? ... How...
Read more >
NOTICE TO CONTRACTORS BULLETIN | Illinois Department ...
This bulletin is issued weekly by the Bureau of Local Roads and Streets. ... IL-19.0, N50 (273 Ton); HMA Surface Course, Mix "C", ......
Read more >
Food Handling Regulation Enforcement Act
The training indicated in subsections (c) and (d) of this Section is not transferable between individuals or employers. Proof that a food handler...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found