mescc: Refactor mlibc compilation.

* libc/libc-mes.c: New file.  Contents from module/mes/libc.mes, module/mes/libc-i386.mes.
* libc/libc-gcc.c: Rename from libc/mlibc.c, include libc/mstart.c
* libc/mstart.c: Remove.
* module/mes/libc-i386.mes: Remove.
* module/mes/libc-i386.scm: Remove.
* module/mes/libc.mes: Remove.
* module/mes/libc.scm: Remove.
* GNUmakefile (CFLAGS): Include libc-gcc.c (WAS: mlibc.c).
* make/bin-mlibc.make (C_FLAGS): Remove start.c include.
* make/mescc-guile.make: Rewrite using compile, link.
* make/mescc-mes.make: Likewise.
* scaffold/m.c: Update.
This commit is contained in:
Jan Nieuwenhuizen 2017-05-21 22:25:02 +02:00
parent 2027754a59
commit 3c880bbb56
21 changed files with 635 additions and 756 deletions

View file

@ -1,11 +1,12 @@
SHELL:=bash
export SHELL
.export: SHELL
QUIET:=@
default: all
MES_DEBUG:=1
CFLAGS:=--std=gnu99 -O0 -g --include mlibc.c
CFLAGS:=--std=gnu99 -O0 -g --include libc-gcc.c
OUT:=out
SUBDIRS:=\

View file

@ -24,9 +24,11 @@ int g_stdin = 0;
#include <stdio.h>
#include <mlibc.h>
#if __GNUC__ && !POSIX
#if __GNUC__
#include <stdlib.h>
#endif
#if __GNUC__ && !POSIX
void
exit (int code)
@ -503,3 +505,39 @@ fdungetc (int c, int fd)
}
#endif // POSIX
#if __GNUC__ && !POSIX
void
_start ()
{
// char **;
asm (
"mov %%ebp,%%eax\n\t"
"addl $4,%%eax\n\t"
"movzbl (%%eax),%%eax\n\t"
"addl $3,%%eax\n\t"
"shl $2,%%eax\n\t"
"add %%ebp,%%eax\n\t"
"movl %%eax,%0\n\t"
: "=g_environment" (g_environment)
: //no inputs ""
);
int r;
asm (
"mov %%ebp,%%eax\n\t"
"addl $8,%%eax\n\t"
"push %%eax\n\t"
"mov %%ebp,%%eax\n\t"
"addl $4,%%eax\n\t"
"movzbl (%%eax),%%eax\n\t"
"push %%eax\n\t"
"call main\n\t"
"movl %%eax,%0\n\t"
: "=r" (r)
: //no inputs ""
);
exit (r);
}
#endif // __GNUC__ && !POSIX

387
libc/libc-mes.c Normal file
View file

