summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-11-16 09:16:07 -0800
committerOri Bernstein <ori@eigenstate.org>2015-11-16 20:37:55 -0800
commit53921862b61b4c33f29c8810898deb354d02fb28 (patch)
tree7795c7e299f88ae50b75da65787035f40cbd55d3
parent3c348076e792369472ec5c01a9c81e22440eb488 (diff)
downloadmcbind-53921862b61b4c33f29c8810898deb354d02fb28.tar.gz
Mostly working parsing and code gen.
-rw-r--r--Makefile13
-rw-r--r--asmgen.c0
-rw-r--r--cgen.c52
-rw-r--r--cparse.c268
-rw-r--r--dclrepo.c0
-rw-r--r--htab.c257
-rw-r--r--main.c4
-rw-r--r--mcbind.h22
-rw-r--r--myrgen.c121
-rw-r--r--types.c151
-rw-r--r--util.c18
-rw-r--r--util.h2
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
diff --git a/cgen.c b/cgen.c
index b59d352..d689f11 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
}
diff --git a/cparse.c b/cparse.c
index 170e75f..2822c6d 100644
--- a/cparse.c
+++ b/cparse.c
@@ -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
diff --git a/htab.c b/htab.c
new file mode 100644
index 0000000..d11ddc4
--- /dev/null
+++ b/htab.c
@@ -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;
+}
diff --git a/main.c b/main.c
index afcc2be..0ea47e0 100644
--- a/main.c
+++ b/main.c
@@ -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) {
diff --git a/mcbind.h b/mcbind.h
index 104ca31..d65d2be 100644
--- a/mcbind.h
+++ b/mcbind.h
@@ -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);
diff --git a/myrgen.c b/myrgen.c
index 32aa322..7289825 100644
--- a/myrgen.c
+++ b/myrgen.c
@@ -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++) {
diff --git a/types.c b/types.c
new file mode 100644
index 0000000..f5e135e
--- /dev/null
+++ b/types.c
@@ -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;
+}
diff --git a/util.c b/util.c
index 592523e..36e50fb 100644
--- a/util.c
+++ b/util.c
@@ -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;
+}
diff --git a/util.h b/util.h
index ef2f150..e5f184e 100644
--- a/util.h
+++ b/util.h
@@ -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);