Day 1. Assembly code is being generated, on a monkey see, monkey do basis;

but it doesn't link because of a missing library; and having moved source
files around the Makefile currently doesn't work.
This commit is contained in:
Simon Brooke 2026-04-06 09:48:44 +01:00
parent 8e9ad73229
commit 882f991db4
13 changed files with 206 additions and 36 deletions

3
.gitignore vendored
View file

@ -57,3 +57,6 @@ dkms.conf
.project .project
.settings/ .settings/
build/ build/
# Munit
src/munit.*

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "munit"]
path = munit
url = https://github.com/nemequ/munit.git

View file

@ -15,7 +15,7 @@ else
$(error Build mode $(BUILD_MODE) not supported by this Makefile) $(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif endif
SRC_DIR=$(PROJECT_ROOT)/src SRC_DIR=$(PROJECT_ROOT)/src/c
all: grendel all: grendel

View file

@ -36,11 +36,11 @@ Tags will be allocated as follows:
| 3-bit value | 7-bit value | (Hex) | Interpretation | | 3-bit value | 7-bit value | (Hex) | Interpretation |
| ----------- | ----------- | ----- | ------------------------------------------------------------ | | ----------- | ----------- | ----- | ------------------------------------------------------------ |
| 0 | 0 | 0x0 | a pointer; an offset into the vector of words. | | 0 | 0 | 0x0 | an error object, whose payload is a 3 character error code. |
| 1 | 1 | 0x1 | a signed 28 bit integer. | | 1 | 1 | 0x1 | a pointer; an offset into the vector of words. |
| 2 | 2 | 0x2 | a character; possibly just a byte, or possibly a 16 bit wchar. | | 2 | 2 | 0x2 | a signed 28 bit integer. |
| 3 | 3 | 0x3 | unassigned (possibly a floating point number, later.) | | 3 | 3 | 0x3 | a character; possibly just a byte, or possibly a 16 bit wchar. |
| 4 | 4 | 0x4 | unassigned | | 4 | 4 | 0x4 | unassigned (possibly a floating point number, later.) |
| 5 | 5 | 0x5 | unassigned | | 5 | 5 | 0x5 | unassigned |
| 6 | 6 | 0x6 | unassigned | | 6 | 6 | 0x6 | unassigned |
| 7 | 7 | 0x7 | a cons cell | | 7 | 7 | 0x7 | a cons cell |

1
munit Submodule

@ -0,0 +1 @@
Subproject commit fbbdf1467eb0d04a6ee465def2e529e4c87f2118

26
src/c/day1.c Normal file
View file

@ -0,0 +1,26 @@
/**
* day1.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* Day 1 of work towards a compiler... eventually..
*
* This is a straight copy of Noah Zentzis' work. There's no original work of
* mine here, yet
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
__attribute__((__cdecl__))
extern int lisp_entry();
int main(int argc, const char **argv) {
int val = lisp_entry();
printf("%d\n", val);
return 0;
}

29
src/c/error.c Normal file
View file

@ -0,0 +1,29 @@
/**
* error.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* The error handling subsystem.
*
* Error codes are detailed in section 6.3, page 32, of the
* Lisp 1.5 Programmer's Manual. I shall in so far as possible follow
* those codes.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "error.h"
#include "memory.h"
uint32_t make_error( char* code) {
uint32_t error = 0;
strncpy( (char *)((&error) &1), code, 3);
return error;
}

45
src/c/error.h Normal file
View file

@ -0,0 +1,45 @@
/**
* error.h
*
* Grendel: a compiling Beowulf reimplementation.
*
* The error handling subsystem.
*
* Error codes are detailed in section 6.3, page 32, of the
* Lisp 1.5 Programmer's Manual. I shall in so far as possible follow
* those codes.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __grendel_error_h
#define __grendel_error_h
#include <stdint.h>
uint32_t make_error( char* code);
/**
* @brief error codes
*
* Error codes are detailed in section 6.3, page 32, of the
* Lisp 1.5 Programmer's Manual. I shall in so far as possible follow
* those codes.
*
* Error codes comprise a one or two alphabetic character category, followed
* by a single digit number. A space is shown in the manual between the
* category and the number, but I have not followed that here for reasons.
*/
#define APPLIED_FUNCTION_CALLED_ERROR (make_error( "A1"))
#define UNDEFINED_FUNCTION_APPLY_ERROR (make_error( "A2"))
#define COND_UNSATISFIED_ERROR (make_error( "A3"))
#define SETQ_ON_NONEXISTANT_VAR_ERROR (make_error( "A4"))
#define SET_ON_NONEXISTANT_VAR_ERROR (make_error( "A5"))
#define NO_TARGET_FOR_GO_ERROR (make_error( "A6"))
#define TOO_MANY_ARGUMENTS_ERROR (make_error( "A7"))
#define UNBOUND_VARIABLE_ERROR (make_error( "A8"))
#define UNDEFINED_FUNCTION_EVAL_ERROR (make_error( "A9"))
#endif

View file

@ -15,6 +15,11 @@
#include <stdint.h> #include <stdint.h>
#include "memory.h" #include "memory.h"
#include "version.h"
__attribute__((__cdecl__))
extern int lisp_entry();
void showbits( unsigned int x ) void showbits( unsigned int x )
{ {
@ -28,18 +33,12 @@ void showbits( unsigned int x )
int main(int argc, char **argv) { int main(int argc, char **argv) {
printf( "Grendel:\n"); printf( "Grendel, a compiler for Beowulf: version %s\n", VERSION);
int i;
for ( i = 0; i < 8; i++) {
printf( "\ti = %d (%b, 0x%x);\n", i, i, i);
}
for ( ; i < 128; i++) {
if ((i & TAG32MASK) == TAG32MASK) {
printf( "\ti = %d (%b, 0x%x);\n", i, i, i);
}
}
int val = lisp_entry();
printf("%d\n", val);
return 0;
}
return 0; return 0;
} }

19
src/c/lisp.c Normal file
View file

@ -0,0 +1,19 @@
/**
* lisp.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* The compiler... eventually..
*
* Error codes are detailed in section 6.3, page 32, of the
* Lisp 1.5 Programmer's Manual. I shall in so far as possible follow
* those codes.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>

View file

@ -16,28 +16,28 @@
/* Tags for 32 bit objects, with 3 bits of tag an one mark bit */ /* Tags for 32 bit objects, with 3 bits of tag an one mark bit */
#define ERRORTV (0)
/** /**
* @brief This pointer object is an actual pointer -- an offset into consspace. * @brief This pointer object is an actual pointer -- an offset into consspace.
*/ */
#define OFFSETTV (0) #define OFFSETTV (1)
/** /**
* @brief This pointer object is actually a 28 bit integer value. * @brief This pointer object is actually a 28 bit integer value.
*/ */
#define INTEGERTV (1) #define INTEGERTV (2)
/** /**
* @brief A character; initially just a byte. but potentially a 16 bit wchar. * @brief A character; initially just a byte. but potentially a 16 bit wchar.
*/ */
#define CHARTV (2) #define CHARTV (3)
/** /**
* @brief A 16 bit floating point number. (future expansion) * @brief A 16 bit floating point number. (future expansion)
* *
* Yes, it could be 28 bit, but I think that would hurt my brain. * Yes, it could be 28 bit, but I think that would hurt my brain.
*/ */
#define FLOATTV (3) #define FLOATTV (4)
/* /*
* Values 4..6 inclusive reserved further data types, including maybe * Values 5 and 6 are available for further 32 bit data types.
* implementing reals later.
*/ */
/** /**
@ -87,12 +87,12 @@
#define FREETV (0x7f) #define FREETV (0x7f)
#define MARKMASK ((unsigned int)1) #define MARKMASK ((uint64_t)1)
#define TAG32MASK ((unsigned int)7) #define TAG32MASK ((uint64_t)7)
#define TAG64MASK ((unsigned int)0xf) #define TAG64MASK ((uint64_t)0xf)
#define MASK64 (0xffffffffffffffff) #define MASK64 ((uint64_t)0xffffffffffffffff)
#define MASK32 (0xffffffff) #define MASK32 ((uint64_t)0xffffffff)
/** /**
* @brief Return the mark bit of this object. * @brief Return the mark bit of this object.

15
src/c/version.h Normal file
View file

@ -0,0 +1,15 @@
/**
* version.h
*
* Grendel: a compiling Beowulf reimplementation.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __grendel_version_h
#define __grendel_version_h
#define VERSIOM "Aelfhere"
#ifndef

30
src/guile/day1.scm Normal file
View file

@ -0,0 +1,30 @@
(define emit (lambda args (apply simple-format #t args)
(newline)))
(define (compile-program program)
(emit ".text")
(emit ".p2align 4,,15")
(emit ".globl lisp_entry")
(emit "lisp_entry:")
; handle incoming call from C
(emit "push %esi")
(emit "push %edi")
(emit "push %edx")
; our code goes here
(emit "movl $42, %eax")
; restore state for return to C
(emit "pop %edx")
(emit "pop %edi")
(emit "pop %esi")
(emit "ret"))
(define (compile-to-binary program)
(begin
(with-output-to-file "/tmp/compiled.s"
(lambda () (compile-program program)))
(system "gcc -fomit-frame-pointer -m32 /tmp/compiled.s src/c/day1.c")))