From: BGB / cr88192 on 27 Feb 2010 11:47
well, basically I have hacked on a few more extensions to the macro
facilities for my assembler.
sadly, I don't really know what actually "good" ASM macro systems do (mine
is, essentially, just a hacked-over C preprocessor...).
note that the primary usage of my assembler is as a library for use within a
(mostly) C app for dynamic code generation (typically JIT and dynamic thunk
writing...). the reason I might want to use macros to gloss over arch issues
is that, as is, I am ending up with lots of special-purpose code-writers
which need to be tweaked for each target, and reducing the needed level of
tweaking could be convinient...
note: my project already has a few HLL's and IL's, so I had meant "another
one for this purpose".
the main limitation is that to be useful for my purposes, the overall
performance overhead (of compilation/assembly) has to be kept fairly low
(invoking my C compiler is far too slow...), and it is also needed to be
able to retain the level of control ASM offers for many of these thunks to
work (many do fairly low-level/specialized tasks, often outside the reach of
well, text is from a few emails:
well, here is another idle thought...
after wandering around some, thinking and reading stuff, I was reminded some
of MASM, TASM, and HLA...
so, what these languages did was basically to add some HLL-like features to
ASM essentially as part of a preprocessing step...
similarly, I had wanted some ways to abstract over some of the OS/arch
specific issues, without having to invest in the overhead and limitations of
a full HLL or IL, but how to do this without issue was itself a problem
(resulting in several started but failed ideas).
then I thought about this, and my assembler already has a preprocessor...
so, I have a preprocessor, and it does some basic macro-processing stuff.
this is lame, granted...
however, it is currently limited in that, at present, if I were to do an
"#include", it would actually access a file, which is not always desirable.
so, I am left with the idle thought that I could add a few API calls so that
I could submit "assembly headers" in addition to assembly modules, which
would reside in easy reach of the assembler's preprocessor, yet remain in
this way, I can declare globs of ASM macros, and then include them much as I
would C headers, allowing to some extent "extending" the capabilities of the
assembler, and abstracting over some things, without introducing an actually
new layer of abstraction.
granted, all this could require adding a few new capabilities to the
preprocessor, such as, for example, requesting the preprocessor to evaluate
expressions, introducing nested scoping, possibly looping or recursion, ...
admitted, a partial hack could be to use recursive inclusion (and some added
pp-directives) to simulate looping and nestable scope.
more thought is needed.
so, I went and added a few features to the preprocessor for my assembler:
"virtual headers", or the feature described before;
scoping-levels and "local defines";
multi-line macros can contain expansion-time directives;
for example, it would now be possible to declare a macro like:
##include <foo> //becomes pp-directive post-expand
//note: ##include "foo" //will not work, as "foo" looks like a string
#define gensym_state 0
##assign gensym_state (gensym_state+1)
##assignlocal loop_start gensym()
more so, recursive macros, macros which produce macros, ... are also
possible (because "###foo" and "####foo" also work, each macro-level eating
off one "#" until it becomes a directive).
note: "#define" and "#assign" are similar (both will replace a prior
binding), however, "#define" is lazy (its payload is not expanded until the
point of use), whereas "#assign" will attempt to expand/evaluate at the
point of declaration (sort of like "#if"), essentially allowing state
capture and usable mutable state.
note: this is actually essentially just a hacked-over C preprocessor, and
most internal changes were fairly minor (so, potentially
bizarre/counter-intuitive expansion semantics remain...). however, some of
these changes make the preprocessor no longer conformant with the C
standard, but I don't care since this one is being used for ASM...
now, if and how all this can be usable, I am not really sure...
if and how this can gloss over x86 vs x86-64 differences, I don't know...
an idle thought here is that it "could" be possible to make it possible to
also register user callbacks into the preprocessor, such that some macros
could also be implemented in C land (but then I would have to provide some
sort of API into the preprocessor internals, ... which would be ugly...).