Hugs is a neat system, but the very idea of compiling from source code each time you run a program makes Hugs unsuited for many purposes. So my question is, has anyone tried to rearrange the components of Hugs into a bytecode compiler plus runtime? And if not, maybe the Hugs maintainers had a word of advice on how to go about this? There is nch98, of course, but it is somewhat bulky for the purposes I have in mind. I am looking for something small that would compile to 16-bit code that would run in 64K code + 64K data. The raw material for such a system is probably present in Hugs, but what's the best way to extract it with a minimum of fuss? Grateful for any hint. -- Tore
There is nhc98, of course, but it is somewhat bulky for the purposes I have in mind. I am looking for something small that would compile to 16-bit code that would run in 64K code + 64K data.
It's a shame that nhc98 doesn't fit your requirements, since it is specifically designed for creating small-memory-footprint programs. But as far as I know, Hugs is the only Haskell system that can produce 16-bit code.
So my question is, has anyone tried to rearrange the components of Hugs into a bytecode compiler plus runtime?
The predecessor of Hugs was Gofer, which was supplied with a variant called Gofcc that produced standalone bytecodes, just as you desire. Gofer was very like Haskell 1.2. It is still available by FTP: http://www.cse.ogi.edu/~mpj/goferarc/index.html Many years ago for my PhD work, I modified Gofer/Gofcc to create standalone programs to run on an embedded system. The resulting a.out program had to be encoded into S-records and downloaded to the board via a serial cable. Back then, I was targeting a 32-bit processor (M68000), but Gofer was equally capable of producing 16-bit code. As I recall, my most complex example (a liftshaft control program, attached to a real physical liftshaft made of mecchano) probably needed around 250Kb of memory in total (code + heap + stack), although the board was fitted with a generous 768Kb. My modified version of Gofer/Gofcc is available here: ftp://ftp.cs.york.ac.uk/pub/malcolm/goferp.tar.Z It includes several other features that might be of use to you if you are writing embedded systems: a realtime garbage collector, concurrent processes, device control and interrupts, and a heap-profiler (producer/construction/retainer variants) to help you minimise your runtime space usage. Some papers describing the various features are available from my homepage: http://www-users.cs.york.ac.uk/~malcolm/ Regards, Malcolm
Malcolm Wallace wrote:
There is nhc98, of course, but it is somewhat bulky for the purposes I have in mind. I am looking for something small that would compile to 16-bit code that would run in 64K code + 64K data.
It's a shame that nhc98 doesn't fit your requirements, since it is specifically designed for creating small-memory-footprint programs. But as far as I know, Hugs is the only Haskell system that can produce 16-bit code.
Thanks for your info. Do you know roughly how small nhc98 can get? Even if a 16-bit system is impossible, having a small 32-bit Haskell could be of interest in other connections. And is it absolutely impossible to make a 16-bit nch98? After all, the compiler could remain 32-bit - it's just the bytecode interpreter that would have to be 16-bit. A rudimentary system might suffice as long as there is a good FFI. And a somewhat unrelated question: is nhc98 going to have native code generation in the foreseeable future? -- Tore
Do you know roughly how small nhc98 can get? Even if a 16-bit system is impossible, having a small 32-bit Haskell could be of interest in other connections.
The executable for a "hello world" type program currently comes out at about 115kb code size when compiled with nhc98. We have done some tests on manually stripping the excess dead weight from that (by removing class overloading, simplifying the error-handling, cutting out big Integers, etc. etc.), and ended up with a 45kb executable. Most of that is the bytecode interpreter itself, so it can't be reduced much further - although we did once toy with the idea of automatically removing code from the interpreter for individual bytecodes that were discovered not to be used in a particular program... :-) For runtime memory usage, nhc98 uses a default 20kb stack, and a default 400kb heap, but both of these are configurable. (There are some other small static tables, of typically 1-2kb each.) The absolute minimum heap size possible is 2512 bytes - and I have some non-trivial programs that run happily in that tiny heap (including one that runs for over 60 seconds and writes a complex 44Mb output file!).
And is it absolutely impossible to make a 16-bit nch98? After all, the compiler could remain 32-bit - it's just the bytecode interpreter that would have to be 16-bit. A rudimentary system might suffice as long as there is a good FFI.
It should be quite possible, yes. At a guess, the main change needed is to adjust some hard-coded constants to determine the size of ints, addresses, and alignment boundaries. Provided you have a C cross-compiler for the 16-bit machine, that should be all you need. (As a bonus on a 16-bit system, the bytecode files nhc98 generates will become somewhat smaller due to the size reduction of in-lined address labels.)
And a somewhat unrelated question: is nhc98 going to have native code generation in the foreseeable future?
Not in the immediate future, unless some eager Haskell developer or student decides they would like to take it on as a project. I know there are several people who would be keen to see a native backend for nhc98 (including myself), but no-one has yet found sufficient time to devote to it. Regards, Malcolm
Malcolm Wallace wrote:
Do you know roughly how small nhc98 can get? Even if a 16-bit system is impossible, having a small 32-bit Haskell could be of interest in other connections.
The executable for a "hello world" type program currently comes out at about 115kb code size when compiled with nhc98. We have done some tests on manually stripping the excess dead weight from that (by removing class overloading, simplifying the error-handling, cutting out big Integers, etc. etc.), and ended up with a 45kb executable.
Okay. Now, if those 45K consist of e.g. 40K code (or "text") and 5K data, this leaves us with 24K free in the code segement and 59K minus heap/stack in the data segment. That should be abundant for a small system. In fact, if bytecode is kept in the data segment - which I suppose it is - one would not have to pare down the code ("text") that much.
Provided you have a C cross-compiler for the 16-bit machine, that should be all you need.
Well, I don't, so I suppose I would have to use a 16-bit compiler. And this probably means having to change a good deal of Unix-specific stuff. This is the sort of thing one would also have to do for a Win32 port, so it's not a bad form of exercise at all. But it would probably take a good deal of effort. In short, I don't think I have the time or inclination at the moment to get into nhc98 internals. So if you are able to lend me makefiles for that 45K version and/or give some advice on which files to exclude, where to place #ifdefs etc., then I *might* try to make a 16-bit nhc98. Otherwise, I shall have to look elsewhere. Regards, -- Tore
participants (2)
-
Malcolm Wallace -
Tore Lund