Re: initial lang spec: SXIL...
- From: "cr88192" <cr88192@xxxxxxxxxxx>
- Date: Fri, 6 Mar 2009 10:28:30 +1000
"Rod Pemberton" <do_not_have@xxxxxxxxxxxxx> wrote in message
news:gophn7$quv$1@xxxxxxxxxxx
"cr88192" <cr88192@xxxxxxxxxxx> wrote in message
news:gon257$u1q$1@xxxxxxxxxxxxxxxxxxxx
IP
wont work, because BeginTry and EndTry were actually used to capture the
ranges and possible return state. the first time they are run, they set
up
the state, but later than this could become theoretically no-op...
Shouldn't some of that functionality be moved into the exception
handler...
?
And, can the initialization be done on application startup... ?
it could, with compiler support...
if one is using good ol' gcc as-is, they are fairly limited as to what can
be done at startup, and more often have to result to runtime initialization
of features...
if one could safely have pointers to labels, especially between functions,
then this case would be less of a problem, but I don't know of any compiler
which does this (nor of a way in which a compiler could make this safely
usable).
so, the general issue is:
for efficient exception handling, support needs to be built into the
compiler in question (or, at least, one needs some fairly powerful
control-flow constructs and/or macro facilities, which C doesn't have
either...).
I also want to be able to use whatever exception handling mechanism with
whatever code I compile with gcc as well...
(sadly, there seems to be no common ABI for exception handling on x86,
and
infact numerous conflicting strategies in use...).
What model comes closest to your needs?
SEH...
but, of course, natively using SEH requires compiler support.
I have since implemented a basic unwinding mechanism, for which the
internals are based on SEH (primarily written in assembler). it basically
throws a fixed exception code in my case, and generic handlers are used.
for the Linux case, it is modified some (TLS is used instead, and there is
no generic handler).
x86-64 is not handled at present...
of course, as-is, it is still based on begin/end pairs...
likewise, due to past experience, I have generally learned to be veryproducing
careful when incorporating other's code, as most other people like
big tangled messes of code that tend to fall apart if not handled with
extreme care (has happened a few times IME...), where I like code I can
fairly easily rip apart and reorganize...
I agree. But, we are limited by time...
time is not as much an issue in my case, if anything, because there is not
much point in all my efforts...
as for SXIL, the primary reasons are this:
I will have control over the implementation;
That's always good.
the design is relatively little work to implement with my existingcodebase
Very good reason, IMO.
I personally have experience with, and some nostalgia for, Scheme;
From Wikipedia - since I've no experience with Scheme, it seems Scheme (or
Lisp) has solved the operator precedence problem. For many years, C
programmers have away from operator precedence and have moved towards
using
parenthesis to override or force operation order. A combination of a few
ideas, like transforming an operator precedence language like C to
parenthesized notation like Scheme, infix notation to RPN like FORTH,
multi-operand parameters to 0-operand like FORTH, and context-free-grammar
to NPDA (an FSM), might turn out well. It seems that they are all
implementable using stacks, and some other minor logic... I also ran
across
something useful on Wikipedia for string parsing: Cocke-Younger-Kasami
algorithm.
I have a full-fledged parser in my case...
but, the reason this stage is needed, is that I have found that directly
targeting RPN (and having this take a fairly direct path to the generated
machine code) is just too inflexible in the case of internal architectural
issues (it works fine for x86, but doesn't hold up as well in the x86-64
case).
so, going to S-Exps allows keeping most of the codegen machinery intact, but
leaving more freedom to reorganize things in target-specific ways, and
likewise deal with some of the more "high-level" issues.
in this way, the RPN stage can have its level of abstraction lowered,
becomming more of a straight codegen (likewise, I will no longer be required
to more or less force everything into an RPN-based model, but may be freer
to adopt a looser, more ASM-like approach).
the alternative would be making the language-specific frontends output a
target-specialized IL, which is not desirable (even with RPNIL, this was an
issue, as RPNIL has more than a few "x86-isms", such as requiring args to be
given in right-to-left order, ...).
of course, CIL and JBC will remain as RPN, but the idea in this case is that
they would be "unwound" into S-Exps, and then passed to SXIL, and
re-flattened as RPN (in the JBC-case, this will require regenerating a lot
of info which is not present in the class files, such as the types of local
variables, ...).
the reason for this is, partly, that JBC and CIL don't fit onto the model
used by the low-level codegen (differing in terms of evaluation order,
argument order, ...), and it didn't look like there was a good way to
resolve this apart from creating a new set of calling conventions, ...
I personally have experience with, and some nostalgia for, Scheme;
Ah, your first love always dies hard...
It took many years, and a language review, before I realized that my fond
memories about the strength of BASIC were misplaced. It was more a
representation of my strength or skill than the language's. Although,
BASIC
does have a few useful language constructs for string processing which are
still useful. In fact, I implemented a left$, right$, mid$ for another
language that was lacking in string processing functionality.
Unfortunately, native language syntax for concatentation wasn't available.
For C, I usually just put up with the slightly extra work of using C's
string functions since they are more compatible with each other than with
an
implementation of left$, right$, mid$.
yeah.
I started with BASIC as well, but stopped using it long ago...
but, Scheme (and Lisp in general) have some fairly useful features.
now, as is, I have already implemented much of Scheme in C, apart from those
constructions which just don't map so well...
this is partly what makes SXIL easy to implement, since most of the basic
machinery was already there...
(the parser, typesystem, ... were already at hand).
the main thing though was that the core interpreter was written clean, as it
is a style I have not used in a long time (due to its low performance and
high garbage production). note that I could have used a bytecoded
interpreter easily enough, but this would have been at the cost of the
expressiveness of the macro system.
I don't expect anyone else to use it as such, but hell, it is an IL, and
most ILs tend to be project-specific anyways...
What about LLVM? (Which I forgot to mention...) Isn't it supposed to be
both language and architecture neutral?
my issues with LLVM:
it is a good deal lower-level and I would have to produce SSA to make it
work;
the way in which the "bottom-levels" of LLVM work are not really compatible
with my project (at the level of the assembler and linker), and shows a
general disregard for things I felt were fairly important (being able to
dynamically relink running code, ...), and is slow to address these
problems;
it is "teh large" and written in C++ (C would be vastly preferable);
they take the "one true supercomponent does everything" stance/mindset,
which I dislike (my approach is far more modular and decentralized);
....
now, in terms of LLVM's IL, that is decent enough, just I don't like their
implementation...
(actually, I can say the same of Mono, but my complaints about Mono's
internals are a good deal different, well, that and my inability to get it
built on Windows thus far...).
now, the great problem when it comes to exceptions, is I can't think of a
good way to structure an API for this within the confines of C...
I don't have a solution for you. C is just weak here. The majority of C
is
implemented as single threaded code and typically uses a stack to handle
parameters and control flow information (a "call stack" as Wikipedia calls
it...). Anything that bypasses this method of implementation is going to
cause some issues. setjmp(), longjmp(), raise(), signal(), exec(),
system(), and exit() are the functions that come to mind that bypass this
normal control flow within C. FWIW, two Wikipedia entries "Exception
handling syntax" and "Comparison of programming languages (basic
instructions)" pages shows how try-throw-catch could be implemented in C
using setjmp and longjmp (and for other languages too). For C, use of
setjmp and longjmp is less than optimal since they have many side effects
like 1) requiring volatile on automatic variables in the local procedure
2)
may cause loss of modified values in local procedure upon use 3)
non-portable, but more portable than signal and raise 4) tends to be
implemented on x86 by saving all registers to the jump buffer which is
slow
5) may not work in interrupt or exception handlers for pre-ANSI C.
yep...
my hack for implementing exceptions thus far has been to build an unwind
mechanism which internally works similar to setjmp/longjmp...
namely, the current form (actually, the main machinery is located in my
linker machinery, as are a few other related parts) has a few calls:
void *BASM_StartUnwind(BASM_JmpBuf *ctx);
does something similar to a setjmp, and links the handler into SEH.
actually, more correctly, it sets it up with SEH, and tail-calls into a
custom setjmp...
when it returns NULL, we know it is a normal call (not a return).
void BASM_EndUnwind(BASM_JmpBuf *ctx);
unregisters handler...
void BASM_DoUnwind(void *val);
technically, throws an exception via SEH (currently, via the Win32 API
related calls).
presumably, control will then come back out of the last StartUnwind,
however, it will return a pointer to the associated BASM_JmpBuf rather than
the value (however, info from SEH and similar is stuffed into the context,
which can be retrieved).
a slight optimization would be to bypass the Win32 API calls when it can be
determined that there are no "proper" SEH handlers waiting (since the SEH
crap is hairy...). in this case, it would be similar to initiating a
longjmp...
the idea then is that the frontend excpetion API (likely located in DYLL,
not BASM), will wrap these calls and provide more generic exception-handling
stuff.
dynamically compiled code could either use this API, or I could implement
IP-range based handlers instead...
performance should be acceptable so long as no one decides to use exceptions
as an alternative to loops or similar (registering and unregistering should
be cheap enough, only that throwing is not so likely to be cheap...).
Rod Pemberton
.
- References:
- initial lang spec: SXIL...
- From: cr88192
- Re: initial lang spec: SXIL...
- From: Bartc
- Re: initial lang spec: SXIL...
- From: cr88192
- Re: initial lang spec: SXIL...
- From: Harold Aptroot
- Re: initial lang spec: SXIL...
- From: cr88192
- Re: initial lang spec: SXIL...
- From: Rod Pemberton
- Re: initial lang spec: SXIL...
- From: cr88192
- Re: initial lang spec: SXIL...
- From: Rod Pemberton
- initial lang spec: SXIL...
- Prev by Date: Re: initial lang spec: SXIL...
- Next by Date: Re: What's lacking: a good intermediate form
- Previous by thread: Re: initial lang spec: SXIL...
- Next by thread: Re: What's lacking: a good intermediate form
- Index(es):