diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-11-16 09:16:07 -0800 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-11-16 20:37:55 -0800 |
commit | 53921862b61b4c33f29c8810898deb354d02fb28 (patch) | |
tree | 7795c7e299f88ae50b75da65787035f40cbd55d3 | |
parent | 3c348076e792369472ec5c01a9c81e22440eb488 (diff) | |
download | mcbind-53921862b61b4c33f29c8810898deb354d02fb28.tar.gz |
Mostly working parsing and code gen.
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | asmgen.c | 0 | ||||
-rw-r--r-- | cgen.c | 52 | ||||
-rw-r--r-- | cparse.c | 268 | ||||
-rw-r--r-- | dclrepo.c | 0 | ||||
-rw-r--r-- | htab.c | 257 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | mcbind.h | 22 | ||||
-rw-r--r-- | myrgen.c | 121 | ||||
-rw-r--r-- | types.c | 151 | ||||
-rw-r--r-- | util.c | 18 | ||||
-rw-r--r-- | util.h | 2 |
12 files changed, 763 insertions, 145 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..756bfee --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +INSTBIN=mcbind +OBJ = \ + cparse.o \ + htab.o \ + main.o \ + cgen.o \ + myrgen.o \ + optctx.o \ + types.o \ + util.o \ + +include config.mk +include mk/c.mk diff --git a/asmgen.c b/asmgen.c deleted file mode 100644 index e69de29..0000000 --- a/asmgen.c +++ /dev/null @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <assert.h> @@ -9,9 +10,9 @@ void writecdecl(FILE *fd, Type *ty, char *name) { - size_t i; - char *sep; char buf[64]; + char *sep; + size_t i; switch (ty->type) { case Tynone: die("invalid type\n"); break; @@ -39,16 +40,15 @@ void writecdecl(FILE *fd, Type *ty, char *name) case Tyflt64: fprintf(fd, "double %s", name); break; case Typtr: - fprintf(fd, "(*"); writecdecl(fd, ty->sub[0], ""); - fprintf(fd, ")"); + fprintf(fd, "(*%s)", name); break; case Tyfunc: - writecdecl(fd, ty->sub[0], ""); + writecdecl(fd, ty->sub[0], name); fprintf(fd, " %s(", name); sep = ""; - for (i = 0; i < ty->nsub - 1; i++) { + for (i = 1; i < ty->nsub; i++) { fprintf(fd, "%s", sep); if (ty->subname[i]) { writecdecl(fd, ty->sub[i], ty->subname[i]); @@ -85,36 +85,42 @@ void writecdecl(FILE *fd, Type *ty, char *name) fprintf(fd, "}"); break; case Tyname: - fprintf(fd, "typedef "); - writecdecl(fd, ty->sub[0], ty->defname); - break; - case Tyopaque: - fprintf(fd, "/*opaque %s: */byte[%zd]", ty->defname, ty->arraysz); + if (ty->sub) + fprintf(fd, "%s %s", ty->defname, name); + else + fprintf(fd, "(struct {byte buf[%zu];}) %s", ty->size, name); break; } } void writewrapper(FILE *fd, Dcl *dcl) { + size_t i, argoff; char buf[64]; char *sep; Type *ty; - size_t i; ty = dcl->type; - fprintf(fd, "{\n"); + argoff = 0; + fprintf(fd, "{\n"); fprintf(fd, "\t"); - if (ty->sub[0]->type != Tyvoid) + if (needswrapper(ty->sub[0])) { + argoff = 1; + fprintf(fd, "*a1 = "); + } else if (ty->sub[0]->type != Tyvoid) { fprintf(fd, "return "); + } fprintf(fd, "%s(", dcl->name); sep = ""; - for (i = 0; i < ty->nsub - 1; i++) { + for (i = 1; i < ty->nsub; i++) { + if (needswrapper(ty->sub[i])) + fprintf(fd, "*"); if (ty->subname[i]) { fprintf(fd, "%s%s", sep, ty->subname[i]); } else { - snprintf(buf, sizeof buf, "a%zd", i); + snprintf(buf, sizeof buf, "a%zd", i + argoff); fprintf(fd, "%s%s", sep, buf); } sep = ", "; @@ -135,9 +141,17 @@ void aliasdecl(FILE *fd, Dcl *dcl, char *pkg) void funcdcl(FILE *fd, Dcl *dcl, char *pkg) { char buf[512]; - - snprintf(buf, sizeof buf, "%s$%s", pkg, dcl->name); - writecdecl(fd, dcl->type, buf); + char *suffix; + Type *w; + + suffix = ""; + w = dcl->type; + if (funcneedswrapper(dcl->type)) { + suffix = "_wrapped"; + w = wrappedtype(w); + } + snprintf(buf, sizeof buf, "%s$%s%s", pkg, dcl->name, suffix); + writecdecl(fd, w, buf); fprintf(fd, "\n"); writewrapper(fd, dcl); } @@ -1,6 +1,8 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> +#include <stdbool.h> +#include <stdarg.h> #include <string.h> #include <assert.h> @@ -9,7 +11,33 @@ #include "util.h" #include "mcbind.h" -Type *gettype(CXType t); +Type *gettype(CXCursor c, CXType t); +Type *gettypex(CXCursor c, CXType t, const char *tydef, bool defn); + +void p(CXCursor c) +{ + printf("%s\n", clang_getCString(clang_getCursorSpelling(c))); +} + +void parsefail(CXCursor c, char *msg, ...) +{ + CXSourceLocation loc; + unsigned line, col; + CXString path; + CXFile file; + va_list ap; + + loc = clang_getCursorLocation(c); + clang_getFileLocation(loc, &file, &line, &col, NULL); + path = clang_getFileName(file); + + + va_start(ap, msg); + fprintf(stderr, "%s:%u,%u: ", clang_getCString(path), line, col); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); +} Dcl *mkdcl(char *cname, Type *type, int isconst) { @@ -28,6 +56,11 @@ void initargs(char ***args, size_t *nargs, char *f) *args = NULL; *nargs = 0; + lappend(args, nargs, "/usr/lib/gcc/x86_64-linux-gnu/5/include"); + lappend(args, nargs, "-I/usr/local/include"); + lappend(args, nargs, "-I/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed"); + lappend(args, nargs, "-I/usr/lib/gcc/x86_64-linux-gnu/5/include"); + lappend(args, nargs, "-I/usr/lib/gcc/x86_64-linux-gnu"); lappend(args, nargs, "-I/usr/include"); lappend(args, nargs, "-I."); lappend(args, nargs, f); @@ -49,25 +82,39 @@ addmembers(CXCursor c, CXCursor pc, CXClientData d) CXString str, dname; CXType mtype; Type *ty, *mty; + char buf[64]; char *name; - - if (clang_getCursorKind(c) != CXCursor_FieldDecl) { - str = clang_getCursorSpelling(c); - printf("%s is not a member\n", clang_getCString(str)); - clang_disposeString(str); - return CXChildVisit_Continue; - } ty = d; mtype = clang_getCursorType(c); - dname = clang_getCursorSpelling(c); - name = strdup(clang_getCString(dname)); - mty = gettype(mtype); + + switch (clang_getCursorKind(c)) { + case CXCursor_FieldDecl: + dname = clang_getCursorSpelling(c); + name = strdup(clang_getCString(dname)); + mty = gettype(c, mtype); + break; + case CXCursor_UnionDecl: + snprintf(buf, sizeof buf, "__anon%zd", ty->nsub); + name = strdup(buf); + mty = gettypex(c, mtype, name, true); + case CXCursor_StructDecl: + snprintf(buf, sizeof buf, "__anon%zd", ty->nsub); + name = strdup(buf); + mty = gettypex(c, mtype, name, true); + break; + default: + str = clang_getCursorSpelling(c); + printf("%s is not a member\n", clang_getCString(str)); + clang_disposeString(str); + return CXChildVisit_Continue; + } lappend(&ty->sub, &ty->nsub, mty); lappend(&ty->subname, &ty->nsubname, name); return CXChildVisit_Continue; } + Type *gettyperecord(CXType t, const char *tydef) { CXCursor c; @@ -97,96 +144,114 @@ Type *gettyperecord(CXType t, const char *tydef) return ty; } -Type *gettypex(CXType t, const char *tydef) +Type *gettypex(CXCursor c, CXType t, const char *tydef, bool defn) { - size_t narg, sz, i; - CXType subt; CXString str; - char *s; + CXType subt; + size_t narg, sz, i; Type *ty; + const char *s; switch (t.kind) { case CXType_Invalid: - case CXType_Void: return mktype(Tyvoid); break; - case CXType_Bool: return mktype(Tybool); break; - case CXType_Char_U: return mktype(Tybyte); break; - case CXType_UChar: return mktype(Tybyte); break; - case CXType_Char32: return mktype(Tychar); break; - case CXType_UShort: return mktype(Tyuint16); break; - case CXType_UInt: return mktype(Tyuint32); break; - case CXType_ULong: return mktype(Tyuint64); break; - case CXType_ULongLong: return mktype(Tyuint64); break; - - case CXType_Char_S: return mktype(Tyint8); break; - case CXType_SChar: return mktype(Tyint8); break; - case CXType_Short: return mktype(Tyint16); break; - case CXType_Int: return mktype(Tyint32); break; - case CXType_Long: return mktype(Tyint64); break; - case CXType_LongLong: return mktype(Tyint64); break; - - case CXType_Float: return mktype(Tyflt32); break; - case CXType_Double: return mktype(Tyflt64); break; + case CXType_Void: ty = mktype(Tyvoid); break; + case CXType_Bool: ty = mktype(Tybool); break; + case CXType_Char_U: ty = mktype(Tybyte); break; + case CXType_UChar: ty = mktype(Tybyte); break; + case CXType_Char32: ty = mktype(Tychar); break; + case CXType_UShort: ty = mktype(Tyuint16); break; + case CXType_UInt: ty = mktype(Tyuint32); break; + case CXType_ULong: ty = mktype(Tyuint64); break; + case CXType_ULongLong: ty = mktype(Tyuint64); break; + + case CXType_Char_S: ty = mktype(Tyint8); break; + case CXType_SChar: ty = mktype(Tyint8); break; + case CXType_Short: ty = mktype(Tyint16); break; + case CXType_Int: ty = mktype(Tyint32); break; + case CXType_Long: ty = mktype(Tyint64); break; + case CXType_LongLong: ty = mktype(Tyint64); break; + + case CXType_Float: ty = mktype(Tyflt32); break; + case CXType_Double: ty = mktype(Tyflt64); break; case CXType_ConstantArray: - subt = clang_getArrayElementType(t); - sz = clang_getArraySize(t); - return mktyarray(gettype(subt), sz); - break; + subt = clang_getArrayElementType(t); + sz = clang_getArraySize(t); + ty = mktyarray(gettype(c, subt), sz); + break; case CXType_IncompleteArray: - subt = clang_getArrayElementType(t); - return mktyptr(gettype(subt)); - break; + subt = clang_getArrayElementType(t); + ty = mktyptr(gettype(c, subt)); + break; case CXType_Pointer: - subt = clang_getPointeeType(t); - return mktyptr(gettype(subt)); - break; + subt = clang_getPointeeType(t); + ty = mktyptr(gettype(c, subt)); + break; case CXType_Enum: - printf("ENUM %s\n", clang_getCString(clang_getTypeSpelling(t))); - return NULL; - break; + printf("ENUM %s\n", clang_getCString(clang_getTypeSpelling(t))); + ty = NULL; + break; case CXType_Typedef: - str = clang_getTypeSpelling(t); - s = strdup(clang_getCString(str)); - return mktyname(s); - break; + str = clang_getTypeSpelling(t); + s = clang_getCString(str); + if (!strcmp(s, "__builtin_va_list")) + ty = mktyptr(mktype(Tyvoid)); + else + ty = mktyname(strdup(s)); + clang_disposeString(str); + break; + case CXType_FunctionNoProto: case CXType_FunctionProto: - ty = mktype(Tyfunc); - lappend(&ty->sub, &ty->nsub, gettype(clang_getResultType(t))); - lappend(&ty->subname, &ty->nsubname, NULL); - narg = clang_getNumArgTypes(t); - for (i = 0; i < narg; i++) { - subt = clang_getArgType(t, i); - lappend(&ty->sub, &ty->nsub, gettype(subt)); - lappend(&ty->subname, &ty->nsubname, NULL); - } - return ty; - break; - /* union and enum */ + ty = mktype(Tyfunc); + lappend(&ty->sub, &ty->nsub, gettype(c, clang_getResultType(t))); + lappend(&ty->subname, &ty->nsubname, NULL); + narg = clang_getNumArgTypes(t); + for (i = 0; i < narg; i++) { + subt = clang_getArgType(t, i); + lappend(&ty->sub, &ty->nsub, gettype(c, subt)); + lappend(&ty->subname, &ty->nsubname, NULL); + } + break; + /* union and enum */ case CXType_Record: - return gettyperecord(t, tydef); - + if (!defn) { + str = clang_getTypeSpelling(t); + ty = mktyname(striptype(clang_getCString(str))); + clang_disposeString(str); + } else { + ty = gettyperecord(t, tydef); + } + break; + /* funky char types */ + case CXType_Char16: ty = mktype(Tyint16); break; + case CXType_WChar: ty = mktype(Tyint32); break; + /* Unsupported or non-C type */ case CXType_Unexposed: - str = clang_getTypeSpelling(t); - s = strdup(clang_getCString(str)); - fprintf(stderr, "warning: stubbed type %s: unexposed type\n", s); - clang_disposeString(str); - return mktyopaque(s, clang_Type_getSizeOf(t)); - break; - /* Unsupported or non-C type */ - case CXType_FunctionNoProto: + str = clang_getTypeSpelling(t); + s = clang_getCString(str); + parsefail(c, "warning: unexposed type %s", s); + if (!strcmp(s, "__builtin_va_list")) + ty = mktyptr(mktype(Tyvoid)); + else + ty = mktyname(striptype(clang_getCString(str))); + clang_disposeString(str); + break; default: - str = clang_getTypeSpelling(t); - die("unsupported type %s\n", clang_getCString(str)); - break; + str = clang_getTypeSpelling(t); + parsefail(c, "unsupported type %s", clang_getCString(str)); + exit(0); + break; } + ty->size = clang_Type_getSizeOf(t); + return ty; } -Type *gettype(CXType t) +Type *gettype(CXCursor c, CXType t) { Type *ty; - ty = gettypex(t, NULL); + ty = gettypex(c, t, NULL, false); assert(ty != NULL); return ty; } @@ -205,11 +270,11 @@ void addfuncdcl(CXCursor c) if (clang_isFunctionTypeVariadic(type)) { fprintf(stderr, "rejected %s of type %s: variadics unsupported\n", - clang_getCString(dname), clang_getCString(dtype)); + clang_getCString(dname), clang_getCString(dtype)); goto dispose; } n = strdup(clang_getCString(dname)); - ty = gettype(type); + ty = gettype(c, type); if (ty) { dcl = mkdcl(n, ty, 1); lappend(&binding.dcl, &binding.ndcl, dcl); @@ -232,7 +297,7 @@ void addvardcl(CXCursor c) dname = clang_getCursorSpelling(c); n = strdup(clang_getCString(dname)); - ty = gettype(type); + ty = gettype(c, type); if (ty) { dcl = mkdcl(n, ty, 1); lappend(&binding.dcl, &binding.ndcl, dcl); @@ -244,13 +309,29 @@ void addvardcl(CXCursor c) void addtypedef(CXCursor c) { CXString str; + CXCursor dcl; CXType sub; - Type *ty; + bool defn; + Type *ty; + char *s; str = clang_getCursorSpelling(c); sub = clang_getTypedefDeclUnderlyingType(c); - ty = gettypex(sub, clang_getCString(str)); - lappend(&binding.type, &binding.ntype, ty); + switch (sub.kind) { + case CXType_Unexposed: + dcl = clang_getTypeDeclaration(sub); + sub = clang_getCursorType(dcl); + defn = false; + break; + default: + dcl = c; + defn = true; + break; + }; + s = strdup(clang_getCString(str)); + ty = gettypex(dcl, sub, s, defn); + if (!htget(binding.tydefs, s)) + htput(binding.tydefs, s, ty); clang_disposeString(str); } @@ -258,16 +339,16 @@ void addstructdef(CXCursor c) { Type *ty; - ty = gettypex(clang_getCursorType(c), NULL); - lappend(&binding.type, &binding.ntype, ty); + ty = gettypex(c, clang_getCursorType(c), NULL, true); + htput(binding.tydefs, ty->defname, ty); } void adduniondef(CXCursor c) { Type *ty; - ty = gettypex(clang_getCursorType(c), NULL); - lappend(&binding.type, &binding.ntype, ty); + ty = gettypex(c, clang_getCursorType(c), NULL, true); + htput(binding.tydefs, ty->defname, ty); } enum CXChildVisitResult scrapedcl(CXCursor c, CXCursor pc, CXClientData d) @@ -295,19 +376,20 @@ enum CXChildVisitResult scrapedcl(CXCursor c, CXCursor pc, CXClientData d) return CXChildVisit_Continue; } -void + void loadhdr(char *f) { char **args; size_t nargs; + CXTranslationUnit tu; lappend(&binding.hdr, &binding.nhdr, f); initargs(&args, &nargs, f); CXIndex idx = clang_createIndex(0, 1); - CXTranslationUnit tu = clang_parseTranslationUnit( - idx, 0, - (const char * const *) args, nargs, - 0, 0, CXTranslationUnit_None); + tu = clang_parseTranslationUnit( + idx, 0, + (const char * const *) args, nargs, + 0, 0, CXTranslationUnit_None); clang_visitChildren(clang_getTranslationUnitCursor(tu), scrapedcl, NULL); clang_disposeTranslationUnit(tu); clang_disposeIndex(idx); diff --git a/dclrepo.c b/dclrepo.c deleted file mode 100644 index e69de29..0000000 --- a/dclrepo.c +++ /dev/null @@ -0,0 +1,257 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <inttypes.h> +#include <assert.h> +#include <limits.h> +#include <string.h> + +#include "util.h" + +#define Initsz 16 + +/* Creates a new empty hash table, using 'hash' as the + * hash funciton, and 'cmp' to verify that there are no + * hash collisions. */ +Htab *mkht(ulong (*hash)(void *key), int (*cmp)(void *k1, void *k2)) +{ + Htab *ht; + + ht = xalloc(sizeof(Htab)); + ht->nelt = 0; + ht->sz = Initsz; + ht->hash = hash; + ht->cmp = cmp; + ht->keys = zalloc(Initsz*sizeof(void*)); + ht->vals = zalloc(Initsz*sizeof(void*)); + ht->hashes = zalloc(Initsz*sizeof(void*)); + ht->dead = zalloc(Initsz*sizeof(char)); + + return ht; +} + +/* Frees a hash table. Passing this function + * NULL is a no-op. */ +void htfree(Htab *ht) +{ + if (!ht) + return; + free(ht->keys); + free(ht->vals); + free(ht->hashes); + free(ht->dead); + free(ht); +} + +/* Offsets the hash so that '0' can be + * used as a 'no valid value */ +static ulong hash(Htab *ht, void *k) +{ + ulong h; + h = ht->hash(k); + if (h == 0) + return 1; + else + return h; +} + +/* Resizes the hash table by copying all + * the old keys into the right slots in a + * new table. */ +static void grow(Htab *ht, int sz) +{ + void **oldk; + void **oldv; + ulong *oldh; + char *oldd; + int oldsz; + int i; + + oldk = ht->keys; + oldv = ht->vals; + oldh = ht->hashes; + oldd = ht->dead; + oldsz = ht->sz; + + ht->nelt = 0; + ht->sz = sz; + ht->keys = zalloc(sz*sizeof(void*)); + ht->vals = zalloc(sz*sizeof(void*)); + ht->hashes = zalloc(sz*sizeof(void*)); + ht->dead = zalloc(sz*sizeof(void*)); + + for (i = 0; i < oldsz; i++) + if (oldh[i] && !oldd[i]) + htput(ht, oldk[i], oldv[i]); + free(oldh); + free(oldk); + free(oldv); + free(oldd); +} + +/* Inserts 'k' into the hash table, possibly + * killing any previous key that compares + * as equal. */ +int htput(Htab *ht, void *k, void *v) +{ + int i; + ulong h; + int di; + + di = 0; + h = hash(ht, k); + i = h & (ht->sz - 1); + while (ht->hashes[i] && !ht->dead[i]) { + /* second insertion overwrites first. nb, we shouldn't touch the + * keys for dead values */ + if (ht->hashes[i] == h) { + if (ht->dead[i]) + break; + else if (ht->cmp(ht->keys[i], k)) + goto conflicted; + } + di++; + i = (h + di) & (ht->sz - 1); + } + ht->nelt++; +conflicted: + ht->hashes[i] = h; + ht->keys[i] = k; + ht->vals[i] = v; + ht->dead[i] = 0; + if (ht->sz < ht->nelt*2) + grow(ht, ht->sz*2); + return 1; +} + +/* Finds the index that we would insert + * the key into */ +static ssize_t htidx(Htab *ht, void *k) +{ + ssize_t i; + ulong h; + int di; + + di = 0; + h = hash(ht, k); + i = h & (ht->sz - 1); + while (ht->hashes[i] && !ht->dead[i] && ht->hashes[i] != h) { +searchmore: + di++; + i = (h + di) & (ht->sz - 1); + } + if (!ht->hashes[i] || ht->dead[i]) + return -1; + if (!ht->cmp(ht->keys[i], k)) + goto searchmore; /* collision */ + return i; +} + +/* Looks up a key, returning NULL if + * the value is not present. Note, + * if NULL is a valid value, you need + * to check with hthas() to see if it's + * not there */ +void *htget(Htab *ht, void *k) +{ + ssize_t i; + + i = htidx(ht, k); + if (i < 0) + return NULL; + else + return ht->vals[i]; +} + +void htdel(Htab *ht, void *k) +{ + ssize_t i; + + i = htidx(ht, k); + if (i < 0) + return; + ht->dead[i] = 1; + ht->nelt--; +} + + +/* Tests for 'k's presence in 'ht' */ +int hthas(Htab *ht, void *k) +{ + return htidx(ht, k) >= 0; +} + +/* Returns a list of all keys in the hash + * table, storing the size of the returned + * array in 'nkeys'. NB: the value returned + * is allocated on the heap, and it is the + * job of the caller to free it */ +void **htkeys(Htab *ht, size_t *nkeys) +{ + void **k; + size_t i, j; + + j = 0; + k = xalloc(sizeof(void*)*ht->nelt); + for (i = 0; i < ht->sz; i++) + if (ht->hashes[i] && !ht->dead[i]) + k[j++] = ht->keys[i]; + *nkeys = ht->nelt; + return k; +} + +ulong strhash(void *_s) +{ + char *s; + ulong h; + ulong g; + + s = _s; + h = 0; + while (s && *s) { + h = ((h << 4) + *s++); + + if ((g = (h & 0xF0000000))) + h ^= (g >> 24); + + h &= ~g; + } + return h; +} + +int streq(void *a, void *b) +{ + if (a == b) + return 1; + if (a == NULL || b == NULL) + return 0; + return !strcmp(a, b); +} + +ulong ptrhash(void *key) +{ + return inthash((uintptr_t)key); +} + +ulong inthash(uint64_t key) +{ + uintptr_t h; + + h = (uintptr_t) key; + h *= 357913941; + h ^= h << 24; + h += ~357913941; + h ^= h >> 31; + h ^= h << 31; + return h; +} + +int inteq(uint64_t a, uint64_t b) +{ + return a == b; +} + +int ptreq(void *a, void *b) +{ + return a == b; +} @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> +#include <stdbool.h> #include <clang-c/Index.h> #include "util.h" @@ -27,6 +28,7 @@ int main(int argc, char **argv) size_t i; optinit(&ctx, "hp:P:", argv, argc); + binding.tydefs = mkht(strhash, streq); while (!optdone(&ctx)) { switch (optnext(&ctx)) { case 'h': usage(argv[0]); break; @@ -36,7 +38,7 @@ int main(int argc, char **argv) } if (!binding.pkg) { - fprintf(stderr, "package name is mandatory"); + fprintf(stderr, "package name is mandatory\n"); exit(1); } if (ctx.nargs == 0) { @@ -1,6 +1,7 @@ typedef struct Type Type; typedef struct Dcl Dcl; typedef struct Binding Binding; +typedef struct Loc Loc; extern char *opt_pkgname; extern char *opt_cprefix; @@ -36,20 +37,27 @@ typedef enum { Tystruct, Tyunion, Tyname, - Tyopaque, } Ty; +struct Loc { + char *file; + int line; +}; + struct Type { Ty type; + Loc loc; size_t arraysz; Type **sub; size_t nsub; char **subname; size_t nsubname; char *defname; + size_t size; }; struct Dcl { + Loc loc; char *name; char *cname; Type *type; @@ -62,11 +70,10 @@ struct Binding { char **hdr; /* the C headers the glue needs to include */ size_t nhdr; /* the count of headers to include */ FILE *rejfile; /* the rejected functions that need manual binding */ - Htab *defs; /* the definitions */ - Type **type; /* the C types */ - size_t ntype; /* the number of C types */ + Htab *tydefs; /* the type definitions */ Dcl **dcl; /* the C declarations */ size_t ndcl; /* the number of C declarations */ + char **files; /* the source files loaded */ }; extern Binding binding; @@ -76,13 +83,16 @@ void loadhdr(char *f); /* type */ Type *mktype(Ty ty); Type *mktyarray(Type *sub, size_t sz); -Type *mktydefn(Type *sub, char *name); +Type *mktydefn(char *name, Type *sub); Type *mktyptr(Type *sub); Type *mktyname(char *s); Type *mktystruct(char *s, Dcl **dcl, size_t ndcl); Type *mktyunion(char *s, Dcl **dcl, size_t ndcl); Type *mktyopaque(char *name, size_t sz); -void writetype(FILE *fd, Type *t); +Type *tybase(Type *t); +Type *wrappedtype(Type *ty); +bool funcneedswrapper(Type *ty); +bool needswrapper(Type *ty); /* code gen */ void myrgen(char *hdr); @@ -1,17 +1,37 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <assert.h> #include "util.h" #include "mcbind.h" -void writemyrtype(FILE *fd, Type *ty) +void writemyrtype(FILE *fd, Type *ty); + +void writefunctypebody(FILE *fd, Type *ty) { size_t i; char *sep; + sep = ""; + for (i = 0; i < ty->nsub - 1; i++) { + if (ty->subname[i]) + fprintf(fd, "%s%s : ", sep, ty->subname[i]); + else + fprintf(fd, "%sa%zd : ", sep, i); + writemyrtype(fd, ty->sub[i + 1]); + sep = ", "; + } + fprintf(fd, " -> "); + writemyrtype(fd, ty->sub[0]); +} + +void writemyrtype(FILE *fd, Type *ty) +{ + size_t i; + switch (ty->type) { case Tynone: die("invalid type\n"); break; @@ -44,17 +64,7 @@ void writemyrtype(FILE *fd, Type *ty) case Tyfunc: fprintf(fd, "("); - sep = ""; - for (i = 0; i < ty->nsub - 1; i++) { - if (ty->subname[i]) - fprintf(fd, "%s%s : ", sep, ty->subname[i]); - else - fprintf(fd, "%sa%zd : ", sep, i); - writemyrtype(fd, ty->sub[i + 1]); - sep = ", "; - } - fprintf(fd, " -> "); - writemyrtype(fd, ty->sub[0]); + writefunctypebody(fd, ty); fprintf(fd, ")"); break; @@ -75,38 +85,95 @@ void writemyrtype(FILE *fd, Type *ty) fprintf(fd, ";;"); break; case Tyunion: - fprintf(fd, "union\n"); + fprintf(fd, "struct\n"); for (i = 0; i < ty->nsub; i++) { fprintf(fd, "\t%s : ", ty->subname[i]); writemyrtype(fd, ty->sub[i]); - fprintf(fd, "[0]"); - fprintf(fd, "\n"); + fprintf(fd, "[0]\n"); } + fprintf(fd, "__pad : byte[%zd]\n", ty->size); fprintf(fd, ";;"); break; case Tyname: - fprintf(fd, "type %s =", ty->defname); - break; - case Tyopaque: - fprintf(fd, "/*opaque %s: */byte[%zd]", ty->defname, ty->arraysz); + fprintf(fd, "%s", ty->defname); break; } } +void writewrappedargs(FILE *fd, Type *ty) +{ + char *sep, *ptr; + size_t i, argoff; + + sep = ""; + if (needswrapper(ty->sub[0])) + argoff = 1; + for (i = 1; i < ty->nsub; i++) { + if (needswrapper(ty->sub[i])) + ptr = "&"; + else + ptr = ""; + if (ty->subname[i]) + fprintf(fd, "%s%s%s", sep, ptr, ty->subname[i]); + else + fprintf(fd, "%s%sa%zd", sep, ptr, i - argoff); + sep = ", "; + } +} + +void writewrapcall(FILE *fd, Dcl *d) +{ + Type *ty; + + ty = d->type; + fprintf(fd, " = {"); + writefunctypebody(fd, ty); + fprintf(fd, "\n"); + + if (needswrapper(ty->sub[0])) { + fprintf(fd, "\tvar ret\n"); + fprintf(fd, "\t%s_wrapper(&ret, ", d->name); + writewrappedargs(fd, ty); + fprintf(fd, ")\n"); + fprintf(fd, "\t-> ret\n"); + } else { + fprintf(fd, "\t-> %s_wrapper(", d->name); + writewrappedargs(fd, ty); + fprintf(fd, ")\n"); + } + fprintf(fd, "}\n\n"); +} + +void writewraptype(FILE *fd, Dcl *d) +{ + Type *w; + + w = wrappedtype(d->type); + fprintf(fd, "const %s_wrapper : ", d->name); + writemyrtype(fd, w); +} + void writemyrdcl(FILE *fd, Dcl *d) { if (d->isconst) - fprintf(fd, "const\t%s : ", d->name); + fprintf(fd, "const %s ", d->name); else - fprintf(fd, "var\t%s : ", d->name); - writemyrtype(fd, d->type); - + fprintf(fd, "var %s ", d->name); + if (funcneedswrapper(d->type)) { + writewrapcall(fd, d); + writewraptype(fd, d); + } else { + fprintf(fd, " : "); + writemyrtype(fd, d->type); + fprintf(fd, "\n"); + } } void myrgen(char *hdr) { char out[512]; - size_t i; + size_t i, nk; + void **k; FILE *fd; swapsuffix(out, sizeof out, hdr, ".h", ".myr"); @@ -118,8 +185,10 @@ void myrgen(char *hdr) fprintf(fd, "*/\n\n"); fprintf(fd, "pkg %s =\n", binding.pkg ? binding.pkg : ""); - for (i = 0; i < binding.ntype; i++) { - writemyrtype(fd, binding.type[i]); + k = htkeys(binding.tydefs, &nk); + for (i = 0; i < nk; i++) { + fprintf(fd, "type %s = ", (char*)k[i]); + writemyrtype(fd, htget(binding.tydefs, k[i])); fprintf(fd, "\n"); } for (i = 0; i < binding.ndcl; i++) { @@ -0,0 +1,151 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <assert.h> + +#include <clang-c/Index.h> + +#include "util.h" +#include "mcbind.h" + +Type *mktype(Ty ty) +{ + Type *t; + + t = zalloc(sizeof(Type)); + t->type = ty; + return t; +} + +Type *mktyarray(Type *sub, size_t sz) +{ + Type *t; + t = mktype(Tyarray); + lappend(&t->sub, &t->nsub, sub); + t->arraysz = sz; + return t; +} + +Type *mktyptr(Type *sub) +{ + Type *t; + t = mktype(Typtr); + lappend(&t->sub, &t->nsub, sub); + return t; +} + +Type *mktydefn(char *name, Type *sub) +{ + Type *t; + t = mktype(Tyname); + lappend(&t->sub, &t->nsub, sub); + t->defname = name; + htput(binding.tydefs, t->defname, t); + return t; +} + +Type *mktyname(char *name) +{ + Type *t; + t = mktype(Tyname); + t->defname = name; + return t; +} + +Type *mktystruct(char *name, Dcl **dcls, size_t ndcls) +{ + Type *t; + t = mktype(Tystruct); + t->defname = name; + htput(binding.tydefs, t->defname, t); + return t; +} + +Type *mktyunion(char *name, Dcl **dcls, size_t ndcls) +{ + Type *t; + t = mktype(Tyunion); + t->defname = name; + htput(binding.tydefs, t->defname, t); + return t; +} + +Type *mktyopaque(char *name, size_t sz) +{ + Type *t; + t = mktype(Tyname); + t->arraysz = sz; + t->defname = name; + return t; +} + +Type *tybase(Type *orig) +{ + Type *ty, *sub; + + ty = orig; + while (ty->type == Tyname) { + if (!ty->sub || !ty->sub[0]) { + sub = htget(binding.tydefs, ty->defname); + if (!ty->sub) + lappend(&ty->sub, &ty->nsub, sub); + else + ty->sub[0] = sub; + } + if (!ty->sub || !ty->sub[0]) { + fprintf(stderr, "no type definition for %s\n", ty->defname); + return NULL; + } + ty = ty->sub[0]; + } + assert(ty != NULL); + return ty; +} + +bool needswrapper(Type *orig) +{ + Type *ty; + + ty = tybase(orig); + switch (ty->type) { + case Tystruct: return 1; + case Tyunion: return 1; + case Tyarray: return 1; + default: return 0; + } +} + +bool funcneedswrapper(Type *ty) +{ + size_t i; + + ty = tybase(ty); + if (ty->type != Tyfunc) + return 0; + for (i = 0; i < ty->nsub; i++) + if (needswrapper(ty->sub[i])) + return 1; + return 0; +} + +Type *wrappedtype(Type *ty) +{ + Type *w; + size_t i; + + w = mktype(Tyfunc); + if (needswrapper(ty->sub[0])) { + lappend(&w->sub, &w->nsub, mktype(Tyvoid)); + lappend(&w->subname, &w->nsubname, NULL); + } + for (i = 0; i < ty->nsub; i++) { + if (needswrapper(ty->sub[i])) + lappend(&w->sub, &w->nsub, mktyptr(ty->sub[i])); + else + lappend(&w->sub, &w->nsub, ty->sub[i]); + lappend(&w->subname, &w->nsubname, NULL); + } + return w; +} @@ -19,6 +19,19 @@ void die(char *msg, ...) abort(); } +/* errors */ +void fatal(char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + + void *zalloc(size_t sz) { void *mem; @@ -143,3 +156,8 @@ char *swapsuffix(char *buf, size_t sz, char *s, char *suf, char *swap) return buf; } + +int hasprefix(char *str, char *pfx) +{ + return strstr(str, pfx) == str; +} @@ -41,6 +41,7 @@ int inteq(uint64_t a, uint64_t b); /* death */ void die(char *msg, ...) FATAL; +void fatal(char *msg, ...) FATAL; /* memory allocation */ void *zalloc(size_t size); @@ -57,3 +58,4 @@ void lfree(void *l, size_t *len); /* string utils */ char *swapsuffix(char *buf, size_t sz, char *s, char *suf, char *swap); +int hasprefix(char *str, char *pfx); |