@ -0,0 +1,387 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
int g_stdin = 0;
void
exit ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0xb8 0x01 0x00 0x00 0x00"); // mov $0x1,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
read ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0x8b 0x4d 0x0c"); // mov 0xc(%ebp),%ecx
asm (".byte 0x8b 0x55 0x10"); // mov 0x10(%ebp),%edx
asm (".byte 0xb8 0x03 0x00 0x00 0x00"); // mov $0x3,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
write ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0x8b 0x4d 0x0c"); // mov 0xc(%ebp),%ecx
asm (".byte 0x8b 0x55 0x10"); // mov 0x10(%ebp),%edx
asm (".byte 0xb8 0x04 0x00 0x00 0x00"); // mov $0x4,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
open ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0x8b 0x4d 0x0c"); // mov 0xc(%ebp),%ecx
asm (".byte 0x8b 0x55 0x10"); // mov 0x10(%ebp),%edx
asm (".byte 0xb8 0x05 0x00 0x00 0x00"); // mov $0x5,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
access ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0x8b 0x4d 0x0c"); // mov 0xc(%ebp),%ecx
asm (".byte 0xb8 0x21 0x00 0x00 0x00"); // mov $0x21,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
brk ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0xb8 0x2d 0x00 0x00 0x00"); // mov $0x2d,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
fsync ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0xb8 0x76 0x00 0x00 0x00"); // mov $0x76,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
int
strlen (char const* s)
{
int i = 0;
while (s[i]) i++;
return i;
}
int
eputs (char const* s)
{
int i = strlen (s);
write (2, s, i);
return 0;
}
int
fputs (char const* s, int fd)
{
int i = strlen (s);
write (fd, s, i);
return 0;
}
int
puts (char const* s)
{
int i = strlen (s);
write (1, s, i);
return 0;
}
int
putchar (int c)
{
write (1, (char*)&c, 1);
return 0;
}
int
fputc (int c, int fd)
{
write (fd, (char*)&c, 1);
return 0;
}
void
assert_fail (char* s)
{
eputs ("assert fail: ");
eputs (s);
eputs ("\n");
//*((int*)0) = 0;
char *fail = s;
fail = 0;
*fail = 0;
}
int ungetc_char = -1;
char ungetc_buf[2];
int
getchar ()
{
char c;
int i;
if (ungetc_char == -1)
{
int r = read (g_stdin, &c, 1);
if (r < 1) return -1;
i = c;
}
else
{
//FIXME
//i = ungetc_buf[ungetc_char--];
i = ungetc_buf[ungetc_char];
//ungetc_char--;
ungetc_char = ungetc_char - 1;
}
if (i < 0) i += 256;
return i;
}
//#define assert(x) ((x) ? (void)0 : assert_fail (#x))
int
ungetc (int c, int fd)
{
//FIXME
//assert (ungetc_char < 2);
//assert (ungetc_char == -1 || ungetc_char < 2);
//FIXME
//ungetc_buf[++ungetc_char] = c;
ungetc_char++;
ungetc_buf[ungetc_char] = c;
return c;
}
int
strcmp (char const* a, char const* b)
{
while (*a && *b && *a == *b)
{
a++;b++;
}
return *a - *b;
}
char *
strcpy (char *dest, char const *src)
{
char *p = dest;
while (*src) *p++ = *src++;
*p = 0;
return dest;
}
char itoa_buf[10];
char const*
itoa (int x)
{
//static char itoa_buf[10];
//char *p = buf+9;
char *p = itoa_buf;
p += 9;
*p-- = 0;
//int sign = x < 0; // FIXME
int sign = 0;
if (x < 0) sign = 1;
if (sign)
x = -x;
do
{
*p-- = '0' + (x % 10);
x = x / 10;
} while (x);
if (sign && *(p + 1) != '0')
*p-- = '-';
return p+1;
}
int
isdigit (char c)
{
//return (c>='0') && (c<='9');
if (c>='0' && c<='9') return 1;
return 0;
}
int
atoi (char const *s)
{
int i = 0;
int sign = 1;
if (*s && *s == '-')
{
sign = -1;
s++;
}
while (isdigit (*s))
{
i *= 10;
i += (*s - '0');
s++;
}
return i * sign;
}
//void *g_malloc_base = 0;
char *g_malloc_base = 0;
//void *
int *
malloc (int size)
{
//void *p = brk (0);
char *p = 0;
p = brk (0);
if (!g_malloc_base) g_malloc_base = p;
brk (p+size);
return p;
}
//void *
int *
//realloc (void *p, int size)
realloc (int *p, int size)
{
brk (g_malloc_base + size);
return g_malloc_base;
}
int
strncmp (char const* a, char const* b, int length)
{
while (*a && *b && *a == *b && --length) {a++;b++;}
return *a - *b;
}
char **g_environment;
char const*
getenv (char const* s)
{
char **p = g_environment;
p = *g_environment;
int length = strlen (s);
while (*p)
{
if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
p++;
}
return 0;
}
#if 0
// !__MESC__
// FIXME: mes+nyacc parser bug here
// works fine with Guile, but let's keep a single input source
#define pop_va_arg \
asm (".byte 0x8b 0x45 0xfc"); /* mov -<0x4>(%ebp),%eax :va_arg */ \
asm (".byte 0xc1 0xe0 0x02"); /* shl $0x2,%eax */ \
asm (".byte 0x01 0xe8"); /* add %ebp,%eax */ \
asm (".byte 0x83 0xc0 0x0c"); /* add $0xc,%eax */ \
asm (".byte 0x8b 0x00"); /* mov (%eax),%eax */ \
asm (".byte 0x89 0x45 0xf8"); /* mov %eax,-0x8(%ebp) :va */ \
asm (".byte 0x50") /* push %eax */
#else // __MESC__
#define pop_va_arg asm (".byte 0x8b 0x45 0xfc 0xc1 0xe0 0x02 0x01 0xe8 0x83 0xc0 0x0c 0x8b 0x00 0x89 0x45 0xf8 0x50")
#endif
int
printf (char const* format, int va_args)
{
int va_arg = 0;
int va;
char *p = format;
while (*p)
if (*p != '%')
putchar (*p++);
else
{
p++;
char c = *p;
switch (c)
{
case '%': {putchar (*p); break;}
case 'c': {pop_va_arg; putchar ((char)va); va_arg++; break;}
case 'd': {pop_va_arg; puts (itoa (va)); va_arg++; break;}
case 's': {pop_va_arg; puts ((char*)va); va_arg++; break;}
default: putchar (*p);
}
p++;
}
return 0;
}
char **g_environment;
char **
_env (char **e)
{
return e;
}
int
_start ()
{
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x08"); // add $0x8,%eax
asm (".byte 0x50"); // push %eax
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x04"); // add $0x4,%eax
asm (".byte 0x0f 0xb6 0x00"); // movzbl (%eax),%eax
asm (".byte 0x50"); // push %eax
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x04"); // add $0x4,%eax
asm (".byte 0x0f 0xb6 0x00"); // movzbl (%eax),%eax
asm (".byte 0x83 0xc0 0x03"); // add $0x3,%eax
asm (".byte 0xc1 0xe0 0x02"); // shl $0x2,%eax
asm (".byte 0x01 0xe8"); // add %ebp,%eax
asm (".byte 0x50"); // push %eax
g_environment = _env ();
asm (".byte 0x58");
int r = main ();
exit (r);
}

