Permalink
Browse files

Stub of code generation

  • Loading branch information...
1 parent 753a08e commit b84e2af2bb37f7edb8af5c64e0e587b8d4438a10 @nickg committed Aug 27, 2011
Showing with 263 additions and 22 deletions.
  1. +12 −11 .gitignore
  2. +1 −1 autogen.sh
  3. +6 −0 config.h.in
  4. +3 −1 configure.ac
  5. +111 −0 m4/ax_llvm_c.m4
  6. +10 −2 src/Makefile.am
  7. +34 −0 src/cgen.c
  8. +43 −1 src/elab.c
  9. +26 −0 src/lib.c
  10. +4 −0 src/lib.h
  11. +2 −1 src/nhdl.c
  12. +1 −0 src/phase.h
  13. +5 −1 src/sem.c
  14. +3 −3 src/tree.c
  15. +2 −1 src/tree.h
View
23 .gitignore
@@ -1,15 +1,16 @@
build/
Makefile.in
-INSTALL
-aclocal.m4
-autom4te.cache/
-configure
-depcomp
-install-sh
-missing
-configure.scan
-autoscan.log
-ylwrap
+/INSTALL
+/aclocal.m4
+/autom4te.cache/
+/configure
+/depcomp
+/install-sh
+/missing
+/configure.scan
+/autoscan.log
+/ylwrap
+/compile
*.o
*~
-TAGS
+TAGS
View
2 autogen.sh
@@ -1,3 +1,3 @@
-aclocal
+aclocal -I m4
autoconf
automake -a
View
6 config.h.in
@@ -36,6 +36,9 @@
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
+/* define if the llvm library is available */
+#undef HAVE_LLVM
+
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
@@ -128,6 +131,9 @@
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
/* Name of package */
#undef PACKAGE
View
4 configure.ac
@@ -5,6 +5,8 @@ AM_INIT_AUTOMAKE([color-tests])
AC_PROG_CC
AC_PROG_CC_C99
+AM_PROG_CC_C_O
+AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_PROG_YACC
@@ -33,7 +35,7 @@ AC_CHECK_FUNCS([strdup mkdir realpath rmdir strerror strcasecmp \
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([limits.h stddef.h fcntl.h libintl.h malloc.h])
-#AX_LLVM([])
+AX_LLVM_C([core bitwriter])
AX_DEFINE_DIR([DATADIR], [datadir/nhdl], [Installation data directory])
View
111 m4/ax_llvm_c.m4
@@ -0,0 +1,111 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_llvm.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_LLVM([llvm-libs])
+#
+# DESCRIPTION
+#
+# Test for the existance of llvm, and make sure that it can be linked with
+# the llvm-libs argument that is passed on to llvm-config i.e.:
+#
+# llvm --libs <llvm-libs>
+#
+# llvm-config will also include any libraries that are depended apon.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Andy Kitchen <agimbleinthewabe@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#
+# Modified by Nick Gasson to work with the C bindings
+#
+
+#serial 12
+
+AC_DEFUN([AX_LLVM_C],
+[
+AC_ARG_WITH([llvm],
+ AS_HELP_STRING([--with-llvm@<:@=DIR@:>@], [use llvm (default is yes) - it is possible to specify the root directory for llvm (optional)]),
+ [
+ if test "$withval" = "no"; then
+ want_llvm="no"
+ elif test "$withval" = "yes"; then
+ want_llvm="yes"
+ ac_llvm_config_path=`which llvm-config`
+ else
+ want_llvm="yes"
+ ac_llvm_config_path="$withval"
+ fi
+ ],
+ [want_llvm="yes"])
+
+ succeeded=no
+ if test -z "$ac_llvm_config_path"; then
+ ac_llvm_config_path=`which llvm-config`
+ fi
+
+ if test "x$want_llvm" = "xyes"; then
+ if test -e "$ac_llvm_config_path"; then
+ LLVM_CFLAGS=`$ac_llvm_config_path --cflags`
+ LLVM_CXXFLAGS=`$ac_llvm_config_path --cxxflags`
+ LLVM_LDFLAGS="$($ac_llvm_config_path --ldflags)"
+ LLVM_LIBS="$($ac_llvm_config_path --libs $1)"
+
+ AC_REQUIRE([AC_PROG_CXX])
+
+ CFLAGS_SAVED="$CFLAGS"
+ CFLAGS="$CFLAGS $LLVM_CFLAGS"
+ export CFLAGS
+
+ CXXFLAGS_SAVED="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $LLVM_CXXFLAGS"
+ export CXXFLAGS
+
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $LLVM_LDFLAGS"
+ export LDFLAGS
+
+ LIBS_SAVED="$LIBS"
+ LIBS="$LIBS $LLVM_LIBS"
+ export LIBS
+
+ AC_CACHE_CHECK(for LLVM ([$1]),
+ ax_cv_llvm,
+ [AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include <llvm-c/Core.h>
+ ]],
+ [[LLVMModuleCreateWithName("test"); return 0;]])],
+ ax_cv_llvm=yes, ax_cv_llvm=no)
+ AC_LANG_POP([C++])
+ ])
+
+ if test "x$ax_cv_llvm" = "xyes"; then
+ succeeded=yes
+ fi
+
+ CFLAGS="$CFLAGS_SAVED"
+ CXXFLAGS="$CXXFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ LIBS="$LIBS_SAVED"
+ else
+ succeeded=no
+ fi
+ fi
+
+ if test "$succeeded" != "yes" ; then
+ AC_MSG_ERROR([[We could not detect the llvm libraries make sure that llvm-config is on your path or specified by --with-llvm.]])
+ else
+ AC_SUBST(LLVM_CFLAGS)
+ AC_SUBST(LLVM_LDFLAGS)
+ AC_SUBST(LLVM_LIBS)
+ AC_DEFINE(HAVE_LLVM,,[define if the llvm library is available])
+ fi
+])
View
12 src/Makefile.am
@@ -1,15 +1,23 @@
bin_PROGRAMS = nhdl
lib_LIBRARIES = libnhdl.a
+noinst_LIBRARIES = libcgen.a
AM_CFLAGS = -Wall -Werror
AM_YFLAGS = -d --locations
-AM_LDFLAGS = -rdynamic
+AM_LDFLAGS = -rdynamic $(LLVM_LDFLAGS)
BUILT_SOURCES = parse.h
libnhdl_a_SOURCES = lib.c util.c ident.c parse.y lexer.l tree.c type.c \
sem.c elab.c
+libcgen_a_SOURCES = cgen.c
+libcgen_a_CFLAGS = $(LLVM_CFLAGS)
+
nhdl_SOURCES = nhdl.c
-nhdl_LDADD = libnhdl.a
+# Force C++ linking
+nodist_EXTRA_nhdl_SOURCES = dummy.cxx
+
+nhdl_LDADD = libnhdl.a libcgen.a $(LLVM_LIBS)
+
View
34 src/cgen.c
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2011 Nick Gasson
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "phase.h"
+#include "util.h"
+
+#include <llvm-c/Core.h>
+#include <llvm-c/BitWriter.h>
+
+static LLVMModuleRef module = NULL;
+
+void cgen(tree_t top)
+{
+ if (tree_kind(top) != T_ELAB)
+ fatal("cannot generate code for tree kind %d", tree_kind(top));
+
+ LLVMModuleCreateWithName("nhdl");
+
+ LLVMDisposeModule(module);
+}
View
44 src/elab.c
@@ -18,14 +18,56 @@
#include "phase.h"
#include "util.h"
+static void elab_arch(tree_t t, tree_t out)
+{
+ for (unsigned i = 0; i < tree_stmts(t); i++)
+ tree_add_stmt(out, tree_stmt(t, i));
+}
+
+struct arch_search_params {
+ ident_t name;
+ tree_t *arch;
+};
+
+static void find_arch(tree_t t, void *context)
+{
+ struct arch_search_params *params = context;
+
+ if (tree_kind(t) == T_ARCH && tree_ident2(t) == params->name)
+ *(params->arch) = t;
+}
+
+static void elab_entity(tree_t t, tree_t out)
+{
+ // XXX: LRM rules for selecting architecture?
+
+ tree_t arch = NULL;
+ struct arch_search_params params = { tree_ident(t), &arch };
+ lib_foreach(lib_work(), find_arch, &params);
+
+ if (arch == NULL)
+ fatal("no suitable architecture for entity %s", istr(tree_ident(t)));
+
+ printf("selected architecture %s of %s\n", istr(tree_ident(t)),
+ istr(tree_ident(arch)));
+
+ elab_arch(arch, out);
+}
+
tree_t elab(tree_t top)
{
+ lib_load_all(lib_work());
+
+ tree_t e = tree_new(T_ELAB);
+ tree_set_ident(e, tree_ident(top));
+
switch (tree_kind(top)) {
case T_ENTITY:
+ elab_entity(top, e);
break;
default:
fatal("%s is not a suitable top-level unit", istr(tree_ident(top)));
}
- return NULL;
+ return e;
}
View
26 src/lib.c
@@ -269,6 +269,24 @@ tree_t lib_get(lib_t lib, ident_t ident)
return unit;
}
+void lib_load_all(lib_t lib)
+{
+ assert(lib != NULL);
+
+ DIR *d = opendir(lib->path);
+ if (d == NULL)
+ fatal("%s: %s", lib->path, strerror(errno));
+
+ struct dirent *e;
+ while ((e = readdir(d))) {
+ if (e->d_name[0] != '.' && e->d_name[0] != '_')
+ (void)lib_get(lib, ident_new(e->d_name));
+ }
+
+ closedir(d);
+
+}
+
ident_t lib_name(lib_t lib)
{
assert(lib != NULL);
@@ -287,3 +305,11 @@ void lib_save(lib_t lib)
fclose(f);
}
}
+
+void lib_foreach(lib_t lib, lib_iter_fn_t fn, void *context)
+{
+ assert(lib != NULL);
+
+ for (unsigned i = 0; i < lib->n_units; i++)
+ (*fn)(lib->units[i], context);
+}
View
4 src/lib.h
@@ -34,12 +34,16 @@ FILE *lib_fopen(lib_t lib, const char *name, const char *mode);
void lib_destroy(lib_t lib);
struct trie *lib_name(lib_t lib);
void lib_save(lib_t lib);
+void lib_load_all(lib_t lib);
lib_t lib_work(void);
void lib_set_work(lib_t lib);
void lib_put(lib_t lib, struct tree *unit);
struct tree *lib_get(lib_t lib, struct trie *ident);
+typedef void (*lib_iter_fn_t)(struct tree *t, void *context);
+void lib_foreach(lib_t lib, lib_iter_fn_t fn, void *context);
+
#endif // _LIB_H
View
3 src/nhdl.c
@@ -106,7 +106,8 @@ static int elaborate(int argc, char **argv)
fatal("cannot find unit %s in library %s",
istr(unit_i), istr(lib_name(lib_work())));
- (void)elab(unit);
+ tree_t e = elab(unit);
+ cgen(e);
return EXIT_SUCCESS;
}
View
1 src/phase.h
@@ -21,5 +21,6 @@
#include "tree.h"
tree_t elab(tree_t top);
+void cgen(tree_t top);
#endif // _PHASE_H
View
6 src/sem.c
@@ -674,8 +674,12 @@ static bool sem_check_arch(tree_t t)
scope_pop();
// Prefix the architecture with the current library name
- ident_t qual = ident_prefix(lib_name(lib_work()), tree_ident(t));
+ ident_t lname = lib_name(lib_work());
+ ident_t qual = ident_prefix(lname, tree_ident(t));
tree_set_ident(t, qual);
+ ident_t ent_qual = ident_prefix(lname, tree_ident2(t));
+ tree_set_ident2(t, ent_qual);
+
lib_put(lib_work(), t);
return ok;
View
6 src/tree.c
@@ -84,7 +84,7 @@ struct tree_rd_ctx {
|| IS(t, T_SIGNAL_DECL) || IS(t, T_PROCESS) || IS(t, T_VAR_DECL) \
|| IS(t, T_REF) || IS(t, T_TYPE_DECL) || IS(t, T_PACKAGE) \
|| IS(t, T_QUALIFIED) || IS(t, T_ENUM_LIT) || IS(t, T_CONST_DECL) \
- || IS(t, T_FUNC_DECL))
+ || IS(t, T_FUNC_DECL) || IS(t, T_ELAB))
#define HAS_IDENT2(t) (IS(t, T_ARCH))
#define HAS_PORTS(t) (IS(t, T_ENTITY) || IS(t, T_FUNC_DECL))
#define HAS_GENERICS(t) (IS(t, T_ENTITY))
@@ -94,7 +94,7 @@ struct tree_rd_ctx {
|| IS(t, T_CONST_DECL) || IS(t, T_FUNC_DECL))
#define HAS_PARAMS(t) (IS(t, T_FCALL))
#define HAS_DECLS(t) (IS(t, T_ARCH) || IS(t, T_PROCESS) || IS(t, T_PACKAGE))
-#define HAS_STMTS(t) (IS(t, T_ARCH) || IS(t, T_PROCESS))
+#define HAS_STMTS(t) (IS(t, T_ARCH) || IS(t, T_PROCESS) || IS(t, T_ELAB))
#define HAS_DELAY(t) (IS(t, T_WAIT))
#define HAS_TARGET(t) (IS(t, T_VAR_ASSIGN) || IS(t, T_SIGNAL_ASSIGN))
#define HAS_VALUE(t) \
@@ -920,7 +920,7 @@ static void tree_dump_aux(tree_t t, int indent)
"entity", "arch", "port_decl", "fcall", "literal", "signal_decl",
"var_decl", "process", "ref", "wait", "type_decl", "var_assign",
"package", "signal_assign", "qualified", "enum_lit", "const_decl",
- "func_decl"
+ "func_decl", "elab"
};
printf(kind_names[t->kind]);
View
3 src/tree.h
@@ -49,7 +49,8 @@ typedef enum tree_kind {
T_QUALIFIED,
T_ENUM_LIT,
T_CONST_DECL,
- T_FUNC_DECL
+ T_FUNC_DECL,
+ T_ELAB
} tree_kind_t;
typedef struct literal {

0 comments on commit b84e2af

Please sign in to comment.