views:

272

answers:

4

Is there a way in .NET, using Reflection.Emit, to access the topmost-but-one item from the stack? So if A is topmost, and B next - I want to process B then A. It would be fine to duplicate B above A (since I can simply "pop" the second B when I get to it).

Currently, I am declaring a local:

    LocalBuilder loc = il.DeclareLocal(typeof(Foo));
    il.Emit(OpCodes.Stloc, loc); // store and pop topmost stack item
    // work with (pop) previous stack item 
    il.Emit(OpCodes.Ldloc, loc); // push old topmost stack item

Is there a route that doesn't need the explicit local?

+5  A: 

I don't think so. In IL there aren't any instructions like swap which would allow you to do what you want. Why do you see using a local as objectionable? If the JIT compiler is good enough this won't result in any slower machine code than using a hypothetical swap operation in IL.

kvb
For the "why" - this is in generated code that would have to introduce more locals that I want. If I could use the top of the stack instead, I could save non-trivial amounts of stack space (locals are reserved regardless of usage, AFAIK).
Marc Gravell
+1  A: 

+1 for kvbs answer, see: http://www.codeproject.com/KB/msil/msilenhancement.aspx

Sam Saffron
The codeproject author has similar thoughts to me, then. SWAP or OVER would do the job ;-p I'll have to check my 4.0 VM, but I'm not hopeful that it is any different there...
Marc Gravell
+1  A: 

Inline with what kvb said, you could try a small function to do some reordering. Not sure if it would be any faster.

leppie
Good thought, but almost certainly not; even if the JUT inlined it.
Marc Gravell
+1  A: 

I encountered this same problem. I wanted to generate a rather large method and I often wanted to 'swap' in order to store a calculated value. I was unhappy with the large volume of locals showing up in ildasm and noticed that BeginScope/EndScope wasn't any help. I wound up creating a local 'swap' for the context of my method and reusing it for every swap operation. It makes the generated IL cleaner; not sure if it has any meaningful impact on performance.

Dan Bryant