87
libc/mini-libc-mes.c Normal file
View file

@ -0,0 +1,87 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
void
exit ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0xb8 0x01 0x00 0x00 0x00"); // mov $0x1,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
void
write ()
{
asm (".byte 0x8b 0x5d 0x08"); // mov 0x8(%ebp),%ebx
asm (".byte 0x8b 0x4d 0x0c"); // mov 0xc(%ebp),%ecx
asm (".byte 0x8b 0x55 0x10"); // mov 0x10(%ebp),%edx
asm (".byte 0xb8 0x04 0x00 0x00 0x00"); // mov $0x4,%eax
asm (".byte 0xcd 0x80"); // int $0x80
}
int
strlen (char const* s)
{
int i = 0;
while (s[i]) i++;
return i;
}
int
eputs (char const* s)
{
int i = strlen (s);
write (2, s, i);
return 0;
}
char **g_environment;
char **
_env (char **e)
{
return e;
}
int
_start ()
{
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x08"); // add $0x8,%eax
asm (".byte 0x50"); // push %eax
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x04"); // add $0x4,%eax
asm (".byte 0x0f 0xb6 0x00"); // movzbl (%eax),%eax
asm (".byte 0x50"); // push %eax
asm (".byte 0x89 0xe8"); // mov %ebp,%eax
asm (".byte 0x83 0xc0 0x04"); // add $0x4,%eax
asm (".byte 0x0f 0xb6 0x00"); // movzbl (%eax),%eax
asm (".byte 0x83 0xc0 0x03"); // add $0x3,%eax
asm (".byte 0xc1 0xe0 0x02"); // shl $0x2,%eax
asm (".byte 0x01 0xe8"); // add %ebp,%eax
asm (".byte 0x50"); // push %eax
g_environment = _env ();
asm (".byte 0x58");
int r = main ();
exit (r);
}

View file

@ -1,55 +0,0 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#if __GNUC__
void
_start ()
{
// char **;
asm (
"mov %%ebp,%%eax\n\t"
"addl $4,%%eax\n\t"
"movzbl (%%eax),%%eax\n\t"
"addl $3,%%eax\n\t"
"shl $2,%%eax\n\t"
"add %%ebp,%%eax\n\t"
"movl %%eax,%0\n\t"
: "=g_environment" (g_environment)
: //no inputs ""
);
int r;
asm (
"mov %%ebp,%%eax\n\t"
"addl $8,%%eax\n\t"
"push %%eax\n\t"
"mov %%ebp,%%eax\n\t"
"addl $4,%%eax\n\t"
"movzbl (%%eax),%%eax\n\t"
"push %%eax\n\t"
"call main\n\t"
"movl %%eax,%0\n\t"
: "=r" (r)
: //no inputs ""
);
exit (r);
}
#endif // __GNUC__

View file

@ -1,4 +1,4 @@
C_FLAGS:=-nostdinc --include mstart.c -fno-builtin
C_FLAGS:=-nostdinc -fno-builtin
LD_FLAGS:=-nostdlib
CROSS:=$(CC32:%gcc=%)

View file

@ -5,7 +5,7 @@ ifneq ($(DEBUG),)
$(info TARGET=$(TARGET))
$(info C_FILES=$(C_FILES))
$(info O_FILES=$(O_FILES))
$(info O_FILES=$(D_FILES))
$(info D_FILES=$(D_FILES))
endif
CLEAN+=$(O_FILES) $(OUT)/$(TARGET)
@ -19,7 +19,7 @@ $(OUT)/$(TARGET): CC:=$(CROSS)$(CC)
$(OUT)/$(TARGET): LDFLAGS:=$(LDFLAGS) $(LD_FLAGS) $(LINK)
$(OUT)/$(TARGET): O_FILES:=$(O_FILES)
$(OUT)/$(TARGET): $(O_FILES)
@echo " $(ld) $(notdir $^) -> $(notdir $@)"
@echo " $(ld) $(notdir $^) -> $(notdir $@)"
$(QUIET)$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
include make/compile.make

View file

