Home All Groups Group Topic Archive Search About

MSIL Indirect Goto?

Author
24 Feb 2006 1:48 PM
paul.at.gmail
I am starting experimenting with IL code generation for a Forth-like
stack-based language that uses the CLR evaluation stack as the
Parameter stack (i.e. not a call stack) and a separate array for the
call stack. Therefore I expect I must avoid the IL ret instruction,
which enforces an empty evaluation stack on method return. To achieve
this I need to perform an indirect branch or jump as suggested below.
Does anyone know how to achieve this indirect jump efficiently in IL?

..method private hidebysig static void MyMethod() cil managed
{
  .entrypoint
  .maxstack  2
  stind stackPtr // push the return address on the seperate call stack
  ldsfld stackPtr // increment the stack pointer
  ldc.i4.1
  add
  stsfld stackPtr
  :
  ..execute the method..
  :
  // I don't want to use ret therefore...
  ldsfld stackPtr
  ldc.i4.1
  sub
  stsfld stackPtr
  ldind stackPtr 
  ?? // bra indirect or similar required here
}

Author
25 Feb 2006 7:59 AM
Daniel O'Connell [C# MVP]
"paul.at.gmail" <paul.r.sta***@gmail.com> wrote in message
news:1140788885.049586.156460@v46g2000cwv.googlegroups.com...
>I am starting experimenting with IL code generation for a Forth-like
> stack-based language that uses the CLR evaluation stack as the
> Parameter stack (i.e. not a call stack) and a separate array for the
> call stack. Therefore I expect I must avoid the IL ret instruction,
> which enforces an empty evaluation stack on method return. To achieve
> this I need to perform an indirect branch or jump as suggested below.
> Does anyone know how to achieve this indirect jump efficiently in IL?

I don't believe there is. AFAIK the runtime does not let you branch outside
of the current method.

I am curious, is this the right way to go about things? Is there a good
reason for using the evaluation stack as a parameter stack instead of using
it as the call stack it wants to be? What precisely is the reason you want
to try to force the runtime into working differently than it is really
designed to?

Show quote
>
> .method private hidebysig static void MyMethod() cil managed
> {
>  .entrypoint
>  .maxstack  2
>  stind stackPtr // push the return address on the seperate call stack
>  ldsfld stackPtr // increment the stack pointer
>  ldc.i4.1
>  add
>  stsfld stackPtr
>  :
>  ..execute the method..
>  :
>  // I don't want to use ret therefore...
>  ldsfld stackPtr
>  ldc.i4.1
>  sub
>  stsfld stackPtr
>  ldind stackPtr
>  ?? // bra indirect or similar required here
> }
>
Author
25 Feb 2006 2:51 PM
paul.at.gmail
I want to compare how a stack-based language (like Forth) would use the
CLR stack model with how a conventional language (e.g. C#) uses it.
Forth has two stacks - a Parameter stack and a Return stack. The CLR
implements a single stack and uses it for both purposes. In Forth, the
Parameter stack is a global resource and not restricted to the scope of
a single method (word in Forth), hence the workaround required. I agree
I am trying to workaround the designed CLR behaviour, which will
introduce inefficiencies and defeat my objective of making best use of
a (virtual) stack machine with a stack-oriented high-level language.

BTW, I think the following may be a solution:

..method private hidebysig static void MyMethod() cil managed
{
  stind stackPtr // push the return address on the seperate call stack
  ldsfld stackPtr // increment the stack pointer
  ldc.i4.1
  add
  stsfld stackPtr
  :
  ..execute the method..
  :
  call void _MyRet()
}

..method private hidebysig static void _MyRet() cil managed
{
  pop // Discard the MyMethod() return address
  ldsfld stackPtr
  ldc.i4.1
  sub
  stsfld stackPtr
  ldind stackPtr
  ret // Returns to the caller of MyMethod()
}

What do you think?
Author
27 Feb 2006 4:46 AM
Daniel O'Connell [C# MVP]
"paul.at.gmail" <paul.r.sta***@gmail.com> wrote in message
news:1140879110.267465.303330@i39g2000cwa.googlegroups.com...
>I want to compare how a stack-based language (like Forth) would use the
> CLR stack model with how a conventional language (e.g. C#) uses it.
> Forth has two stacks - a Parameter stack and a Return stack. The CLR
> implements a single stack and uses it for both purposes. In Forth, the
> Parameter stack is a global resource and not restricted to the scope of
> a single method (word in Forth), hence the workaround required. I agree
> I am trying to workaround the designed CLR behaviour, which will
> introduce inefficiencies and defeat my objective of making best use of
> a (virtual) stack machine with a stack-oriented high-level language.

Ahh, I see. Its messy, and I know hte CLR has some problems with alot of
less conventional languages. Good luck.

Show quote
>
> BTW, I think the following may be a solution:
>
> .method private hidebysig static void MyMethod() cil managed
> {
>  stind stackPtr // push the return address on the seperate call stack
>  ldsfld stackPtr // increment the stack pointer
>  ldc.i4.1
>  add
>  stsfld stackPtr
>  :
>  ..execute the method..
>  :
>  call void _MyRet()
> }
>
> .method private hidebysig static void _MyRet() cil managed
> {
>  pop // Discard the MyMethod() return address
>  ldsfld stackPtr
>  ldc.i4.1
>  sub
>  stsfld stackPtr
>  ldind stackPtr
>  ret // Returns to the caller of MyMethod()
> }
>
> What do you think?

It looks like it will work, assuming the CLR doesn't balk at it(didn't try
it.) It is still messy, and either swaping the stacks around or using a
three stack approach where both the parameter and the return stacks are
arrays and the CLR stack is just an implementation detail that you use to
make the system work would be cleaner, but perhaps contrary to your efforts.
Again, good luck.

AddThis Social Bookmark Button