From dea68bafe81c40adf29e45630cfeceb97b91a630 Mon Sep 17 00:00:00 2001 From: lemon Date: Tue, 30 Aug 2022 10:41:16 +0200 Subject: Makefile and such --- Makefile | 42 ++++++++++++++++++++++++++ bootstrap/bootstrap.sh | 2 ++ bootstrap/cgen.c | 3 ++ src/llvm.cff | 9 +++--- src/main.cff | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- src/parse.cff | 4 +++ src/targ.cff | 2 +- test/3.cff | 19 ++++++++++++ 8 files changed, 150 insertions(+), 11 deletions(-) create mode 100644 Makefile create mode 100644 test/3.cff 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)); +} -- cgit v1.2.3