From 6628d0312691327de8484341511b26bb00b13e1e Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 18 Jan 2019 15:14:02 +0100 Subject: [PATCH] Port of OCaml bytecode runtime A minimal runtime for executing portable OCaml bytecode. A bytecode standard library is not yet provided. --- lib/mk/ocaml-str.mk | 10 ++++ lib/mk/ocaml-threads.mk | 10 ++++ lib/mk/ocaml-unix.mk | 26 ++++++++++ lib/mk/ocaml.inc | 4 ++ ports/ocaml.hash | 1 + ports/ocaml.port | 7 +++ run/ocamlrun.run | 69 +++++++++++++++++++++++++++ src/app/ocamlrun/caml/version.h | 0 src/app/ocamlrun/floatingpoint.h | 1 + src/app/ocamlrun/m.h | 12 +++++ src/app/ocamlrun/osreldate.h | 0 src/app/ocamlrun/s.h | 62 ++++++++++++++++++++++++ src/app/ocamlrun/target.mk | 81 ++++++++++++++++++++++++++++++++ 13 files changed, 283 insertions(+) create mode 100644 lib/mk/ocaml-str.mk create mode 100644 lib/mk/ocaml-threads.mk create mode 100644 lib/mk/ocaml-unix.mk create mode 100644 lib/mk/ocaml.inc create mode 100644 ports/ocaml.hash create mode 100644 ports/ocaml.port create mode 100644 run/ocamlrun.run create mode 100644 src/app/ocamlrun/caml/version.h create mode 100644 src/app/ocamlrun/floatingpoint.h create mode 100644 src/app/ocamlrun/m.h create mode 100644 src/app/ocamlrun/osreldate.h create mode 100644 src/app/ocamlrun/s.h create mode 100644 src/app/ocamlrun/target.mk diff --git a/lib/mk/ocaml-str.mk b/lib/mk/ocaml-str.mk new file mode 100644 index 0000000..1a4c262 --- /dev/null +++ b/lib/mk/ocaml-str.mk @@ -0,0 +1,10 @@ +include $(REP_DIR)/lib/mk/ocaml.inc + +LIBS += libc + +INC_DIR += $(OCAML_SRC_DIR)/byterun +INC_DIR += $(OCAML_SRC_DIR)/byterun/caml + +vpath %.c $(OCAML_SRC_DIR)/otherlibs/str + +SRC_C += strstubs.c diff --git a/lib/mk/ocaml-threads.mk b/lib/mk/ocaml-threads.mk new file mode 100644 index 0000000..11011e8 --- /dev/null +++ b/lib/mk/ocaml-threads.mk @@ -0,0 +1,10 @@ +include $(REP_DIR)/lib/mk/ocaml.inc + +LIBS += libc + +INC_DIR += $(OCAML_SRC_DIR)/byterun +INC_DIR += $(OCAML_SRC_DIR)/byterun/caml + +vpath %.c $(OCAML_SRC_DIR)/otherlibs/threads + +SRC_C += scheduler.c diff --git a/lib/mk/ocaml-unix.mk b/lib/mk/ocaml-unix.mk new file mode 100644 index 0000000..8ad9325 --- /dev/null +++ b/lib/mk/ocaml-unix.mk @@ -0,0 +1,26 @@ +include $(REP_DIR)/lib/mk/ocaml.inc + +LIBS += libc + +INC_DIR += $(OCAML_SRC_DIR)/byterun +INC_DIR += $(OCAML_SRC_DIR)/byterun/caml + +vpath %.c $(OCAML_SRC_DIR)/otherlibs/unix + +SRC_C += accept.c access.c addrofstr.c alarm.c bind.c chdir.c chmod.c \ + chown.c chroot.c close.c closedir.c connect.c cst2constr.c cstringv.c \ + dup.c dup2.c envir.c errmsg.c execv.c execve.c execvp.c exit.c \ + fchmod.c fchown.c fcntl.c fork.c ftruncate.c \ + getaddrinfo.c getcwd.c getegid.c geteuid.c getgid.c \ + getgr.c getgroups.c gethost.c gethostname.c getlogin.c \ + getnameinfo.c getpeername.c getpid.c getppid.c getproto.c getpw.c \ + gettimeofday.c getserv.c getsockname.c getuid.c gmtime.c \ + initgroups.c isatty.c itimer.c kill.c link.c listen.c lockf.c lseek.c \ + mkdir.c mkfifo.c mmap.c mmap_ba.c \ + nice.c open.c opendir.c pipe.c putenv.c read.c \ + readdir.c readlink.c rename.c rewinddir.c rmdir.c select.c sendrecv.c \ + setgid.c setgroups.c setsid.c setuid.c shutdown.c signals.c \ + sleep.c socket.c socketaddr.c \ + socketpair.c sockopt.c stat.c strofaddr.c symlink.c termios.c \ + time.c times.c truncate.c umask.c unixsupport.c unlink.c \ + utimes.c wait.c write.c diff --git a/lib/mk/ocaml.inc b/lib/mk/ocaml.inc new file mode 100644 index 0000000..d79cd0c --- /dev/null +++ b/lib/mk/ocaml.inc @@ -0,0 +1,4 @@ +OCAML_PORT_DIR := $(call select_from_ports,ocaml) +OCAML_SRC_DIR := $(OCAML_PORT_DIR)/src/ocaml + +INC_DIR += $(REP_DIR)/src/app/ocamlrun diff --git a/ports/ocaml.hash b/ports/ocaml.hash new file mode 100644 index 0000000..6cb6232 --- /dev/null +++ b/ports/ocaml.hash @@ -0,0 +1 @@ +23ddf9418fd8dffbde8f8d52071a13d0541715d4 diff --git a/ports/ocaml.port b/ports/ocaml.port new file mode 100644 index 0000000..079eb45 --- /dev/null +++ b/ports/ocaml.port @@ -0,0 +1,7 @@ +LICENSE = LGPLv2.1 +VERSION = 4.07.1 +DOWNLOADS = ocaml.archive + +URL(ocaml) := http://caml.inria.fr/pub/distrib/ocaml-4.07/ocaml-4.07.1.tar.xz +SHA(ocaml) := dfe48b1da31da9c82d77612582fae74c80e8d1ac650e1c24f5ac9059e48307b8 +DIR(ocaml) := src/ocaml diff --git a/run/ocamlrun.run b/run/ocamlrun.run new file mode 100644 index 0000000..e214336 --- /dev/null +++ b/run/ocamlrun.run @@ -0,0 +1,69 @@ +set ocamlc [installed_command ocamlc] + +create_boot_directory + +proc depot_user {} { return [get_cmd_arg --depot-user genodelabs] } + +import_from_depot \ + [depot_user]/src/[base_src] \ + [depot_user]/src/init \ + +append build_components { + app/ocamlrun +} + +build $build_components + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +# +# Compile some bytecode and TAR it +# + +set fd [open [run_dir]/hello.ml w] +puts $fd "print_string \"Hello world!\n\";;" +close $fd + +exec ocamlc -o [run_dir]/a.out [run_dir]/hello.ml +exec tar cf [run_dir]/genode/bytecode.tar -C [run_dir] a.out + +build_boot_image { + ocamlrun libc.lib.so vfs.lib.so libm.lib.so posix.lib.so +} + +append qemu_args " -nographic -serial mon:stdio " + +run_genode_until {child "ocamlrun" exited with exit value 0.*\n} 30 diff --git a/src/app/ocamlrun/caml/version.h b/src/app/ocamlrun/caml/version.h new file mode 100644 index 0000000..e69de29 diff --git a/src/app/ocamlrun/floatingpoint.h b/src/app/ocamlrun/floatingpoint.h new file mode 100644 index 0000000..fbcdd56 --- /dev/null +++ b/src/app/ocamlrun/floatingpoint.h @@ -0,0 +1 @@ +#include diff --git a/src/app/ocamlrun/m.h b/src/app/ocamlrun/m.h new file mode 100644 index 0000000..6b40e5c --- /dev/null +++ b/src/app/ocamlrun/m.h @@ -0,0 +1,12 @@ +#define ARCH_SIXTYFOUR +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_PTR 8 +#define SIZEOF_SHORT 2 +#define SIZEOF_LONGLONG 8 +#define INT64_LITERAL(s) s ## LL +#undef ARCH_BIG_ENDIAN +#undef ARCH_ALIGN_DOUBLE +#define ARCH_ALIGN_INT64 +#define PROFINFO_WIDTH 0 +#define FLAT_FLOAT_ARRAY diff --git a/src/app/ocamlrun/osreldate.h b/src/app/ocamlrun/osreldate.h new file mode 100644 index 0000000..e69de29 diff --git a/src/app/ocamlrun/s.h b/src/app/ocamlrun/s.h new file mode 100644 index 0000000..720b38f --- /dev/null +++ b/src/app/ocamlrun/s.h @@ -0,0 +1,62 @@ +#define OCAML_OS_TYPE "Unix" +#define OCAML_STDLIB_DIR "/usr/local/lib/ocaml" +#define POSIX_SIGNALS +#define HAS_C99_FLOAT_OPS +#undef HAS_GETRUSAGE +#define HAS_TIMES +#undef HAS_SECURE_GETENV +#define HAS_SOCKETS +#define HAS_SOCKLEN_T +#define HAS_INET_ATON +#define HAS_IPV6 +#define HAS_STDINT_H +#define HAS_UNISTD +#define HAS_OFF_T +#define HAS_DIRENT +#define HAS_REWINDDIR +#define HAS_LOCKF +#define HAS_MKFIFO +#define HAS_GETCWD +#define HAS_GETPRIORITY +#define HAS_UTIME +#define HAS_UTIMES +#define HAS_DUP2 +#define HAS_FCHMOD +#define HAS_TRUNCATE +#define HAS_SYS_SELECT_H +#define HAS_SELECT +#define HAS_NANOSLEEP +#define HAS_SYMLINK +#define HAS_WAITPID +#define HAS_WAIT4 +#define HAS_GETGROUPS +#define HAS_SETGROUPS +#define HAS_INITGROUPS +#define HAS_TERMIOS +#define HAS_ASYNC_IO +#define HAS_SETITIMER +#define HAS_GETHOSTNAME +#define HAS_UNAME +#define HAS_GETTIMEOFDAY +#define HAS_MKTIME +#define HAS_SETSID +#undef HAS_PUTENV +#define HAS_LOCALE +#define SUPPORT_DYNAMIC_LINKING +#define HAS_MMAP +#define HAS_PWRITE +#undef HAS_NANOSECOND_STAT +#define HAS_GETHOSTBYNAME_R 6 +#define HAS_GETHOSTBYADDR_R 8 +#define HAS_MKSTEMP +#undef HAS_NICE +#undef HAS_DUP3 +#undef HAS_PIPE2 +#define HAS_ACCEPT4 +#undef HAS_GETAUXVAL +#undef HAS_SYS_SHM_H +#undef HAS_EXECVPE +#undef HAS_STACK_OVERFLOW_DETECTION +#undef HAS_SIGWAIT +#undef HAS_HUGE_PAGES +#undef HUGE_PAGE_SIZE diff --git a/src/app/ocamlrun/target.mk b/src/app/ocamlrun/target.mk new file mode 100644 index 0000000..652c18c --- /dev/null +++ b/src/app/ocamlrun/target.mk @@ -0,0 +1,81 @@ +TARGET = ocamlrun +LIBS += ocaml-unix ocaml-str ocaml-threads posix libc + +OCAML_PORT_DIR := $(call select_from_ports,ocaml) + +BYTERUN_DIR := $(OCAML_PORT_DIR)/src/ocaml/byterun + +INC_DIR += $(PRG_DIR) +INC_DIR += $(BYTERUN_DIR) + +OCAML_VERSION_STRING := $(shell head -n 1 $(BYTERUN_DIR)/../VERSION) + +CC_DEF += -DOCAML_VERSION_STRING=\"$(OCAML_VERSION_STRING)\" +CC_DEF += -DOCAML_VERSION=\"$(OCAML_VERSION_STRING)\" + +# CC_DEF += -DDEBUG + +PRIMS=\ + alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \ + intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \ + signals.c str.c sys.c callback.c weak.c finalise.c stacks.c \ + dynlink.c backtrace_prim.c backtrace.c spacetime.c afl.c \ + bigarray.c + +BYTERUN_SRC=$(addsuffix .c, \ + interp misc stacks fix_code startup_aux startup \ + freelist major_gc minor_gc memory alloc roots globroots \ + fail signals signals_byt printexc backtrace_prim backtrace \ + compare ints floats str array io extern intern \ + hash sys meta parsing gc_ctrl md5 obj \ + lexing callback debugger weak compact finalise custom \ + dynlink spacetime afl unix bigarray main instrtrace) + +primitives : $(addprefix $(BYTERUN_DIR)/,$(PRIMS)) + $(MSG_CONVERT $@) + $(VERBOSE)sed -n -e "s/CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p" $^ \ + | LC_ALL=C sort | uniq > primitives + +.headers: caml/opnames.h caml/jumptbl.h + $(VERBOSE)touch $@ + +prims.c : primitives .headers + $(MSG_CONVERT $@) + $(VERBOSE)(echo '#define CAML_INTERNALS'; \ + echo '#include "caml/mlvalues.h"'; \ + echo '#include "caml/prims.h"'; \ + sed -e 's/.*/extern value &();/' primitives; \ + echo 'c_primitive caml_builtin_cprim[] = {'; \ + sed -e 's/.*/ &,/' primitives; \ + echo ' 0 };'; \ + echo 'char * caml_names_of_builtin_cprim[] = {'; \ + sed -e 's/.*/ "&",/' primitives; \ + echo ' 0 };') > prims.c + +caml/opnames.h : $(BYTERUN_DIR)/caml/instruct.h + $(MSG_CONVERT $@) + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)cat $^ | tr -d '\r' | \ + sed -e '/\/\*/d' \ + -e '/^#/d' \ + -e 's/enum /char * names_of_/' \ + -e 's/{$$/[] = {/' \ + -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' > $@ + +caml/jumptbl.h: $(BYTERUN_DIR)/caml/instruct.h + $(MSG_CONVERT $@) + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)sed -E -n -e '/^ /s/ ([A-Z])/ \&\&lbl_\1/gp' -e '/^}/q' $< > $@ + +caml/version.h: + $(MSG_CONVERT $@) + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)echo #define OCAML_VERSION $(OCAML_VERSION_STRING) > $@ + +SRC_C += $(PRIMS) +SRC_C += $(BYTERUN_SRC) +SRC_C += prims.c + +vpath %.c $(BYTERUN_DIR) + +$(BYTERUN_SRC:.c=.o): .headers