LLVM backend for Glulx

Yes, @dettus has done some excellent work in this area. There’s a a thread on it.

1 Like

btw i saw this line " I’ll try to keep updated binaries for Intel Macs on the GitHub page; others are welcome to produce and distribute binaries for other platforms" on the github why not setup a production “pipeline” using something like appveyor, etc.

For the simple reason that I don’t know how to do it. If it’s easy to set up (i.e. I don’t need to do anything other than provide the CMake command) and you can send me a pointer to instructions, I’ll try it out.

If you want to render pictures on the console, you could use libaa, libsixel and the like.
Or have a look at this site here: Character representation of grey scale images

It explains how you can give users the illusion of greyscales by using ASCII characters that have gradually more pixels, called a “ramp”. This is the easiest way to render pictures on a console.
My personal ramp is this one: " .,-=oxOX@$" (note that it starts with a space)

I am rn seeing if i can setup some kind of basic setup

I got pretty close as seen here AppVeyor using this config file glulx-llvm/appveyor.yml at main · jfm535/glulx-llvm · GitHub

Thanks for putting this together! It looks like you’re hitting a 60-minute time limit that AppVeyor imposes, which isn’t surprising - I’ll ask them whether they can raise it for me.

another way besides raising the limit could be building it in parts eg each static lib which is then cached and sent to the next job.

Btw I will admit the moment I saw you basically only providing binaries for osx It spurred me into motion to attempt to fix that “issue”.

does the compiler have support of “va_start” and “va_end”?

Edit:
side note: since we don’t exactly have c++ support it may be possible to use this GitHub - JuliaComputingOSS/llvm-cbe: resurrected LLVM "C Backend", with improvements to convert c++ to c first.

Deadfish - Esolang I am trying to convert this example into at least partial c.

so far I have this

int isglkSupported() {
   int boolval = glk_gestalt(4, 2);
   return boolval;
}
winid_t openbaseWindow() {
   winid_t win = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
   return win;
}
strid_t openbaseWindowAndGetStream() {
   winid_t win = openbaseWindow();
   glk_set_window(win);
   strid_t str = glk_window_get_stream(win);
   return str;
}

I am not sure how to go about converting this part

	; Prompt and get input
	streamstr Prompt
	!pushr $2,Buf,1,0
	glk glk_request_line_event,4,0
1h	push Event
	glk glk_select,1,0
	jne @Etype,glk.evtype_LineInput,1b
	jz @Eval1,0b

The backend does support variadic functions (e.g. I6 uses printf).

If you have C++ you want to compile, give it a try and let me know how it goes - unless you use exceptions or the standard library it might just work.

For your sample above, try something like this (although you might find it easier to start with Zarf’s “model.c”, which has the required Glk event loop but is already in C):

#define GLK_ALLOW_CSTRINGS
#include <clangglk.h>
char *prompt = "> ";
char Buf[1];
...
glk_put_string(prompt);
glk_request_line_event(win, Buf, 1, 0);
event_t ev;
ev.type = evtype_None;
while (ev.type != evtype_LineInput)
    glk_select(&ev);

I’m using glk_put_string here instead of __streamstr (an intrinsic the backend defines to allow direct use of that opcode) so that you can pass in an ordinary C string if you compile with GLK_ALLOW_CSTRINGS defined: otherwise you’d get a VM error since prompt is not prefixed with the proper byte to indicate it is a Glulx string object.

2 Likes

ah so far i haven’t attempted to run any of my experiments I’ve just been testing if its compilable.
btw have my current attempt at a workingish form of printf

mycode.zip (5.9 KB)

its base code comes from here C/developer_tools at master · TheAlgorithms/C · GitHub

Edit:

I may try running the compiler on this test suite llvm-test-suite/SingleSource/UnitTests at main · llvm/llvm-test-suite · GitHub

btw I found an issue with memset I am not sure how it occurs but below is what I observed.

glasm output

callfiii	memset_, inv_comp_perm_, 255, 56, 0

I found it when compiling des.c from https://downloads.uclibc-ng.org/releases/1.0.39/uClibc-ng-1.0.39.tar.xz
I am also including my version of des.c for possible reproducibility.
des.zip (6.7 KB)

most significant change is the addition of

static inline unsigned short int
__bswap_16 (unsigned short int __bsx)
{
  return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
}
static inline unsigned int
__bswap_32 (unsigned int __bsx)
{
  return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |
	  (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24));
}
static inline
uint32_t ntohl (uint32_t x)
{
	return __bswap_32(x);
}
static inline
uint16_t ntohs (uint16_t x)
{
	return __bswap_16(x);
}

