ref: 378fb4a0d93ceb5cae74fd6da682d1669fdfa6c6
parent: 5c185d0fad931e47299d282edfa834d10c28142e
author: Ori Bernstein <[email protected]>
date: Mon Aug 11 15:34:12 EDT 2014
Spit out the runtime from libstd. This will allow linking code without libstd, as well as fixing link order on freebsd. Freebsd seems to be picky aobut where '_start' is searched from.
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
6 \
muse \
myrbuild \
+ rt \
libstd \
doc
--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -53,7 +53,6 @@
waitstatus.myr \
ASMSRC= \
- start.s \
syscall.s \
util.s
--- a/libstd/start-freebsd.s
+++ /dev/null
@@ -1,123 +1,0 @@
-.data
-/* std._environment : byte[:][:] */
-.globl std$_environment
-std$_environment:
-.envbase:
-.quad 0 /* env size */
-.envlen:
-.quad 0 /* env ptr */
-
-.globl std$__cenvp
-std$__cenvp:
-.quad 0
-
-.text
-/*
- * counts the length of the string pointed to
- * by %r8, returning len in %r9. Does not modify
- * any registers outside of %r9
- */
-cstrlen:
- xorq %r9,%r9
- jmp .lentest
-
- .lenloop:
- incq %r9
- .lentest:
- cmpb $0,(%r8,%r9)
- jne .lenloop
- ret
-
-
-/*
- * Counts the size of the null terminated string vector
- * pointed to by %rbx. Clobbers %r10,%r11
- */
-count:
- xorq %r9,%r9
- movq %rbx,%r11
-.countloop:
- movq (%r11),%r10
- testq %r10,%r10
- jz .countdone
- addq $1,%r9
- addq $8,%r11
- jmp .countloop
-.countdone:
- ret
-
-/*
- * iterate over the strings for argc, and put
- * them into the args array.
- *
- * Args:
- * %rax: holds argc
- * %rbx: holds argv
- * %rcx: output destination
- * Clobbers:
- * %r8, %r9
- */
-cvt:
- jmp .cvttest
-.cvtloop:
- subq $1,%rax
- movq (%rbx),%r8
- call cstrlen
- movq %r8, (%rcx)
- movq %r9, 8(%rcx)
- addq $8, %rbx
- addq $16, %rcx
-.cvttest:
- testq %rax,%rax
- jnz .cvtloop
-.cvtdone:
- ret
-
-/*
- * The entry point for the whole program.
- * This is called by the OS. In order, it:
- * - Sets up all argc entries as slices
- * - Sets up all envp entries as slices
- * - Converts argc/argv to a slice
- * - Stashes envp in std._environment
- * - Stashes a raw envp copy in __cenvp (for syscalls to use)
- * - Calls main()
- */
-.globl _start
-_start:
- /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
- movq (%rdi),%rax
- leaq 16(%rdi,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
- call count
- addq %r9,%rax
- imulq $16,%rax
- subq %rax,%rsp
- movq %rsp, %rdx /* saved args[:] */
-
- /* convert envp to byte[:][:] for std._environment */
- movq (%rdi),%rax
- leaq 16(%rdi,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
- /* store envp for some syscalls to use without spurious conversion. */
- movq %rbx,std$__cenvp(%rip)
- movq %r9,%rax
- movq %rsp, %rcx
- movq %r9,.envlen
- movq %rdx,.envbase
- call cvt
- movq %rcx,%rdx
-
- /* convert argc, argv to byte[:][:] for args. */
- movq (%rdi), %rax /* argc */
- leaq 8(%rdi), %rbx /* argv */
- movq (%rdi), %rsi /* saved argc */
- call cvt
- pushq %rsi
- pushq %rdx
-
- /* enter the main program */
- call main
- /* exit(0) */
- xorq %rdi,%rdi
- movq $1,%rax
- syscall
-
--- a/libstd/start-linux.s
+++ /dev/null
@@ -1,121 +1,0 @@
-.data
-/* std._environment : byte[:][:] */
-.globl std$_environment
-std$_environment:
-.envbase:
-.quad 0 /* env size */
-.envlen:
-.quad 0 /* env ptr */
-
-.globl std$__cenvp
-std$__cenvp:
-.quad 0
-
-.text
-/*
- * counts the length of the string pointed to
- * by %r8, returning len in %r9. Does not modify
- * any registers outside of %r9
- */
-cstrlen:
- xorq %r9,%r9
- jmp .lentest
-
- .lenloop:
- incq %r9
- .lentest:
- cmpb $0,(%r8,%r9)
- jne .lenloop
- ret
-
-
-/*
- * Counts the size of the null terminated string vector
- * pointed to by %rbx. Clobbers %r10,%r11
- */
-count:
- xorq %r9,%r9
- movq %rbx,%r11
-.countloop:
- movq (%r11),%r10
- testq %r10,%r10
- jz .countdone
- addq $1,%r9
- addq $8,%r11
- jmp .countloop
-.countdone:
- ret
-
-/*
- * iterate over the strings for argc, and put
- * them into the args array.
- *
- * argc in %rax, argv in %rbx, dest vector in %rcx
- */
-cvt:
- jmp .cvttest
-.cvtloop:
- subq $1,%rax
- movq (%rbx),%r8
- call cstrlen
- movq %r8, (%rcx)
- movq %r9, 8(%rcx)
- addq $8, %rbx
- addq $16, %rcx
-.cvttest:
- testq %rax,%rax
- jnz .cvtloop
-.cvtdone:
- ret
-
-/*
- * The entry point for the whole program.
- * This is called by the OS. In order, it:
- * - Sets up all argc entries as slices
- * - Sets up all envp entries as slices
- * - Converts argc/argv to a slice
- * - Stashes envp in std._environment
- * - Stashes a raw envp copy in __cenvp (for syscalls to use)
- * - Calls main()
- */
-.globl _start
-_start:
- /* turn args into a slice */
- movq %rsp,%rbp
-
- /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
- movq (%rbp),%rax
- leaq 16(%rbp,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
- call count
- addq %r9,%rax
- imulq $16,%rax
- subq %rax,%rsp
- movq %rsp, %rdx /* saved args[:] */
-
- /* convert envp to byte[:][:] for std._environment */
- movq (%rbp),%rax
- leaq 16(%rbp,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
- /* store envp for some syscalls to use without converting */
- movq %rbx,std$__cenvp(%rip)
- movq %r9,%rax
- movq %rsp, %rcx
- movq %r9,.envlen
- movq %rdx,.envbase
- call cvt
- movq %rcx,%rdx
-
- /* convert argc, argv to byte[:][:] for args. */
- movq (%rbp), %rax /* argc */
- leaq 8(%rbp), %rbx /* argv */
- movq (%rbp), %rsi /* saved argc */
- call cvt
- pushq %rsi
- pushq %rdx
-
- /* enter the main program */
- call main
- /* exit(0) */
- xorq %rdi,%rdi
- movq $60,%rax
- syscall
-
--- a/libstd/start-osx.s
+++ /dev/null
@@ -1,119 +1,0 @@
-.data
-/* std._environment : byte[:][:] */
-.globl _std$_environment
-_std$_environment:
-.envbase:
-.quad 0 /* env size */
-.envlen:
-.quad 0 /* env ptr */
-
-.globl _std$__cenvp
-_std$__cenvp:
-.quad 0
-
-.text
-/*
- * counts the length of the string pointed to
- * by %r8, returning len in %r9. Does not modify
- * any registers outside of %r9
- */
-cstrlen:
- xorq %r9,%r9
- jmp .lentest
-
- .lenloop:
- incq %r9
- .lentest:
- cmpb $0,(%r8,%r9)
- jne .lenloop
- ret
-
-
-/*
- * Counts the size of the null terminated string vector
- * pointed to by %rbx. Clobbers %r10,%r11
- */
-count:
- xorq %r9,%r9
- movq %rbx,%r11
-.countloop:
- movq (%r11),%r10
- testq %r10,%r10
- jz .countdone
- addq $1,%r9
- addq $8,%r11
- jmp .countloop
-.countdone:
- ret
-
-/*
- * iterate over the strings for argc, and put
- * them into the args array.
- *
- * argc in %rax, argv in %rbx, dest vector in %rcx
- */
-cvt:
- jmp .cvttest
-.cvtloop:
- subq $1,%rax
- movq (%rbx),%r8
- call cstrlen
- movq %r8, (%rcx)
- movq %r9, 8(%rcx)
- addq $8, %rbx
- addq $16, %rcx
-.cvttest:
- testq %rax,%rax
- jnz .cvtloop
-.cvtdone:
- ret
-
-/*
- * The entry point for the whole program.
- * This is called by the OS. In order, it:
- * - Sets up all argc entries as slices
- * - Sets up all envp entries as slices
- * - Converts argc/argv to a slice
- * - Stashes envp in std._environment
- * - Stashes a raw envp copy in __cenvp (for syscalls to use)
- * - Calls main()
- */
-.globl start
-start:
- /* turn args into a slice */
- movq %rsp,%rbp
- /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
- movq (%rbp),%rax
- leaq 16(%rbp,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
- call count
- addq %r9,%rax
- imulq $16,%rax
- subq %rax,%rsp
- movq %rsp, %rdx /* saved args[:] */
-
- /* convert envp to byte[:][:] for std._environment */
- movq (%rbp),%rax
- leaq 16(%rbp,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
- movq %rbx,_std$__cenvp(%rip)
- movq %r9,%rax
- movq %rsp, %rcx
- movq %r9,.envlen(%rip)
- movq %rdx,.envbase(%rip)
- call cvt
- movq %rcx,%rdx
-
- /* convert argc, argv to byte[:][:] for args. */
- movq (%rbp), %rax /* argc */
- leaq 8(%rbp), %rbx /* argv */
- movq (%rbp), %rsi /* saved argc */
- call cvt
- pushq %rsi
- pushq %rdx
-
- /* enter the main program */
- call _main
- /* exit */
- xorq %rdi,%rdi
- movq $0x2000001,%rax
- syscall
-
--- a/myrbuild/myrbuild.c
+++ b/myrbuild/myrbuild.c
@@ -30,6 +30,8 @@
char *ar = "ar";
char *ld = "ld";
char *muse = "muse";
+char *runtime = "_myrrt.o";
+char *runtimepath;
/* the name of the output file */
char *libname;
char *binname;
@@ -194,7 +196,6 @@
char buf[1024];
size_t i;
- snprintf(buf, sizeof buf, "%s/%s/%s", Instroot, "/lib/myr", lib);
f = fopen(buf, "r");
if (f)
return f;
@@ -404,6 +405,10 @@
lappend(&args, &nargs, strdup(buf));
}
+ if (runtimepath) {
+ lappend(&args, &nargs, strdup(runtimepath));
+ }
+
/* ld -T ldscript -o outfile foo.o bar.o baz.o */
for (i = 0; i < nfiles; i++) {
if (hassuffix(files[i], ".myr"))
@@ -420,8 +425,6 @@
snprintf(buf, sizeof buf, "-L%s", incpaths[i]);
lappend(&args, &nargs, strdup(buf));
}
- snprintf(buf, sizeof buf, "-L%s%s", Instroot, "/lib/myr");
- lappend(&args, &nargs, strdup(buf));
/* ld -T ldscript -o outfile foo.o bar.o baz.o -L/path1 -L/path2 -llib1 -llib2*/
addlibs(&args, &nargs, libgraph);
@@ -442,6 +445,24 @@
lfree(&args, &nargs);
}
+void findruntime()
+{
+ char buf[2048];
+ size_t i;
+
+ if (!strcmp(runtime, "none"))
+ runtimepath = NULL;
+ for (i = 0; i < nincpaths; i++) {
+ snprintf(buf, sizeof buf, "%s/%s", incpaths[i], runtime);
+ if (access(buf, R_OK) == 0) {
+ printf("Got %s\n", buf);
+ runtimepath = strdup(buf);
+ return;
+ }
+ }
+ err(1, "Could not find runtime %s", runtime);
+}
+
int main(int argc, char **argv)
{
int opt;
@@ -450,7 +471,8 @@
if (uname(&name) == 0)
sysname = strdup(name.sysname);
- while ((opt = getopt(argc, argv, "hb:l:s:SI:C:A:M:L:R:")) != -1) {
+ lappend(&incpaths, &nincpaths, strdup(Instroot "/lib/myr"));
+ while ((opt = getopt(argc, argv, "hb:l:s:r:SI:C:A:M:L:R:")) != -1) {
switch (opt) {
case 'b': binname = optarg; break;
case 'l': libname = optarg; break;
@@ -461,8 +483,9 @@
case 'M': muse = optarg; break;
case 'L': ld = optarg; break;
case 'R': ar = optarg; break;
+ case 'r': runtime = optarg; break;
case 'I':
- lappend(&incpaths, &nincpaths, optarg);
+ lappend(&incpaths, &nincpaths, strdup(optarg));
break;
case 'h':
usage(argv[0]);
@@ -481,6 +504,7 @@
libgraph = mkht(strhash, streq);
compiled = mkht(strhash, streq);
loopdetect = mkht(strhash, streq);
+ findruntime();
regcomp(&usepat, "^[[:space:]]*use[[:space:]]+([^[:space:]]+)", REG_EXTENDED);
for (i = optind; i < argc; i++)
compile(argv[i]);
--- /dev/null
+++ b/rt/Makefile
@@ -1,0 +1,25 @@
+OBJ = _myrrt.o
+ASMSRC = start.s common.s
+
+all: _myrrt.o
+
+include ../config.mk
+
+_myrrt.o: _myrrt.s
+ as -g -o $@ $^
+
+_myrrt.s: $(ASMSRC)
+ cat $(ASMSRC) > $@
+
+%.s: %-$(SYS).s
+ cp $< $@
+
+install: all
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/lib/myr)
+ install _myrrt.o $(abspath $(DESTDIR)/$(INST_ROOT)/lib/myr)
+
+uninstall:
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/myr/_myrrt.o)
+
+clean:
+ rm -f _myrrt.o _myrrt.s start.s
--- /dev/null
+++ b/rt/start-freebsd.s
@@ -1,0 +1,62 @@
+.data
+/* std._environment : byte[:][:] */
+.globl std$_environment
+std$_environment:
+.envbase:
+.quad 0 /* env size */
+.envlen:
+.quad 0 /* env ptr */
+
+.globl std$__cenvp
+std$__cenvp:
+.quad 0
+
+.text
+/*
+ * The entry point for the whole program.
+ * This is called by the OS. In order, it:
+ * - Sets up all argc entries as slices
+ * - Sets up all envp entries as slices
+ * - Converts argc/argv to a slice
+ * - Stashes envp in std._environment
+ * - Stashes a raw envp copy in __cenvp (for syscalls to use)
+ * - Calls main()
+ */
+.globl _start
+_start:
+ /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
+ movq (%rdi),%rax
+ leaq 16(%rdi,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
+ call count
+ addq %r9,%rax
+ imulq $16,%rax
+ subq %rax,%rsp
+ movq %rsp, %rdx /* saved args[:] */
+
+ /* convert envp to byte[:][:] for std._environment */
+ movq (%rdi),%rax
+ leaq 16(%rdi,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
+ /* store envp for some syscalls to use without spurious conversion. */
+ movq %rbx,std$__cenvp(%rip)
+ movq %r9,%rax
+ movq %rsp, %rcx
+ movq %r9,.envlen
+ movq %rdx,.envbase
+ call cvt
+ movq %rcx,%rdx
+
+ /* convert argc, argv to byte[:][:] for args. */
+ movq (%rdi), %rax /* argc */
+ leaq 8(%rdi), %rbx /* argv */
+ movq (%rdi), %rsi /* saved argc */
+ call cvt
+ pushq %rsi
+ pushq %rdx
+
+ /* enter the main program */
+ call main
+ /* exit(0) */
+ xorq %rdi,%rdi
+ movq $1,%rax
+ syscall
+
--- /dev/null
+++ b/rt/start-linux.s
@@ -1,0 +1,74 @@
+.data
+/* std._environment : byte[:][:] */
+.globl std$_environment
+std$_environment:
+.envbase:
+.quad 0 /* env size */
+.envlen:
+.quad 0 /* env ptr */
+
+.globl std$__cenvp
+std$__cenvp:
+.quad 0
+
+.text
+/*
+ * The entry point for the whole program.
+ * This is called by the OS. In order, it:
+ * - Sets up all argc entries as slices
+ * - Sets up all envp entries as slices
+ * - Converts argc/argv to a slice
+ * - Stashes envp in std._environment
+ * - Stashes a raw envp copy in __cenvp (for syscalls to use)
+ * - Calls main()
+ */
+.globl _start
+_start:
+ /* turn args into a slice */
+ movq %rsp,%rbp
+
+ /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
+ movq (%rbp),%rax
+ leaq 16(%rbp,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
+ call count
+ addq %r9,%rax
+ imulq $16,%rax
+ subq %rax,%rsp
+ movq %rsp, %rdx /* saved args[:] */
+
+ /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
+ movq (%rbp),%rax
+ leaq 16(%rbp,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
+ call count
+ addq %r9,%rax
+ imulq $16,%rax
+ subq %rax,%rsp
+ movq %rsp, %rdx /* saved args[:] */
+
+ /* convert envp to byte[:][:] for std._environment */
+ movq (%rbp),%rax
+ leaq 16(%rbp,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
+ /* store envp for some syscalls to use without converting */
+ movq %rbx,std$__cenvp(%rip)
+ movq %r9,%rax
+ movq %rsp, %rcx
+ movq %r9,.envlen
+ movq %rdx,.envbase
+ call cvt
+ movq %rcx,%rdx
+
+ /* convert argc, argv to byte[:][:] for args. */
+ movq (%rbp), %rax /* argc */
+ leaq 8(%rbp), %rbx /* argv */
+ movq (%rbp), %rsi /* saved argc */
+ call cvt
+ pushq %rsi
+ pushq %rdx
+
+ /* enter the main program */
+ call main
+ /* exit(0) */
+ xorq %rdi,%rdi
+ movq $60,%rax
+ syscall
+
--- /dev/null
+++ b/rt/start-osx.s
@@ -1,0 +1,63 @@
+.data
+/* std._environment : byte[:][:] */
+.globl _std$_environment
+_std$_environment:
+.envbase:
+.quad 0 /* env size */
+.envlen:
+.quad 0 /* env ptr */
+
+.globl _std$__cenvp
+_std$__cenvp:
+.quad 0
+
+.text
+/*
+ * The entry point for the whole program.
+ * This is called by the OS. In order, it:
+ * - Sets up all argc entries as slices
+ * - Sets up all envp entries as slices
+ * - Converts argc/argv to a slice
+ * - Stashes envp in std._environment
+ * - Stashes a raw envp copy in __cenvp (for syscalls to use)
+ * - Calls main()
+ */
+.globl start
+start:
+ /* turn args into a slice */
+ movq %rsp,%rbp
+ /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
+ movq (%rbp),%rax
+ leaq 16(%rbp,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
+ call count
+ addq %r9,%rax
+ imulq $16,%rax
+ subq %rax,%rsp
+ movq %rsp, %rdx /* saved args[:] */
+
+ /* convert envp to byte[:][:] for std._environment */
+ movq (%rbp),%rax
+ leaq 16(%rbp,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
+ movq %rbx,_std$__cenvp(%rip)
+ movq %r9,%rax
+ movq %rsp, %rcx
+ movq %r9,.envlen(%rip)
+ movq %rdx,.envbase(%rip)
+ call cvt
+ movq %rcx,%rdx
+
+ /* convert argc, argv to byte[:][:] for args. */
+ movq (%rbp), %rax /* argc */
+ leaq 8(%rbp), %rbx /* argv */
+ movq (%rbp), %rsi /* saved argc */
+ call cvt
+ pushq %rsi
+ pushq %rdx
+
+ /* enter the main program */
+ call _main
+ /* exit */
+ xorq %rdi,%rdi
+ movq $0x2000001,%rax
+ syscall
+
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -16,7 +16,7 @@
function build {
rm -f $1 $1.o $1.s $1.use
- ../myrbuild/myrbuild -b $1 -C../6/6m -M../muse/muse -I../libstd $1.myr
+ ../myrbuild/myrbuild -b $1 -C../6/6m -M../muse/muse -I../libstd -I../rt $1.myr
}
function pass {