@ -2,7 +2,9 @@ ifeq ($(TEST),)
TEST:=$(TARGET)-check
$(TEST): EXT:=$(EXT)
$(TEST): EXPECT:=$(EXPECT)
$(TEST): SHELL:=$(SHELL)
$(TEST): $(OUT)/$(TARGET)
@export SHELL=$(SHELL)
ifeq ($(EXPECT),)
$< - arg1 arg2 arg3 arg4 > $(<:.$(EXT)=.stdout)
else

View file

@ -1,7 +1,9 @@
ifeq ($(TEST),)
TEST:=$(TARGET)-check
$(TEST): EXPECT:=$(EXPECT)
$(TEST): SHELL:=$(SHELL)
$(TEST): $(OUT)/$(TARGET)
@export SHELL=$(SHELL)
ifeq ($(EXPECT),)
$<
else

View file

@ -5,7 +5,7 @@ $(OUT)/$(1:.c=.$(CROSS)o): CC:=$(CROSS)$(CC)
$(OUT)/$(1:.c=.$(CROSS)o): CPPFLAGS:=$$(CPPFLAGS) $$(CPP_FLAGS) $(2:%=-D%) $(3:%=-I%)
$(OUT)/$(1:.c=.$(CROSS)o): CFLAGS:=$$(CFLAGS) $$(C_FLAGS)
$(OUT)/$(1:.c=.$(CROSS)o): $(1)
@echo " $$(cc) $$(notdir $$<) -> $$(notdir $$@)"
@echo " $$(cc) $$(notdir $$<) -> $$(notdir $$@)"
@mkdir -p $$(dir $$@)
$$(QUIET)$$(COMPILE.c) $$(OUTPUT_OPTION) -MMD -MF $$(@:%.$(CROSS)o=%.$(CROSS)d) -MT '$$(@:.%$(CROSS)o=%.$(CROSS)d)' $$<
endef

View file

@ -1,10 +1,51 @@
CROSS:=guile-
C_FILES:=libc/libc-mes.c $(C_FILES)
#C_FILES:=libc/mini-libc-mes.c $(C_FILES)
O_FILES:=$(C_FILES:%.c=$(OUT)/%.$(CROSS)o)
ifneq ($(DEBUG),)
$(info TARGET=$(TARGET))
$(info C_FILES=$(C_FILES))
$(info O_FILES=$(O_FILES))
endif
CLEAN+=$(O_FILES) $(OUT)/$(TARGET)
CLEAN+=$(OUT)/$(TARGET)
$(OUT)/$(TARGET): C_INCLUDE_PATH:=$(INCLUDES)
$(OUT)/$(TARGET): $(MAKEFILE_LIST)
$(OUT)/$(TARGET): $(INSTALL_GO_FILES)
$(OUT)/$(TARGET): $(C_FILES)
@echo " mescc.scm $(notdir $<) -> $(notdir $@)"
@rm -f $@
$(QUIET) guile/mescc.scm $(C_INCLUDE_PATH:%=-I %) -o $@ $< || rm -f $@
@[ -f $@ ] && chmod +x $@ ||:
INCLUDES+=libc/include libc $(OUT)/$(DIR)
MESCC.scm:=guile/mescc.scm
MESLD.scm:=guile/mescc.scm
$(OUT)/$(TARGET): ld:=MESLD.scm
$(OUT)/$(TARGET): LD:=$(MESLD.scm)
$(OUT)/$(TARGET): CC:=$(MESCC.scm)
$(OUT)/$(TARGET): CFLAGS:=
$(OUT)/$(TARGET): LDFLAGS:=
$(OUT)/$(TARGET): O_FILES:=$(O_FILES)
$(OUT)/$(TARGET): $(O_FILES)
@echo " $(ld) $(notdir $(O_FILES)) -> $(notdir $@)"
$(QUIET)$(LINK.c) $(O_FILES) $(LOADLIBES) $(LDLIBS) -o $@
define mescc.scm-c-compile
$(OUT)/$(1:.c=.$(CROSS)o): $(MAKEFILE_LIST)
$(OUT)/$(1:.c=.$(CROSS)o): cc:=MESCC.scm
$(OUT)/$(1:.c=.$(CROSS)o): CC:=$(MESCC.scm)
$(OUT)/$(1:.c=.$(CROSS)o): CPPFLAGS:=$(2:%=-D %) $(3:%=-I %)
$(OUT)/$(1:.c=.$(CROSS)o): COMPILE.c:=$(MESCC.scm) -c $(CPPFLAGS)
$(OUT)/$(1:.c=.$(CROSS)o): $(INSTALL_GO_FILES)
$(OUT)/$(1:.c=.$(CROSS)o): $(1)
@echo " $$(cc) $$(notdir $(1)) -> $$(notdir $$@)"
@mkdir -p $$(dir $$@)
$$(QUIET)$$(COMPILE.c) $$(CPPFLAGS) $$(OUTPUT_OPTION) $(1)
endef
ifeq ($(MLIBC.scm),)
MLIBC.scm:=DONE
else
C_FILES:=$(filter-out libc/libc-mes.c,$(C_FILES))
C_FILES:=$(filter-out libc/mini-libc-mes.c,$(C_FILES))
endif
$(foreach c-file,$(strip $(filter %.c,$(C_FILES))),$(eval $(call mescc.scm-c-compile,$(c-file),$(DEFINES),$(INCLUDES))))
include make/reset.make

