aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile42
-rwxr-xr-xbootstrap/bootstrap.sh2
-rw-r--r--bootstrap/cgen.c3
-rw-r--r--src/llvm.cff9
-rw-r--r--src/main.cff80
-rw-r--r--src/parse.cff4
-rw-r--r--src/targ.cff2
-rw-r--r--test/3.cff19
8 files changed, 150 insertions, 11 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..72d7007
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,42 @@
+CFFC ?= cffc
+SRCS=src/env.cff \
+ src/fmt.cff \
+ src/fold.cff \
+ src/host-target-triple.cff \
+ src/llvm.cff \
+ src/main.cff \
+ src/parse.cff \
+ src/targ.cff \
+ src/type.cff \
+ src/util.cff
+
+OBJ=$(foreach o,$(subst .cff,.o,$(SRCS)),build/$o)
+OUT ?= cffc
+
+
+ifneq ($(VERBOSE),)
+ V=
+else
+ V=@
+endif
+
+all: $(OUT)
+
+clean:
+ $(RM) -r build/ src/host-target-triple.cff
+
+$(OUT): $(OBJ)
+
+src/host-target-triple.cff:
+ echo "extern static host_target_triple const *const u8 = \"`clang -print-target-triple`\";" > $@
+
+$(OBJ): $(wildcard src/*.hff)
+
+build/%.o: %.cff
+ $Vmkdir -p `dirname $@`
+ @echo -e '\e[1mCFFC\e[0m' '\e[32m'"$<"'\e[0m' '->' '\e[34m'"$@"'\e[0m'
+ $V$(CFFC) $< -o $@.ll
+ $Vset -euo pipefail;\
+ (opt -Oz -opaque-pointers $@.ll | llc --relocation-model=pic -opaque-pointers | as - -o $@) || ($(RM) $@; false)
+
+
diff --git a/bootstrap/bootstrap.sh b/bootstrap/bootstrap.sh
index 1d682dc..64b7186 100755
--- a/bootstrap/bootstrap.sh
+++ b/bootstrap/bootstrap.sh
@@ -29,3 +29,5 @@ for f in $(find ../src/ -name '*.c'); do
done
set -x
$CC $CFLAGS -ocff1 obj1/*.o
+
+CFFC=$(dirname "$0")/cff1 make -C ../
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 0bd7851..7db84ea 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -815,6 +815,9 @@ defctype(const struct type *ty, void *_) {
}
break;
case TYslice:
+ if (ty->konst) {
+ ty = unconstify(ty);
+ }
if (ty->child->konst) {
const struct type *ty2 = unconstifychild(ty);
defctype(ty2, NULL);
diff --git a/src/llvm.cff b/src/llvm.cff
index d8c8a32..97d1e3c 100644
--- a/src/llvm.cff
+++ b/src/llvm.cff
@@ -93,7 +93,6 @@ fn gen(fmt *const u8, ...) void {
case Bool; gen("i%z", ty.size*8);
case Int; gen("i%z", ty.size*8);
case Flo; gen(ty.size == 4 ? "float" : "double");
- // case Ptr p; gen("%t*", p->is(:Void) ? ty_i8 : p);
case Ptr p; gen("ptr");
case Slice p; gen("{ %t, %t }", mkptrtype(p), ty_usize);
case Arr arr;
@@ -485,9 +484,8 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value {
case to->is(:Ptr) and from->is(:Arr);
let addr = genref(f, ex).Addr;
- let t = mktmp(ex.ty);
- gen("\t%v = getelementptr %t, %t %v, %t 0, %t 0\n", &t, addr.ty.u.Ptr, addr.ty, &addr,
- ty_usize, ty_usize);
+ let t = mktmp(to);
+ gen("\t%v = getelementptr %t, %t %v, i32 0, i32 0\n", &t, addr.ty.u.Ptr, addr.ty, &addr);
return t;
case to->is(:Arr) and from->is(:Arr);
@@ -621,6 +619,7 @@ fn genexpr(f *Fn, ex *Expr) Value {
case '=';
let ref = genref(f, b.lhs);
let rhs = convert(f, b.lhs.ty, b.rhs);
+ gen("; %t\n",b.lhs.ty);
genstore(f, ref, rhs);
return genload(f, ref); // load again because value could have overflowed when storing it
@@ -1272,8 +1271,8 @@ extern fn llvm_genfn(externp bool, name *const u8, f *Fn) void {
if i < f.paramnames.#len - 1 or f.variadic {
gen(", ");
}
- if f.variadic { gen("..."); }
}
+ if f.variadic { gen("..."); }
gen(") { \n");
let id = 0;
foreach(nam, i, f.paramnames) {
diff --git a/src/main.cff b/src/main.cff
index b8829a7..9f9181c 100644
--- a/src/main.cff
+++ b/src/main.cff
@@ -1,21 +1,91 @@
import "cffc.hff";
import "common.hff";
+fn prihelp(f *FILE, progname *const u8) void {
+ fprintf(f, "Usage: %s: [OPTION]... [FILE]\n", progname);
+ fprintf(f, "Compile cffc source code in FILE\n"
+ "\n"
+ "Options:\n"
+ " --help, -h:\t\tshow this help message\n"
+ " --target triple:\tset compilation target triple\n"
+ " -:\t\t\tread input from stdin\n"
+ " -o -:\t\tset output to stdout\n"
+ " -o path:\t\tset output file path\n");
+}
+
extern fn main(argc int, argv **u8) int {
- assert(argc > 1, "args?");
+ let triple = #null;
+ let path *const u8 = #null;
+ let outfile *FILE = #null;
+ for let i = 1; i < argc; ++i {
+ let arg = argv[i];
+ defmacro nextarg() [
+ (do let $next = argv[++i];
+ if $next == #null {
+ fprintf(stderr, "%s: error: argument expected after `%s'\n", argv[0], arg);
+ fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
+ return 1;
+ }
+ $next;);
+ ]
+ switch {
+ case streq(arg, "-h") or streq(arg, "--help");
+ prihelp(stdout, argv[1]);
+ return 0;
+
+ case streq(arg, "-");
+ path = "/dev/stdin";
+
+ case streq(arg, "--target");
+ triple = nextarg();
+
+ case streq(arg, "-o");
+ let outpath = nextarg();
+ outfile = streq(outpath, "-") ? stdout : fopen(outpath, "wb");
+ if outfile == #null {
+ fprintf(stderr, "%s: error: cannot open '%s': %s\n", argv[0], outpath, strerror(errno));
+ return 1;
+ }
+
+ case *arg == '-';
+ fprintf(stderr, "%s: error: unknown option '%s'\n1", argv[0], arg);
+ fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
+ return 1;
+
+ case else
+ if path {
+ fprintf(stderr, "%s: error: path was already given\n", argv[0]);
+ fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
+ return 1;
+ }
+ path = arg;
+ }
+ }
+
+ if path == #null {
+ fprintf(stderr, "%s: error: no input file\n", argv[0]);
+ fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
+ return 1;
+ }
+
+ if outfile == #null {
+ fprintf(stderr, "%s: error: no output file\n", argv[0]);
+ fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
+ return 1;
+ }
- let triple = host_target_triple;
+ triple = triple ?? host_target_triple;
let targ = triple2targ(triple);
if targ == #null {
- fprintf(stderr, "error: unsupported target triple `%s'\n", triple);
+ fprintf(stderr, "%s: error: unsupported target triple `%s'\n", argv[0], triple);
return 1;
}
targ_ini(targ);
g_targ.triple = triple;
let p = Parser {};
- parser_init(&p, argv[1]);
- llvm_init(stdout);
+ parser_init(&p, path);
+ llvm_init(outfile);
let decls = parse(&p);
defer free(decls.#ptr);
if p.error { return 1; }
diff --git a/src/parse.cff b/src/parse.cff
index aad88d1..dbc8e29 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -3014,7 +3014,11 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
}
}
+
switch {
+ case lexmatch(P, &tok, ';') or lexmatch(P, &tok, :eof);
+ // no-op
+
case lexmatch(P, &tok, :kw_fn);
let name = lexmatch(P, &tok, :ident) ? tok.u.ident : #null;
decl = parsefn(P, tok.loc, toplevel, externp, name);
diff --git a/src/targ.cff b/src/targ.cff
index 583a733..fefd10a 100644
--- a/src/targ.cff
+++ b/src/targ.cff
@@ -36,7 +36,7 @@ extern fn triple2targ(triple *const u8) *const u8 {
delim ? triple[0::delim - triple] : spanz(triple);
);
let rest = arch.#ptr + arch.#len;
- defmacro archp(s) [ (strncmp(s, arch.#ptr, arch.#len) == 0) ]
+ defmacro archp(s) [ (arch.#len == (s.#len-1) and memcmp(arch.#ptr, s, arch.#len) == 0) ]
defmacro restp(s) [ (strstr(rest, s) != #null) ]
switch {
case archp("x86_64") and !restp("windows"); return "amd64-sysv";
diff --git a/test/3.cff b/test/3.cff
new file mode 100644
index 0000000..7103225
--- /dev/null
+++ b/test/3.cff
@@ -0,0 +1,19 @@
+import "libc.hff";
+
+fn sum(res int, ...) int {
+ let ap va_list = {};
+ ap->start();
+ printf("%d ", res);
+ for ;; {
+ let n = ap->arg(int);
+ printf("+ %d ", n);
+ res += n;
+ if n == 0 { break; }
+ }
+ ap->end();
+ return res;
+}
+
+extern fn main(argc int, argv **u8) int {
+ printf("= %d\n", sum(1,2,3,42,-1,0));
+}