to the des.c file so there are no missing functions.
I am also including the output of the compilation

final.zip (7.9 KB)

Not sure what issue you mean, since the glasm output looks fine to me - is it just that you don’t have an implementation of memset? The backend can optimize stores into calls to memset (which can sometimes help even on Glulx, since you may be able to use @mzero), so in general you need to include an implementation. There is one in the libc folder of my repository.

I just learned I forgot to link memset

btw i think an honestly possibly good first complex program test could be seeing if we can embed a lua repl into a program.

The demo in my first post was a 28k-line program… Since maybe it’s annoying for people to get it running, here is a transcript:

Transcript
dfremont@hal9004 play % ./glulxe inform6.ulx 
Welcome to the Cheap Glk Implementation, library version 1.0.4.

The thousand injuries of GN you had suffered in silence; but when he ventured
upon making unary minus have higher precedence than array indexing, you vowed
revenge -- and very unwisely challenged him to a compilation duel. So here you
find yourself, at the end of your rope, having just barely survived your
opponent's last attack; and knowing that if you cannot stump him in the next
round, you will not have the strength to fight on.

Compilation
A not very interactive demo by Daniel Fremont
(with apologies and many thanks to Graham Nelson)
Release 1 / Serial number 211016 / LLVM 13.0.0

Oxford Union
Graham Nelson is here.

>graham, compile advent
Your opponent furrows his brow, and then...

Inform 6.35 for the Glulx VM (22nd May 2021)
In:  8 source code files             13553 syntactic lines
 17686 textual lines                613795 characters (ISO 8859-1 Latin1)
Allocated:
  1927 symbols (maximum 6400)     1292953 bytes of memory
Out:   Glulx story file 9.060321 (229K long):
    15 classes (maximum  64)           277 objects (maximum 512)
   179 global vars (maximum 512)      6299 variable/array space (maximum 10000)
   117 verbs (maximum 140)             794 dictionary entries (maximum 1300)
   240 grammar lines (version 2)       377 grammar tokens (unlimited)
   131 actions (maximum 200)            34 attributes (maximum 56)
    51 common props (maximum 256)       68 individual props (unlimited)
 73124 characters used in text       49074 bytes compressed (rate 0.671)
     0 abbreviations (maximum 64)      694 routines (unlimited)
 21960 instructions of code           7867 sequence points
 58880 bytes writable memory used   175360 bytes read-only memory used
234240 bytes used in machine    1073507584 bytes free in machine
Completed in 6 seconds

Your opponent dispatches your challenge with ease, triumphantly displaying his
compiled 'output.glkdata' file. Your hopes fail, something gives way inside, and
everything goes black.

   *** You have died ***

dfremont@hal9004 play % mv output.glkdata advent.ulx
dfremont@hal9004 play % ./glulxe advent.ulx 
Welcome to the Cheap Glk Implementation, library version 1.0.4.







Welcome to Adventure!
(Please type HELP for instructions and information.)



ADVENTURE
The Interactive Original
By Will Crowther (1976) and Don Woods (1977)
Reconstructed in three steps by:
Donald Ekman, David M. Baggett (1993) and Graham Nelson (1994)
[In memoriam Stephen Bishop (1820?-1857): GN]

Release 9 / Serial number 060321 / Inform v6.35 Library v6.12.5 S

At End Of Road
You are standing at the end of a road before a small brick building. Around you is a forest. A small stream flows out of the building and down a gully.

>

I leave figuring out how to win the duel as an exercise to the reader.

3 Likes

I’ve pushed my implementation of the (decently-large) fragment of the C standard library needed to compile I6. In place of uClibc-ng’s printf I’m using nanoprintf.

This should be enough to let you compile some interesting programs.

3 Likes

FYI, AppVeyor has been progressively increasing my build timeout, so hopefully I’ll be able to make Windows binaries soon. To speed up incremental builds, I’m looking into caching the object files, but this seems a bit tricky: the Ninja build system only looks at timestamps, not file contents, so every time we clone the repository it would think all the code has been changed (and the AppVeyor cache isn’t large enough for us to cache the whole repository rather than cloning it each time). I see some people have used ccache to help with this, but it doesn’t support clang-cl. @jfmherokiller, is there a reason you used clang-cl instead of just plain old cl as suggested in the clang build instructions (section “Using Ninja alongside Visual Studio”)? I can’t test this myself since I don’t have a Windows system.

First is personal prefrence and second was a possibly observed but could be wrong assumption that clang would be able to compile itself faster. (was mostly hoping it would compile faster) you can go back to cl if needed.