guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: guile-vm 0.3


From: Marius Vollmer
Subject: Re: guile-vm 0.3
Date: 13 Apr 2001 04:48:51 +0200
User-agent: Gnus/5.0803 (Gnus v5.8.3) Emacs/20.7

Keisuke Nishida <address@hidden> writes:

> Marius Vollmer wrote:
>  
> > What about something along these lines (this is from guile-lightning,
> > and in flux):
> 
> Looks interesting, and this is more like the internal form of my GHIL,
> which is a structured language like yours.  After parsing and macro
> expansion, GHIL is reduced to a simpler form like this language.

I see.  I haven't really looked at your VM yet (shame, shame).  It's
too damn much fun playing with assembly language in an interactive
system.

> So, maybe I should stop transformation at the end of the GHIL stage.

Yes.  The language that I presented (looks like I need a name for it,
hmm, what about Glow, in lieu of Lightning ;-) will need quite a
sophisticated front-end, I think, since Glow is very limited.
Especially closure conversion (with lambda lifting etc) is likely a
non-trivial thing, and then of course type inference to be able to
inline simple operations.

> > ;; - (lambda-template (ARGS... :rest REST :env ENV) BODY...)
> > ;;
> > ;;   ARGS, REST and ENV are symbols and BODY is a list of expressions.
> > ;;   Both `:rest' and `:env' are optional.
> 
> How do you use ENV?  Are you adding `env-ref' or something?
> Is it dynamic or static? (i.e., when do you look up?)

I'm not sure about :env yet.  ENV will probably be just another
argument for the function that can be accessed via `(local ENV)'.

Lookup using ENV will be explicit, like

    (inline env-ref (local env) 2 3)

which could mean something like `get the value in slot 3 of frame 2 in
the environment'.  How the environment is represented is of no concern
to this compiler.  Maybe it should, but I try to ignore this issue for
now.

> > ;; - (global SYMBOL)
> > ;;
> > ;;   Retrieve the value of the global variable that is named by SYMBOL
> > ;;   in the current module.  (Current at the time of linking.)
> 
> Are you going to look up global variables at loading time?

Yes.

> If so, you can't do global analysis at compile time, can you?

Not without help from the code that is analysed, no.

I can imagine using declarations to guide the compiler.  For example,
we could have a way to declare certain bindings as being constant:

    (define foo ...)
    (declare foo (constant))

This would allow the compiler to notice that the value of this binding
is not going to change (mostly, see below), and to arrange things so
that the linker can hard-code an efficient way to, say, invoke `foo'
at load time.  This might be quite noticeable with `subrs'.  Or not.

Although such a binding is declared constant, this wouldn't mean that
it doesn't change.  You will not be able to change it programmatically
via `set!', but the user can do so interactively.  The module system
will provide notifications about this to the linker, so that the
hard-coding mentioned above can be redone.

For example, the compiler could notice that `union' constantly refers
to a compiled Scheme procedure and could generate code to invoke it
directly.  The linker will then patch in the real locations of the
actual code and the environment whenever the `union' binding changes.
When it changes to something different from a compiled Scheme
procedure, the linker could patch in trampoline code (and emit a
warning).

The user might also put a declaration that allows the compiler to
inline certain functions.  This means that you can't change the
definition of these functions without recompiling the code that uses
them, of course.  This declaration need not be colocated with the
definition of the functions being inlined.  We might have somthing
like this, for example

    (define-module (bla)
      :use-module (ice-9 core))

    (declare (inline-module (ice-9 core)))

This would allow the compiler to inline all functions defined in the
(ice-9 core) module.  It wont necessarily inline the whole function
but it will very likely generate a specialiced calling sequence that
will be incompatible when the arguments of the `inlined' function
changes.  (If the arguments change incompatably, we can just patch in
a stub that throws an error, tho.)

This would also be the mechanism that allows the compiler to figure
out that `+' really refers to the standard addition procedure, all the
time.

> (But in my current VM, MODULE-NAME is just ignored.)
> 
> > ;; A `functions' form where all `calls' appear in tail positions is
> > ;; semantically equivalent to a `labels' form, but the compiler
> > ;; doesn't detect this.  It still emits code to handle the general
> > ;; case.  You have to help it by explicitely using a `labels' form
> > ;; when possible.  This might change in the future, but right now,
> > ;; `functions' isn't even implemented at all.
> 
> Do you really need the `functions' form?  You distinguish global
> function calls (`invoke') from local function calls (`call'),
> which complicates the system, I think.

I think unknown functions are sufficiently different from known local
functions.  For known local functions, we can have a customized
calling convention, while for unknown functions, we must adhere to a
standard convention.  Incidentally, all stack manipulation, register
allocation, and register spilling is concentrated in the calling
sequences in the guile-lightning compiler.  That is, register
allocation is done by assigning certain arguments of known local
functions to registers.

There might actually be a need for a third kind of known local
functions: ones that are known local, but have no references to free
variables (after closure conversion).  They would be used for known
local functions that are closed over by escaping lambdas.  We want to
have a custom calling convention for them, but we don't know at
compile time in what environment they will execute.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]