View file

@ -1,16 +1,52 @@
CLEAN+=$(OUT)/$(TARGET)
ifneq ($(MES_MAX_ARENA),)
$(OUT)/$(TARGET): MES_MAX_ARENA-flag:=MES_MAX_ARENA=$(MES_MAX_ARENA)
CROSS:=mes-
C_FILES:=libc/libc-mes.c $(C_FILES)
O_FILES:=$(C_FILES:%.c=$(OUT)/%.$(CROSS)o)
ifneq ($(DEBUG),)
$(info TARGET=$(TARGET))
$(info C_FILES=$(C_FILES))
$(info O_FILES=$(O_FILES))
endif
$(OUT)/$(TARGET): C_INCLUDE_PATH:=$(INCLUDES)
$(OUT)/$(TARGET): $(MAKEFILE_LIST)
$(OUT)/$(TARGET): module/mes/read-0.mo
$(OUT)/$(TARGET): module/mes/read-0-32.mo
$(OUT)/$(TARGET): $(INSTALL_MES_FILES)
$(OUT)/$(TARGET): scripts/mes
$(OUT)/$(TARGET): $(C_FILES)
@echo " mescc.mes $(notdir $<) -> $(notdir $@)"
@rm -f $@
$(QUIET)MES_DEBUG=$(MES_DEBUG) $(MES_MAX_ARENA-flag) MES_FLAGS=--load scripts/mescc.mes $(C_INCLUDE_PATH:%=-I %) -o $@ $< || rm -f $@
@[ -f $@ ] && chmod +x $@ ||:
CLEAN+=$(O_FILES) $(OUT)/$(TARGET)
CLEAN+=$(OUT)/$(TARGET)
INCLUDES+=libc/include libc $(OUT)/$(DIR)
MESCC.mes:=scripts/mescc.mes
MESLD.mes:=scripts/mescc.mes
$(OUT)/$(TARGET): ld:=MESLD.mes
$(OUT)/$(TARGET): LD:=$(MESLD.mes)
$(OUT)/$(TARGET): CC:=$(MESCC.mes)
$(OUT)/$(TARGET): CFLAGS:=
$(OUT)/$(TARGET): LDFLAGS:=
$(OUT)/$(TARGET): O_FILES:=$(O_FILES)
$(OUT)/$(TARGET): $(O_FILES)
@echo " $(ld) $(notdir $(O_FILES)) -> $(notdir $@)"
$(QUIET)$(LINK.c) $(O_FILES) $(LOADLIBES) $(LDLIBS) -o $@
define mescc.mes-c-compile
$(OUT)/$(1:.c=.$(CROSS)o): $(MAKEFILE_LIST)
$(OUT)/$(1:.c=.$(CROSS)o): cc:=MESCC.mes
$(OUT)/$(1:.c=.$(CROSS)o): CC:=$(MESCC.mes)
$(OUT)/$(1:.c=.$(CROSS)o): COMPILE.c:=$(MESCC.mes) -c
$(OUT)/$(1:.c=.$(CROSS)o): CPPFLAGS:=$(2:%=-D %) $(3:%=-I %)
$(OUT)/$(1:.c=.$(CROSS)o): COMPILE.c:=$(MESCC.mes) -c $(CPPFLAGS)
$(OUT)/$(1:.c=.$(CROSS)o): all-mo
$(OUT)/$(1:.c=.$(CROSS)o): $(INSTALL_MES_FILES)
$(OUT)/$(1:.c=.$(CROSS)o): $(1)
@echo " $$(cc) $$(notdir $(1)) -> $$(notdir $$@)"
@mkdir -p $$(dir $$@)
$$(QUIET)$$(COMPILE.c) $$(OUTPUT_OPTION) $(1)
endef
ifeq ($(MLIBC.mes),)
MLIBC.mes:=DONE
else
C_FILES:=$(filter-out libc/libc-mes.c,$(C_FILES))
endif
$(foreach c-file,$(strip $(filter %.c,$(C_FILES))),$(eval $(call mescc.mes-c-compile,$(c-file),$(DEFINES),$(INCLUDES))))
include make/reset.make

View file

@ -35,7 +35,6 @@
(mes-use-module (mes elf-util))
(mes-use-module (mes elf))
(mes-use-module (mes as-i386))
(mes-use-module (mes libc))
(mes-use-module (mes optargs))))
(define (logf port string . rest)
@ -1149,7 +1148,7 @@
(or (assoc-ref (.locals info) o)
(assoc-ref (.globals info) o)
(begin
(stderr "NO IDENT: ~a\n" (assoc-ref (.functions info) o))
(stderr "NO IDENT: ~a\n" o)
(assoc-ref (.functions info) o))))
(define (ident->type info o)
@ -1261,6 +1260,12 @@
((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements))
((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))
(if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list))))
(append-text info (wrap-as (asm->hex arg0))))
(let ((info ((expr->accu info) `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))))
(append-text info (wrap-as (i386:accu-zero?))))))
((if ,test ,body)
(let* ((text-length (length text))
@ -2161,18 +2166,11 @@
(define* (c99-input->info #:key (defines '()) (includes '()))
(lambda ()
(let* ((info (make <info>
#:functions i386:libc
#:types i386:type-alist))
(foo (stderr "compiling: mlibc\n"))
(info (let loop ((info info) (libc libc))
(if (null? libc) info
(loop ((ast->info info) ((car libc))) (cdr libc)))))
(let* ((info (make <info> #:types i386:type-alist))
(foo (stderr "parsing: input\n"))
(ast (c99-input->ast #:defines defines #:includes includes))
(foo (stderr "compiling: input\n"))
(info ((ast->info info) ast))
(info ((ast->info info) (_start)))
(info (clone info #:text '() #:locals '())))
info)))

View file

@ -20,7 +20,7 @@
;;; Commentary:
;;; libc-i386.mes defines i386 assembly
;;; as-i386.mes defines i386 assembly
;;; Code:

View file

@ -1,170 +0,0 @@
;;; -*-scheme-*-
;;; Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of Mes.
;;;
;;; Mes is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Mes is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; libc-i386.mes defines C library routines
;;; Code:
(define i386:exit
'(lambda (f g ta t d)
(list
#x5b ; pop %ebx
#x5b ; pop %ebx
#xb8 #x01 #x00 #x00 #x00 ; mov $0x1,%eax
#xcd #x80 ; int $0x80
)))
(define i386:read
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
#x8b #x55 #x10 ; mov 0x10(%ebp),%edx
#xb8 #x03 #x00 #x00 #x00 ; mov $0x3,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define i386:write
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
#x8b #x55 #x10 ; mov 0x10(%ebp),%edx
#xb8 #x04 #x00 #x00 #x00 ; mov $0x4,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define i386:open
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
#x8b #x55 #x10 ; mov 0x10(%ebp),%edx
#xb8 #x05 #x00 #x00 #x00 ; mov $0x5,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define i386:access
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#x8b #x4d #x0c ; mov 0xc(%ebp),%ecx
#xb8 #x21 #x00 #x00 #x00 ; mov $0x21,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define i386:brk
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#xb8 #x2d #x00 #x00 #x00 ; mov $0x2d,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define i386:fsync
'(lambda (f g ta t d)
(list
#x55 ; push %ebp
#x89 #xe5 ; mov %esp,%ebp
#x8b #x5d #x08 ; mov 0x8(%ebp),%ebx
#xb8 #x76 #x00 #x00 #x00 ; mov $0x76,%eax
#xcd #x80 ; int $0x80
#xc9 ; leave
#xc3 ; ret
)))
(define (i386:_start)
(string-append ".byte"
" 0x89 0xe8" ; mov %ebp,%eax
" 0x83 0xc0 0x08" ; add $0x8,%eax
" 0x50" ; push %eax
" 0x89 0xe8" ; mov %ebp,%eax
" 0x83 0xc0 0x04" ; add $0x4,%eax
" 0x0f 0xb6 0x00" ; movzbl (%eax),%eax
" 0x50" ; push %eax
" 0x89 0xe8" ; mov %ebp,%eax
" 0x83 0xc0 0x04" ; add $0x4,%eax
" 0x0f 0xb6 0x00" ; movzbl (%eax),%eax
" 0x83 0xc0 0x03" ; add $0x3,%eax
" 0xc1 0xe0 0x02" ; shl $0x2,%eax
" 0x01 0xe8" ; add %ebp,%eax
" 0x50" ; push %eax
))
(define (i386:va-arg)
(string-append ".byte"
" 0x8b 0x45 0xfc" ; mov -<0x4>(%ebp),%eax :va_arg
" 0xc1 0xe0 0x2" ; shl $0x2,%eax
" 0x01 0xe8" ; add %ebp,%eax
" 0x83 0xc0 0xc" ; add $0xc,%eax
" 0x8b 0x00" ; mov (%eax),%eax
" 0x89 0x45 0xf8" ; mov %eax,-0x8(%ebp) :va
" 0x50" ; push %eax
))
(define i386:libc
(list
(cons "exit" (list i386:exit))
(cons "read" (list i386:read))
(cons "write" (list i386:write))
(cons "open" (list i386:open))
(cons "access" (list i386:access))
(cons "brk" (list i386:brk))
(cons "fsync" (list i386:fsync))))

View file

@ -1,32 +0,0 @@
;;; -*-scheme-*-
;;; Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of Mes.
;;;
;;; Mes is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Mes is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; libc-i386.mes defines C library routines
;;; Code:
(define-module (mes libc-i386)
#:export (i386:libc
i386:_start
i386:va-arg))
(include-from-path "mes/libc-i386.mes")

View file

@ -1,421 +0,0 @@
;;; -*-scheme-*-
;;; Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of Mes.
;;;
;;; Mes is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Mes is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; libc.mes provides a minimal portable C library for mescc.
;;; Code:
(cond-expand
(guile-2)
(guile)
(mes
(mes-use-module (nyacc lang c99 parser))
(mes-use-module (mes libc-i386))))
(define (_start)
(let ((argc-argv (i386:_start)))
(format (current-error-port) "parsing: _start\n")
(with-input-from-string
(string-append "
char **g_environment;
char **
_env (char **e)
{
return e;
}
int
_start ()
{
asm(\"" argc-argv "\");
g_environment = _env ();
asm (\".byte 0x58\");
int r = main ();
exit (r);
}
") parse-c99)))
(define (strlen)
(format (current-error-port) "parsing: strlen\n")
(with-input-from-string
"
int
strlen (char const* s)
{
int i = 0;
while (s[i]) i++;
return i;
}
" parse-c99))
(define (getchar)
(format (current-error-port) "parsing: getchar\n")
(with-input-from-string
"
int g_stdin = 0;
int ungetc_char = -1;
char ungetc_buf[2];
int
getchar ()
{
char c;
int i;
if (ungetc_char == -1)
{
int r = read (g_stdin, &c, 1);
if (r < 1) return -1;
i = c;
}
else
{
//FIXME
//i = ungetc_buf[ungetc_char--];
i = ungetc_buf[ungetc_char];
//ungetc_char--;
ungetc_char = ungetc_char - 1;
}
if (i < 0) i += 256;
return i;
}
" parse-c99))
(define (assert_fail)
(format (current-error-port) "parsing: assert_fail\n")
(with-input-from-string
"
void
assert_fail (char* s)
{
eputs (\"assert fail: \");
eputs (s);
eputs (\"\n\");
//*((int*)0) = 0;
char *fail = s;
fail = 0;
*fail = 0;
}
" parse-c99))
(define (ungetc)
(format (current-error-port) "parsing: ungetc\n")
(with-input-from-string
"
//#define assert(x) ((x) ? (void)0 : assert_fail (#x))
int
ungetc (int c, int fd)
{
//FIXME
//assert (ungetc_char < 2);
//assert (ungetc_char == -1 || ungetc_char < 2);
//FIXME
//ungetc_buf[++ungetc_char] = c;
ungetc_char++;
ungetc_buf[ungetc_char] = c;
return c;
}
" parse-c99))
(define (putchar)
(format (current-error-port) "parsing: putchar\n")
(with-input-from-string
"
int
putchar (int c)
{
write (1, (char*)&c, 1);
return 0;
}
" parse-c99))
(define (fputc)
(format (current-error-port) "parsing: fputc\n")
(with-input-from-string
"
int
fputc (int c, int fd)
{
write (fd, (char*)&c, 1);
return 0;
}
" parse-c99))
(define (eputs)
(format (current-error-port) "parsing: eputs\n")
(with-input-from-string
"
int
eputs (char const* s)
{
int i = strlen (s);
write (2, s, i);
return 0;
}
" parse-c99))
(define (fputs)
(format (current-error-port) "parsing: fputs\n")
(with-input-from-string
"
int
fputs (char const* s, int fd)
{
int i = strlen (s);
write (fd, s, i);
return 0;
}
" parse-c99))
(define (puts)
(format (current-error-port) "parsing: puts\n")
(with-input-from-string
"
int
puts (char const* s)
{
int i = strlen (s);
write (1, s, i);
return 0;
}
" parse-c99))
(define (strcmp)
(format (current-error-port) "parsing: strcmp\n")
(with-input-from-string
"
int
strcmp (char const* a, char const* b)
{
while (*a && *b && *a == *b)
{
a++;b++;
}
return *a - *b;
}
" parse-c99))
(define (strcpy)
(format (current-error-port) "parsing: strcpy\n")
(with-input-from-string
"
char *
strcpy (char *dest, char const *src)
{
char *p = dest;
while (*src) *p++ = *src++;
*p = 0;
return dest;
}
" parse-c99))
(define (itoa)
(format (current-error-port) "parsing: itoa\n")
(with-input-from-string
"
char itoa_buf[10];
char const*
itoa (int x)
{
//static char itoa_buf[10];
//char *p = buf+9;
char *p = itoa_buf;
p += 9;
*p-- = 0;
//int sign = x < 0; // FIXME
int sign = 0;
if (x < 0) sign = 1;
if (sign)
x = -x;
do
{
*p-- = '0' + (x % 10);
x = x / 10;
} while (x);
if (sign && *(p + 1) != '0')
*p-- = '-';
return p+1;
}
" parse-c99))
(define (isdigit)
(format (current-error-port) "parsing: isdigit\n")
(with-input-from-string
"
int
isdigit (char c)
{
//return (c>='0') && (c<='9');
if (c>='0' && c<='9') return 1;
return 0;
}
" parse-c99))
(define (atoi)
(format (current-error-port) "parsing: atoi\n")
(with-input-from-string
"
int
atoi (char const *s)
{
int i = 0;
int sign = 1;
if (*s && *s == '-')
{
sign = -1;
s++;
}
while (isdigit (*s))
{
i *= 10;
i += (*s - '0');
s++;
}
return i * sign;
}
" parse-c99))
(define (malloc)
(format (current-error-port) "parsing: malloc\n")
(with-input-from-string
"
//void *g_malloc_base = 0;
char *g_malloc_base = 0;
//void *
int *
malloc (int size)
{
//void *p = brk (0);
char *p = 0;
p = brk (0);
if (!g_malloc_base) g_malloc_base = p;
brk (p+size);
return p;
}
" parse-c99))
(define (realloc)
(format (current-error-port) "parsing: realloc\n")
(with-input-from-string
"
//void *
int *
//realloc (void *p, int size)
realloc (int *p, int size)
{
brk (g_malloc_base + size);
return g_malloc_base;
}
" parse-c99))
(define (strncmp)
(format (current-error-port) "parsing: strncmp\n")
(with-input-from-string
"
int
strncmp (char const* a, char const* b, int length)
{
while (*a && *b && *a == *b && --length) {a++;b++;}
return *a - *b;
}
" parse-c99))
(define (c:getenv)
(format (current-error-port) "parsing: getenv\n")
(with-input-from-string
"
char **g_environment;
char const*
getenv (char const* s)
{
char **p = g_environment;
p = *g_environment;
int length = strlen (s);
while (*p)
{
if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
p++;
}
return 0;
}
" parse-c99))
(define (printf)
(format (current-error-port) "parsing: printf\n")
(let ((va-arg (i386:va-arg)))
(with-input-from-string
(string-append "
int
printf (char const* format, int va_args)
{
int va_arg = 0;
int va;
char *p = format;
while (*p)
if (*p != '%')
putchar (*p++);
else
{
p++;
char c = *p;
switch (c)
{
case '%': {putchar (*p); break;}
case 'c': {asm (\"" va-arg "\"); putchar ((char)va); va_arg++; break;}
case 'd': {asm (\"" va-arg "\"); puts (itoa (va)); va_arg++; break;}
case 's': {asm (\"" va-arg "\"); puts ((char*)va); va_arg++; break;}
default: putchar (*p);
}
p++;
}
return 0;
}
") parse-c99)))
(define libc
(list
strlen
getchar
assert_fail
ungetc
putchar
fputc
eputs
fputs
puts
strcmp
strcpy
itoa
isdigit
atoi
malloc
realloc
strncmp
c:getenv
printf
))

View file

@ -1,36 +0,0 @@
;;; -*-scheme-*-
;;; Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of Mes.
;;;
;;; Mes is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Mes is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(define-module (mes libc)
#:use-module (nyacc lang c99 parser)
#:use-module (mes libc-i386)
#:export (libc _start))
(cond-expand
(guile-2)
(guile
(use-modules (ice-9 syncase)))
(mes))
(include-from-path "mes/libc.mes")

View file

@ -18,7 +18,7 @@
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mlibc.h>
#include <stdio.h>
int
main (int argc, char *argv[])

View file

@ -22,6 +22,7 @@
#error "POSIX not supported"
#endif
#include <stdio.h>
#include <mlibc.h>
char arena[300];

View file

@ -59,7 +59,7 @@ include make/mescc-guile.make
MAINTAINER-CLEAN+=mes.mes
ifeq ($(wildcard mes.mes),)
safe-MES_MAX_ARENA=$(MES_MAX_ARENA)
safe-MES_MAX_ARENA:=$(MES_MAX_ARENA)
MES_MAX_ARENA:=80000000
TARGET:=mes.mes
$(OUT)/mes.mes: module/mes/read-0-32.mo