summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-10-05 19:27:59 +0000
committerChris Lattner <sabre@nondot.org>2003-10-05 19:27:59 +0000
commitf5bd1b7a8e141df5bfebdd9749c1e11bc4607766 (patch)
tree79b60f4661c49df6b0576c9d064c90f31ae575ba /llvm
parent5f0c08e9cfe2d8a1233c0e92ac2dea62b4dc40b0 (diff)
downloadbcm5719-llvm-f5bd1b7a8e141df5bfebdd9749c1e11bc4607766.tar.gz
bcm5719-llvm-f5bd1b7a8e141df5bfebdd9749c1e11bc4607766.zip
Move support/tools/* back into utils
llvm-svn: 8875
Diffstat (limited to 'llvm')
-rw-r--r--llvm/utils/Burg/COPYRIGHT13
-rw-r--r--llvm/utils/Burg/Doc/Makefile84
-rw-r--r--llvm/utils/Burg/Doc/doc.aux50
-rw-r--r--llvm/utils/Burg/Doc/doc.dvibin0 -> 29856 bytes
-rw-r--r--llvm/utils/Burg/Doc/doc.log157
-rw-r--r--llvm/utils/Burg/Doc/doc.tex596
-rw-r--r--llvm/utils/Burg/LOG_CHANGES10
-rw-r--r--llvm/utils/Burg/Makefile28
-rw-r--r--llvm/utils/Burg/README14
-rw-r--r--llvm/utils/Burg/b.h311
-rw-r--r--llvm/utils/Burg/be.c1052
-rw-r--r--llvm/utils/Burg/burg.shar.gzbin0 -> 38843 bytes
-rw-r--r--llvm/utils/Burg/burs.c71
-rw-r--r--llvm/utils/Burg/closure.c95
-rw-r--r--llvm/utils/Burg/delta.c143
-rw-r--r--llvm/utils/Burg/fe.c403
-rw-r--r--llvm/utils/Burg/fe.h132
-rw-r--r--llvm/utils/Burg/gram.yc91
-rw-r--r--llvm/utils/Burg/item.c133
-rw-r--r--llvm/utils/Burg/lex.c259
-rw-r--r--llvm/utils/Burg/list.c75
-rw-r--r--llvm/utils/Burg/main.c182
-rw-r--r--llvm/utils/Burg/map.c135
-rw-r--r--llvm/utils/Burg/nonterminal.c49
-rw-r--r--llvm/utils/Burg/operator.c48
-rw-r--r--llvm/utils/Burg/pattern.c38
-rw-r--r--llvm/utils/Burg/plank.c921
-rw-r--r--llvm/utils/Burg/queue.c64
-rw-r--r--llvm/utils/Burg/rule.c49
-rw-r--r--llvm/utils/Burg/sample.gr150
-rw-r--r--llvm/utils/Burg/string.c65
-rw-r--r--llvm/utils/Burg/symtab.c38
-rw-r--r--llvm/utils/Burg/table.c552
-rw-r--r--llvm/utils/Burg/trim.c412
-rw-r--r--llvm/utils/Burg/zalloc.c35
-rw-r--r--llvm/utils/Makefile6
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp217
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.h24
-rw-r--r--llvm/utils/TableGen/CodeGenWrappers.cpp89
-rw-r--r--llvm/utils/TableGen/CodeGenWrappers.h56
-rw-r--r--llvm/utils/TableGen/FileLexer.l222
-rw-r--r--llvm/utils/TableGen/FileParser.y510
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp160
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.h34
-rw-r--r--llvm/utils/TableGen/InstrSelectorEmitter.cpp1287
-rw-r--r--llvm/utils/TableGen/InstrSelectorEmitter.h387
-rw-r--r--llvm/utils/TableGen/Makefile18
-rw-r--r--llvm/utils/TableGen/Record.cpp676
-rw-r--r--llvm/utils/TableGen/Record.h849
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.cpp234
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.h29
-rw-r--r--llvm/utils/TableGen/TableGen.cpp482
-rw-r--r--llvm/utils/TableGen/TableGenBackend.cpp27
-rw-r--r--llvm/utils/TableGen/TableGenBackend.h34
54 files changed, 11796 insertions, 0 deletions
diff --git a/llvm/utils/Burg/COPYRIGHT b/llvm/utils/Burg/COPYRIGHT
new file mode 100644
index 00000000000..1de0aad6f2f
--- /dev/null
+++ b/llvm/utils/Burg/COPYRIGHT
@@ -0,0 +1,13 @@
+Copyright (C) 1991 Todd A. Proebsting
+All Rights Reserved.
+
+This software is in the public domain. You may use and copy this material
+freely. This privilege extends to modifications, although any modified
+version of this system given to a third party should clearly identify your
+modifications as well as the original source.
+
+The responsibility for the use of this material resides entirely with you.
+We make no warranty of any kind concerning this material, nor do we make
+any claim as to the suitability of BURG for any application. This software
+is experimental in nature and there is no written or implied warranty. Use
+it at your own risk.
diff --git a/llvm/utils/Burg/Doc/Makefile b/llvm/utils/Burg/Doc/Makefile
new file mode 100644
index 00000000000..226210d6ca4
--- /dev/null
+++ b/llvm/utils/Burg/Doc/Makefile
@@ -0,0 +1,84 @@
+# $Id$
+
+#CFLAGS =
+#CFLAGS = -O
+#CFLAGS = -O -DNOLEX
+CFLAGS = -g -DDEBUG
+#CFLAGS = -g -DNOLEX -DDEBUG
+
+SRCS = \
+ be.c \
+ burs.c \
+ closure.c \
+ delta.c \
+ fe.c \
+ item.c \
+ lex.c \
+ list.c \
+ main.c \
+ map.c \
+ nonterminal.c \
+ operator.c \
+ pattern.c \
+ plank.c \
+ queue.c \
+ rule.c \
+ string.c \
+ symtab.c \
+ table.c \
+ trim.c \
+ zalloc.c
+
+BU_OBJS = \
+ burs.o \
+ closure.o \
+ delta.o \
+ item.o \
+ list.o \
+ map.o \
+ nonterminal.o \
+ operator.o \
+ pattern.o \
+ queue.o \
+ rule.o \
+ table.o \
+ trim.o \
+ zalloc.o
+
+FE_OBJS = \
+ be.o \
+ fe.o \
+ lex.o \
+ main.o \
+ plank.o \
+ string.o \
+ symtab.o \
+ y.tab.o
+
+all: test
+
+burg: $(BU_OBJS) $(FE_OBJS)
+ $(CC) -o burg $(CFLAGS) $(BU_OBJS) $(FE_OBJS)
+
+y.tab.c y.tab.h: gram.y
+ yacc -d gram.y
+
+clean:
+ rm -f *.o y.tab.h y.tab.c core burg *.aux *.log *.dvi sample sample.c tmp
+
+$(FE_OBJS): b.h
+$(BU_OBJS): b.h
+$(FE_OBJS): fe.h
+
+lex.o: y.tab.h
+
+doc.dvi: doc.tex
+ latex doc; latex doc
+
+test: burg sample.gr
+ ./burg -I <sample.gr >sample.c && cc $(CFLAGS) -o sample sample.c && ./sample
+ ./burg -I sample.gr >tmp && cmp tmp sample.c
+ ./burg -I <sample.gr -o tmp && cmp tmp sample.c
+ ./burg -I sample.gr -o tmp && cmp tmp sample.c
+ ./burg -I -O0 <sample.gr >tmp && cmp tmp sample.c
+ ./burg -I -= <sample.gr >tmp && cmp tmp sample.c
diff --git a/llvm/utils/Burg/Doc/doc.aux b/llvm/utils/Burg/Doc/doc.aux
new file mode 100644
index 00000000000..0f7c13f0208
--- /dev/null
+++ b/llvm/utils/Burg/Doc/doc.aux
@@ -0,0 +1,50 @@
+\relax
+\bibstyle{alpha}
+\citation{aho-twig-toplas}
+\citation{appel-87}
+\citation{balachandran-complang}
+\citation{kron-phd}
+\citation{hoffmann-jacm}
+\citation{hatcher-popl}
+\citation{chase-popl}
+\citation{pelegri-popl}
+\citation{pelegri-phd}
+\citation{wilhelm-tr}
+\citation{henry-budp}
+\citation{fraser-henry-spe-91}
+\citation{proebsting-91}
+\@writefile{toc}{\contentsline {section}{\numberline {1}Overview}{1}}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Input}{1}}
+\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces A Sample Tree Grammar}}{2}}
+\newlabel{fig-tree-grammar}{{1}{2}}
+\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces EBNF Grammar for Tree Grammars for {\sc Burg}\ }}{3}}
+\newlabel{fig-grammar-grammar}{{2}{3}}
+\@writefile{toc}{\contentsline {section}{\numberline {3}Output}{3}}
+\citation{aho-johnson-dp-classic}
+\citation{fraser-henry-spe-91}
+\citation{henry-budp}
+\citation{pelegri-phd}
+\@writefile{toc}{\contentsline {section}{\numberline {4}Debugging}{6}}
+\@writefile{toc}{\contentsline {section}{\numberline {5}Running {\sc Burg}\ }{6}}
+\newlabel{sec-man-page}{{5}{6}}
+\citation{pelegri-popl}
+\citation{henry-budp}
+\citation{balachandran-complang}
+\citation{proebsting-91}
+\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces A Diverging Tree Grammar}}{7}}
+\newlabel{fig-diverge-grammar}{{3}{7}}
+\@writefile{toc}{\contentsline {section}{\numberline {6}Acknowledgements}{7}}
+\bibcite{aho-twig-toplas}{AGT89}
+\bibcite{aho-johnson-dp-classic}{AJ76}
+\bibcite{appel-87}{App87}
+\bibcite{balachandran-complang}{BDB90}
+\bibcite{wilhelm-tr}{BMW87}
+\bibcite{chase-popl}{Cha87}
+\bibcite{fraser-henry-spe-91}{FH91}
+\bibcite{hatcher-popl}{HC86}
+\bibcite{henry-budp}{Hen89}
+\bibcite{hoffmann-jacm}{HO82}
+\bibcite{kron-phd}{Kro75}
+\bibcite{pelegri-phd}{PL87}
+\bibcite{pelegri-popl}{PLG88}
+\bibcite{proebsting-91}{Pro91}
diff --git a/llvm/utils/Burg/Doc/doc.dvi b/llvm/utils/Burg/Doc/doc.dvi
new file mode 100644
index 00000000000..3211f32c96d
--- /dev/null
+++ b/llvm/utils/Burg/Doc/doc.dvi
Binary files differ
diff --git a/llvm/utils/Burg/Doc/doc.log b/llvm/utils/Burg/Doc/doc.log
new file mode 100644
index 00000000000..a224a4edf72
--- /dev/null
+++ b/llvm/utils/Burg/Doc/doc.log
@@ -0,0 +1,157 @@
+This is TeX, Version 3.14159 (Web2C 7.3.2) (format=latex 2000.8.30) 4 JUN 2001 13:20
+**doc
+(doc.tex
+LaTeX2e <2000/06/01>
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/latex209.def
+File: latex209.def 1998/05/13 v0.52 Standard LaTeX file
+
+
+ Entering LaTeX 2.09 COMPATIBILITY MODE
+ *************************************************************
+ !!WARNING!! !!WARNING!! !!WARNING!! !!WARNING!!
+
+ This mode attempts to provide an emulation of the LaTeX 2.09
+ author environment so that OLD documents can be successfully
+ processed. It should NOT be used for NEW documents!
+
+ New documents should use Standard LaTeX conventions and start
+ with the \documentclass command.
+
+ Compatibility mode is UNLIKELY TO WORK with LaTeX 2.09 style
+ files that change any internal macros, especially not with
+ those that change the FONT SELECTION or OUTPUT ROUTINES.
+
+ Therefore such style files MUST BE UPDATED to use
+ Current Standard LaTeX: LaTeX2e.
+ If you suspect that you may be using such a style file, which
+ is probably very, very old by now, then you should attempt to
+ get it updated by sending a copy of this error message to the
+ author of that file.
+ *************************************************************
+
+\footheight=\dimen102
+\@maxsep=\dimen103
+\@dblmaxsep=\dimen104
+\@cla=\count79
+\@clb=\count80
+\mscount=\count81
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/tracefnt.sty
+Package: tracefnt 1997/05/29 v3.0j Standard LaTeX package (font tracing)
+\tracingfonts=\count82
+LaTeX Info: Redefining \selectfont on input line 96.
+)
+\symbold=\mathgroup4
+\symsans=\mathgroup5
+\symtypewriter=\mathgroup6
+\symitalic=\mathgroup7
+\symsmallcaps=\mathgroup8
+\symslanted=\mathgroup9
+LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 288.
+LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 289.
+LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 290.
+LaTeX Font Info: Redeclaring math alphabet \mathit on input line 296.
+LaTeX Info: Redefining \em on input line 306.
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/latexsym.sty
+Package: latexsym 1998/08/17 v2.2e Standard LaTeX package (lasy symbols)
+\symlasy=\mathgroup10
+LaTeX Font Info: Overwriting symbol font `lasy' in version `bold'
+(Font) U/lasy/m/n --> U/lasy/b/n on input line 42.
+)
+LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 370.
+LaTeX Font Info: Redeclaring math delimiter \rgroup on input line 372.
+LaTeX Font Info: Redeclaring math delimiter \bracevert on input line 374.
+
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/config/latex209.cf
+g
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/tools/rawfonts.sty
+Compatibility mode: package `' requested, but `rawfonts' provided.
+Package: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility
+
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/tools/somedefs.sty
+Package: somedefs 1994/06/01 Toolkit for optional definitions
+)
+LaTeX Font Info: Try loading font information for U+lasy on input line 44.
+ (/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/ulasy.fd
+File: ulasy.fd 1998/08/17 v2.2eLaTeX symbol font definitions
+)))) (/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/article.
+cls
+Document Class: article 2000/05/19 v1.4b Standard LaTeX document class
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/size11.clo
+File: size11.clo 2000/05/19 v1.4b Standard LaTeX file (size option)
+)
+\c@part=\count83
+\c@section=\count84
+\c@subsection=\count85
+\c@subsubsection=\count86
+\c@paragraph=\count87
+\c@subparagraph=\count88
+\c@figure=\count89
+\c@table=\count90
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+Compatibility mode: definition of \rm ignored.
+Compatibility mode: definition of \sf ignored.
+Compatibility mode: definition of \tt ignored.
+Compatibility mode: definition of \bf ignored.
+Compatibility mode: definition of \it ignored.
+Compatibility mode: definition of \sl ignored.
+Compatibility mode: definition of \sc ignored.
+LaTeX Info: Redefining \cal on input line 501.
+LaTeX Info: Redefining \mit on input line 502.
+\bibindent=\dimen105
+)
+(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/pstex/fullpage.sty
+) (doc.aux)
+\openout1 = `doc.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 2.
+LaTeX Font Info: ... okay on input line 2.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <12> on input line 33.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <8> on input line 33.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <6> on input line 33.
+LaTeX Font Info: Try loading font information for OMS+cmtt on input line 100
+.
+LaTeX Font Info: No file OMScmtt.fd. on input line 100.
+LaTeX Font Warning: Font shape `OMS/cmtt/m/n' undefined
+(Font) using `OMS/cmsy/m/n' instead
+(Font) for symbol `textbraceleft' on input line 100.
+ [1
+
+]
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <10.95> on input line 150.
+ [2] [3] [4] [5] [6]
+Overfull \hbox (1.38191pt too wide) in paragraph at lines 480--484
+[]\OT1/cmr/m/n/10.95 Emit code for \OT1/cmtt/m/n/10.95 burm[]arity\OT1/cmr/m/n/
+10.95 , \OT1/cmtt/m/n/10.95 burm[]child\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95
+ burm[]cost\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 burm[]ntname\OT1/cmr/m/n/10
+.95 , \OT1/cmtt/m/n/10.95 burm[]op[]label\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.
+95 burm[]opname\OT1/cmr/m/n/10.95 ,
+ []
+
+[7] [8] [9] (doc.aux)
+LaTeX Font Warning: Some font shapes were not available, defaults substituted.
+ )
+Here is how much of TeX's memory you used:
+ 543 strings out of 12968
+ 6147 string characters out of 289029
+ 446019 words of memory out of 1453895
+ 3433 multiletter control sequences out of 10000+10000
+ 23403 words of font info for 87 fonts, out of 400000 for 2000
+ 14 hyphenation exceptions out of 1000
+ 21i,6n,20p,308b,283s stack positions out of 300i,100n,500p,50000b,4000s
+
+Output written on doc.dvi (9 pages, 29856 bytes).
diff --git a/llvm/utils/Burg/Doc/doc.tex b/llvm/utils/Burg/Doc/doc.tex
new file mode 100644
index 00000000000..3dc67be3176
--- /dev/null
+++ b/llvm/utils/Burg/Doc/doc.tex
@@ -0,0 +1,596 @@
+\documentstyle[11pt,fullpage]{article}
+\begin{document}
+
+\def\AddSpace#1{\ifcat#1a\ \fi#1} % if next is a letter, add a space
+\def\YACC#1{{\sc Yacc}\AddSpace#1}
+\def\TWIG#1{{\sc Twig}\AddSpace#1}
+\def\PROG#1{{\sc Burg}\AddSpace#1}
+\def\PARSER#1{{\sc Burm}\AddSpace#1}
+\def\CODEGEN#1{{\sc Codegen}\AddSpace#1}
+
+\title{{\sc Burg} --- Fast Optimal Instruction Selection and Tree Parsing}
+\author{
+Christopher W. Fraser \\
+AT\&T Bell Laboratories \\
+600 Mountain Avenue 2C-464 \\
+Murray Hill, NJ 07974-0636 \\
+{\tt cwf@research.att.com}
+\and
+Robert R. Henry \\
+Tera Computer Company \\
+400 N. 34th St., Suite 300 \\
+Seattle, WA 98103-8600 \\
+{\tt rrh@tera.com}
+\and
+Todd A. Proebsting \\
+Dept. of Computer Sciences \\
+University of Wisconsin \\
+Madison, WI 53706 \\
+{\tt todd@cs.wisc.edu}
+}
+\date{December 1991}
+
+\maketitle
+\bibliographystyle{alpha}
+\newcommand\term[1]{{\it #1}}
+\newcommand\secref[1]{\S\ref{#1}}
+\newcommand\figref[1]{Figure~\ref{#1}}
+%
+% rationale table making
+%
+{\catcode`\^^M=13 \gdef\Obeycr{\catcode`\^^M=13 \def^^M{\\}}%
+\gdef\Restorecr{\catcode`\^^M=5 }} %
+
+%
+% for printing out options
+%
+\newcommand\option[1]{% #1=option character
+{\tt -#1}%
+}
+\newcommand\var[1]{%
+{\tt #1}%
+}
+\section{Overview}
+
+\PROG is a program that generates a fast tree parser using BURS
+(Bottom-Up Rewrite System) technology. It accepts a cost-augmented
+tree grammar and emits a C program that discovers in linear time an
+optimal parse of trees in the language described by the grammar. \PROG
+has been used to construct fast optimal instruction selectors for use
+in code generation. \PROG addresses many of the problems addressed by
+{\sc Twig}~\cite{aho-twig-toplas,appel-87}, but it is somewhat less flexible and
+much faster. \PROG is available via anonymous \var{ftp} from
+\var{kaese.cs.wisc.edu}. The compressed \var{shar} file
+\var{pub/burg.shar.Z} holds the complete distribution.
+
+This document describes only that fraction of the BURS model that is
+required to use \PROG. Readers interested in more detail might start
+with Reference~\cite{balachandran-complang}. Other relevant documents
+include References~\cite{kron-phd,hoffmann-jacm,hatcher-popl,chase-popl,pelegri-popl,pelegri-phd,wilhelm-tr,henry-budp,fraser-henry-spe-91,proebsting-91}.
+
+\section{Input}
+
+\PROG accepts a tree grammar and emits a BURS tree parser.
+\figref{fig-tree-grammar} shows a sample grammar that implements a very
+simple instruction selector.
+\begin{figure}
+\begin{verbatim}
+%{
+#define NODEPTR_TYPE treepointer
+#define OP_LABEL(p) ((p)->op)
+#define LEFT_CHILD(p) ((p)->left)
+#define RIGHT_CHILD(p) ((p)->right)
+#define STATE_LABEL(p) ((p)->state_label)
+#define PANIC printf
+%}
+%start reg
+%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6
+%%
+con: Constant = 1 (0);
+con: Four = 2 (0);
+addr: con = 3 (0);
+addr: Plus(con,reg) = 4 (0);
+addr: Plus(con,Mul(Four,reg)) = 5 (0);
+reg: Fetch(addr) = 6 (1);
+reg: Assign(addr,reg) = 7 (1);
+\end{verbatim}
+\caption{A Sample Tree Grammar\label{fig-tree-grammar}}
+\end{figure}
+\PROG grammars are structurally similar to \YACC's. Comments follow C
+conventions. Text between ``\var{\%\{}'' and ``\var{\%\}}'' is called
+the \term{configuration section}; there may be several such segments.
+All are concatenated and copied verbatim into the head of the generated
+parser, which is called \PARSER. Text after the second ``\var{\%\%}'',
+if any, is also copied verbatim into \PARSER, at the end.
+
+The configuration section configures \PARSER for the trees being parsed
+and the client's environment. This section must define
+\var{NODEPTR\_TYPE} to be a visible typedef symbol for a pointer to a
+node in the subject tree. \PARSER invokes \var{OP\_LABEL(p)},
+\var{LEFT\_CHILD(p)}, and \var{RIGHT\_CHILD(p)} to read the operator
+and children from the node pointed to by \var{p}. It invokes
+\var{PANIC} when it detects an error. If the configuration section
+defines these operations as macros, they are implemented in-line;
+otherwise, they must be implemented as functions. The section on
+diagnostics elaborates on \var{PANIC}.
+
+\PARSER computes and stores a single integral \term{state} in each node
+of the subject tree. The configuration section must define a macro
+\var{STATE\_LABEL(p)} to access the state field of the node pointed to
+by \var{p}. A macro is required because \PROG uses it as an lvalue. A
+C \var{short} is usually the right choice; typical code generation
+grammars require 100--1000 distinct state labels.
+
+The tree grammar follows the configuration section.
+\figref{fig-grammar-grammar} gives an EBNF grammar for \PROG tree
+grammars.
+\begin{figure}
+\begin{verbatim}
+grammar: {dcl} '%%' {rule}
+
+dcl: '%start' Nonterminal
+dcl: '%term' { Identifier '=' Integer }
+
+rule: Nonterminal ':' tree '=' Integer cost ';'
+cost: /* empty */
+cost: '(' Integer { ',' Integer } ')'
+
+tree: Term '(' tree ',' tree ')'
+tree: Term '(' tree ')'
+tree: Term
+tree: Nonterminal
+\end{verbatim}
+\caption{EBNF Grammar for Tree Grammars for \PROG\ \label{fig-grammar-grammar}}
+\end{figure}
+Comments, the text between ``\var{\%\{}'' and ``\var{\%\}}'', and the
+text after the optional second ``\var{\%\%}'' are treated lexically, so
+the figure omits them. In the EBNF grammar, quoted text must appear
+literally, \var{Nonterminal} and \var{Integer} are self-explanatory,
+and \var{Term} denotes an identifier previously declared as a
+terminal. {\tt\{$X$\}} denotes zero or more instances of $X$.
+
+Text before the first ``\var{\%\%}'' declares the start symbol and the
+terminals or operators in subject trees. All terminals must be
+declared; each line of such declarations begins with \var{\%term}.
+Each terminal has fixed arity, which \PROG infers from the rules using that terminal.
+\PROG restricts terminals to have at most two children. Each terminal
+is declared with a positive, unique, integral \term{external symbol
+number} after a ``\var{=}''. \var{OP\_LABEL(p)} must return the valid
+external symbol number for \var{p}. Ideally, external symbol numbers
+form a dense enumeration. Non-terminals are not declared, but the
+start symbol may be declared with a line that begins with
+\var{\%start}.
+
+Text after the first ``\var{\%\%}'' declares the rules. A tree grammar
+is like a context-free grammar: it has rules, non-terminals,
+terminals, and a special start non-terminal. The right-hand side of a
+rule, called the \term{pattern}, is a tree. Tree patterns appear in
+prefix parenthesized form. Every non-terminal denotes a tree. A chain
+rule is a rule whose pattern is another non-terminal. If no start
+symbol is declared, \PROG uses the non-terminal defined by the first
+rule. \PROG needs a single start symbol; grammars for which it is
+natural to use multiple start symbols must be augmented with an
+artificial start symbol that derives, with zero cost, the grammar's
+natural start symbols. \PARSER will automatically select one
+that costs least for any given tree.
+
+\PROG accepts no embedded semantic actions like \YACC's, because no one
+format suited all intended applications. Instead, each rule has a
+positive, unique, integral \term{external rule number}, after the
+pattern and preceded by a ``\var{=}''. Ideally, external rule numbers
+form a dense enumeration. \PARSER uses these numbers to report the
+matching rule to a user-supplied routine, which must implement any
+desired semantic action; see below. Humans may select these integers
+by hand, but \PROG is intended as a \term{server} for building BURS
+tree parsers. Thus some \PROG clients will consume a richer
+description and translate it into \PROG's simpler input.
+
+Rules end with a vector of non-negative, integer costs, in parentheses
+and separated by commas. If the cost vector is omitted, then all
+elements are assumed to be zero. \PROG retains only the first four
+elements of the list. The cost of a derivation is the sum of the costs
+for all rules applied in the derivation. Arithmetic on cost vectors
+treats each member of the vector independently. The tree parser finds
+the cheapest parse of the subject tree. It breaks ties arbitrarily.
+By default, \PROG uses only the \term{principal cost} of each cost
+vector, which defaults to the first element, but options described
+below provide alternatives.
+
+\section{Output}
+
+\PARSER traverses the subject tree twice. The first pass or
+\term{labeller} runs bottom-up and left-to-right, visiting each node
+exactly once. Each node is labeled with a state, a single number that
+encodes all full and partial optimal pattern matches viable at that
+node. The second pass or \term{reducer} traverses the subject tree
+top-down. The reducer accepts a tree node's state label and a
+\term{goal} non-terminal --- initially the root's state label and the
+start symbol --- which combine to determine the rule to be applied at
+that node. By construction, the rule has the given goal non-terminal
+as its left-hand side. The rule's pattern identifies the subject
+subtrees and goal non-terminals for all recursive visits. Here, a
+``subtree'' is not necessarily an immediate child of the current node.
+Patterns with interior operators cause the reducer to skip the
+corresponding subject nodes, so the reducer may proceed directly to
+grandchildren, great-grandchildren, and so on. On the other hand,
+chain rules cause the reducer to revisit the current subject node, with
+a new goal
+non-terminal, so \term{x} is also regarded as a subtree of \term{x}.
+
+As the reducer visits (and possibly revisits) each node, user-supplied
+code implements semantic action side effects and controls the order in
+which subtrees are visited. The labeller is self-contained, but the
+reducer combines code from \PROG with code from the user, so \PARSER
+does not stand alone.
+
+The \PARSER that is generated by \PROG provides primitives for
+labelling and reducing trees. These mechanisms are a compromise
+between expressibility, abstraction, simplicity, flexibility and
+efficiency. Clients may combine primitives into labellers and reducers
+that can traverse trees in arbitrary ways, and they may call semantic
+routines when and how they wish during traversal. Also, \PROG
+generates a few higher level routines that implement common
+combinations of primitives, and it generates mechanisms that help debug
+the tree parse.
+
+\PROG generates the labeller as a function named \var{burm\_label} with
+the signature
+\begin{verbatim}
+extern int burm_label(NODEPTR_TYPE p);
+\end{verbatim}
+It labels the entire subject tree pointed to by \var{p} and returns the
+root's state label. State zero labels unmatched trees. The trees may
+be corrupt or merely inconsistent with the grammar.
+
+The simpler \var{burm\_state} is \var{burm\_label} without the
+code to traverse the tree and to read and write its fields. It may be
+used to integrate labelling into user-supplied traversal code. A
+typical signature is
+\begin{verbatim}
+extern int burm_state(int op, int leftstate, int rightstate);
+\end{verbatim}
+It accepts an external symbol number for a node and the labels for the
+node's left and right children. It returns the state label to assign
+to that node. For unary operators, the last argument is ignored; for
+leaves, the last two arguments are ignored. In general, \PROG
+generates a \var{burm\_state} that accepts the maximum number of child
+states required by the input grammar. For example, if the grammar
+includes no binary operators, then \var{burm\_state} will have the
+signature
+\begin{verbatim}
+extern int burm_state(int op, int leftstate);
+\end{verbatim}
+This feature is included to permit future expansion to operators with
+more than two children.
+
+The user must write the reducer, but \PARSER writes code and data that
+help. Primary is
+\begin{verbatim}
+extern int burm_rule(int state, int goalnt);
+\end{verbatim}
+which accepts a tree's state label and a goal non-terminal and returns the
+external rule number of a rule. The rule will have matched the tree
+and have the goal non-terminal on the left-hand side; \var{burm\_rule}
+returns zero when the tree labelled with the given state did not match
+the goal non-terminal. For the initial, root-level call, \var{goalnt}
+must be one, and \PARSER exports an array that identifies the values
+for nested calls:
+\begin{verbatim}
+extern short *burm_nts[] = { ... };
+\end{verbatim}
+is an array indexed by external rule numbers. Each element points to a
+zero-terminated vector of short integers, which encode the goal
+non-terminals for that rule's pattern, left-to-right. The user needs
+only these two externals to write a complete reducer, but a third
+external simplifies some applications:
+\begin{verbatim}
+extern NODEPTR_TYPE *burm_kids(NODEPTR_TYPE p, int eruleno, NODEPTR_TYPE kids[]);
+\end{verbatim}
+accepts the address of a tree \var{p}, an external rule number, and an
+empty vector of pointers to trees. The procedure assumes that \var{p}
+matched the given rule, and it fills in the vector with the subtrees (in
+the sense described above) of \var{p} that must be reduced recursively.
+\var{kids} is returned. It is not zero-terminated.
+
+The simple user code below labels and then fully reduces a subject tree;
+the reducer prints the tree cover. \var{burm\_string} is defined below.
+\begin{verbatim}
+parse(NODEPTR_TYPE p) {
+ burm_label(p); /* label the tree */
+ reduce(p, 1, 0); /* and reduce it */
+}
+
+reduce(NODEPTR_TYPE p, int goalnt, int indent) {
+ int eruleno = burm_rule(STATE_LABEL(p), goalnt); /* matching rule number */
+ short *nts = burm_nts[eruleno]; /* subtree goal non-terminals */
+ NODEPTR_TYPE kids[10]; /* subtree pointers */
+ int i;
+
+ for (i = 0; i < indent; i++)
+ printf("."); /* print indented ... */
+ printf("%s\n", burm_string[eruleno]); /* ... text of rule */
+ burm_kids(p, eruleno, kids); /* initialize subtree pointers */
+ for (i = 0; nts[i]; i++) /* traverse subtrees left-to-right */
+ reduce(kids[i], nts[i], indent+1); /* and print them recursively */
+}
+\end{verbatim}
+The reducer may recursively traverse subtrees in any order, and it may
+interleave arbitrary semantic actions with recursive traversals.
+Multiple reducers may be written, to implement multi-pass algorithms
+or independent single-pass algorithms.
+
+For each non-terminal $x$, \PROG emits a preprocessor directive to
+equate \var{burm\_}$x$\var{\_NT} with $x$'s integral encoding. It also
+defines a macro \var{burm\_}$x$\var{\_rule(a)} that is equivalent to
+\var{burm\_rule(a,}$x$\var{)}. For the grammar in
+\figref{fig-tree-grammar}, \PROG emits
+\begin{verbatim}
+#define burm_reg_NT 1
+#define burm_con_NT 2
+#define burm_addr_NT 3
+#define burm_reg_rule(a) ...
+#define burm_con_rule(a) ...
+#define burm_addr_rule(a) ...
+\end{verbatim}
+Such symbols are visible only to the code after the second
+``\var{\%\%}''. If the symbols \var{burm\_}$x$\var{\_NT} are needed
+elsewhere, extract them from the \PARSER source.
+
+The \option{I} option directs \PROG to emit an encoding of the input
+that may help the user produce diagnostics. The vectors
+\begin{verbatim}
+extern char *burm_opname[];
+extern char burm_arity[];
+\end{verbatim}
+hold the name and number of children, respectively, for each terminal.
+They are indexed by the terminal's external symbol number. The vectors
+\begin{verbatim}
+extern char *burm_string[];
+extern short burm_cost[][4];
+\end{verbatim}
+hold the text and cost vector for each rule. They are indexed by the
+external rule number. The zero-terminated vector
+\begin{verbatim}
+extern char *burm_ntname[];
+\end{verbatim}
+is indexed by \var{burm\_}$x$\var{\_NT} and holds the name of
+non-terminal $x$. Finally, the procedures
+\begin{verbatim}
+extern int burm_op_label(NODEPTR_TYPE p);
+extern int burm_state_label(NODEPTR_TYPE p);
+extern NODEPTR_TYPE burm_child(NODEPTR_TYPE p, int index);
+\end{verbatim}
+are callable versions of the configuration macros.
+\var{burm\_child(p,0)} implements \var{LEFT\_CHILD(p)}, and
+\var{burm\_child(p,1)} implements \var{RIGHT\_CHILD(p)}. A sample use
+is the grammar-independent expression
+\var{burm\_opname[burm\_op\_label(p)]}, which yields the textual name
+for the operator in the tree node pointed to by \var{p}.
+
+A complete tree parser can be assembled from just \var{burm\_state},
+\var{burm\_rule}, and \var{burm\_nts}, which use none of the
+configuration section except \var{PANIC}. The generated routines that
+use the rest of the configuration section are compiled only if the
+configuration section defines \var{STATE\_LABEL}, so they can be
+omitted if the user prefers to hide the tree structure from \PARSER.
+This course may be wise if, say, the tree structure is defined in a
+large header file with symbols that might collide with \PARSER's.
+
+\PARSER selects an optimal parse without dynamic programming at compile
+time~\cite{aho-johnson-dp-classic}. Instead, \PROG does the dynamic
+programming at compile-compile time, as it builds \PARSER.
+Consequently, \PARSER parses quickly. Similar labellers have taken as
+few as 15 instructions per node, and reducers as few as 35 per node
+visited~\cite{fraser-henry-spe-91}.
+
+\section{Debugging}
+
+\PARSER invokes \var{PANIC} when an error prevents it from proceeding.
+\var{PANIC} has the same signature as \var{printf}. It should pass its
+arguments to \var{printf} if diagnostics are desired and then either
+abort (say via \var{exit}) or recover (say via \var{longjmp}). If it
+returns, \PARSER aborts. Some errors are not caught.
+
+\PROG assumes a robust preprocessor, so it omits full consistency
+checking and error recovery. \PROG constructs a set of states using a
+closure algorithm like that used in LR table construction. \PROG
+considers all possible trees generated by the tree grammar and
+summarizes infinite sets of trees with finite sets. The summary
+records the cost of those trees but actually manipulates the
+differences in costs between viable alternatives using a dynamic
+programming algorithm. Reference~\cite{henry-budp} elaborates.
+
+Some grammars derive trees whose optimal parses depend on arbitrarily
+distant data. When this happens, \PROG and the tree grammar
+\term{cost diverge}, and \PROG attempts to build an infinite
+set of states; it first thrashes and ultimately exhausts
+memory and exits. For example, the tree grammar in
+\figref{fig-diverge-grammar}
+\begin{figure}
+\begin{verbatim}
+%term Const=17 RedFetch=20 GreenFetch=21 Plus=22
+%%
+reg: GreenFetch(green_reg) = 10 (0);
+reg: RedFetch(red_reg) = 11 (0);
+
+green_reg: Const = 20 (0);
+green_reg: Plus(green_reg,green_reg) = 21 (1);
+
+red_reg: Const = 30 (0);
+red_reg: Plus(red_reg,red_reg) = 31 (2);
+\end{verbatim}
+\caption{A Diverging Tree Grammar\label{fig-diverge-grammar}}
+\end{figure}
+diverges, since non-terminals \var{green\_reg} and \var{red\_reg}
+derive identical infinite trees with different costs. If the cost of
+rule 31 is changed to 1, then the grammar does not diverge.
+
+Practical tree grammars describing instruction selection do not
+cost-diverge because infinite trees are derived from non-terminals
+that model temporary registers. Machines can move data between
+different types of registers for a small bounded cost, and the rules
+for these instructions prevent divergence. For example, if
+\figref{fig-diverge-grammar} included rules to move data between red
+and green registers, the grammar would not diverge. If a bonafide
+machine grammar appears to make \PROG loop, try a host with more
+memory. To apply \PROG to problems other than instruction selection,
+be prepared to consult the literature on
+cost-divergence~\cite{pelegri-phd}.
+
+\section{Running \PROG\ }\label{sec-man-page}
+
+\PROG reads a tree grammar and writes a \PARSER in C. \PARSER can be
+compiled by itself or included in another file. When suitably named
+with the \option{p} option, disjoint instances of \PARSER should link
+together without name conflicts. The command:
+\begin{flushleft}
+\var{burg} [ {\it arguments} ] [ {\it file} ]
+\end{flushleft}
+invokes \PROG. If a {\it file} is named, \PROG expects its grammar
+there; otherwise it reads the standard input. The options include:
+\def\Empty{}
+%
+\newcommand\odescr[2]{% #1=option character, #2=optional argument
+\gdef\Arg2{#2}%
+\item[\option{#1}\ifx\Arg2\Empty\else{{\it #2}}\fi]
+}
+\begin{description}
+%
+\odescr{c}{} $N$
+Abort if any relative cost exceeds $N$, which keeps \PROG from looping on
+diverging grammars. Several
+references~\cite{pelegri-popl,henry-budp,balachandran-complang,proebsting-91}
+explain relative costs.
+%
+\odescr{d}{}
+Report a few statistics and flag unused rules and terminals.
+%
+\odescr{o}{} {\it file}
+Write parser into {\it file}. Otherwise it writes to the standard output.
+%
+\odescr{p}{} {\it prefix}
+Start exported names with {\it prefix}. The default is \var{burm}.
+%
+\odescr{t}{}
+Generates smaller tables faster, but all goal non-terminals passed to
+\var{burm\_rule} must come from an appropriate \var{burm\_nts}. Using
+\var{burm\_}$x$\var{\_NT} instead may give unpredictable results.
+%
+\odescr{I}{}
+Emit code for \var{burm\_arity}, \var{burm\_child}, \var{burm\_cost},
+\var{burm\_ntname}, \var{burm\_op\_label}, \var{burm\_opname},
+\var{burm\_state\_label}, and \var{burm\_string}.
+%
+\odescr{O}{} $N$
+Change the principal cost to $N$. Elements of each cost vector are
+numbered from zero.
+%
+\odescr{=}{}
+Compare costs lexicographically, using all costs in the given order.
+This option slows \PROG and may produce a larger parser. Increases
+range from small to astronomical.
+\end{description}
+
+\section{Acknowledgements}
+
+The first \PROG was adapted by the second author from his \CODEGEN
+package, which was developed at the University of Washington with
+partial support from NSF Grant CCR-88-01806. It was unbundled from
+\CODEGEN with the support of Tera Computer. The current \PROG was
+written by the third author with the support of NSF grant
+CCR-8908355. The interface, documentation, and testing involved
+all three authors.
+
+Comments from a large group at the 1991 Dagstuhl Seminar on Code
+Generation improved \PROG's interface. Robert Giegerich and Susan
+Graham organized the workshop, and the International Conference and
+Research Center for Computer Science, Schloss Dagstuhl, provided an
+ideal environment for such collaboration. Beta-testers included Helmut
+Emmelmann, Dave Hanson, John Hauser, Hugh Redelmeier, and Bill Waite.
+
+\begin{thebibliography}{BMW87}
+
+\bibitem[AGT89]{aho-twig-toplas}
+Alfred~V. Aho, Mahadevan Ganapathi, and Steven W.~K. Tjiang.
+\newblock Code generation using tree matching and dynamic programming.
+\newblock {\em ACM Transactions on Programming Languages and Systems},
+ 11(4):491--516, October 1989.
+
+\bibitem[AJ76]{aho-johnson-dp-classic}
+Alfred~V. Aho and Steven~C. Johnson.
+\newblock Optimal code generation for expression trees.
+\newblock {\em Journal of the ACM}, 23(3):458--501, July 1976.
+
+\bibitem[App87]{appel-87}
+Andrew~W. Appel.
+\newblock Concise specification of locally optimal code generators.
+\newblock Technical report CS-TR-080-87, Princeton University, 1987.
+
+\bibitem[BDB90]{balachandran-complang}
+A.~Balachandran, D.~M. Dhamdhere, and S.~Biswas.
+\newblock Efficient retargetable code generation using bottom-up tree pattern
+ matching.
+\newblock {\em Computer Languages}, 15(3):127--140, 1990.
+
+\bibitem[BMW87]{wilhelm-tr}
+J\"{u}rgen B\"{o}rstler, Ulrich M\"{o}nche, and Reinhard Wilhelm.
+\newblock Table compression for tree automata.
+\newblock Technical Report Aachener Informatik-Berichte No. 87-12, RWTH Aachen,
+ Fachgruppe Informatik, Aachen, Fed. Rep. of Germany, 1987.
+
+\bibitem[Cha87]{chase-popl}
+David~R. Chase.
+\newblock An improvement to bottom up tree pattern matching.
+\newblock {\em Fourteenth Annual ACM Symposium on Principles of Programming
+ Languages}, pages 168--177, January 1987.
+
+\bibitem[FH91]{fraser-henry-spe-91}
+Christopher~W. Fraser and Robert~R. Henry.
+\newblock Hard-coding bottom-up code generation tables to save time and space.
+\newblock {\em Software---Practice\&Experience}, 21(1):1--12, January 1991.
+
+\bibitem[HC86]{hatcher-popl}
+Philip~J. Hatcher and Thomas~W. Christopher.
+\newblock High-quality code generation via bottom-up tree pattern matching.
+\newblock {\em Thirteenth Annual ACM Symposium on Principles of Programming
+ Languages}, pages 119--130, January 1986.
+
+\bibitem[Hen89]{henry-budp}
+Robert~R. Henry.
+\newblock Encoding optimal pattern selection in a table-driven bottom-up
+ tree-pattern matcher.
+\newblock Technical Report 89-02-04, University of Washington Computer Science
+ Department, Seattle, WA, February 1989.
+
+\bibitem[HO82]{hoffmann-jacm}
+Christoph Hoffmann and Michael~J. O'Donnell.
+\newblock Pattern matching in trees.
+\newblock {\em Journal of the ACM}, 29(1):68--95, January 1982.
+
+\bibitem[Kro75]{kron-phd}
+H.~H. Kron.
+\newblock {\em Tree Templates and Subtree Transformational Grammars}.
+\newblock PhD thesis, UC Santa Cruz, December 1975.
+
+\bibitem[PL87]{pelegri-phd}
+Eduardo Pelegri-Llopart.
+\newblock {\em Tree Transformations in Compiler Systems}.
+\newblock PhD thesis, UC Berkeley, December 1987.
+
+\bibitem[PLG88]{pelegri-popl}
+Eduardo Pelegri-Llopart and Susan~L. Graham.
+\newblock Optimal code generation for expression trees: An application of
+ {BURS} theory.
+\newblock {\em Fifteenth Annual ACM Symposium on Principles of Programming
+ Languages}, pages 294--308, January 1988.
+
+\bibitem[Pro91]{proebsting-91}
+Todd~A. Proebsting.
+\newblock Simple and efficient {BURS} table generation.
+\newblock Technical report, Department of Computer Sciences, University of
+ Wisconsin, 1991.
+
+\end{thebibliography}
+
+\end{document}
+
diff --git a/llvm/utils/Burg/LOG_CHANGES b/llvm/utils/Burg/LOG_CHANGES
new file mode 100644
index 00000000000..804f00378b2
--- /dev/null
+++ b/llvm/utils/Burg/LOG_CHANGES
@@ -0,0 +1,10 @@
+8/20/02 -- Vikram Adve
+ be.c: Replaced "char*" with "const char*" to avoid compiler warnings.
+
+9/9/03 -- John Criswell
+ b.h be.c fe.h gram.y lex.c main.c map.c nontermainl.c plan.c zalloc.c:
+ A cursory look through our logs and comments indicates that these are
+ the only modified files. No feature enhancements have been made;
+ rather, all changes either fix minor programming errors, get rid of
+ warnings, ANSI-ify the code, or integrate Burg into our build system.
+
diff --git a/llvm/utils/Burg/Makefile b/llvm/utils/Burg/Makefile
new file mode 100644
index 00000000000..5797161619b
--- /dev/null
+++ b/llvm/utils/Burg/Makefile
@@ -0,0 +1,28 @@
+LEVEL = ../..
+TOOLNAME = burg
+ExtraSource = gram.tab.c
+
+include $(LEVEL)/Makefile.common
+
+gram.tab.c gram.tab.h:: gram.yc
+ $(VERB) $(BISON) -o gram.tab.c -d $<
+
+$(SourceDir)/lex.c: gram.tab.h
+
+clean::
+ rm -rf gram.tab.h gram.tab.c core* *.aux *.log *.dvi sample sample.c tmp
+
+#$(BUILD_OBJ_DIR)/Release/lex.o $(BUILD_OBJ_DIR)/Profile/lex.o $(BUILD_OBJ_DIR)/Debug/lex.o: gram.tab.h
+
+doc.dvi: doc.tex
+ latex doc; latex doc
+
+
+test:: $(TOOLEXENAME_G) sample.gr
+ $(TOOLEXENAME_G) -I <sample.gr >sample.c && $(CC) $(CFLAGS) -o sample sample.c && ./sample
+ $(TOOLEXENAME_G) -I sample.gr >tmp && cmp tmp sample.c
+ $(TOOLEXENAME_G) -I <sample.gr -o tmp && cmp tmp sample.c
+ $(TOOLEXENAME_G) -I sample.gr -o tmp && cmp tmp sample.c
+ $(TOOLEXENAME_G) -I -O0 <sample.gr >tmp && cmp tmp sample.c
+ $(TOOLEXENAME_G) -I -= <sample.gr >tmp && cmp tmp sample.c
+ $(RM) -f tmp sample.c
diff --git a/llvm/utils/Burg/README b/llvm/utils/Burg/README
new file mode 100644
index 00000000000..bc26405727e
--- /dev/null
+++ b/llvm/utils/Burg/README
@@ -0,0 +1,14 @@
+To format the documentation, type "make doc.dvi" and print the result.
+
+The length of the cost vectors is fixed at 4 for reasons that are
+primarily historical. To change it, edit the definition of DELTAWIDTH
+in b.h.
+
+Burg is compiled without optimization by default to avoid problems
+with initial installation. To improve burg's performance, add '-O' to
+CFLAGS in the Makefile and rebuild burg with a high quality optimizing
+compiler.
+
+To be added to the Burg mailing list, send your preferred electronic
+mail address to cwf@research.att.com.
+
diff --git a/llvm/utils/Burg/b.h b/llvm/utils/Burg/b.h
new file mode 100644
index 00000000000..164325dc976
--- /dev/null
+++ b/llvm/utils/Burg/b.h
@@ -0,0 +1,311 @@
+/* $Id$ */
+
+#define MAX_ARITY 2
+
+typedef int ItemSetNum;
+typedef int OperatorNum;
+typedef int NonTerminalNum;
+typedef int RuleNum;
+typedef int ArityNum;
+typedef int ERuleNum;
+
+extern NonTerminalNum last_user_nonterminal;
+extern NonTerminalNum max_nonterminal;
+extern RuleNum max_rule;
+extern ERuleNum max_erule_num;
+extern int max_arity;
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+#ifndef NOLEX
+#define DELTAWIDTH 4
+typedef short DeltaCost[DELTAWIDTH];
+typedef short *DeltaPtr;
+extern void ASSIGNCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ADDCOST ARGS((DeltaPtr, DeltaPtr));
+extern void MINUSCOST ARGS((DeltaPtr, DeltaPtr));
+extern void ZEROCOST ARGS((DeltaPtr));
+extern int LESSCOST ARGS((DeltaPtr, DeltaPtr));
+extern int EQUALCOST ARGS((DeltaPtr, DeltaPtr));
+#define PRINCIPLECOST(x) (x[0])
+#else
+#define DELTAWIDTH 1
+typedef int DeltaCost;
+typedef int DeltaPtr;
+#define ASSIGNCOST(l, r) ((l) = (r))
+#define ADDCOST(l, r) ((l) += (r))
+#define MINUSCOST(l, r) ((l) -= (r))
+#define ZEROCOST(x) ((x) = 0)
+#define LESSCOST(l, r) ((l) < (r))
+#define EQUALCOST(l, r) ((l) == (r))
+#define PRINCIPLECOST(x) (x)
+#endif /* NOLEX */
+#define NODIVERGE(c,state,nt,base) if (prevent_divergence > 0) CHECKDIVERGE(c,state,nt,base);
+
+struct list {
+ void *x;
+ struct list *next;
+};
+typedef struct list *List;
+
+struct intlist {
+ int x;
+ struct intlist *next;
+};
+typedef struct intlist *IntList;
+
+struct operator {
+ char *name;
+ unsigned int ref:1;
+ OperatorNum num;
+ ItemSetNum baseNum;
+ ItemSetNum stateCount;
+ ArityNum arity;
+ struct table *table;
+};
+typedef struct operator *Operator;
+
+struct nonterminal {
+ char *name;
+ NonTerminalNum num;
+ ItemSetNum baseNum;
+ ItemSetNum ruleCount;
+ struct plankMap *pmap;
+
+ struct rule *sampleRule; /* diagnostic---gives "a" rule that with this lhs */
+};
+typedef struct nonterminal *NonTerminal;
+
+struct pattern {
+ NonTerminal normalizer;
+ Operator op; /* NULL if NonTerm -> NonTerm */
+ NonTerminal children[MAX_ARITY];
+};
+typedef struct pattern *Pattern;
+
+struct rule {
+ DeltaCost delta;
+ ERuleNum erulenum;
+ RuleNum num;
+ RuleNum newNum;
+ NonTerminal lhs;
+ Pattern pat;
+ unsigned int used:1;
+};
+typedef struct rule *Rule;
+
+struct item {
+ DeltaCost delta;
+ Rule rule;
+};
+typedef struct item Item;
+
+typedef short *Relevant; /* relevant non-terminals */
+
+typedef Item *ItemArray;
+
+struct item_set { /* indexed by NonTerminal */
+ ItemSetNum num;
+ ItemSetNum newNum;
+ Operator op;
+ struct item_set *kids[2];
+ struct item_set *representative;
+ Relevant relevant;
+ ItemArray virgin;
+ ItemArray closed;
+};
+typedef struct item_set *Item_Set;
+
+#define DIM_MAP_SIZE (1 << 8)
+#define GLOBAL_MAP_SIZE (1 << 15)
+
+struct mapping { /* should be a hash table for TS -> int */
+ List *hash;
+ int hash_size;
+ int max_size;
+ ItemSetNum count;
+ Item_Set *set; /* map: int <-> Item_Set */
+};
+typedef struct mapping *Mapping;
+
+struct index_map {
+ ItemSetNum max_size;
+ Item_Set *class;
+};
+typedef struct index_map Index_Map;
+
+struct dimension {
+ Relevant relevant;
+ Index_Map index_map;
+ Mapping map;
+ ItemSetNum max_size;
+ struct plankMap *pmap;
+};
+typedef struct dimension *Dimension;
+
+
+struct table {
+ Operator op;
+ List rules;
+ Relevant relevant;
+ Dimension dimen[MAX_ARITY]; /* 1 for each dimension */
+ Item_Set *transition; /* maps local indices to global
+ itemsets */
+};
+typedef struct table *Table;
+
+struct relation {
+ Rule rule;
+ DeltaCost chain;
+ NonTerminalNum nextchain;
+ DeltaCost sibling;
+ int sibFlag;
+ int sibComputed;
+};
+typedef struct relation *Relation;
+
+struct queue {
+ List head;
+ List tail;
+};
+typedef struct queue *Queue;
+
+struct plank {
+ char *name;
+ List fields;
+ int width;
+};
+typedef struct plank *Plank;
+
+struct except {
+ short index;
+ short value;
+};
+typedef struct except *Exception;
+
+struct plankMap {
+ List exceptions;
+ int offset;
+ struct stateMap *values;
+};
+typedef struct plankMap *PlankMap;
+
+struct stateMap {
+ char *fieldname;
+ Plank plank;
+ int width;
+ short *value;
+};
+typedef struct stateMap *StateMap;
+
+struct stateMapTable {
+ List maps;
+};
+
+extern void CHECKDIVERGE ARGS((DeltaPtr, Item_Set, int, int));
+extern void zero ARGS((Item_Set));
+extern ItemArray newItemArray ARGS((void));
+extern ItemArray itemArrayCopy ARGS((ItemArray));
+extern Item_Set newItem_Set ARGS((Relevant));
+extern void freeItem_Set ARGS((Item_Set));
+extern Mapping newMapping ARGS((int));
+extern NonTerminal newNonTerminal ARGS((char *));
+extern int nonTerminalName ARGS((char *, int));
+extern Operator newOperator ARGS((char *, OperatorNum, ArityNum));
+extern Pattern newPattern ARGS((Operator));
+extern Rule newRule ARGS((DeltaPtr, ERuleNum, NonTerminal, Pattern));
+extern List newList ARGS((void *, List));
+extern IntList newIntList ARGS((int, IntList));
+extern int length ARGS((List));
+extern List appendList ARGS((void *, List));
+extern Table newTable ARGS((Operator));
+extern Queue newQ ARGS((void));
+extern void addQ ARGS((Queue, Item_Set));
+extern Item_Set popQ ARGS((Queue));
+extern int equivSet ARGS((Item_Set, Item_Set));
+extern Item_Set decode ARGS((Mapping, ItemSetNum));
+extern Item_Set encode ARGS((Mapping, Item_Set, int *));
+extern void build ARGS((void));
+extern Item_Set *transLval ARGS((Table, int, int));
+
+typedef void * (*ListFn) ARGS((void *));
+extern void foreachList ARGS((ListFn, List));
+extern void reveachList ARGS((ListFn, List));
+
+extern void addToTable ARGS((Table, Item_Set));
+
+extern void closure ARGS((Item_Set));
+extern void trim ARGS((Item_Set));
+extern void findChainRules ARGS((void));
+extern void findAllPairs ARGS((void));
+extern void addRelevant ARGS((Relevant, NonTerminalNum));
+
+extern void *zalloc ARGS((unsigned int));
+extern void zfree ARGS((void *));
+
+extern NonTerminal start;
+extern List rules;
+extern List chainrules;
+extern List operators;
+extern List leaves;
+extern List nonterminals;
+extern List grammarNts;
+extern Queue globalQ;
+extern Mapping globalMap;
+extern int exceptionTolerance;
+extern int prevent_divergence;
+extern int principleCost;
+extern int lexical;
+extern struct rule stub_rule;
+extern Relation *allpairs;
+extern Item_Set *sortedStates;
+extern Item_Set errorState;
+
+extern void dumpRelevant ARGS((Relevant));
+extern void dumpOperator ARGS((Operator, int));
+extern void dumpOperator_s ARGS((Operator));
+extern void dumpOperator_l ARGS((Operator));
+extern void dumpNonTerminal ARGS((NonTerminal));
+extern void dumpRule ARGS((Rule));
+extern void dumpRuleList ARGS((List));
+extern void dumpItem ARGS((Item *));
+extern void dumpItem_Set ARGS((Item_Set));
+extern void dumpMapping ARGS((Mapping));
+extern void dumpQ ARGS((Queue));
+extern void dumpIndex_Map ARGS((Index_Map *));
+extern void dumpDimension ARGS((Dimension));
+extern void dumpPattern ARGS((Pattern));
+extern void dumpTable ARGS((Table, int));
+extern void dumpTransition ARGS((Table));
+extern void dumpCost ARGS((DeltaCost));
+extern void dumpAllPairs ARGS((void));
+extern void dumpRelation ARGS((Relation));
+extern void dumpSortedStates ARGS((void));
+extern void dumpSortedRules ARGS((void));
+extern int debugTrim;
+
+#ifdef DEBUG
+#define debug(a,b) if (a) b
+#else
+#define debug(a,b)
+#endif
+extern int debugTables;
+
+#define TABLE_INCR 8
+#define STATES_INCR 64
+
+#ifdef NDEBUG
+#define assert(c) ((void) 0)
+#else
+#define assert(c) ((void) ((c) || fatal(__FILE__,__LINE__)))
+#endif
+
+extern void doStart ARGS((char *));
+extern void exit ARGS((int));
+extern int fatal ARGS((const char *, int));
+extern void yyerror ARGS((const char *));
+extern void yyerror1 ARGS((const char *));
diff --git a/llvm/utils/Burg/be.c b/llvm/utils/Burg/be.c
new file mode 100644
index 00000000000..defe948d2db
--- /dev/null
+++ b/llvm/utils/Burg/be.c
@@ -0,0 +1,1052 @@
+char rcsid_be[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+FILE *outfile;
+const char *prefix = "burm";
+
+static void doKids ARGS((RuleAST));
+static void doLabel ARGS((Operator));
+static void doLayout ARGS((RuleAST));
+static void doMakeTable ARGS((Operator));
+static void doVector ARGS((RuleAST));
+static void layoutNts ARGS((PatternAST));
+static void makeIndex_Map ARGS((Dimension));
+static void makePvector ARGS((void));
+static void makeState ARGS((void));
+static void printPatternAST ARGS((PatternAST));
+static void printPatternAST_int ARGS((PatternAST));
+static void setVectors ARGS((PatternAST));
+static void trailing_zeroes ARGS((int));
+static int seminal ARGS((int from, int to));
+static void printRule ARGS((RuleAST, const char *));
+
+static void
+doLabel(op) Operator op;
+{
+ fprintf(outfile, "\tcase %d:\n", op->num);
+
+ switch (op->arity) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->num);
+ break;
+ case 1:
+ if (op->table->rules) {
+ fprintf(outfile, "\t\treturn %s_%s_transition[l];\n", prefix, op->name);
+ } else {
+ fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+ }
+ break;
+ case 2:
+ if (op->table->rules) {
+ fprintf(outfile, "\t\treturn %s_%s_transition[%s_%s_imap_1[l]][%s_%s_imap_2[r]];\n", prefix, op->name, prefix, op->name, prefix, op->name);
+ } else {
+ fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+ }
+ break;
+ }
+}
+
+int
+opsOfArity(arity) int arity;
+{
+ int c;
+ List l;
+
+ c = 0;
+ for (l = operators; l; l = l->next) {
+ Operator op = (Operator) l->x;
+ if (op->arity == arity) {
+ fprintf(outfile, "\tcase %d:\n", op->num);
+ c++;
+ }
+ }
+ return c;
+}
+
+static void
+trailing_zeroes(z) int z;
+{
+ int i;
+
+ for (i = 0; i < z; i++) {
+ fprintf(outfile, ", 0");
+ }
+}
+
+void
+makeLabel()
+{
+ int flag;
+
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "int %s_label(%s_NODEPTR_TYPE n) {\n", prefix, prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_label(n) %s_NODEPTR_TYPE n; {\n", prefix, prefix);
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile,
+ "\t%s_assert(n, %s_PANIC(\"NULL pointer passed to %s_label\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile, "\tswitch (%s_OP_LABEL(n)) {\n", prefix);
+ fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_label\\n\", %s_OP_LABEL(n)); abort(); return 0;\n",
+ prefix, prefix, prefix);
+
+ flag = opsOfArity(0);
+ if (flag > 0) {
+ fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n)",
+ prefix, prefix, prefix);
+ trailing_zeroes(max_arity);
+ fprintf(outfile, ");\n");
+ }
+ flag = opsOfArity(1);
+ if (flag > 0) {
+ fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n))",
+ prefix, prefix, prefix, prefix, prefix);
+ trailing_zeroes(max_arity-1);
+ fprintf(outfile, ");\n");
+ }
+ flag = opsOfArity(2);
+ if (flag > 0) {
+ fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n)), %s_label(%s_RIGHT_CHILD(n))",
+ prefix, prefix, prefix, prefix, prefix, prefix, prefix);
+ trailing_zeroes(max_arity-2);
+ fprintf(outfile, ");\n");
+
+ }
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "}\n");
+}
+
+static void
+makeState()
+{
+ fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+ fprintf(outfile,
+ "\t%s_assert(l >= 0 && l < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+ prefix, globalMap->count, prefix);
+ fprintf(outfile,
+ "\t%s_assert(r >= 0 && r < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+ prefix, globalMap->count, prefix);
+ fprintf(outfile, "\tswitch (op) {\n");
+ fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix);
+
+ foreachList((ListFn) doLabel, operators);
+
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "}\n");
+}
+
+static char cumBuf[4000];
+static int vecIndex;
+char vecBuf[4000];
+
+static void
+setVectors(ast) PatternAST ast;
+{
+ char old[4000];
+
+ switch (ast->sym->tag) {
+ default:
+ assert(0);
+ break;
+ case NONTERMINAL:
+ sprintf(old, "\t\tkids[%d] = %s;\n", vecIndex, vecBuf);
+ strcat(cumBuf, old);
+ vecIndex++;
+ return;
+ case OPERATOR:
+ switch (ast->sym->u.op->arity) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ return;
+ case 1:
+ strcpy(old, vecBuf);
+ sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+ setVectors((PatternAST) ast->children->x);
+ strcpy(vecBuf, old);
+ return;
+ case 2:
+ strcpy(old, vecBuf);
+ sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
+ setVectors((PatternAST) ast->children->x);
+
+ sprintf(vecBuf, "%s_RIGHT_CHILD(%s)", prefix, old);
+ setVectors((PatternAST) ast->children->next->x);
+ strcpy(vecBuf, old);
+ return;
+ }
+ break;
+ }
+}
+
+#define MAX_VECTOR 10
+
+void
+makeRuleTable()
+{
+ int s,nt;
+
+ fprintf(outfile, "static short %s_RuleNo[%d][%d] = {\n", prefix, globalMap->count, last_user_nonterminal-1);
+ for (s = 0; s < globalMap->count; s++) {
+ Item_Set ts = globalMap->set[s];
+ if (s > 0) {
+ fprintf(outfile, ",\n");
+ }
+ fprintf(outfile, "/* state %d */\n", s);
+ fprintf(outfile, "{");
+ for (nt = 1; nt < last_user_nonterminal; nt++) {
+ if (nt > 1) {
+ fprintf(outfile, ",");
+ if (nt % 10 == 1) {
+ fprintf(outfile, "\t/* state %d; Nonterminals %d-%d */\n", s, nt-10, nt-1);
+ }
+ }
+ if (ts->closed[nt].rule) {
+ ts->closed[nt].rule->used = 1;
+ fprintf(outfile, "%5d", ts->closed[nt].rule->erulenum);
+ } else {
+ fprintf(outfile, "%5d", ERROR_VAL);
+ }
+ }
+ fprintf(outfile, "}");
+ }
+ fprintf(outfile, "};\n");
+}
+
+static void
+makeIndex_Map(d) Dimension d;
+{
+ int s;
+
+ for (s = 0; s < globalMap->count; s++) {
+ if (s > 0) {
+ fprintf(outfile, ",");
+ if (s % 10 == 0) {
+ fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+ }
+ }
+ fprintf(outfile, "%5d", d->map->set[d->index_map.class[s]->num]->num);
+ }
+ fprintf(outfile, "};\n");
+}
+
+static void
+doMakeTable(op) Operator op;
+{
+ int s;
+ int i,j;
+ Dimension d;
+
+ switch (op->arity) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ return;
+ case 1:
+ if (!op->table->rules) {
+ return;
+ }
+ d = op->table->dimen[0];
+ fprintf(outfile, "static short %s_%s_transition[%d] = {\n", prefix, op->name, globalMap->count);
+ for (s = 0; s < globalMap->count; s++) {
+ if (s > 0) {
+ fprintf(outfile, ", ");
+ if (s % 10 == 0) {
+ fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
+ }
+ }
+ fprintf(outfile, "%5d", op->table->transition[d->map->set[d->index_map.class[s]->num]->num]->num);
+ }
+ fprintf(outfile, "};\n");
+ break;
+ case 2:
+ if (!op->table->rules) {
+ return;
+ }
+ fprintf(outfile, "static short %s_%s_imap_1[%d] = {\n", prefix, op->name, globalMap->count);
+ makeIndex_Map(op->table->dimen[0]);
+ fprintf(outfile, "static short %s_%s_imap_2[%d] = {\n", prefix, op->name, globalMap->count);
+ makeIndex_Map(op->table->dimen[1]);
+
+ fprintf(outfile, "static short %s_%s_transition[%d][%d] = {", prefix, op->name,
+ op->table->dimen[0]->map->count,
+ op->table->dimen[1]->map->count);
+ for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+ if (i > 0) {
+ fprintf(outfile, ",");
+ }
+ fprintf(outfile, "\n");
+ fprintf(outfile, "{");
+ for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+ Item_Set *ts = transLval(op->table, i, j);
+ if (j > 0) {
+ fprintf(outfile, ",");
+ }
+ fprintf(outfile, "%5d", (*ts)->num);
+ }
+ fprintf(outfile, "}\t/* row %d */", i);
+ }
+ fprintf(outfile, "\n};\n");
+
+ break;
+ }
+}
+
+void
+makeTables()
+{
+ foreachList((ListFn) doMakeTable, operators);
+}
+
+RuleAST *pVector;
+
+void
+makeLHSmap()
+{
+ int i;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ fprintf(outfile, "short %s_lhs[] = {\n", prefix);
+ for (i = 0; i <= max_erule_num; i++) {
+ if (pVector[i]) {
+ fprintf(outfile, "\t%s_%s_NT,\n", prefix, pVector[i]->lhs);
+ } else {
+ fprintf(outfile, "\t0,\n");
+ }
+ }
+ fprintf(outfile, "};\n\n");
+}
+
+static int seminal(int from, int to)
+{
+ return allpairs[from][to].rule ? allpairs[from][to].rule->erulenum : 0;
+
+ /*
+ int tmp, last;
+ tmp = 0;
+ for (;;) {
+ last = tmp;
+ tmp = allpairs[to][from].rule ? allpairs[to][from].rule->erulenum : 0;
+ if (!tmp) {
+ break;
+ }
+ assert(pVector[tmp]);
+ to = pVector[tmp]->rule->pat->children[0]->num;
+ }
+ return last;
+ */
+}
+
+void
+makeClosureArray()
+{
+ int i, j;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ fprintf(outfile, "short %s_closure[%d][%d] = {\n", prefix, last_user_nonterminal, last_user_nonterminal);
+ for (i = 0; i < last_user_nonterminal; i++) {
+ fprintf(outfile, "\t{");
+ for (j = 0; j < last_user_nonterminal; j++) {
+ if (j > 0 && j%10 == 0) {
+ fprintf(outfile, "\n\t ");
+ }
+ fprintf(outfile, " %4d,", seminal(i,j));
+ }
+ fprintf(outfile, "},\n");
+ }
+ fprintf(outfile, "};\n");
+}
+
+void
+makeCostVector(z,d) int z; DeltaCost d;
+{
+ fprintf(outfile, "\t{");
+#ifdef NOLEX
+ if (z) {
+ fprintf(outfile, "%5d", d);
+ } else {
+ fprintf(outfile, "%5d", 0);
+ }
+#else
+ {
+ int j;
+ for (j = 0; j < DELTAWIDTH; j++) {
+ if (j > 0) {
+ fprintf(outfile, ",");
+ }
+ if (z) {
+ fprintf(outfile, "%5d", d[j]);
+ } else {
+ fprintf(outfile, "%5d", 0);
+ }
+ }
+ }
+#endif /* NOLEX */
+ fprintf(outfile, "}");
+}
+
+void
+makeCostArray()
+{
+ int i;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH);
+ for (i = 0; i <= max_erule_num; i++) {
+ makeCostVector(pVector[i], pVector[i] ? pVector[i]->rule->delta : 0);
+ fprintf(outfile, ", /* ");
+ printRule(pVector[i], "(none)");
+ fprintf(outfile, " = %d */\n", i);
+ }
+ fprintf(outfile, "};\n");
+}
+
+void
+makeStateStringArray()
+{
+ int s;
+ int nt;
+ int states;
+
+ states = globalMap->count;
+ fprintf(outfile, "\nconst char * %s_state_string[] = {\n", prefix);
+ fprintf(outfile, "\" not a state\", /* state 0 */\n");
+ for (s = 0; s < states-1; s++) {
+ fprintf(outfile, "\t\"");
+ printRepresentative(outfile, sortedStates[s]);
+ fprintf(outfile, "\", /* state #%d */\n", s+1);
+ }
+ fprintf(outfile, "};\n");
+}
+
+void
+makeDeltaCostArray()
+{
+ int s;
+ int nt;
+ int states;
+
+ states = globalMap->count;
+ fprintf(outfile, "\nshort %s_delta_cost[%d][%d][%d] = {\n", prefix, states, last_user_nonterminal, DELTAWIDTH);
+ fprintf(outfile, "{{0}}, /* state 0 */\n");
+ for (s = 0; s < states-1; s++) {
+ fprintf(outfile, "{ /* state #%d: ", s+1);
+ printRepresentative(outfile, sortedStates[s]);
+ fprintf(outfile, " */\n");
+ fprintf(outfile, "\t{0},\n");
+ for (nt = 1; nt < last_user_nonterminal; nt++) {
+ makeCostVector(1, sortedStates[s]->closed[nt].delta);
+ fprintf(outfile, ", /* ");
+ if (sortedStates[s]->closed[nt].rule) {
+ int erulenum = sortedStates[s]->closed[nt].rule->erulenum;
+ printRule(pVector[erulenum], "(none)");
+ fprintf(outfile, " = %d */", erulenum);
+ } else {
+ fprintf(outfile, "(none) */");
+ }
+ fprintf(outfile, "\n");
+ }
+ fprintf(outfile, "},\n");
+ }
+ fprintf(outfile, "};\n");
+}
+
+static void
+printPatternAST_int(p) PatternAST p;
+{
+ List l;
+
+ if (p) {
+ switch (p->sym->tag) {
+ case NONTERMINAL:
+ fprintf(outfile, "%5d,", -p->sym->u.nt->num);
+ break;
+ case OPERATOR:
+ fprintf(outfile, "%5d,", p->sym->u.op->num);
+ break;
+ default:
+ assert(0);
+ }
+ if (p->children) {
+ for (l = p->children; l; l = l->next) {
+ PatternAST pat = (PatternAST) l->x;
+ printPatternAST_int(pat);
+ }
+ }
+ }
+}
+
+static void
+printPatternAST(p) PatternAST p;
+{
+ List l;
+
+ if (p) {
+ fprintf(outfile, "%s", p->op);
+ if (p->children) {
+ fprintf(outfile, "(");
+ for (l = p->children; l; l = l->next) {
+ PatternAST pat = (PatternAST) l->x;
+ if (l != p->children) {
+ fprintf(outfile, ", ");
+ }
+ printPatternAST(pat);
+ }
+ fprintf(outfile, ")");
+ }
+ }
+}
+
+static void
+layoutNts(ast) PatternAST ast;
+{
+ char out[30];
+
+ switch (ast->sym->tag) {
+ default:
+ assert(0);
+ break;
+ case NONTERMINAL:
+ sprintf(out, "%d, ", ast->sym->u.nt->num);
+ strcat(cumBuf, out);
+ return;
+ case OPERATOR:
+ switch (ast->sym->u.op->arity) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ return;
+ case 1:
+ layoutNts((PatternAST) ast->children->x);
+ return;
+ case 2:
+ layoutNts((PatternAST) ast->children->x);
+ layoutNts((PatternAST) ast->children->next->x);
+ return;
+ }
+ break;
+ }
+}
+
+static void
+doVector(ast) RuleAST ast;
+{
+ if (pVector[ast->rule->erulenum]) {
+ fprintf(stderr, "ERROR: non-unique external rule number: (%d)\n", ast->rule->erulenum);
+ exit(1);
+ }
+ pVector[ast->rule->erulenum] = ast;
+}
+
+static void
+makePvector()
+{
+ pVector = (RuleAST*) zalloc((max_erule_num+1) * sizeof(RuleAST));
+ foreachList((ListFn) doVector, ruleASTs);
+}
+
+static void
+doLayout(ast) RuleAST ast;
+{
+ sprintf(cumBuf, "{ ");
+ layoutNts(ast->pat);
+ strcat(cumBuf, "0 }");
+}
+
+void
+makeNts()
+{
+ int i;
+ int new;
+ StrTable nts;
+
+ nts = newStrTable();
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ for (i = 0; i <= max_erule_num; i++) {
+ if (pVector[i]) {
+ doLayout(pVector[i]);
+ pVector[i]->nts = addString(nts, cumBuf, i, &new);
+ if (new) {
+ char ename[50];
+
+ sprintf(ename, "%s_r%d_nts", prefix, i);
+ pVector[i]->nts->ename = (char*) zalloc(strlen(ename)+1);
+ strcpy(pVector[i]->nts->ename, ename);
+ fprintf(outfile, "static short %s[] =", ename);
+ fprintf(outfile, "%s;\n", cumBuf);
+ }
+ }
+ }
+
+ fprintf(outfile, "short *%s_nts[] = {\n", prefix);
+ for (i = 0; i <= max_erule_num; i++) {
+ if (pVector[i]) {
+ fprintf(outfile, "\t%s,\n", pVector[i]->nts->ename);
+ } else {
+ fprintf(outfile, "\t0,\n");
+ }
+ }
+ fprintf(outfile, "};\n");
+}
+
+static void
+printRule(RuleAST r, const char *d)
+{
+ if (r) {
+ fprintf(outfile, "%s: ", r->rule->lhs->name);
+ printPatternAST(r->pat);
+ } else {
+ fprintf(outfile, "%s", d);
+ }
+}
+
+void
+makeRuleDescArray()
+{
+ int i;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ if (last_user_nonterminal != max_nonterminal) {
+ /* not normal form */
+ fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 0 };\n", prefix);
+ } else {
+ fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 1 };\n", prefix);
+ }
+ for (i = 1; i <= max_erule_num; i++) {
+ if (pVector[i]) {
+ Operator o;
+ NonTerminal t;
+
+ fprintf(outfile, "short %s_rule_descriptor_%d[] = {", prefix, i);
+ fprintf(outfile, "%5d,", -pVector[i]->rule->lhs->num);
+ printPatternAST_int(pVector[i]->pat);
+ fprintf(outfile, " };\n");
+ }
+ }
+
+ fprintf(outfile, "/* %s_rule_descriptors[0][1] = 1 iff grammar is normal form. */\n", prefix);
+ fprintf(outfile, "short * %s_rule_descriptors[] = {\n", prefix);
+ fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+ for (i = 1; i <= max_erule_num; i++) {
+ if (pVector[i]) {
+ fprintf(outfile, "\t%s_rule_descriptor_%d,\n", prefix, i);
+ } else {
+ fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
+ }
+ }
+ fprintf(outfile, "};\n");
+}
+
+
+void
+makeRuleDescArray2()
+{
+ int i;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ fprintf(outfile, "struct { int lhs, op, left, right; } %s_rule_struct[] = {\n", prefix);
+ if (last_user_nonterminal != max_nonterminal) {
+ /* not normal form */
+ fprintf(outfile, "\t{-1},");
+ } else {
+ fprintf(outfile, "\t{0},");
+ }
+ fprintf(outfile, " /* 0 if normal form, -1 if not normal form */\n");
+ for (i = 1; i <= max_erule_num; i++) {
+ fprintf(outfile, "\t");
+ if (pVector[i]) {
+ Operator o;
+ NonTerminal t1, t2;
+
+ fprintf(outfile, "{");
+ fprintf(outfile, "%5d, %5d, %5d, %5d",
+ pVector[i]->rule->lhs->num,
+ (o = pVector[i]->rule->pat->op) ? o->num : 0,
+ (t1 = pVector[i]->rule->pat->children[0]) ? t1->num : 0,
+ (t2 = pVector[i]->rule->pat->children[1]) ? t2->num : 0
+ );
+ fprintf(outfile, "} /* ");
+ printRule(pVector[i], "0");
+ fprintf(outfile, " = %d */", i);
+ } else {
+ fprintf(outfile, "{0}");
+ }
+ fprintf(outfile, ",\n");
+ }
+ fprintf(outfile, "};\n");
+}
+
+void
+makeStringArray()
+{
+ int i;
+
+ if (!pVector) {
+ makePvector();
+ }
+
+ fprintf(outfile, "const char *%s_string[] = {\n", prefix);
+ for (i = 0; i <= max_erule_num; i++) {
+ fprintf(outfile, "\t");
+ if (pVector[i]) {
+ fprintf(outfile, "\"");
+ printRule(pVector[i], "0");
+ fprintf(outfile, "\"");
+ } else {
+ fprintf(outfile, "0");
+ }
+ fprintf(outfile, ",\n");
+ }
+ fprintf(outfile, "};\n");
+ fprintf(outfile, "int %s_max_rule = %d;\n", prefix, max_erule_num);
+ fprintf(outfile, "#define %s_Max_rule %d\n", prefix, max_erule_num);
+}
+
+void
+makeRule()
+{
+ fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+ fprintf(outfile,
+ "\t%s_assert(state >= 0 && state < %d, PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+ prefix, globalMap->count, prefix);
+ fprintf(outfile,
+ "\t%s_assert(goalnt >= 1 && goalnt < %d, PANIC(\"Bad goalnt %%d passed to %s_rule\\n\", state));\n",
+ prefix, max_nonterminal, prefix);
+ fprintf(outfile, "\treturn %s_RuleNo[state][goalnt-1];\n", prefix);
+ fprintf(outfile, "};\n");
+}
+
+static StrTable kids;
+
+static void
+doKids(ast) RuleAST ast;
+{
+ int new;
+
+ vecIndex = 0;
+ cumBuf[0] = 0;
+ strcpy(vecBuf, "p");
+ setVectors(ast->pat);
+
+ ast->kids = addString(kids, cumBuf, ast->rule->erulenum, &new);
+
+}
+
+void
+makeKids()
+{
+ List e;
+ IntList r;
+
+ kids = newStrTable();
+
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(%s_NODEPTR_TYPE p, int rulenumber, %s_NODEPTR_TYPE *kids) {\n", prefix, prefix, prefix, prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(p, rulenumber, kids) %s_NODEPTR_TYPE p; int rulenumber; %s_NODEPTR_TYPE *kids; {\n", prefix, prefix, prefix, prefix);
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile,
+ "\t%s_assert(p, %s_PANIC(\"NULL node pointer passed to %s_kids\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile,
+ "\t%s_assert(kids, %s_PANIC(\"NULL kids pointer passed to %s_kids\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile, "\tswitch (rulenumber) {\n");
+ fprintf(outfile, "\tdefault:\n");
+ fprintf(outfile, "\t\t%s_PANIC(\"Unknown Rule %%d in %s_kids;\\n\", rulenumber);\n", prefix, prefix);
+ fprintf(outfile, "\t\tabort();\n");
+ fprintf(outfile, "\t\t/* NOTREACHED */\n");
+
+ foreachList((ListFn) doKids, ruleASTs);
+
+ for (e = kids->elems; e; e = e->next) {
+ StrTableElement el = (StrTableElement) e->x;
+ for (r = el->erulenos; r; r = r->next) {
+ int i = r->x;
+ fprintf(outfile, "\tcase %d:\n", i);
+ }
+ fprintf(outfile, "%s", el->str);
+ fprintf(outfile, "\t\tbreak;\n");
+ }
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "\treturn kids;\n");
+ fprintf(outfile, "}\n");
+}
+
+void
+makeOpLabel()
+{
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "int %s_op_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_op_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+ fprintf(outfile, "#endif\n");
+ fprintf(outfile,
+ "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_op_label\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile, "\treturn %s_OP_LABEL(p);\n", prefix);
+ fprintf(outfile, "}\n");
+}
+
+void
+makeStateLabel()
+{
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "int %s_state_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_state_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile,
+ "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_state_label\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile, "\treturn %s_STATE_LABEL(p);\n", prefix);
+ fprintf(outfile, "}\n");
+}
+
+void
+makeChild()
+{
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "%s_NODEPTR_TYPE %s_child(%s_NODEPTR_TYPE p, int index) {\n", prefix, prefix, prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "%s_NODEPTR_TYPE %s_child(p, index) %s_NODEPTR_TYPE p; int index; {\n", prefix, prefix, prefix);
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile,
+ "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_child\\n\"));\n",
+ prefix, prefix, prefix);
+ fprintf(outfile, "\tswitch (index) {\n");
+ fprintf(outfile, "\tcase 0:\n");
+ fprintf(outfile, "\t\treturn %s_LEFT_CHILD(p);\n", prefix);
+ fprintf(outfile, "\tcase 1:\n");
+ fprintf(outfile, "\t\treturn %s_RIGHT_CHILD(p);\n", prefix);
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "\t%s_PANIC(\"Bad index %%d in %s_child;\\n\", index);\n", prefix, prefix);
+ fprintf(outfile, "\tabort();\n");
+ fprintf(outfile, "\treturn 0;\n");
+ fprintf(outfile, "}\n");
+}
+
+static Operator *opVector;
+static int maxOperator;
+
+void
+makeOperatorVector()
+{
+ List l;
+
+ maxOperator = 0;
+ for (l = operators; l; l = l->next) {
+ Operator op = (Operator) l->x;
+ if (op->num > maxOperator) {
+ maxOperator = op->num;
+ }
+ }
+ opVector = (Operator*) zalloc((maxOperator+1) * sizeof(*opVector));
+ for (l = operators; l; l = l->next) {
+ Operator op = (Operator) l->x;
+ if (opVector[op->num]) {
+ fprintf(stderr, "ERROR: Non-unique external symbol number (%d)\n", op->num);
+ exit(1);
+ }
+ opVector[op->num] = op;
+ }
+}
+
+void
+makeOperators()
+{
+ int i;
+
+ if (!opVector) {
+ makeOperatorVector();
+ }
+ fprintf(outfile, "const char * %s_opname[] = {\n", prefix);
+ for (i = 0; i <= maxOperator; i++) {
+ if (i > 0) {
+ fprintf(outfile, ", /* %d */\n", i-1);
+ }
+ if (opVector[i]) {
+ fprintf(outfile, "\t\"%s\"", opVector[i]->name);
+ } else {
+ fprintf(outfile, "\t0");
+ }
+ }
+ fprintf(outfile, "\n};\n");
+ fprintf(outfile, "char %s_arity[] = {\n", prefix);
+ for (i = 0; i <= maxOperator; i++) {
+ if (i > 0) {
+ fprintf(outfile, ", /* %d */\n", i-1);
+ }
+ fprintf(outfile, "\t%d", opVector[i] ? opVector[i]->arity : -1);
+ }
+ fprintf(outfile, "\n};\n");
+ fprintf(outfile, "int %s_max_op = %d;\n", prefix, maxOperator);
+ fprintf(outfile, "int %s_max_state = %d;\n", prefix, globalMap->count-1);
+ fprintf(outfile, "#define %s_Max_state %d\n", prefix, globalMap->count-1);
+}
+
+void
+makeDebug()
+{
+ fprintf(outfile, "#ifdef DEBUG\n");
+ fprintf(outfile, "int %s_debug;\n", prefix);
+ fprintf(outfile, "#endif /* DEBUG */\n");
+}
+
+void
+makeSimple()
+{
+ makeRuleTable();
+ makeTables();
+ makeRule();
+ makeState();
+}
+
+void
+startOptional()
+{
+ fprintf(outfile, "#ifdef %s_STATE_LABEL\n", prefix);
+ fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "#ifdef STATE_LABEL\n");
+ fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
+ fprintf(outfile, "#define %s_STATE_LABEL \tSTATE_LABEL\n", prefix);
+ fprintf(outfile, "#define %s_NODEPTR_TYPE\tNODEPTR_TYPE\n", prefix);
+ fprintf(outfile, "#define %s_LEFT_CHILD \tLEFT_CHILD\n", prefix);
+ fprintf(outfile, "#define %s_OP_LABEL \tOP_LABEL\n", prefix);
+ fprintf(outfile, "#define %s_RIGHT_CHILD \tRIGHT_CHILD\n", prefix);
+ fprintf(outfile, "#endif /* STATE_LABEL */\n");
+ fprintf(outfile, "#endif /* %s_STATE_LABEL */\n\n", prefix);
+
+ fprintf(outfile, "#ifdef %s_INCLUDE_EXTRA\n\n", prefix);
+
+}
+
+void
+makeNonterminals()
+{
+ List l;
+
+ for (l = nonterminals; l; l = l->next) {
+ NonTerminal nt = (NonTerminal) l->x;
+ if (nt->num < last_user_nonterminal) {
+ fprintf(outfile, "#define %s_%s_NT %d\n", prefix, nt->name, nt->num);
+ }
+ }
+ fprintf(outfile, "#define %s_NT %d\n", prefix, last_user_nonterminal-1);
+}
+
+void
+makeNonterminalArray()
+{
+ int i;
+ List l;
+ NonTerminal *nta;
+
+ nta = (NonTerminal *) zalloc(sizeof(*nta) * last_user_nonterminal);
+
+ for (l = nonterminals; l; l = l->next) {
+ NonTerminal nt = (NonTerminal) l->x;
+ if (nt->num < last_user_nonterminal) {
+ nta[nt->num] = nt;
+ }
+ }
+
+ fprintf(outfile, "const char *%s_ntname[] = {\n", prefix);
+ fprintf(outfile, "\t\"Error: Nonterminals are > 0\",\n");
+ for (i = 1; i < last_user_nonterminal; i++) {
+ fprintf(outfile, "\t\"%s\",\n", nta[i]->name);
+ }
+ fprintf(outfile, "\t0\n");
+ fprintf(outfile, "};\n\n");
+
+ zfree(nta);
+}
+
+void
+endOptional()
+{
+ fprintf(outfile, "#endif /* %s_INCLUDE_EXTRA */\n", prefix);
+}
+
+void
+startBurm()
+{
+ fprintf(outfile, "#ifndef %s_PANIC\n", prefix);
+ fprintf(outfile, "#define %s_PANIC\tPANIC\n", prefix);
+ fprintf(outfile, "#endif /* %s_PANIC */\n", prefix);
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "extern void abort(void);\n");
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "extern void abort();\n");
+ fprintf(outfile, "#endif\n");
+ fprintf(outfile, "#ifdef NDEBUG\n");
+ fprintf(outfile, "#define %s_assert(x,y)\t;\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "#define %s_assert(x,y)\tif(!(x)) {y; abort();}\n", prefix);
+ fprintf(outfile, "#endif\n");
+}
+
+void
+reportDiagnostics()
+{
+ List l;
+
+ for (l = operators; l; l = l->next) {
+ Operator op = (Operator) l->x;
+ if (!op->ref) {
+ fprintf(stderr, "warning: Unreferenced Operator: %s\n", op->name);
+ }
+ }
+ for (l = rules; l; l = l->next) {
+ Rule r = (Rule) l->x;
+ if (!r->used && r->num < max_ruleAST) {
+ fprintf(stderr, "warning: Unused Rule: #%d\n", r->erulenum);
+ }
+ }
+ if (!start->pmap) {
+ fprintf(stderr, "warning: Start Nonterminal (%s) does not appear on LHS.\n", start->name);
+ }
+
+ fprintf(stderr, "start symbol = \"%s\"\n", start->name);
+ fprintf(stderr, "# of states = %d\n", globalMap->count-1);
+ fprintf(stderr, "# of nonterminals = %d\n", max_nonterminal-1);
+ fprintf(stderr, "# of user nonterminals = %d\n", last_user_nonterminal-1);
+ fprintf(stderr, "# of rules = %d\n", max_rule);
+ fprintf(stderr, "# of user rules = %d\n", max_ruleAST);
+}
diff --git a/llvm/utils/Burg/burg.shar.gz b/llvm/utils/Burg/burg.shar.gz
new file mode 100644
index 00000000000..173bbfde9f6
--- /dev/null
+++ b/llvm/utils/Burg/burg.shar.gz
Binary files differ
diff --git a/llvm/utils/Burg/burs.c b/llvm/utils/Burg/burs.c
new file mode 100644
index 00000000000..b4f8b83d00e
--- /dev/null
+++ b/llvm/utils/Burg/burs.c
@@ -0,0 +1,71 @@
+char rcsid_burs[] = "$Id$";
+
+#include "b.h"
+
+Item_Set errorState;
+
+static void doLeaf ARGS((Operator));
+
+static void
+doLeaf(leaf) Operator leaf;
+{
+ int new;
+ List pl;
+ Item_Set ts;
+ Item_Set tmp;
+
+ assert(leaf->arity == 0);
+
+ ts = newItem_Set(leaf->table->relevant);
+
+ for (pl = rules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ if (p->pat->op == leaf) {
+ if (!ts->virgin[p->lhs->num].rule || p->delta < ts->virgin[p->lhs->num].delta) {
+ ts->virgin[p->lhs->num].rule = p;
+ ASSIGNCOST(ts->virgin[p->lhs->num].delta, p->delta);
+ ts->op = leaf;
+ }
+ }
+ }
+ trim(ts);
+ zero(ts);
+ tmp = encode(globalMap, ts, &new);
+ if (new) {
+ closure(ts);
+ leaf->table->transition[0] = ts;
+ addQ(globalQ, ts);
+ } else {
+ leaf->table->transition[0] = tmp;
+ freeItem_Set(ts);
+ }
+}
+
+void
+build()
+{
+ int new;
+ List ol;
+ Item_Set ts;
+
+ globalQ = newQ();
+ globalMap = newMapping(GLOBAL_MAP_SIZE);
+
+ ts = newItem_Set(0);
+ errorState = encode(globalMap, ts, &new);
+ ts->closed = ts->virgin;
+ addQ(globalQ, ts);
+
+ foreachList((ListFn) doLeaf, leaves);
+
+ debug(debugTables, printf("---initial set of states ---\n"));
+ debug(debugTables, dumpMapping(globalMap));
+ debug(debugTables, foreachList((ListFn) dumpItem_Set, globalQ->head));
+
+ for (ts = popQ(globalQ); ts; ts = popQ(globalQ)) {
+ for (ol = operators; ol; ol = ol->next) {
+ Operator op = (Operator) ol->x;
+ addToTable(op->table, ts);
+ }
+ }
+}
diff --git a/llvm/utils/Burg/closure.c b/llvm/utils/Burg/closure.c
new file mode 100644
index 00000000000..70e16264ebb
--- /dev/null
+++ b/llvm/utils/Burg/closure.c
@@ -0,0 +1,95 @@
+char rcsid_closure[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+int prevent_divergence = 0;
+
+List chainrules;
+
+void
+findChainRules()
+{
+ List pl;
+
+ assert(!chainrules);
+
+ for (pl = rules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ if (!p->pat->op) {
+ chainrules = newList(p, chainrules);
+ } else {
+ p->pat->op->table->rules = newList(p, p->pat->op->table->rules);
+ addRelevant(p->pat->op->table->relevant, p->lhs->num);
+ }
+ }
+}
+
+void
+zero(t) Item_Set t;
+{
+ int i;
+ DeltaCost base;
+ int exists;
+ int base_nt;
+
+ assert(!t->closed);
+
+ ZEROCOST(base);
+ exists = 0;
+ for (i = 0; i < max_nonterminal; i++) {
+ if (t->virgin[i].rule) {
+ if (exists) {
+ if (LESSCOST(t->virgin[i].delta, base)) {
+ ASSIGNCOST(base, t->virgin[i].delta);
+ base_nt = i;
+ }
+ } else {
+ ASSIGNCOST(base, t->virgin[i].delta);
+ exists = 1;
+ base_nt = i;
+ }
+ }
+ }
+ if (!exists) {
+ return;
+ }
+ for (i = 0; i < max_nonterminal; i++) {
+ if (t->virgin[i].rule) {
+ MINUSCOST(t->virgin[i].delta, base);
+ }
+ NODIVERGE(t->virgin[i].delta, t, i, base_nt);
+ }
+}
+
+void
+closure(t) Item_Set t;
+{
+ int changes;
+ List pl;
+
+ assert(!t->closed);
+ t->closed = itemArrayCopy(t->virgin);
+
+ changes = 1;
+ while (changes) {
+ changes = 0;
+ for (pl = chainrules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ register Item *rhs_item = &t->closed[p->pat->children[0]->num];
+
+ if (rhs_item->rule) { /* rhs is active */
+ DeltaCost dc;
+ register Item *lhs_item = &t->closed[p->lhs->num];
+
+ ASSIGNCOST(dc, rhs_item->delta);
+ ADDCOST(dc, p->delta);
+ if (LESSCOST(dc, lhs_item->delta) || !lhs_item->rule) {
+ ASSIGNCOST(lhs_item->delta, dc);
+ lhs_item->rule = p;
+ changes = 1;
+ }
+ }
+ }
+ }
+}
diff --git a/llvm/utils/Burg/delta.c b/llvm/utils/Burg/delta.c
new file mode 100644
index 00000000000..d79654910fc
--- /dev/null
+++ b/llvm/utils/Burg/delta.c
@@ -0,0 +1,143 @@
+char rcsid_delta[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int principleCost = 0;
+int lexical = 0;
+
+#ifndef NOLEX
+void
+ASSIGNCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ l[i] = r[i];
+ }
+ } else {
+ l[0] = r[0];
+ }
+}
+
+void
+ADDCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ l[i] += r[i];
+ }
+ } else {
+ l[0] += r[0];
+ }
+}
+
+void
+MINUSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ l[i] -= r[i];
+ }
+ } else {
+ l[0] -= r[0];
+ }
+}
+
+void
+ZEROCOST(x) DeltaPtr x;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ x[i] = 0;
+ }
+ } else {
+ x[0] = 0;
+ }
+}
+
+int
+LESSCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ if (l[i] < r[i]) {
+ return 1;
+ } else if (l[i] > r[i]) {
+ return 0;
+ }
+ }
+ return 0;
+ } else {
+ return l[0] < r[0];
+ }
+}
+
+int
+EQUALCOST(l, r) DeltaPtr l; DeltaPtr r;
+{
+ int i;
+
+ if (lexical) {
+ for (i = 0; i < DELTAWIDTH; i++) {
+ if (l[i] != r[i]) {
+ return 0;
+ }
+ }
+ return 1;
+ } else {
+ return l[0] == r[0];
+ }
+}
+#endif /* NOLEX */
+
+void
+CHECKDIVERGE(c, its, nt, base) DeltaPtr c; Item_Set its; int nt; int base;
+{
+ int i;
+
+ if (prevent_divergence <= 0) {
+ return;
+ }
+ if (lexical) {
+#ifndef NOLEX
+ for (i = 0; i < DELTAWIDTH; i++) {
+ if (c[i] > prevent_divergence) {
+ char ntname[100];
+ char basename[100];
+ nonTerminalName(ntname, nt);
+ nonTerminalName(basename, base);
+ fprintf(stderr, "ERROR: The grammar appears to diverge\n");
+ fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, c[i]);
+ fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+ fprintf(stderr, "\tOffending Tree: ");
+ printRepresentative(stderr, its);
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ }
+#endif /*NOLEX*/
+ } else if (PRINCIPLECOST(c) > prevent_divergence) {
+ char ntname[100];
+ char basename[100];
+ nonTerminalName(ntname, nt);
+ nonTerminalName(basename, base);
+ fprintf(stderr, "ERROR: The grammar appears to diverge\n");
+ fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, PRINCIPLECOST(c));
+ fprintf(stderr, "\tOffending Operator: %s\n", its->op->name);
+ fprintf(stderr, "\tOffending Tree: ");
+ printRepresentative(stderr, its);
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+}
diff --git a/llvm/utils/Burg/fe.c b/llvm/utils/Burg/fe.c
new file mode 100644
index 00000000000..36b373dd650
--- /dev/null
+++ b/llvm/utils/Burg/fe.c
@@ -0,0 +1,403 @@
+char rcsid_fe[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+int grammarflag;
+
+static int arity;
+
+List ruleASTs;
+List grammarNts;
+
+static void doBinding ARGS((Binding));
+static void doDecl ARGS((Arity));
+static NonTerminal lookup ARGS((Pattern));
+static NonTerminal normalize ARGS((PatternAST, NonTerminal, Pattern *));
+static void doEnterNonTerm ARGS((RuleAST));
+static void doRule ARGS((RuleAST));
+static void doTable ARGS((Operator));
+
+static void
+doBinding(b) Binding b;
+{
+ int new;
+ Symbol s;
+
+ s = enter(b->name, &new);
+ if (!new) {
+ fprintf(stderr, "Non-unique name: %s\n", b->name);
+ exit(1);
+ }
+ s->tag = OPERATOR;
+ s->u.op = newOperator(b->name, b->opnum, arity);
+ if (arity == 0) {
+ leaves = newList(s->u.op, leaves);
+ }
+}
+
+static void
+doDecl(a) Arity a;
+{
+ if (!a) {
+ return;
+ }
+ arity = a->arity;
+ foreachList((ListFn) doBinding, a->bindings);
+}
+
+
+static List xpatterns;
+static int tcount;
+
+static NonTerminal
+lookup(p) Pattern p;
+{
+ char buf[10];
+ char *s;
+ List l;
+ NonTerminal n;
+ DeltaCost dummy;
+
+ for (l = xpatterns; l; l = l->next) {
+ Pattern x = (Pattern) l->x;
+ if (x->op == p->op
+ && x->children[0] == p->children[0]
+ && x->children[1] == p->children[1]) {
+ return x->normalizer;
+ }
+ }
+ sprintf(buf, "n%%%d", tcount++);
+ s = (char *) zalloc(strlen(buf)+1);
+ strcpy(s, buf);
+ n = newNonTerminal(s);
+ p->normalizer = n;
+ xpatterns = newList(p, xpatterns);
+ ZEROCOST(dummy);
+ (void) newRule(dummy, 0, n, p);
+ return n;
+}
+
+static NonTerminal
+normalize(ast, nt, patt) PatternAST ast; NonTerminal nt; Pattern *patt;
+{
+ Symbol s;
+ int new;
+ Pattern dummy;
+
+ s = enter(ast->op, &new);
+ ast->sym = s;
+ if (new) {
+ fprintf(stderr, "Illegal use of %s --- undefined symbol\n", s->name);
+ exit(1);
+ return 0; /* shut up compilers */
+ } else if (s->tag == NONTERMINAL) {
+ if (ast->children) {
+ fprintf(stderr, "Illegal use of %s, a non-terminal, as a terminal\n", s->name);
+ exit(1);
+ }
+ *patt = newPattern(0);
+ (*patt)->children[0] = s->u.nt;
+ return s->u.nt;
+ } else {
+ s->u.op->ref = 1;
+ *patt = newPattern(s->u.op);
+ if (s->u.op->arity == -1) {
+ if (!ast->children) {
+ s->u.op->arity = 0;
+ leaves = newList(s->u.op, leaves);
+ } else if (!ast->children->next) {
+ s->u.op->arity = 1;
+ } else if (!ast->children->next->next) {
+ s->u.op->arity = 2;
+ } else {
+ fprintf(stderr, "ERROR: Too many children (max = 2) for \"%s\"\n", s->name);
+ exit(1);
+ }
+ if (s->u.op->arity > max_arity) {
+ max_arity = s->u.op->arity;
+ }
+ }
+ switch (s->u.op->arity) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ if (ast->children) {
+ fprintf(stderr, "ERROR: Incorrect number of children for leaf operator, \"%s\"\n", s->name);
+ exit(1);
+ }
+ break;
+ case 1:
+ if (!ast->children || ast->children->next) {
+ fprintf(stderr, "ERROR: Incorrect number of children for unary operator, \"%s\"\n", s->name);
+ exit(1);
+ }
+ (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+ break;
+ case 2:
+ if (!ast->children || !ast->children->next) {
+ fprintf(stderr, "ERROR: Incorrect number of children for binary operator, \"%s\"\n", s->name);
+ exit(1);
+ }
+ (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy);
+ (*patt)->children[1] = normalize((PatternAST) ast->children->next->x, 0, &dummy);
+ break;
+ }
+ if (nt) {
+ (*patt)->normalizer = nt;
+ return nt;
+ } else {
+ return lookup(*patt);
+ }
+ }
+}
+
+static void
+doEnterNonTerm(ast) RuleAST ast;
+{
+ int new;
+ Symbol s;
+ DeltaCost delta;
+ int i;
+ IntList p;
+
+
+ s = enter(ast->lhs, &new);
+ if (new) {
+ s->u.nt = newNonTerminal(s->name);
+ s->tag = NONTERMINAL;
+ } else {
+ if (s->tag != NONTERMINAL) {
+ fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+ exit(1);
+ }
+ }
+ ZEROCOST(delta);
+ for (p = ast->cost, i = 0; p; p = p->next, i++) {
+ int x = p->x;
+#ifndef NOLEX
+ if (lexical) {
+ if (i < DELTAWIDTH) {
+ delta[i] = x;
+ }
+ } else
+#endif /* NOLEX */
+ {
+ if (i == principleCost) {
+ PRINCIPLECOST(delta) = x;
+ }
+ }
+ }
+ ast->rule = newRule(delta, ast->erulenum, s->u.nt, 0);
+}
+
+static void
+doRule(ast) RuleAST ast;
+{
+ Pattern pat;
+
+ (void) normalize(ast->pat, ast->rule->lhs, &pat);
+ ast->rule->pat = pat;
+}
+
+static void
+doTable(op) Operator op;
+{
+ op->table = newTable(op);
+}
+
+void
+doSpec(decls, rules) List decls; List rules;
+{
+ foreachList((ListFn) doDecl, decls);
+ debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+
+ ruleASTs = rules;
+ reveachList((ListFn) doEnterNonTerm, rules);
+
+ last_user_nonterminal = max_nonterminal;
+
+ reveachList((ListFn) doRule, rules);
+ debug(debugTables, foreachList((ListFn) dumpRule, rules));
+
+ foreachList((ListFn) doTable, operators);
+}
+
+void
+doStart(name) char *name;
+{
+ Symbol s;
+ int new;
+
+ if (start) {
+ yyerror1("Redeclaration of start symbol to be ");
+ fprintf(stderr, "\"%s\"\n", name);
+ exit(1);
+ }
+ s = enter(name, &new);
+ if (new) {
+ s->u.nt = newNonTerminal(s->name);
+ s->tag = NONTERMINAL;
+ } else {
+ if (s->tag != NONTERMINAL) {
+ fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name);
+ exit(1);
+ }
+ }
+}
+
+void
+doGrammarNts()
+{
+ List l;
+ int new;
+
+ for (l = grammarNts; l; l = l->next) {
+ char *n = (char*) l->x;
+ Symbol s;
+
+ s = enter(n, &new);
+ if (new) {
+ fprintf(stderr, "ERROR: %%gram, unused non-terminal: \"%s\"\n", n);
+ exit(1);
+ }
+ if (s->tag != NONTERMINAL) {
+ fprintf(stderr, "ERROR: %%gram, Not a non-terminal: \"%s\"\n", n);
+ exit(1);
+ }
+ l->x = s;
+ }
+}
+
+void
+doGram(nts) List nts;
+{
+ if (grammarNts) {
+ yyerror1("Redeclaration of %%gram\n");
+ exit(1);
+ }
+ grammarNts = nts;
+}
+
+Arity
+newArity(ar, b) int ar; List b;
+{
+ Arity a = (Arity) zalloc(sizeof(struct arity));
+ a->arity = ar;
+ a->bindings = b;
+ return a;
+}
+
+Binding
+newBinding(name, opnum) char *name; int opnum;
+{
+ Binding b = (Binding) zalloc(sizeof(struct binding));
+ if (opnum == 0) {
+ yyerror1("ERROR: Non-positive external symbol number, ");
+ fprintf(stderr, "%d", opnum);
+ exit(1);
+ }
+ b->name = name;
+ b->opnum = opnum;
+ return b;
+}
+
+PatternAST
+newPatternAST(op, children) char *op; List children;
+{
+ PatternAST p = (PatternAST) zalloc(sizeof(struct patternAST));
+ p->op = op;
+ p->children = children;
+ return p;
+}
+
+int max_ruleAST;
+
+RuleAST
+newRuleAST(lhs, pat, erulenum, cost) char *lhs; PatternAST pat; int erulenum; IntList cost;
+{
+ RuleAST p = (RuleAST) zalloc(sizeof(struct ruleAST));
+ p->lhs = lhs;
+ p->pat = pat;
+ if (erulenum <= 0) {
+ yyerror1("External Rulenumber ");
+ fprintf(stderr, "(%d) <= 0\n", erulenum);
+ exit(1);
+ }
+ p->erulenum = erulenum;
+ p->cost = cost;
+ max_ruleAST++;
+ return p;
+}
+
+void
+dumpBinding(b) Binding b;
+{
+ printf("%s=%d ", b->name, b->opnum);
+}
+
+void
+dumpArity(a) Arity a;
+{
+ List l;
+
+ printf("Arity(%d) ", a->arity);
+ for (l = a->bindings; l; l = l->next) {
+ Binding b = (Binding) l->x;
+ dumpBinding(b);
+ }
+ printf("\n");
+}
+
+void
+dumpPatternAST(p) PatternAST p;
+{
+ List l;
+
+ printf("%s", p->op);
+ if (p->children) {
+ printf("(");
+ for (l = p->children; l; l = l->next) {
+ PatternAST past = (PatternAST) l->x;
+ dumpPatternAST(past);
+ if (l->next) {
+ printf(", ");
+ }
+ }
+ printf(")");
+ }
+}
+
+void
+dumpRuleAST(p) RuleAST p;
+{
+ printf("%s : ", p->lhs);
+ dumpPatternAST(p->pat);
+ printf(" = %d (%ld)\n", p->erulenum, (long) p->cost);
+}
+
+void
+dumpDecls(decls) List decls;
+{
+ List l;
+
+ for (l = decls; l; l = l->next) {
+ Arity a = (Arity) l->x;
+ dumpArity(a);
+ }
+}
+
+void
+dumpRules(rules) List rules;
+{
+ List l;
+
+ for (l = rules; l; l = l->next) {
+ RuleAST p = (RuleAST) l->x;
+ dumpRuleAST(p);
+ }
+}
+
diff --git a/llvm/utils/Burg/fe.h b/llvm/utils/Burg/fe.h
new file mode 100644
index 00000000000..1c7b2fecbf3
--- /dev/null
+++ b/llvm/utils/Burg/fe.h
@@ -0,0 +1,132 @@
+/* $Id$ */
+
+struct binding {
+ char *name;
+ int opnum;
+};
+typedef struct binding *Binding;
+
+struct arity {
+ int arity;
+ List bindings;
+};
+typedef struct arity *Arity;
+
+struct patternAST {
+ struct symbol *sym;
+ char *op;
+ List children;
+};
+typedef struct patternAST *PatternAST;
+
+struct ruleAST {
+ char *lhs;
+ PatternAST pat;
+ int erulenum;
+ IntList cost;
+ struct rule *rule;
+ struct strTableElement *kids;
+ struct strTableElement *nts;
+};
+typedef struct ruleAST *RuleAST;
+
+typedef enum {
+ UNKNOWN,
+ OPERATOR,
+ NONTERMINAL
+} TagType;
+
+struct symbol {
+ char *name;
+ TagType tag;
+ union {
+ NonTerminal nt;
+ Operator op;
+ } u;
+};
+typedef struct symbol *Symbol;
+
+struct strTableElement {
+ char *str;
+ IntList erulenos;
+ char *ename;
+};
+typedef struct strTableElement *StrTableElement;
+
+struct strTable {
+ List elems;
+};
+typedef struct strTable *StrTable;
+
+extern void doGrammarNts ARGS((void));
+void makeRuleDescArray ARGS((void));
+void makeDeltaCostArray ARGS((void));
+void makeStateStringArray ARGS((void));
+
+extern StrTable newStrTable ARGS((void));
+extern StrTableElement addString ARGS((StrTable, char *, int, int *));
+
+extern void doSpec ARGS((List, List));
+extern Arity newArity ARGS((int, List));
+extern Binding newBinding ARGS((char *, int));
+extern PatternAST newPatternAST ARGS((char *, List));
+extern RuleAST newRuleAST ARGS((char *, PatternAST, int, IntList));
+extern Symbol enter ARGS((char *, int *));
+extern Symbol newSymbol ARGS((char *));
+
+extern void makeDebug ARGS((void));
+extern void makeSimple ARGS((void));
+extern void makePlanks ARGS((void));
+extern void makeOpLabel ARGS((void));
+extern void makeChild ARGS((void));
+extern void makeOperators ARGS((void));
+extern void makeLabel ARGS((void));
+extern void makeString ARGS((void));
+extern void makeString ARGS((void));
+extern void makeReduce ARGS((void));
+extern void makeRuleTable ARGS((void));
+extern void makeTables ARGS((void));
+extern void makeTreecost ARGS((void));
+extern void makePrint ARGS((void));
+extern void makeRule ARGS((void));
+extern void makeNts ARGS((void));
+extern void makeKids ARGS((void));
+extern void startBurm ARGS((void));
+extern void startOptional ARGS((void));
+extern void makePlankLabel ARGS((void));
+extern void makeStateLabel ARGS((void));
+extern void makeStringArray ARGS((void));
+extern void makeNonterminalArray ARGS((void));
+extern void makeCostArray ARGS((void));
+extern void makeLHSmap ARGS((void));
+extern void makeClosureArray ARGS((void));
+extern void makeOperatorVector ARGS((void));
+extern void endOptional ARGS((void));
+extern void reportDiagnostics ARGS((void));
+extern void makeNonterminals ARGS((void));
+extern int opsOfArity ARGS((int));
+
+extern void yypurge ARGS((void));
+extern void yyfinished ARGS((void));
+
+extern void printRepresentative ARGS((FILE *, Item_Set));
+
+extern void dumpRules ARGS((List));
+extern void dumpDecls ARGS((List));
+extern void dumpRuleAST ARGS((RuleAST));
+extern void dumpPatternAST ARGS((PatternAST));
+extern void dumpArity ARGS((Arity));
+extern void dumpBinding ARGS((Binding));
+extern void dumpStrTable ARGS((StrTable));
+
+extern int yylex ARGS((void));
+extern int yyparse ARGS((void));
+
+extern int max_ruleAST;
+extern List ruleASTs;
+
+extern FILE *outfile;
+extern const char *prefix;
+extern int trimflag;
+extern int speedflag;
+extern int grammarflag;
diff --git a/llvm/utils/Burg/gram.yc b/llvm/utils/Burg/gram.yc
new file mode 100644
index 00000000000..9d2f9f4e53f
--- /dev/null
+++ b/llvm/utils/Burg/gram.yc
@@ -0,0 +1,91 @@
+%{
+char rcsid_gram[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+int doGram(List);
+%}
+
+%union {
+ int y_int;
+ char *y_string;
+ Arity y_arity;
+ Binding y_binding;
+ PatternAST y_patternAST;
+ RuleAST y_ruleAST;
+ List y_list;
+ IntList y_intlist;
+}
+
+%start full
+
+%term ERROR
+%term K_TERM
+%term K_GRAM
+%term K_START
+%term K_PPERCENT
+%term INT
+%term ID
+
+%token <y_string> ID
+%token <y_int> INT
+
+%type <y_arity> decl
+%type <y_binding> binding
+%type <y_intlist> cost costtail
+%type <y_ruleAST> rule
+%type <y_patternAST> pattern
+%type <y_list> decls rules bindinglist grammarlist
+%%
+
+
+full : spec
+ | spec K_PPERCENT
+ { yyfinished(); }
+ ;
+
+spec : decls K_PPERCENT rules
+ { doSpec($1, $3); }
+ ;
+
+decls : /* lambda */ { $$ = 0; }
+ | decls decl { $$ = newList($2, $1); }
+ ;
+
+decl : K_TERM bindinglist { $$ = newArity(-1, $2); }
+ | K_GRAM grammarlist { $$ = 0; doGram($2); }
+ | K_START ID { $$ = 0; doStart($2); } /* kludge */
+ ;
+
+grammarlist : /* lambda */ { $$ = 0; }
+ | grammarlist ID { $$ = newList($2, $1); }
+ ;
+
+bindinglist : /* lambda */ { $$ = 0; }
+ | bindinglist binding { $$ = newList($2, $1); }
+ ;
+
+binding : ID '=' INT { $$ = newBinding($1, $3); }
+ ;
+
+rules : /* lambda */ { $$ = 0; }
+ | rules rule { $$ = newList($2, $1); }
+ ;
+
+rule : ID ':' pattern '=' INT cost ';' { $$ = newRuleAST($1, $3, $5, $6); }
+ ;
+
+pattern : ID { $$ = newPatternAST($1, 0); }
+ | ID '(' pattern ')' { $$ = newPatternAST($1, newList($3,0)); }
+ | ID '(' pattern ',' pattern ')' { $$ = newPatternAST($1, newList($3, newList($5, 0))); }
+ ;
+
+cost : /* lambda */ { $$ = 0; }
+ | '(' INT costtail ')' { $$ = newIntList($2, $3); }
+ ;
+
+costtail : /* lambda */ { $$ = 0; }
+ | ',' INT costtail { $$ = newIntList($2, $3); }
+ | INT costtail { $$ = newIntList($1, $2); }
+ ;
diff --git a/llvm/utils/Burg/item.c b/llvm/utils/Burg/item.c
new file mode 100644
index 00000000000..4a9f4a320b6
--- /dev/null
+++ b/llvm/utils/Burg/item.c
@@ -0,0 +1,133 @@
+char rcsid_item[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+#include <string.h>
+#include "fe.h"
+
+static Item_Set fptr;
+
+ItemArray
+newItemArray()
+{
+ ItemArray ia;
+ ia = (ItemArray) zalloc(max_nonterminal *sizeof(*ia));
+ return ia;
+}
+
+ItemArray
+itemArrayCopy(src) ItemArray src;
+{
+ ItemArray dst;
+
+ dst = newItemArray();
+ memcpy(dst, src, max_nonterminal * sizeof(*dst));
+ return dst;
+}
+
+Item_Set
+newItem_Set(relevant) Relevant relevant;
+{
+ Item_Set ts;
+
+ if (fptr) {
+ ts = fptr;
+ fptr = 0;
+ memset(ts->virgin, 0, max_nonterminal * sizeof(struct item));
+ if (ts->closed) {
+ zfree(ts->closed);
+ ts->closed = 0;
+ }
+ ts->num = 0;
+ ts->op = 0;
+ } else {
+ ts = (Item_Set) zalloc(sizeof(struct item_set));
+ ts->virgin = newItemArray();
+ }
+ ts->relevant = relevant;
+ return ts;
+}
+
+void
+freeItem_Set(ts) Item_Set ts;
+{
+ assert(!fptr);
+ fptr = ts;
+}
+
+int
+equivSet(a, b) Item_Set a; Item_Set b;
+{
+ register Relevant r;
+ register int nt;
+ register Item *aa = a->virgin;
+ register Item *ba = b->virgin;
+
+ /*
+ return !bcmp(a->virgin, b->virgin, max_nonterminal * sizeof(Item));
+ */
+
+ r = a->relevant ? a->relevant : b->relevant;
+ assert(r);
+
+ if (a->op && b->op && a->op != b->op) {
+ return 0;
+ }
+ for (; (nt = *r) != 0; r++) {
+ if (aa[nt].rule != ba[nt].rule || !EQUALCOST(aa[nt].delta, ba[nt].delta)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void
+printRepresentative(f, s) FILE *f; Item_Set s;
+{
+ if (!s) {
+ return;
+ }
+ fprintf(f, "%s", s->op->name);
+ switch (s->op->arity) {
+ case 1:
+ fprintf(f, "(");
+ printRepresentative(f, s->kids[0]);
+ fprintf(f, ")");
+ break;
+ case 2:
+ fprintf(f, "(");
+ printRepresentative(f, s->kids[0]);
+ fprintf(f, ", ");
+ printRepresentative(f, s->kids[1]);
+ fprintf(f, ")");
+ break;
+ }
+}
+
+void
+dumpItem(t) Item *t;
+{
+ printf("[%s #%d]", t->rule->lhs->name, t->rule->num);
+ dumpCost(t->delta);
+}
+
+void
+dumpItem_Set(ts) Item_Set ts;
+{
+ int i;
+
+ printf("Item_Set #%d: [", ts->num);
+ for (i = 1; i < max_nonterminal; i++) {
+ if (ts->virgin[i].rule) {
+ printf(" %d", i);
+ dumpCost(ts->virgin[i].delta);
+ }
+ }
+ printf(" ]\n");
+}
+
+void
+dumpCost(dc) DeltaCost dc;
+{
+ printf("(%ld)", (long) dc);
+}
diff --git a/llvm/utils/Burg/lex.c b/llvm/utils/Burg/lex.c
new file mode 100644
index 00000000000..85eb8a738fa
--- /dev/null
+++ b/llvm/utils/Burg/lex.c
@@ -0,0 +1,259 @@
+char rcsid_lex[] = "$Id$";
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+#include "gram.tab.h"
+
+static char buf[BUFSIZ];
+
+static int yyline = 1;
+
+typedef int (*ReadFn) ARGS((void));
+
+static char *StrCopy ARGS((char *));
+static int code_get ARGS((void));
+static int simple_get ARGS((void));
+static void ReadCharString ARGS((ReadFn, int));
+static void ReadCodeBlock ARGS((void));
+static void ReadOldComment ARGS((ReadFn));
+
+static char *
+StrCopy(s) char *s;
+{
+ char *t = (char *)zalloc(strlen(s) + 1);
+ strcpy(t,s);
+ return t;
+}
+
+static int
+simple_get()
+{
+ int ch;
+ if ((ch = getchar()) == '\n') {
+ yyline++;
+ }
+ return ch;
+}
+
+static int
+code_get()
+{
+ int ch;
+ if ((ch = getchar()) == '\n') {
+ yyline++;
+ }
+ if (ch != EOF) {
+ fputc(ch, outfile);
+ }
+ return ch;
+}
+
+void
+yypurge()
+{
+ while (code_get() != EOF) ;
+}
+
+
+static void
+ReadCharString(rdfn, which) ReadFn rdfn; int which;
+{
+ int ch;
+ int backslash = 0;
+ int firstline = yyline;
+
+ while ((ch = rdfn()) != EOF) {
+ if (ch == which && !backslash) {
+ return;
+ }
+ if (ch == '\\' && !backslash) {
+ backslash = 1;
+ } else {
+ backslash = 0;
+ }
+ }
+ yyerror1("Unexpected EOF in string on line ");
+ fprintf(stderr, "%d\n", firstline);
+ exit(1);
+}
+
+static void
+ReadOldComment(rdfn) ReadFn rdfn;
+{
+ /* will not work for comments delimiter in string */
+
+ int ch;
+ int starred = 0;
+ int firstline = yyline;
+
+ while ((ch = rdfn()) != EOF) {
+ if (ch == '*') {
+ starred = 1;
+ } else if (ch == '/' && starred) {
+ return;
+ } else {
+ starred = 0;
+ }
+ }
+ yyerror1("Unexpected EOF in comment on line ");
+ fprintf(stderr, "%d\n", firstline);
+ exit(1);
+}
+
+static void
+ReadCodeBlock()
+{
+ int ch;
+ int firstline = yyline;
+
+ while ((ch = getchar()) != EOF) {
+ if (ch == '%') {
+ ch = getchar();
+ if (ch != '}') {
+ yyerror("bad %%");
+ }
+ return;
+ }
+ fputc(ch, outfile);
+ if (ch == '\n') {
+ yyline++;
+ }
+ if (ch == '"' || ch == '\'') {
+ ReadCharString(code_get, ch);
+ } else if (ch == '/') {
+ ch = getchar();
+ if (ch == '*') {
+ fputc(ch, outfile);
+ ReadOldComment(code_get);
+ continue;
+ } else {
+ ungetc(ch, stdin);
+ }
+ }
+ }
+ yyerror1("Unclosed block of C code started on line ");
+ fprintf(stderr, "%d\n", firstline);
+ exit(1);
+}
+
+static int done;
+void
+yyfinished()
+{
+ done = 1;
+}
+
+int
+yylex()
+{
+ int ch;
+ char *ptr = buf;
+
+ if (done) return 0;
+ while ((ch = getchar()) != EOF) {
+ switch (ch) {
+ case ' ':
+ case '\f':
+ case '\t':
+ continue;
+ case '\n':
+ yyline++;
+ continue;
+ case '(':
+ case ')':
+ case ',':
+ case ':':
+ case ';':
+ case '=':
+ return(ch);
+ case '/':
+ ch = getchar();
+ if (ch == '*') {
+ ReadOldComment(simple_get);
+ continue;
+ } else {
+ ungetc(ch, stdin);
+ yyerror("illegal char /");
+ continue;
+ }
+ case '%':
+ ch = getchar();
+ switch (ch) {
+ case '%':
+ return (K_PPERCENT);
+ case '{':
+ ReadCodeBlock();
+ continue;
+ case 's':
+ case 'g':
+ case 't':
+ do {
+ if (ptr >= &buf[BUFSIZ]) {
+ yyerror("ID too long");
+ return(ERROR);
+ } else {
+ *ptr++ = ch;
+ }
+ ch = getchar();
+ } while (isalpha(ch) || isdigit(ch) || ch == '_');
+ ungetc(ch, stdin);
+ *ptr = '\0';
+ if (!strcmp(buf, "term")) return K_TERM;
+ if (!strcmp(buf, "start")) return K_START;
+ if (!strcmp(buf, "gram")) return K_GRAM;
+ yyerror("illegal character after %%");
+ continue;
+ default:
+ yyerror("illegal character after %%");
+ continue;
+ }
+ default:
+ if (isalpha(ch) ) {
+ do {
+ if (ptr >= &buf[BUFSIZ]) {
+ yyerror("ID too long");
+ return(ERROR);
+ } else {
+ *ptr++ = ch;
+ }
+ ch = getchar();
+ } while (isalpha(ch) || isdigit(ch) || ch == '_');
+ ungetc(ch, stdin);
+ *ptr = '\0';
+ yylval.y_string = StrCopy(buf);
+ return(ID);
+ }
+ if (isdigit(ch)) {
+ int val=0;
+ do {
+ val *= 10;
+ val += (ch - '0');
+ ch = getchar();
+ } while (isdigit(ch));
+ ungetc(ch, stdin);
+ yylval.y_int = val;
+ return(INT);
+ }
+ yyerror1("illegal char ");
+ fprintf(stderr, "(\\%03o)\n", ch);
+ exit(1);
+ }
+ }
+ return(0);
+}
+
+void yyerror1(const char *str)
+{
+ fprintf(stderr, "line %d: %s", yyline, str);
+}
+
+void
+yyerror(const char *str)
+{
+ yyerror1(str);
+ fprintf(stderr, "\n");
+ exit(1);
+}
diff --git a/llvm/utils/Burg/list.c b/llvm/utils/Burg/list.c
new file mode 100644
index 00000000000..d3eefa27d09
--- /dev/null
+++ b/llvm/utils/Burg/list.c
@@ -0,0 +1,75 @@
+char rcsid_list[] = "$Id$";
+
+#include "b.h"
+
+IntList
+newIntList(x, next) int x; IntList next;
+{
+ IntList l;
+
+ l = (IntList) zalloc(sizeof(*l));
+ assert(l);
+ l->x = x;
+ l->next = next;
+
+ return l;
+}
+
+List
+newList(x, next) void *x; List next;
+{
+ List l;
+
+ l = (List) zalloc(sizeof(*l));
+ assert(l);
+ l->x = x;
+ l->next = next;
+
+ return l;
+}
+
+List
+appendList(x, l) void *x; List l;
+{
+ List last;
+ List p;
+
+ last = 0;
+ for (p = l; p; p = p->next) {
+ last = p;
+ }
+ if (last) {
+ last->next = newList(x, 0);
+ return l;
+ } else {
+ return newList(x, 0);
+ }
+}
+
+void
+foreachList(f, l) ListFn f; List l;
+{
+ for (; l; l = l->next) {
+ (*f)(l->x);
+ }
+}
+
+void
+reveachList(f, l) ListFn f; List l;
+{
+ if (l) {
+ reveachList(f, l->next);
+ (*f)(l->x);
+ }
+}
+
+int
+length(l) List l;
+{
+ int c = 0;
+
+ for(; l; l = l->next) {
+ c++;
+ }
+ return c;
+}
diff --git a/llvm/utils/Burg/main.c b/llvm/utils/Burg/main.c
new file mode 100644
index 00000000000..dbfdbf4faca
--- /dev/null
+++ b/llvm/utils/Burg/main.c
@@ -0,0 +1,182 @@
+char rcsid_main[] = "$Id$";
+
+#include <math.h>
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+int debugTables = 0;
+static int simpleTables = 0;
+static int internals = 0;
+static int diagnostics = 0;
+
+static char *inFileName;
+static char *outFileName;
+
+static char version[] = "BURG, Version 1.0";
+
+extern int main ARGS((int argc, char **argv));
+
+int
+main(argc, argv) int argc; char **argv;
+{
+ int i;
+ extern int atoi ARGS((char *));
+
+ for (i = 1; argv[i]; i++) {
+ char **needStr = 0;
+ int *needInt = 0;
+
+ if (argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ case 'V':
+ fprintf(stderr, "%s\n", version);
+ break;
+ case 'p':
+ needStr = (char**)&prefix;
+ break;
+ case 'o':
+ needStr = &outFileName;
+ break;
+ case 'I':
+ internals = 1;
+ break;
+ case 'T':
+ simpleTables = 1;
+ break;
+ case '=':
+#ifdef NOLEX
+ fprintf(stderr, "'%s' was not compiled to support lexicographic ordering\n", argv[0]);
+#else
+ lexical = 1;
+#endif /* NOLEX */
+ break;
+ case 'O':
+ needInt = &principleCost;
+ break;
+ case 'c':
+ needInt = &prevent_divergence;
+ break;
+ case 'e':
+ needInt = &exceptionTolerance;
+ break;
+ case 'd':
+ diagnostics = 1;
+ break;
+ case 'S':
+ speedflag = 1;
+ break;
+ case 't':
+ trimflag = 1;
+ break;
+ case 'G':
+ grammarflag = 1;
+ break;
+ default:
+ fprintf(stderr, "Bad option (%s)\n", argv[i]);
+ exit(1);
+ }
+ } else {
+ if (inFileName) {
+ fprintf(stderr, "Unexpected Filename (%s) after (%s)\n", argv[i], inFileName);
+ exit(1);
+ }
+ inFileName = argv[i];
+ }
+ if (needInt || needStr) {
+ char *v;
+ char *opt = argv[i];
+
+ if (argv[i][2]) {
+ v = &argv[i][2];
+ } else {
+ v = argv[++i];
+ if (!v) {
+ fprintf(stderr, "Expection argument after %s\n", opt);
+ exit(1);
+ }
+ }
+ if (needInt) {
+ *needInt = atoi(v);
+ } else if (needStr) {
+ *needStr = v;
+ }
+ }
+ }
+
+ if (inFileName) {
+ if(freopen(inFileName, "r", stdin)==NULL) {
+ fprintf(stderr, "Failed opening (%s)", inFileName);
+ exit(1);
+ }
+ }
+
+ if (outFileName) {
+ if ((outfile = fopen(outFileName, "w")) == NULL) {
+ fprintf(stderr, "Failed opening (%s)", outFileName);
+ exit(1);
+ }
+ } else {
+ outfile = stdout;
+ }
+
+
+ yyparse();
+
+ if (!rules) {
+ fprintf(stderr, "ERROR: No rules present\n");
+ exit(1);
+ }
+
+ findChainRules();
+ findAllPairs();
+ doGrammarNts();
+ build();
+
+ debug(debugTables, foreachList((ListFn) dumpOperator_l, operators));
+ debug(debugTables, printf("---final set of states ---\n"));
+ debug(debugTables, dumpMapping(globalMap));
+
+
+ startBurm();
+ makeNts();
+ if (simpleTables) {
+ makeSimple();
+ } else {
+ makePlanks();
+ }
+
+ startOptional();
+ makeLabel();
+ makeKids();
+
+ if (internals) {
+ makeChild();
+ makeOpLabel();
+ makeStateLabel();
+ }
+ endOptional();
+
+ makeOperatorVector();
+ makeNonterminals();
+ if (internals) {
+ makeOperators();
+ makeStringArray();
+ makeRuleDescArray();
+ makeCostArray();
+ makeDeltaCostArray();
+ makeStateStringArray();
+ makeNonterminalArray();
+ /*
+ makeLHSmap();
+ */
+ }
+ makeClosureArray();
+
+ if (diagnostics) {
+ reportDiagnostics();
+ }
+
+ yypurge();
+ exit(0);
+}
diff --git a/llvm/utils/Burg/map.c b/llvm/utils/Burg/map.c
new file mode 100644
index 00000000000..588b485eab2
--- /dev/null
+++ b/llvm/utils/Burg/map.c
@@ -0,0 +1,135 @@
+char rcsid_map[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+Mapping globalMap;
+
+static void growMapping ARGS((Mapping));
+static int hash ARGS((Item_Set, int));
+
+Mapping
+newMapping(size) int size;
+{
+ Mapping m;
+
+ m = (Mapping) zalloc(sizeof(struct mapping));
+ assert(m);
+
+ m->count = 0;
+ m->hash = (List*) zalloc(size * sizeof(List));
+ m->hash_size = size;
+ m->max_size = STATES_INCR;
+ m->set = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+ assert(m->set);
+
+ return m;
+}
+
+static void
+growMapping(m) Mapping m;
+{
+ Item_Set *tmp;
+
+ m->max_size += STATES_INCR;
+ tmp = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set));
+ memcpy(tmp, m->set, m->count * sizeof(Item_Set));
+ zfree(m->set);
+ m->set = tmp;
+}
+
+static int
+hash(ts, mod) Item_Set ts; int mod;
+{
+ register Item *p = ts->virgin;
+ register int v;
+ register Relevant r = ts->relevant;
+ register int nt;
+
+ if (!ts->op) {
+ return 0;
+ }
+
+ v = 0;
+ for (; (nt = *r) != 0; r++) {
+ v ^= ((long)p[nt].rule) + (PRINCIPLECOST(p[nt].delta)<<4);
+ }
+ v >>= 4;
+ v &= (mod-1);
+ return v;
+}
+
+Item_Set
+encode(m, ts, new) Mapping m; Item_Set ts; int *new;
+{
+ int h;
+ List l;
+
+ assert(m);
+ assert(ts);
+ assert(m->count <= m->max_size);
+
+ if (grammarNts && errorState && m == globalMap) {
+ List l;
+ int found;
+
+ found = 0;
+ for (l = grammarNts; l; l = l->next) {
+ Symbol s;
+ s = (Symbol) l->x;
+
+ if (ts->virgin[s->u.nt->num].rule) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ *new = 0;
+ return errorState;
+ }
+ }
+
+ *new = 0;
+ h = hash(ts, m->hash_size);
+ for (l = m->hash[h]; l; l = l->next) {
+ Item_Set s = (Item_Set) l->x;
+ if (ts->op == s->op && equivSet(ts, s)) {
+ ts->num = s->num;
+ return s;
+ }
+ }
+ if (m->count >= m->max_size) {
+ growMapping(m);
+ }
+ assert(m->count < m->max_size);
+ m->set[m->count] = ts;
+ ts->num = m->count++;
+ *new = 1;
+ m->hash[h] = newList(ts, m->hash[h]);
+ return ts;
+}
+
+Item_Set
+decode(m, t) Mapping m; ItemSetNum t;
+{
+ assert(m);
+ assert(t);
+ assert(m->count < m->max_size);
+ assert(t < m->count);
+
+ return m->set[t];
+}
+
+void
+dumpMapping(m) Mapping m;
+{
+ int i;
+
+ printf("BEGIN Mapping: Size=%d\n", m->count);
+ for (i = 0; i < m->count; i++) {
+ dumpItem_Set(m->set[i]);
+ }
+ printf("END Mapping\n");
+}
diff --git a/llvm/utils/Burg/nonterminal.c b/llvm/utils/Burg/nonterminal.c
new file mode 100644
index 00000000000..71fd7d49442
--- /dev/null
+++ b/llvm/utils/Burg/nonterminal.c
@@ -0,0 +1,49 @@
+char rcsid_nonterminal[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+#include <string.h>
+
+NonTerminal start;
+NonTerminalNum max_nonterminal = 1;
+NonTerminalNum last_user_nonterminal;
+List nonterminals;
+
+NonTerminal
+newNonTerminal(name) char *name;
+{
+ NonTerminal nt;
+
+ nt = (NonTerminal) zalloc(sizeof(struct nonterminal));
+ assert(nt);
+ if (max_nonterminal == 1) {
+ start = nt;
+ }
+ nt->name = name;
+ nt->num = max_nonterminal++;
+ nonterminals = newList(nt, nonterminals);
+
+ return nt;
+}
+
+int
+nonTerminalName(buf, i) char *buf; int i;
+{
+ List l;
+
+ for (l = nonterminals; l; l = l->next) {
+ NonTerminal nt = (NonTerminal) l->x;
+ if (nt->num == i) {
+ strcpy(buf, nt->name);
+ return 1;
+ }
+ }
+ strcpy(buf, "(Unknown NonTerminal)");
+ return 0;
+}
+
+void
+dumpNonTerminal(n) NonTerminal n;
+{
+ printf("%s(%d)", n->name, n->num);
+}
diff --git a/llvm/utils/Burg/operator.c b/llvm/utils/Burg/operator.c
new file mode 100644
index 00000000000..a6df9e304df
--- /dev/null
+++ b/llvm/utils/Burg/operator.c
@@ -0,0 +1,48 @@
+char rcsid_operator[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+int max_arity = -1;
+
+List operators;
+List leaves;
+
+Operator
+newOperator(name, num, arity) char *name; OperatorNum num; ArityNum arity;
+{
+ Operator op;
+
+ assert(arity <= MAX_ARITY);
+ op = (Operator) zalloc(sizeof(struct operator));
+ assert(op);
+ op->name = name;
+ op->num = num;
+ op->arity = arity;
+
+ operators = newList(op, operators);
+
+ return op;
+}
+
+void
+dumpOperator_s(op) Operator op;
+{
+ printf("Op: %s(%d)=%d\n", op->name, op->arity, op->num);
+}
+
+void
+dumpOperator(op, full) Operator op; int full;
+{
+ dumpOperator_s(op);
+ if (full) {
+ dumpTable(op->table, 0);
+ }
+}
+
+void
+dumpOperator_l(op) Operator op;
+{
+ dumpOperator(op, 1);
+}
+
diff --git a/llvm/utils/Burg/pattern.c b/llvm/utils/Burg/pattern.c
new file mode 100644
index 00000000000..472aca579d0
--- /dev/null
+++ b/llvm/utils/Burg/pattern.c
@@ -0,0 +1,38 @@
+char rcsid_pattern[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+
+Pattern
+newPattern(op) Operator op;
+{
+ Pattern p;
+
+ p = (Pattern) zalloc(sizeof(struct pattern));
+ p->op = op;
+ return p;
+}
+
+void
+dumpPattern(p) Pattern p;
+{
+ int i;
+
+ if (!p) {
+ printf("[no-pattern]");
+ return;
+ }
+
+ if (p->op) {
+ printf("%s", p->op->name);
+ if (p->op->arity > 0) {
+ printf("(");
+ for (i = 0; i < p->op->arity; i++) {
+ printf("%s ", p->children[i]->name);
+ }
+ printf(")");
+ }
+ } else {
+ printf("%s", p->children[0]->name);
+ }
+}
diff --git a/llvm/utils/Burg/plank.c b/llvm/utils/Burg/plank.c
new file mode 100644
index 00000000000..1ce006dd019
--- /dev/null
+++ b/llvm/utils/Burg/plank.c
@@ -0,0 +1,921 @@
+char rcsid_plank[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "b.h"
+#include "fe.h"
+
+#define ERROR_VAL 0
+
+int speedflag = 0;
+
+Item_Set *sortedStates;
+static struct stateMapTable smt;
+int exceptionTolerance = 0;
+static int plankSize = 32;
+
+static Plank newPlank ARGS((void));
+static PlankMap newPlankMap ARGS((int));
+static StateMap newStateMap ARGS((void));
+static Exception newException ARGS((int, int));
+static void enterStateMap ARGS((PlankMap, short *, int, int *));
+static List assemblePlanks ARGS((void));
+static void assignRules ARGS((RuleAST));
+static int stateCompare ARGS((Item_Set *, Item_Set *));
+static int ruleCompare ARGS((RuleAST *, RuleAST *));
+static void renumber ARGS((void));
+static short * newVector ARGS((void));
+static int width ARGS((int));
+static PlankMap mapToPmap ARGS((Dimension));
+static void doDimPmaps ARGS((Operator));
+static void doNonTermPmaps ARGS((NonTerminal));
+static void makePmaps ARGS((void));
+static void outPlank ARGS((Plank));
+static void purgePlanks ARGS((List));
+static void inToEx ARGS((void));
+static void makePlankRuleMacros ARGS((void));
+static void makePlankRule ARGS((void));
+static void exceptionSwitch ARGS((List, const char *, const char *, const char *, int, const char *));
+static void doPlankLabel ARGS((Operator));
+static void doPlankLabelSafely ARGS((Operator));
+static void doPlankLabelMacrosSafely ARGS((Operator));
+static void makePlankState ARGS((void));
+
+static Plank
+newPlank()
+{
+ Plank p;
+ char buf[50];
+ static int num = 0;
+
+ p = (Plank) zalloc(sizeof(struct plank));
+ sprintf(buf, "%s_plank_%d", prefix, num++);
+ p->name = (char *) zalloc(strlen(buf)+1);
+ strcpy(p->name, buf);
+ return p;
+}
+
+static PlankMap
+newPlankMap(offset) int offset;
+{
+ PlankMap im;
+
+ im = (PlankMap) zalloc(sizeof(struct plankMap));
+ im->offset = offset;
+ return im;
+}
+
+static StateMap
+newStateMap()
+{
+ char buf[50];
+ static int num = 0;
+
+ StateMap sm;
+
+ sm = (StateMap) zalloc(sizeof(struct stateMap));
+ sprintf(buf, "f%d", num++);
+ sm->fieldname = (char *) zalloc(strlen(buf)+1);
+ strcpy(sm->fieldname, buf);
+ return sm;
+}
+
+static Exception
+newException(index, value) int index; int value;
+{
+ Exception e;
+
+ e = (Exception) zalloc(sizeof(struct except));
+ e->index = index;
+ e->value = value;
+ return e;
+}
+
+static void
+enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new;
+{
+ int i;
+ StateMap sm;
+ List l;
+ int size;
+
+ assert(im);
+ assert(v);
+ assert(width > 0);
+ size = globalMap->count;
+
+ for (l = smt.maps; l; l = l->next) {
+ int ecount;
+
+ sm = (StateMap) l->x;
+ ecount = 0;
+ for (i = 0; i < size; i++) {
+ if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) {
+ if (++ecount > exceptionTolerance) {
+ goto again;
+ }
+ }
+ }
+ for (i = 0; i < size; i++) {
+ assert(v[i] >= 0);
+ assert(sm->value[i] >= 0);
+ if (v[i] == -1) {
+ continue;
+ }
+ if (sm->value[i] == -1) {
+ sm->value[i] = v[i];
+ } else if (v[i] != sm->value[i]) {
+ im->exceptions = newList(newException(i,v[i]), im->exceptions);
+ }
+ }
+ im->values = sm;
+ if (width > sm->width) {
+ sm->width = width;
+ }
+ *new = 0;
+ return;
+ again: ;
+ }
+ sm = newStateMap();
+ im->values = sm;
+ sm->value = v;
+ sm->width = width;
+ *new = 1;
+ smt.maps = newList(sm, smt.maps);
+}
+
+static List
+assemblePlanks()
+{
+ List planks = 0;
+ Plank pl;
+ List p;
+ List s;
+
+ for (s = smt.maps; s; s = s->next) {
+ StateMap sm = (StateMap) s->x;
+ for (p = planks; p; p = p->next) {
+ pl = (Plank) p->x;
+ if (sm->width <= plankSize - pl->width) {
+ pl->width += sm->width;
+ pl->fields = newList(sm, pl->fields);
+ sm->plank = pl;
+ goto next;
+ }
+ }
+ pl = newPlank();
+ pl->width = sm->width;
+ pl->fields = newList(sm, 0);
+ sm->plank = pl;
+ planks = appendList(pl, planks);
+ next: ;
+ }
+ return planks;
+}
+
+RuleAST *sortedRules;
+
+static int count;
+
+static void
+assignRules(ast) RuleAST ast;
+{
+ sortedRules[count++] = ast;
+}
+
+static int
+stateCompare(s, t) Item_Set *s; Item_Set *t;
+{
+ return strcmp((*s)->op->name, (*t)->op->name);
+}
+
+static int
+ruleCompare(s, t) RuleAST *s; RuleAST *t;
+{
+ return strcmp((*s)->lhs, (*t)->lhs);
+}
+
+void
+dumpSortedStates()
+{
+ int i;
+
+ printf("dump Sorted States: ");
+ for (i = 0; i < globalMap->count; i++) {
+ printf("%d ", sortedStates[i]->num);
+ }
+ printf("\n");
+}
+
+void
+dumpSortedRules()
+{
+ int i;
+
+ printf("dump Sorted Rules: ");
+ for (i = 0; i < max_ruleAST; i++) {
+ printf("%d ", sortedRules[i]->rule->erulenum);
+ }
+ printf("\n");
+}
+
+static void
+renumber()
+{
+ int i;
+ Operator previousOp;
+ NonTerminal previousLHS;
+ int base_counter;
+
+ sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set));
+ for (i = 1; i < globalMap->count; i++) {
+ sortedStates[i-1] = globalMap->set[i];
+ }
+ qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), (int(*)(const void *, const void *))stateCompare);
+ previousOp = 0;
+ for (i = 0; i < globalMap->count-1; i++) {
+ sortedStates[i]->newNum = i;
+ sortedStates[i]->op->stateCount++;
+ if (previousOp != sortedStates[i]->op) {
+ sortedStates[i]->op->baseNum = i;
+ previousOp = sortedStates[i]->op;
+ }
+ }
+
+ sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST));
+ count = 0;
+ foreachList((ListFn) assignRules, ruleASTs);
+ qsort(sortedRules, max_ruleAST, sizeof(RuleAST), (int(*)(const void *, const void *))ruleCompare);
+ previousLHS = 0;
+ base_counter = 0;
+ for (i = 0; i < max_ruleAST; i++) {
+ if (previousLHS != sortedRules[i]->rule->lhs) {
+ sortedRules[i]->rule->lhs->baseNum = base_counter;
+ previousLHS = sortedRules[i]->rule->lhs;
+ base_counter++; /* make space for 0 */
+ }
+ sortedRules[i]->rule->newNum = base_counter;
+ sortedRules[i]->rule->lhs->ruleCount++;
+ sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */
+ base_counter++;
+ }
+}
+
+static short *
+newVector()
+{
+ short *p;
+ p = (short *) zalloc(globalMap->count* sizeof(short));
+ return p;
+}
+
+static int
+width(v) int v;
+{
+ int c;
+
+ for (c = 0; v; v >>= 1) {
+ c++;
+ }
+ return c;
+
+}
+
+static PlankMap
+mapToPmap(d) Dimension d;
+{
+ PlankMap im;
+ short *v;
+ int i;
+ int new;
+
+ if (d->map->count == 1) {
+ return 0;
+ }
+ assert(d->map->count > 1);
+ im = newPlankMap(0);
+ v = newVector();
+ for (i = 0; i < globalMap->count-1; i++) {
+ int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+ assert(index >= 0);
+ v[i+1] = index;
+ }
+ v[0] = 0;
+ enterStateMap(im, v, width(d->map->count), &new);
+ if (!new) {
+ zfree(v);
+ }
+ return im;
+}
+
+static void
+doDimPmaps(op) Operator op;
+{
+ int i, j;
+ Dimension d;
+ short *v;
+ PlankMap im;
+ int new;
+
+ if (!op->table->rules) {
+ return;
+ }
+ switch (op->arity) {
+ case 0:
+ break;
+ case 1:
+ d = op->table->dimen[0];
+ if (d->map->count > 1) {
+ v = newVector();
+ im = newPlankMap(op->baseNum);
+ for (i = 0; i < globalMap->count-1; i++) {
+ int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+ if (index) {
+ Item_Set *ts = transLval(op->table, index, 0);
+ v[i+1] = (*ts)->newNum - op->baseNum+1;
+ assert(v[i+1] >= 0);
+ }
+ }
+ enterStateMap(im, v, width(d->map->count-1), &new);
+ if (!new) {
+ zfree(v);
+ }
+ d->pmap = im;
+ }
+ break;
+ case 2:
+ if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) {
+ op->table->dimen[0]->pmap = 0;
+ op->table->dimen[1]->pmap = 0;
+ } else if (op->table->dimen[0]->map->count == 1) {
+ v = newVector();
+ im = newPlankMap(op->baseNum);
+ d = op->table->dimen[1];
+ for (i = 0; i < globalMap->count-1; i++) {
+ int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+ if (index) {
+ Item_Set *ts = transLval(op->table, 1, index);
+ v[i+1] = (*ts)->newNum - op->baseNum+1;
+ assert(v[i+1] >= 0);
+ }
+ }
+ enterStateMap(im, v, width(d->map->count-1), &new);
+ if (!new) {
+ zfree(v);
+ }
+ d->pmap = im;
+ } else if (op->table->dimen[1]->map->count == 1) {
+ v = newVector();
+ im = newPlankMap(op->baseNum);
+ d = op->table->dimen[0];
+ for (i = 0; i < globalMap->count-1; i++) {
+ int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
+ if (index) {
+ Item_Set *ts = transLval(op->table, index, 1);
+ v[i +1] = (*ts)->newNum - op->baseNum +1;
+ assert(v[i +1] >= 0);
+ }
+ }
+ enterStateMap(im, v, width(d->map->count-1), &new);
+ if (!new) {
+ zfree(v);
+ }
+ d->pmap = im;
+ } else {
+ op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]);
+ op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]);
+ /* output table */
+ fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {",
+ op->stateCount <= 255 ? "char" : "short",
+ prefix,
+ op->name,
+ op->table->dimen[0]->map->count,
+ op->table->dimen[1]->map->count);
+ for (i = 0; i < op->table->dimen[0]->map->count; i++) {
+ if (i > 0) {
+ fprintf(outfile, ",");
+ }
+ fprintf(outfile, "\n{");
+ for (j = 0; j < op->table->dimen[1]->map->count; j++) {
+ Item_Set *ts = transLval(op->table, i, j);
+ short diff;
+ if (j > 0) {
+ fprintf(outfile, ",");
+ if (j % 10 == 0) {
+ fprintf(outfile, "\t/* row %d, cols %d-%d*/\n",
+ i,
+ j-10,
+ j-1);
+ }
+ }
+ if ((*ts)->num > 0) {
+ diff = (*ts)->newNum - op->baseNum +1;
+ } else {
+ diff = 0;
+ }
+ fprintf(outfile, "%5d", diff);
+ }
+ fprintf(outfile, "}\t/* row %d */", i);
+ }
+ fprintf(outfile, "\n};\n");
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static NonTerminal *ntVector;
+
+static void
+doNonTermPmaps(n) NonTerminal n;
+{
+ short *v;
+ PlankMap im;
+ int new;
+ int i;
+
+ ntVector[n->num] = n;
+ if (n->num >= last_user_nonterminal) {
+ return;
+ }
+ if (n->ruleCount <= 0) {
+ return;
+ }
+ im = newPlankMap(n->baseNum);
+ v = newVector();
+ for (i = 0; i < globalMap->count-1; i++) {
+ Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule;
+ if (r) {
+ r->used = 1;
+ v[i+1] = r->newNum - n->baseNum /*safely*/;
+ assert(v[i+1] >= 0);
+ }
+ }
+ enterStateMap(im, v, width(n->ruleCount+1), &new);
+ if (!new) {
+ zfree(v);
+ }
+ n->pmap = im;
+}
+
+static void
+makePmaps()
+{
+ foreachList((ListFn) doDimPmaps, operators);
+ ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal));
+ foreachList((ListFn) doNonTermPmaps, nonterminals);
+}
+
+static void
+outPlank(p) Plank p;
+{
+ List f;
+ int i;
+
+ fprintf(outfile, "static struct {\n");
+
+ for (f = p->fields; f; f = f->next) {
+ StateMap sm = (StateMap) f->x;
+ fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width);
+ }
+
+ fprintf(outfile, "} %s[] = {\n", p->name);
+
+ for (i = 0; i < globalMap->count; i++) {
+ fprintf(outfile, "\t{");
+ for (f = p->fields; f; f = f->next) {
+ StateMap sm = (StateMap) f->x;
+ fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]);
+ }
+ fprintf(outfile, "},\t/* row %d */\n", i);
+ }
+
+ fprintf(outfile, "};\n");
+}
+
+static void
+purgePlanks(planks) List planks;
+{
+ List p;
+
+ for (p = planks; p; p = p->next) {
+ Plank x = (Plank) p->x;
+ outPlank(x);
+ }
+}
+
+static void
+inToEx()
+{
+ int i;
+ int counter;
+
+ fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix);
+ counter = 0;
+ for (i = 0; i < max_ruleAST; i++) {
+ if (counter > 0) {
+ fprintf(outfile, ",");
+ if (counter % 10 == 0) {
+ fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+ }
+ }
+ if (counter < sortedRules[i]->rule->newNum) {
+ assert(counter == sortedRules[i]->rule->newNum-1);
+ fprintf(outfile, "%5d", 0);
+ counter++;
+ if (counter > 0) {
+ fprintf(outfile, ",");
+ if (counter % 10 == 0) {
+ fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
+ }
+ }
+ }
+ fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum);
+ counter++;
+ }
+ fprintf(outfile, "\n};\n");
+}
+
+static void
+makePlankRuleMacros()
+{
+ int i;
+
+ for (i = 1; i < last_user_nonterminal; i++) {
+ List es;
+ PlankMap im = ntVector[i]->pmap;
+ fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name);
+ if (im) {
+ fprintf(outfile, "%s_eruleMap[", prefix);
+ for (es = im->exceptions; es; es = es->next) {
+ Exception e = (Exception) es->x;
+ fprintf(outfile, "((state) == %d ? %d :",
+ e->index, e->value);
+ }
+ fprintf(outfile, "%s[state].%s",
+ im->values->plank->name,
+ im->values->fieldname);
+ for (es = im->exceptions; es; es = es->next) {
+ fprintf(outfile, ")");
+ }
+ fprintf(outfile, " +%d]", im->offset);
+
+ } else {
+ /* nonterminal never appears on LHS. */
+ assert(ntVector[i] == start);
+ fprintf(outfile, "0");
+ }
+ fprintf(outfile, "\n");
+ }
+ fprintf(outfile, "\n");
+}
+
+static void
+makePlankRule()
+{
+ int i;
+
+ makePlankRuleMacros();
+
+ fprintf(outfile, "#ifdef __STDC__\n");
+ fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix);
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile,
+ "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
+ prefix, globalMap->count, prefix, prefix);
+ fprintf(outfile, "\tswitch(goalnt) {\n");
+
+ for (i = 1; i < last_user_nonterminal; i++) {
+ fprintf(outfile, "\tcase %d:\n", i);
+ fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name);
+ }
+ fprintf(outfile, "\tdefault:\n");
+ fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix);
+ fprintf(outfile, "\t\tabort();\n");
+ fprintf(outfile, "\t\treturn 0;\n");
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "}\n");
+}
+
+static void
+exceptionSwitch(es, sw, pre, post, offset, def) List es; const char *sw; const char *pre; const char *post; int offset; const char *def;
+{
+ if (es) {
+ fprintf(outfile, "\t\tswitch (%s) {\n", sw);
+ for (; es; es = es->next) {
+ Exception e = (Exception) es->x;
+ fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post);
+ }
+ if (def) {
+ fprintf(outfile, "\t\tdefault: %s;\n", def);
+ }
+ fprintf(outfile, "\t\t}\n");
+ } else {
+ if (def) {
+ fprintf(outfile, "\t\t%s;\n", def);
+ }
+ }
+}
+
+static void
+doPlankLabel(op) Operator op;
+{
+ PlankMap im0;
+ PlankMap im1;
+ char buf[100];
+
+ fprintf(outfile, "\tcase %d:\n", op->num);
+ switch (op->arity) {
+ case 0:
+ fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum);
+ break;
+ case 1:
+ im0 = op->table->dimen[0]->pmap;
+ if (im0) {
+ exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+ fprintf(outfile, "\t\treturn %s[l].%s + %d;\n",
+ im0->values->plank->name, im0->values->fieldname, im0->offset);
+ } else {
+ Item_Set *ts = transLval(op->table, 1, 0);
+ if (*ts) {
+ fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+ } else {
+ fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+ }
+ }
+ break;
+ case 2:
+ im0 = op->table->dimen[0]->pmap;
+ im1 = op->table->dimen[1]->pmap;
+ if (!im0 && !im1) {
+ Item_Set *ts = transLval(op->table, 1, 1);
+ if (*ts) {
+ fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
+ } else {
+ fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
+ }
+ } else if (!im0) {
+ exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0);
+ fprintf(outfile, "\t\treturn %s[r].%s + %d;\n",
+ im1->values->plank->name, im1->values->fieldname, im1->offset);
+ } else if (!im1) {
+ exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
+ fprintf(outfile, "\t\treturn %s[l].%s + %d;\n",
+ im0->values->plank->name, im0->values->fieldname, im0->offset);
+ } else {
+ assert(im0->offset == 0);
+ assert(im1->offset == 0);
+ sprintf(buf, "l = %s[l].%s",
+ im0->values->plank->name, im0->values->fieldname);
+ exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+ sprintf(buf, "r = %s[r].%s",
+ im1->values->plank->name, im1->values->fieldname);
+ exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+ fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n",
+ prefix,
+ op->name,
+ op->baseNum);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+doPlankLabelMacrosSafely(op) Operator op;
+{
+ PlankMap im0;
+ PlankMap im1;
+
+ switch (op->arity) {
+ case -1:
+ fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name);
+ break;
+ case 0:
+ fprintf(outfile, "#define %s_%s_state", prefix, op->name);
+ fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1);
+ break;
+ case 1:
+ fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name);
+ im0 = op->table->dimen[0]->pmap;
+ if (im0) {
+ if (im0->exceptions) {
+ List es = im0->exceptions;
+ assert(0);
+ fprintf(outfile, "\t\tswitch (l) {\n");
+ for (; es; es = es->next) {
+ Exception e = (Exception) es->x;
+ fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+ }
+ fprintf(outfile, "\t\t}\n");
+ }
+ if (speedflag) {
+ fprintf(outfile, "\t( %s[l].%s + %d )\n",
+ im0->values->plank->name, im0->values->fieldname,
+ im0->offset);
+ } else {
+ fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n",
+ prefix,
+ im0->values->plank->name, im0->values->fieldname,
+ prefix,
+ im0->offset);
+ }
+ } else {
+ Item_Set *ts = transLval(op->table, 1, 0);
+ if (*ts) {
+ fprintf(outfile, "\t%d\n", (*ts)->newNum+1);
+ } else {
+ fprintf(outfile, "\t%d\n", 0);
+ }
+ }
+ break;
+ case 2:
+ fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name);
+
+ im0 = op->table->dimen[0]->pmap;
+ im1 = op->table->dimen[1]->pmap;
+ if (!im0 && !im1) {
+ Item_Set *ts = transLval(op->table, 1, 1);
+ assert(0);
+ if (*ts) {
+ fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1);
+ } else {
+ fprintf(outfile, "\t\treturn %d;\n", 0);
+ }
+ } else if (!im0) {
+ assert(0);
+ if (im1->exceptions) {
+ List es = im1->exceptions;
+ fprintf(outfile, "\t\tswitch (r) {\n");
+ for (; es; es = es->next) {
+ Exception e = (Exception) es->x;
+ fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0);
+ }
+ fprintf(outfile, "\t\t}\n");
+ }
+ fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n",
+ im1->values->plank->name, im1->values->fieldname, im1->offset);
+ fprintf(outfile, "\t\tbreak;\n");
+ } else if (!im1) {
+ assert(0);
+ if (im0->exceptions) {
+ List es = im0->exceptions;
+ fprintf(outfile, "\t\tswitch (l) {\n");
+ for (; es; es = es->next) {
+ Exception e = (Exception) es->x;
+ fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
+ }
+ fprintf(outfile, "\t\t}\n");
+ }
+ fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n",
+ im0->values->plank->name, im0->values->fieldname, im0->offset);
+ fprintf(outfile, "\t\tbreak;\n");
+ } else {
+ assert(im0->offset == 0);
+ assert(im1->offset == 0);
+ /*
+ sprintf(buf, "l = %s[l].%s",
+ im0->values->plank->name, im0->values->fieldname);
+ exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
+ sprintf(buf, "r = %s[r].%s",
+ im1->values->plank->name, im1->values->fieldname);
+ exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
+
+ fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n",
+ prefix,
+ op->name,
+ op->baseNum);
+ fprintf(outfile, "\t\tbreak;\n");
+ */
+
+ if (speedflag) {
+ fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n",
+ prefix,
+ op->name,
+ im0->values->plank->name, im0->values->fieldname,
+ im1->values->plank->name, im1->values->fieldname,
+ op->baseNum);
+ } else {
+ fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ",
+ prefix,
+ prefix,
+ op->name,
+ im0->values->plank->name, im0->values->fieldname,
+ im1->values->plank->name, im1->values->fieldname);
+ fprintf(outfile, "%s_TEMP + %d : 0 )\n",
+ prefix,
+ op->baseNum);
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+static void
+doPlankLabelSafely(op) Operator op;
+{
+ fprintf(outfile, "\tcase %d:\n", op->num);
+ switch (op->arity) {
+ case -1:
+ fprintf(outfile, "\t\treturn 0;\n");
+ break;
+ case 0:
+ fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name);
+ break;
+ case 1:
+ fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name);
+ break;
+ case 2:
+ fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+makePlankState()
+{
+ fprintf(outfile, "\n");
+ fprintf(outfile, "int %s_TEMP;\n", prefix);
+ foreachList((ListFn) doPlankLabelMacrosSafely, operators);
+ fprintf(outfile, "\n");
+
+ fprintf(outfile, "#ifdef __STDC__\n");
+ switch (max_arity) {
+ case -1:
+ fprintf(stderr, "ERROR: no terminals in grammar.\n");
+ exit(1);
+ case 0:
+ fprintf(outfile, "int %s_state(int op) {\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_state(op) int op; {\n", prefix);
+ break;
+ case 1:
+ fprintf(outfile, "int %s_state(int op, int l) {\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix);
+ break;
+ case 2:
+ fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
+ fprintf(outfile, "#else\n");
+ fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix);
+ break;
+ default:
+ assert(0);
+ }
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile, "\tregister int %s_TEMP;\n", prefix);
+
+ fprintf(outfile, "#ifndef NDEBUG\n");
+
+ fprintf(outfile, "\tswitch (op) {\n");
+ opsOfArity(2);
+ if (max_arity >= 2) {
+ fprintf(outfile,
+ "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
+ prefix, globalMap->count, prefix, prefix);
+ fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+ }
+ opsOfArity(1);
+ if (max_arity > 1) {
+ fprintf(outfile,
+ "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
+ prefix, globalMap->count, prefix, prefix);
+ fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
+ }
+ opsOfArity(0);
+ fprintf(outfile, "\t\tbreak;\n");
+ fprintf(outfile, "\t}\n");
+ fprintf(outfile, "#endif\n");
+
+ fprintf(outfile, "\tswitch (op) {\n");
+ fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n",
+ prefix, prefix);
+ foreachList((ListFn) doPlankLabelSafely, operators);
+ fprintf(outfile, "\t}\n");
+
+ fprintf(outfile, "}\n");
+}
+
+void
+makePlanks()
+{
+ List planks;
+ renumber();
+ makePmaps();
+ planks = assemblePlanks();
+ purgePlanks(planks);
+ inToEx();
+ makePlankRule();
+ makePlankState();
+}
diff --git a/llvm/utils/Burg/queue.c b/llvm/utils/Burg/queue.c
new file mode 100644
index 00000000000..76e5ea9b57b
--- /dev/null
+++ b/llvm/utils/Burg/queue.c
@@ -0,0 +1,64 @@
+char rcsid_queue[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+Queue globalQ;
+
+Queue
+newQ()
+{
+ Queue q;
+
+ q = (Queue) zalloc(sizeof(struct queue));
+ assert(q);
+ q->head = 0;
+ q->tail = 0;
+
+ return q;
+}
+
+void
+addQ(q, ts) Queue q; Item_Set ts;
+{
+ List qe;
+
+ assert(q);
+ assert(ts);
+
+ qe = newList(ts, 0);
+ if (q->head) {
+ assert(q->tail);
+ q->tail->next = qe;
+ q->tail = qe;
+ } else {
+ q->head = q->tail = qe;
+ }
+}
+
+Item_Set
+popQ(q) Queue q;
+{
+ List qe;
+ Item_Set ts;
+
+ assert(q);
+
+ if (q->head) {
+ qe = q->head;
+ q->head = q->head->next;
+ ts = (Item_Set) qe->x;
+ zfree(qe);
+ return ts;
+ } else {
+ return 0;
+ }
+}
+
+void
+dumpQ(q) Queue q;
+{
+ printf("Begin Queue\n");
+ foreachList((ListFn)dumpItem_Set, q->head);
+ printf("End Queue\n");
+}
diff --git a/llvm/utils/Burg/rule.c b/llvm/utils/Burg/rule.c
new file mode 100644
index 00000000000..ee5c89e8933
--- /dev/null
+++ b/llvm/utils/Burg/rule.c
@@ -0,0 +1,49 @@
+char rcsid_rule[] = "$Id$";
+
+#include "b.h"
+#include <stdio.h>
+
+RuleNum max_rule;
+int max_erule_num;
+
+struct rule stub_rule;
+
+List rules;
+
+Rule
+newRule(delta, erulenum, lhs, pat) DeltaPtr delta; ERuleNum erulenum; NonTerminal lhs; Pattern pat;
+{
+ Rule p;
+
+ p = (Rule) zalloc(sizeof(struct rule));
+ assert(p);
+ ASSIGNCOST(p->delta, delta);
+ p->erulenum = erulenum;
+ if (erulenum > max_erule_num) {
+ max_erule_num = erulenum;
+ }
+ p->num = max_rule++;
+ p->lhs = lhs;
+ p->pat = pat;
+
+ rules = newList(p, rules);
+
+ return p;
+}
+
+void
+dumpRule(p) Rule p;
+{
+ dumpNonTerminal(p->lhs);
+ printf(" : ");
+ dumpPattern(p->pat);
+ printf(" ");
+ dumpCost(p->delta);
+ printf("\n");
+}
+
+void
+dumpRuleList(l) List l;
+{
+ foreachList((ListFn)dumpRule, l);
+}
diff --git a/llvm/utils/Burg/sample.gr b/llvm/utils/Burg/sample.gr
new file mode 100644
index 00000000000..e1f7283b6d6
--- /dev/null
+++ b/llvm/utils/Burg/sample.gr
@@ -0,0 +1,150 @@
+%{
+#include <stdio.h>
+
+typedef struct node *NODEPTR_TYPE;
+
+struct node {
+ int op, state_label;
+ NODEPTR_TYPE left, right;
+};
+
+#define OP_LABEL(p) ((p)->op)
+#define STATE_LABEL(p) ((p)->state_label)
+#define LEFT_CHILD(p) ((p)->left)
+#define RIGHT_CHILD(p) ((p)->right)
+#define PANIC printf
+%}
+
+%start reg
+%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6
+%%
+con: Constant = 1 (0);
+con: Four = 2 (0);
+addr: con = 3 (0);
+addr: Plus(con,reg) = 4 (0);
+addr: Plus(con,Mul(Four,reg)) = 5 (0);
+reg: Fetch(addr) = 6 (1);
+reg: Assign(addr,reg) = 7 (1);
+
+%%
+
+#define Assign 1
+#define Constant 2
+#define Fetch 3
+#define Four 4
+#define Mul 5
+#define Plus 6
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+NODEPTR_TYPE buildtree ARGS((int, NODEPTR_TYPE, NODEPTR_TYPE));
+void printcover ARGS((NODEPTR_TYPE, int, int));
+void printtree ARGS((NODEPTR_TYPE));
+int treecost ARGS((NODEPTR_TYPE, int, int));
+void printMatches ARGS((NODEPTR_TYPE));
+int main ARGS((void));
+
+NODEPTR_TYPE buildtree(op, left, right) int op; NODEPTR_TYPE left; NODEPTR_TYPE right; {
+ NODEPTR_TYPE p;
+ extern void *malloc ARGS((unsigned));
+
+ p = (NODEPTR_TYPE) malloc(sizeof *p);
+ p->op = op;
+ p->left = left;
+ p->right = right;
+ return p;
+}
+
+void printcover(p, goalnt, indent) NODEPTR_TYPE p; int goalnt; int indent; {
+ int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+ short *nts = burm_nts[eruleno];
+ NODEPTR_TYPE kids[10];
+ int i;
+
+ if (eruleno == 0) {
+ printf("no cover\n");
+ return;
+ }
+ for (i = 0; i < indent; i++)
+ printf(".");
+ printf("%s\n", burm_string[eruleno]);
+ burm_kids(p, eruleno, kids);
+ for (i = 0; nts[i]; i++)
+ printcover(kids[i], nts[i], indent+1);
+}
+
+void printtree(p) NODEPTR_TYPE p; {
+ int op = burm_op_label(p);
+
+ printf("%s", burm_opname[op]);
+ switch (burm_arity[op]) {
+ case 0:
+ break;
+ case 1:
+ printf("(");
+ printtree(burm_child(p, 0));
+ printf(")");
+ break;
+ case 2:
+ printf("(");
+ printtree(burm_child(p, 0));
+ printf(", ");
+ printtree(burm_child(p, 1));
+ printf(")");
+ break;
+ }
+}
+
+int treecost(p, goalnt, costindex) NODEPTR_TYPE p; int goalnt; int costindex; {
+ int eruleno = burm_rule(STATE_LABEL(p), goalnt);
+ int cost = burm_cost[eruleno][costindex], i;
+ short *nts = burm_nts[eruleno];
+ NODEPTR_TYPE kids[10];
+
+ burm_kids(p, eruleno, kids);
+ for (i = 0; nts[i]; i++)
+ cost += treecost(kids[i], nts[i], costindex);
+ return cost;
+}
+
+void printMatches(p) NODEPTR_TYPE p; {
+ int nt;
+ int eruleno;
+
+ printf("Node 0x%lx= ", (unsigned long)p);
+ printtree(p);
+ printf(" matched rules:\n");
+ for (nt = 1; burm_ntname[nt] != (char*)NULL; nt++)
+ if ((eruleno = burm_rule(STATE_LABEL(p), nt)) != 0)
+ printf("\t%s\n", burm_string[eruleno]);
+}
+
+main() {
+ NODEPTR_TYPE p;
+
+ p = buildtree(Assign,
+ buildtree(Constant, 0, 0),
+ buildtree(Fetch,
+ buildtree(Plus,
+ buildtree(Constant, 0, 0),
+ buildtree(Mul,
+ buildtree(Four, 0, 0),
+ buildtree(Fetch, buildtree(Constant, 0, 0), 0)
+ )
+ ),
+ 0
+ )
+ );
+ printtree(p);
+ printf("\n\n");
+ burm_label(p);
+ printcover(p, 1, 0);
+ printf("\nCover cost == %d\n\n", treecost(p, 1, 0));
+ printMatches(p);
+ return 0;
+}
+
diff --git a/llvm/utils/Burg/string.c b/llvm/utils/Burg/string.c
new file mode 100644
index 00000000000..9b69c3045ff
--- /dev/null
+++ b/llvm/utils/Burg/string.c
@@ -0,0 +1,65 @@
+char rcsid_string[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static StrTableElement newStrTableElement ARGS((void));
+
+StrTable
+newStrTable()
+{
+ return (StrTable) zalloc(sizeof(struct strTable));
+}
+
+static StrTableElement
+newStrTableElement()
+{
+ return (StrTableElement) zalloc(sizeof(struct strTableElement));
+}
+
+void
+dumpStrTable(t) StrTable t;
+{
+ List e;
+ IntList r;
+
+ printf("Begin StrTable\n");
+ for (e = t->elems; e; e = e->next) {
+ StrTableElement el = (StrTableElement) e->x;
+ printf("%s: ", el->str);
+ for (r = el->erulenos; r; r = r->next) {
+ int i = r->x;
+ printf("(%d)", i);
+ }
+ printf("\n");
+ }
+ printf("End StrTable\n");
+}
+
+StrTableElement
+addString(t, s, eruleno, new) StrTable t; char *s; int eruleno; int *new;
+{
+ List l;
+ StrTableElement ste;
+
+ assert(t);
+ for (l = t->elems; l; l = l->next) {
+ StrTableElement e = (StrTableElement) l->x;
+
+ assert(e);
+ if (!strcmp(s, e->str)) {
+ e->erulenos = newIntList(eruleno, e->erulenos);
+ *new = 0;
+ return e;
+ }
+ }
+ ste = newStrTableElement();
+ ste->erulenos = newIntList(eruleno, 0);
+ ste->str = (char *) zalloc(strlen(s) + 1);
+ strcpy(ste->str, s);
+ t->elems = newList(ste, t->elems);
+ *new = 1;
+ return ste;
+}
diff --git a/llvm/utils/Burg/symtab.c b/llvm/utils/Burg/symtab.c
new file mode 100644
index 00000000000..3ecab2fc5ff
--- /dev/null
+++ b/llvm/utils/Burg/symtab.c
@@ -0,0 +1,38 @@
+char rcsid_symtab[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+#include "fe.h"
+
+static List symtab;
+
+Symbol
+newSymbol(name) char *name;
+{
+ Symbol s;
+
+ s = (Symbol) zalloc(sizeof(struct symbol));
+ assert(s);
+ s->name = name;
+ return s;
+}
+
+Symbol
+enter(name, new) char *name; int *new;
+{
+ List l;
+ Symbol s;
+
+ *new = 0;
+ for (l = symtab; l; l = l->next) {
+ s = (Symbol) l->x;
+ if (!strcmp(name, s->name)) {
+ return s;
+ }
+ }
+ *new = 1;
+ s = newSymbol(name);
+ symtab = newList(s, symtab);
+ return s;
+}
diff --git a/llvm/utils/Burg/table.c b/llvm/utils/Burg/table.c
new file mode 100644
index 00000000000..1de74f9a107
--- /dev/null
+++ b/llvm/utils/Burg/table.c
@@ -0,0 +1,552 @@
+char rcsid_table[] = "$Id$";
+
+#include "b.h"
+#include <string.h>
+#include <stdio.h>
+
+static void growIndex_Map ARGS((Index_Map *));
+static Relevant newRelevant ARGS((void));
+static Dimension newDimension ARGS((Operator, int));
+static void GT_1 ARGS((Table));
+static void GT_2_0 ARGS((Table));
+static void GT_2_1 ARGS((Table));
+static void growTransition ARGS((Table, int));
+static Item_Set restrict ARGS((Dimension, Item_Set));
+static void addHP_1 ARGS((Table, Item_Set));
+static void addHP_2_0 ARGS((Table, Item_Set));
+static void addHP_2_1 ARGS((Table, Item_Set));
+static void addHyperPlane ARGS((Table, int, Item_Set));
+
+static void
+growIndex_Map(r) Index_Map *r;
+{
+ Index_Map new;
+
+ new.max_size = r->max_size + STATES_INCR;
+ new.class = (Item_Set*) zalloc(new.max_size * sizeof(Item_Set));
+ assert(new.class);
+ memcpy(new.class, r->class, r->max_size * sizeof(Item_Set));
+ zfree(r->class);
+ *r = new;
+}
+
+static Relevant
+newRelevant()
+{
+ Relevant r = (Relevant) zalloc(max_nonterminal * sizeof(*r));
+ return r;
+}
+
+void
+addRelevant(r, nt) Relevant r; NonTerminalNum nt;
+{
+ int i;
+
+ for (i = 0; r[i]; i++) {
+ if (r[i] == nt) {
+ break;
+ }
+ }
+ if (!r[i]) {
+ r[i] = nt;
+ }
+}
+
+static Dimension
+newDimension(op, index) Operator op; ArityNum index;
+{
+ Dimension d;
+ List pl;
+ Relevant r;
+
+ assert(op);
+ assert(index >= 0 && index < op->arity);
+ d = (Dimension) zalloc(sizeof(struct dimension));
+ assert(d);
+
+ r = d->relevant = newRelevant();
+ for (pl = rules; pl; pl = pl->next) {
+ Rule pr = (Rule) pl->x;
+ if (pr->pat->op == op) {
+ addRelevant(r, pr->pat->children[index]->num);
+ }
+ }
+
+ d->index_map.max_size = STATES_INCR;
+ d->index_map.class = (Item_Set*)
+ zalloc(d->index_map.max_size * sizeof(Item_Set));
+ d->map = newMapping(DIM_MAP_SIZE);
+ d->max_size = TABLE_INCR;
+
+ return d;
+}
+
+Table
+newTable(op) Operator op;
+{
+ Table t;
+ int i, size;
+
+ assert(op);
+
+ t = (Table) zalloc(sizeof(struct table));
+ assert(t);
+
+ t->op = op;
+
+ for (i = 0; i < op->arity; i++) {
+ t->dimen[i] = newDimension(op, i);
+ }
+
+ size = 1;
+ for (i = 0; i < op->arity; i++) {
+ size *= t->dimen[i]->max_size;
+ }
+ t->transition = (Item_Set*) zalloc(size * sizeof(Item_Set));
+ t->relevant = newRelevant();
+ assert(t->transition);
+
+ return t;
+}
+
+static void
+GT_1(t) Table t;
+{
+ Item_Set *ts;
+ ItemSetNum oldsize = t->dimen[0]->max_size;
+ ItemSetNum newsize = t->dimen[0]->max_size + TABLE_INCR;
+
+ t->dimen[0]->max_size = newsize;
+
+ ts = (Item_Set*) zalloc(newsize * sizeof(Item_Set));
+ assert(ts);
+ memcpy(ts, t->transition, oldsize * sizeof(Item_Set));
+ zfree(t->transition);
+ t->transition = ts;
+}
+
+static void
+GT_2_0(t) Table t;
+{
+ Item_Set *ts;
+ ItemSetNum oldsize = t->dimen[0]->max_size;
+ ItemSetNum newsize = t->dimen[0]->max_size + TABLE_INCR;
+ int size;
+
+ t->dimen[0]->max_size = newsize;
+
+ size = newsize * t->dimen[1]->max_size;
+
+ ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+ assert(ts);
+ memcpy(ts, t->transition, oldsize*t->dimen[1]->max_size * sizeof(Item_Set));
+ zfree(t->transition);
+ t->transition = ts;
+}
+
+static void
+GT_2_1(t) Table t;
+{
+ Item_Set *ts;
+ ItemSetNum oldsize = t->dimen[1]->max_size;
+ ItemSetNum newsize = t->dimen[1]->max_size + TABLE_INCR;
+ int size;
+ Item_Set *from;
+ Item_Set *to;
+ int i1, i2;
+
+ t->dimen[1]->max_size = newsize;
+
+ size = newsize * t->dimen[0]->max_size;
+
+ ts = (Item_Set*) zalloc(size * sizeof(Item_Set));
+ assert(ts);
+
+ from = t->transition;
+ to = ts;
+ for (i1 = 0; i1 < t->dimen[0]->max_size; i1++) {
+ for (i2 = 0; i2 < oldsize; i2++) {
+ to[i2] = from[i2];
+ }
+ to += newsize;
+ from += oldsize;
+ }
+ zfree(t->transition);
+ t->transition = ts;
+}
+
+static void
+growTransition(t, dim) Table t; ArityNum dim;
+{
+
+ assert(t);
+ assert(t->op);
+ assert(dim < t->op->arity);
+
+ switch (t->op->arity) {
+ default:
+ assert(0);
+ break;
+ case 1:
+ GT_1(t);
+ return;
+ case 2:
+ switch (dim) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ GT_2_0(t);
+ return;
+ case 1:
+ GT_2_1(t);
+ return;
+ }
+ }
+}
+
+static Item_Set
+restrict(d, ts) Dimension d; Item_Set ts;
+{
+ DeltaCost base;
+ Item_Set r;
+ int found;
+ register Relevant r_ptr = d->relevant;
+ register Item *ts_current = ts->closed;
+ register Item *r_current;
+ register int i;
+ register int nt;
+
+ ZEROCOST(base);
+ found = 0;
+ r = newItem_Set(d->relevant);
+ r_current = r->virgin;
+ for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+ if (ts_current[nt].rule) {
+ r_current[nt].rule = &stub_rule;
+ if (!found) {
+ found = 1;
+ ASSIGNCOST(base, ts_current[nt].delta);
+ } else {
+ if (LESSCOST(ts_current[nt].delta, base)) {
+ ASSIGNCOST(base, ts_current[nt].delta);
+ }
+ }
+ }
+ }
+
+ /* zero align */
+ for (i = 0; (nt = r_ptr[i]) != 0; i++) {
+ if (r_current[nt].rule) {
+ ASSIGNCOST(r_current[nt].delta, ts_current[nt].delta);
+ MINUSCOST(r_current[nt].delta, base);
+ }
+ }
+ assert(!r->closed);
+ r->representative = ts;
+ return r;
+}
+
+static void
+addHP_1(t, ts) Table t; Item_Set ts;
+{
+ List pl;
+ Item_Set e;
+ Item_Set tmp;
+ int new;
+
+ e = newItem_Set(t->relevant);
+ assert(e);
+ e->kids[0] = ts->representative;
+ for (pl = t->rules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ if (t->op == p->pat->op && ts->virgin[p->pat->children[0]->num].rule) {
+ DeltaCost dc;
+ ASSIGNCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+ ADDCOST(dc, p->delta);
+ if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+ e->virgin[p->lhs->num].rule = p;
+ ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+ e->op = t->op;
+ }
+ }
+ }
+ trim(e);
+ zero(e);
+ tmp = encode(globalMap, e, &new);
+ assert(ts->num < t->dimen[0]->map->max_size);
+ t->transition[ts->num] = tmp;
+ if (new) {
+ closure(e);
+ addQ(globalQ, tmp);
+ } else {
+ freeItem_Set(e);
+ }
+}
+
+static void
+addHP_2_0(t, ts) Table t; Item_Set ts;
+{
+ List pl;
+ register Item_Set e;
+ Item_Set tmp;
+ int new;
+ int i2;
+
+ assert(t->dimen[1]->map->count <= t->dimen[1]->map->max_size);
+ for (i2 = 0; i2 < t->dimen[1]->map->count; i2++) {
+ e = newItem_Set(t->relevant);
+ assert(e);
+ e->kids[0] = ts->representative;
+ e->kids[1] = t->dimen[1]->map->set[i2]->representative;
+ for (pl = t->rules; pl; pl = pl->next) {
+ register Rule p = (Rule) pl->x;
+
+ if (t->op == p->pat->op
+ && ts->virgin[p->pat->children[0]->num].rule
+ && t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].rule){
+ DeltaCost dc;
+ ASSIGNCOST(dc, p->delta);
+ ADDCOST(dc, ts->virgin[p->pat->children[0]->num].delta);
+ ADDCOST(dc, t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].delta);
+
+ if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+ e->virgin[p->lhs->num].rule = p;
+ ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+ e->op = t->op;
+ }
+ }
+ }
+ trim(e);
+ zero(e);
+ tmp = encode(globalMap, e, &new);
+ assert(ts->num < t->dimen[0]->map->max_size);
+ t->transition[ts->num * t->dimen[1]->max_size + i2] = tmp;
+ if (new) {
+ closure(e);
+ addQ(globalQ, tmp);
+ } else {
+ freeItem_Set(e);
+ }
+ }
+}
+
+static void
+addHP_2_1(t, ts) Table t; Item_Set ts;
+{
+ List pl;
+ register Item_Set e;
+ Item_Set tmp;
+ int new;
+ int i1;
+
+ assert(t->dimen[0]->map->count <= t->dimen[0]->map->max_size);
+ for (i1 = 0; i1 < t->dimen[0]->map->count; i1++) {
+ e = newItem_Set(t->relevant);
+ assert(e);
+ e->kids[0] = t->dimen[0]->map->set[i1]->representative;
+ e->kids[1] = ts->representative;
+ for (pl = t->rules; pl; pl = pl->next) {
+ register Rule p = (Rule) pl->x;
+
+ if (t->op == p->pat->op
+ && ts->virgin[p->pat->children[1]->num].rule
+ && t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].rule){
+ DeltaCost dc;
+ ASSIGNCOST(dc, p->delta );
+ ADDCOST(dc, ts->virgin[p->pat->children[1]->num].delta);
+ ADDCOST(dc, t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].delta);
+ if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) {
+ e->virgin[p->lhs->num].rule = p;
+ ASSIGNCOST(e->virgin[p->lhs->num].delta, dc);
+ e->op = t->op;
+ }
+ }
+ }
+ trim(e);
+ zero(e);
+ tmp = encode(globalMap, e, &new);
+ assert(ts->num < t->dimen[1]->map->max_size);
+ t->transition[i1 * t->dimen[1]->max_size + ts->num] = tmp;
+ if (new) {
+ closure(e);
+ addQ(globalQ, tmp);
+ } else {
+ freeItem_Set(e);
+ }
+ }
+}
+
+static void
+addHyperPlane(t, i, ts) Table t; ArityNum i; Item_Set ts;
+{
+ switch (t->op->arity) {
+ default:
+ assert(0);
+ break;
+ case 1:
+ addHP_1(t, ts);
+ return;
+ case 2:
+ switch (i) {
+ default:
+ assert(0);
+ break;
+ case 0:
+ addHP_2_0(t, ts);
+ return;
+ case 1:
+ addHP_2_1(t, ts);
+ return;
+ }
+ }
+}
+
+void
+addToTable(t, ts) Table t; Item_Set ts;
+{
+ ArityNum i;
+
+ assert(t);
+ assert(ts);
+ assert(t->op);
+
+ for (i = 0; i < t->op->arity; i++) {
+ Item_Set r;
+ Item_Set tmp;
+ int new;
+
+ r = restrict(t->dimen[i], ts);
+ tmp = encode(t->dimen[i]->map, r, &new);
+ if (t->dimen[i]->index_map.max_size <= ts->num) {
+ growIndex_Map(&t->dimen[i]->index_map);
+ }
+ assert(ts->num < t->dimen[i]->index_map.max_size);
+ t->dimen[i]->index_map.class[ts->num] = tmp;
+ if (new) {
+ if (t->dimen[i]->max_size <= r->num) {
+ growTransition(t, i);
+ }
+ addHyperPlane(t, i, r);
+ } else {
+ freeItem_Set(r);
+ }
+ }
+}
+
+Item_Set *
+transLval(t, row, col) Table t; int row; int col;
+{
+ switch (t->op->arity) {
+ case 0:
+ assert(row == 0);
+ assert(col == 0);
+ return t->transition;
+ case 1:
+ assert(col == 0);
+ return t->transition + row;
+ case 2:
+ return t->transition + row * t->dimen[1]->max_size + col;
+ default:
+ assert(0);
+ }
+ return 0;
+}
+
+void
+dumpRelevant(r) Relevant r;
+{
+ for (; *r; r++) {
+ printf("%4d", *r);
+ }
+}
+
+void
+dumpIndex_Map(r) Index_Map *r;
+{
+ int i;
+
+ printf("BEGIN Index_Map: MaxSize (%d)\n", r->max_size);
+ for (i = 0; i < globalMap->count; i++) {
+ printf("\t#%d: -> %d\n", i, r->class[i]->num);
+ }
+ printf("END Index_Map:\n");
+}
+
+void
+dumpDimension(d) Dimension d;
+{
+ printf("BEGIN Dimension:\n");
+ printf("Relevant: ");
+ dumpRelevant(d->relevant);
+ printf("\n");
+ dumpIndex_Map(&d->index_map);
+ dumpMapping(d->map);
+ printf("MaxSize of dimension = %d\n", d->max_size);
+ printf("END Dimension\n");
+}
+
+void
+dumpTable(t, full) Table t; int full;
+{
+ int i;
+
+ if (!t) {
+ printf("NO Table yet.\n");
+ return;
+ }
+ printf("BEGIN Table:\n");
+ if (full) {
+ dumpOperator(t->op, 0);
+ }
+ for (i = 0; i < t->op->arity; i++) {
+ printf("BEGIN dimension(%d)\n", i);
+ dumpDimension(t->dimen[i]);
+ printf("END dimension(%d)\n", i);
+ }
+ dumpTransition(t);
+ printf("END Table:\n");
+}
+
+void
+dumpTransition(t) Table t;
+{
+ int i,j;
+
+ switch (t->op->arity) {
+ case 0:
+ printf("{ %d }", t->transition[0]->num);
+ break;
+ case 1:
+ printf("{");
+ for (i = 0; i < t->dimen[0]->map->count; i++) {
+ if (i > 0) {
+ printf(",");
+ }
+ printf("%5d", t->transition[i]->num);
+ }
+ printf("}");
+ break;
+ case 2:
+ printf("{");
+ for (i = 0; i < t->dimen[0]->map->count; i++) {
+ if (i > 0) {
+ printf(",");
+ }
+ printf("\n");
+ printf("{");
+ for (j = 0; j < t->dimen[1]->map->count; j++) {
+ Item_Set *ts = transLval(t, i, j);
+ if (j > 0) {
+ printf(",");
+ }
+ printf("%5d", (*ts)->num);
+ }
+ printf("}");
+ }
+ printf("\n}\n");
+ break;
+ default:
+ assert(0);
+ }
+}
diff --git a/llvm/utils/Burg/trim.c b/llvm/utils/Burg/trim.c
new file mode 100644
index 00000000000..05ee2d0f646
--- /dev/null
+++ b/llvm/utils/Burg/trim.c
@@ -0,0 +1,412 @@
+char rcsid_trim[] = "$Id$";
+
+#include <stdio.h>
+#include "b.h"
+#include "fe.h"
+
+Relation *allpairs;
+
+int trimflag = 0;
+int debugTrim = 0;
+
+static void siblings ARGS((int, int));
+static void findAllNexts ARGS((void));
+static Relation *newAllPairs ARGS((void));
+
+static void
+siblings(i, j) int i; int j;
+{
+ int k;
+ List pl;
+ DeltaCost Max;
+ int foundmax;
+
+ allpairs[i][j].sibComputed = 1;
+
+ if (i == 1) {
+ return; /* never trim start symbol */
+ }
+ if (i==j) {
+ return;
+ }
+
+ ZEROCOST(Max);
+ foundmax = 0;
+
+ for (k = 1; k < max_nonterminal; k++) {
+ DeltaCost tmp;
+
+ if (k==i || k==j) {
+ continue;
+ }
+ if (!allpairs[k][i].rule) {
+ continue;
+ }
+ if (!allpairs[k][j].rule) {
+ return;
+ }
+ ASSIGNCOST(tmp, allpairs[k][j].chain);
+ MINUSCOST(tmp, allpairs[k][i].chain);
+ if (foundmax) {
+ if (LESSCOST(Max, tmp)) {
+ ASSIGNCOST(Max, tmp);
+ }
+ } else {
+ foundmax = 1;
+ ASSIGNCOST(Max, tmp);
+ }
+ }
+
+ for (pl = rules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ Operator op = p->pat->op;
+ List oprule;
+ DeltaCost Min;
+ int foundmin;
+
+ if (!op) {
+ continue;
+ }
+ switch (op->arity) {
+ case 0:
+ continue;
+ case 1:
+ if (!allpairs[p->pat->children[0]->num ][ i].rule) {
+ continue;
+ }
+ foundmin = 0;
+ for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+ Rule s = (Rule) oprule->x;
+ DeltaPtr Cx;
+ DeltaPtr Csj;
+ DeltaPtr Cpi;
+ DeltaCost tmp;
+
+ if (!allpairs[p->lhs->num ][ s->lhs->num].rule
+ || !allpairs[s->pat->children[0]->num ][ j].rule) {
+ continue;
+ }
+ Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+ Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+ Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+ ASSIGNCOST(tmp, Cx);
+ ADDCOST(tmp, s->delta);
+ ADDCOST(tmp, Csj);
+ MINUSCOST(tmp, Cpi);
+ MINUSCOST(tmp, p->delta);
+ if (foundmin) {
+ if (LESSCOST(tmp, Min)) {
+ ASSIGNCOST(Min, tmp);
+ }
+ } else {
+ foundmin = 1;
+ ASSIGNCOST(Min, tmp);
+ }
+ }
+ if (!foundmin) {
+ return;
+ }
+ if (foundmax) {
+ if (LESSCOST(Max, Min)) {
+ ASSIGNCOST(Max, Min);
+ }
+ } else {
+ foundmax = 1;
+ ASSIGNCOST(Max, Min);
+ }
+ break;
+ case 2:
+ /* do first dimension */
+ if (allpairs[p->pat->children[0]->num ][ i].rule) {
+ foundmin = 0;
+ for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+ Rule s = (Rule) oprule->x;
+ DeltaPtr Cx;
+ DeltaPtr Cb;
+ DeltaPtr Csj;
+ DeltaPtr Cpi;
+ DeltaCost tmp;
+
+ if (allpairs[p->lhs->num ][ s->lhs->num].rule
+ && allpairs[s->pat->children[0]->num ][ j].rule
+ && allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].rule) {
+ Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+ Csj= allpairs[s->pat->children[0]->num ][ j].chain;
+ Cpi= allpairs[p->pat->children[0]->num ][ i].chain;
+ Cb = allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].chain;
+ ASSIGNCOST(tmp, Cx);
+ ADDCOST(tmp, s->delta);
+ ADDCOST(tmp, Csj);
+ ADDCOST(tmp, Cb);
+ MINUSCOST(tmp, Cpi);
+ MINUSCOST(tmp, p->delta);
+ if (foundmin) {
+ if (LESSCOST(tmp, Min)) {
+ ASSIGNCOST(Min, tmp);
+ }
+ } else {
+ foundmin = 1;
+ ASSIGNCOST(Min, tmp);
+ }
+ }
+ }
+ if (!foundmin) {
+ return;
+ }
+ if (foundmax) {
+ if (LESSCOST(Max, Min)) {
+ ASSIGNCOST(Max, Min);
+ }
+ } else {
+ foundmax = 1;
+ ASSIGNCOST(Max, Min);
+ }
+ }
+ /* do second dimension */
+ if (allpairs[p->pat->children[1]->num ][ i].rule) {
+ foundmin = 0;
+ for (oprule = op->table->rules; oprule; oprule = oprule->next) {
+ Rule s = (Rule) oprule->x;
+ DeltaPtr Cx;
+ DeltaPtr Cb;
+ DeltaPtr Csj;
+ DeltaPtr Cpi;
+ DeltaCost tmp;
+
+ if (allpairs[p->lhs->num ][ s->lhs->num].rule
+ && allpairs[s->pat->children[1]->num ][ j].rule
+ && allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].rule) {
+ Cx = allpairs[p->lhs->num ][ s->lhs->num].chain;
+ Csj= allpairs[s->pat->children[1]->num ][ j].chain;
+ Cpi= allpairs[p->pat->children[1]->num ][ i].chain;
+ Cb = allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].chain;
+ ASSIGNCOST(tmp, Cx);
+ ADDCOST(tmp, s->delta);
+ ADDCOST(tmp, Csj);
+ ADDCOST(tmp, Cb);
+ MINUSCOST(tmp, Cpi);
+ MINUSCOST(tmp, p->delta);
+ if (foundmin) {
+ if (LESSCOST(tmp, Min)) {
+ ASSIGNCOST(Min, tmp);
+ }
+ } else {
+ foundmin = 1;
+ ASSIGNCOST(Min, tmp);
+ }
+ }
+ }
+ if (!foundmin) {
+ return;
+ }
+ if (foundmax) {
+ if (LESSCOST(Max, Min)) {
+ ASSIGNCOST(Max, Min);
+ }
+ } else {
+ foundmax = 1;
+ ASSIGNCOST(Max, Min);
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ allpairs[i ][ j].sibFlag = foundmax;
+ ASSIGNCOST(allpairs[i ][ j].sibling, Max);
+}
+
+static void
+findAllNexts()
+{
+ int i,j;
+ int last;
+
+ for (i = 1; i < max_nonterminal; i++) {
+ last = 0;
+ for (j = 1; j < max_nonterminal; j++) {
+ if (allpairs[i ][j].rule) {
+ allpairs[i ][ last].nextchain = j;
+ last = j;
+ }
+ }
+ }
+ /*
+ for (i = 1; i < max_nonterminal; i++) {
+ last = 0;
+ for (j = 1; j < max_nonterminal; j++) {
+ if (allpairs[i ][j].sibFlag) {
+ allpairs[i ][ last].nextsibling = j;
+ last = j;
+ }
+ }
+ }
+ */
+}
+
+static Relation *
+newAllPairs()
+{
+ int i;
+ Relation *rv;
+
+ rv = (Relation*) zalloc(max_nonterminal * sizeof(Relation));
+ for (i = 0; i < max_nonterminal; i++) {
+ rv[i] = (Relation) zalloc(max_nonterminal * sizeof(struct relation));
+ }
+ return rv;
+}
+
+void
+findAllPairs()
+{
+ List pl;
+ int changes;
+ int j;
+
+ allpairs = newAllPairs();
+ for (pl = chainrules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ NonTerminalNum rhs = p->pat->children[0]->num;
+ NonTerminalNum lhs = p->lhs->num;
+ Relation r = &allpairs[lhs ][ rhs];
+
+ if (LESSCOST(p->delta, r->chain)) {
+ ASSIGNCOST(r->chain, p->delta);
+ r->rule = p;
+ }
+ }
+ for (j = 1; j < max_nonterminal; j++) {
+ Relation r = &allpairs[j ][ j];
+ ZEROCOST(r->chain);
+ r->rule = &stub_rule;
+ }
+ changes = 1;
+ while (changes) {
+ changes = 0;
+ for (pl = chainrules; pl; pl = pl->next) {
+ Rule p = (Rule) pl->x;
+ NonTerminalNum rhs = p->pat->children[0]->num;
+ NonTerminalNum lhs = p->lhs->num;
+ int i;
+
+ for (i = 1; i < max_nonterminal; i++) {
+ Relation r = &allpairs[rhs ][ i];
+ Relation s = &allpairs[lhs ][ i];
+ DeltaCost dc;
+ if (!r->rule) {
+ continue;
+ }
+ ASSIGNCOST(dc, p->delta);
+ ADDCOST(dc, r->chain);
+ if (!s->rule || LESSCOST(dc, s->chain)) {
+ s->rule = p;
+ ASSIGNCOST(s->chain, dc);
+ changes = 1;
+ }
+ }
+ }
+ }
+ findAllNexts();
+}
+
+void
+trim(t) Item_Set t;
+{
+ int m,n;
+ static short *vec = 0;
+ int last;
+
+ assert(!t->closed);
+ debug(debugTrim, printf("Begin Trim\n"));
+ debug(debugTrim, dumpItem_Set(t));
+
+ last = 0;
+ if (!vec) {
+ vec = (short*) zalloc(max_nonterminal * sizeof(*vec));
+ }
+ for (m = 1; m < max_nonterminal; m++) {
+ if (t->virgin[m].rule) {
+ vec[last++] = m;
+ }
+ }
+ for (m = 0; m < last; m++) {
+ DeltaCost tmp;
+ int j;
+ int i;
+
+ i = vec[m];
+
+ for (j = allpairs[i ][ 0].nextchain; j; j = allpairs[i ][ j].nextchain) {
+
+ if (i == j) {
+ continue;
+ }
+ if (!t->virgin[j].rule) {
+ continue;
+ }
+ ASSIGNCOST(tmp, t->virgin[j].delta);
+ ADDCOST(tmp, allpairs[i ][ j].chain);
+ if (!LESSCOST(t->virgin[i].delta, tmp)) {
+ t->virgin[i].rule = 0;
+ ZEROCOST(t->virgin[i].delta);
+ debug(debugTrim, printf("Trimmed Chain (%d,%d)\n", i,j));
+ goto outer;
+ }
+
+ }
+ if (!trimflag) {
+ continue;
+ }
+ for (n = 0; n < last; n++) {
+ j = vec[n];
+ if (i == j) {
+ continue;
+ }
+
+ if (!t->virgin[j].rule) {
+ continue;
+ }
+
+ if (!allpairs[i][j].sibComputed) {
+ siblings(i,j);
+ }
+ if (!allpairs[i][j].sibFlag) {
+ continue;
+ }
+ ASSIGNCOST(tmp, t->virgin[j].delta);
+ ADDCOST(tmp, allpairs[i ][ j].sibling);
+ if (!LESSCOST(t->virgin[i].delta, tmp)) {
+ t->virgin[i].rule = 0;
+ ZEROCOST(t->virgin[i].delta);
+ goto outer;
+ }
+ }
+
+ outer: ;
+ }
+
+ debug(debugTrim, dumpItem_Set(t));
+ debug(debugTrim, printf("End Trim\n"));
+}
+
+void
+dumpRelation(r) Relation r;
+{
+ printf("{ %d %ld %d %ld }", r->rule->erulenum, (long) r->chain, r->sibFlag, (long) r->sibling);
+}
+
+void
+dumpAllPairs()
+{
+ int i,j;
+
+ printf("Dumping AllPairs\n");
+ for (i = 1; i < max_nonterminal; i++) {
+ for (j = 1; j < max_nonterminal; j++) {
+ dumpRelation(&allpairs[i ][j]);
+ }
+ printf("\n");
+ }
+}
diff --git a/llvm/utils/Burg/zalloc.c b/llvm/utils/Burg/zalloc.c
new file mode 100644
index 00000000000..9128e4280f2
--- /dev/null
+++ b/llvm/utils/Burg/zalloc.c
@@ -0,0 +1,35 @@
+char rcsid_zalloc[] = "$Id$";
+
+#include <stdio.h>
+#include <string.h>
+#include "b.h"
+
+extern void exit ARGS((int));
+extern void free ARGS((void *));
+extern void *malloc ARGS((unsigned));
+
+int
+fatal(const char *name, int line)
+{
+ fprintf(stderr, "assertion failed: file %s, line %d\n", name, line);
+ exit(1);
+ return 0;
+}
+
+void *
+zalloc(size) unsigned int size;
+{
+ void *t = (void *) malloc(size);
+ if (!t) {
+ fprintf(stderr, "Malloc failed---PROGRAM ABORTED\n");
+ exit(1);
+ }
+ memset(t, 0, size);
+ return t;
+}
+
+void
+zfree(p) void *p;
+{
+ free(p);
+}
diff --git a/llvm/utils/Makefile b/llvm/utils/Makefile
new file mode 100644
index 00000000000..512cc9e06bb
--- /dev/null
+++ b/llvm/utils/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ..
+
+DIRS = Burg TableGen
+
+include $(LEVEL)/Makefile.common
+
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
new file mode 100644
index 00000000000..98976c73363
--- /dev/null
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -0,0 +1,217 @@
+//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
+//
+// FIXME: Document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeEmitterGen.h"
+#include "Record.h"
+#include "Support/Debug.h"
+
+void CodeEmitterGen::run(std::ostream &o) {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ EmitSourceFileHeader("Machine Code Emitter", o);
+
+ std::string Namespace = "V9::";
+ std::string ClassName = "SparcV9CodeEmitter::";
+
+ //const std::string &Namespace = Inst->getValue("Namespace")->getName();
+ o << "unsigned " << ClassName
+ << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
+ << " unsigned Value = 0;\n"
+ << " DEBUG(std::cerr << MI);\n"
+ << " switch (MI.getOpcode()) {\n";
+ for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
+ I != E; ++I) {
+ Record *R = *I;
+ o << " case " << Namespace << R->getName() << ": {\n"
+ << " DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ unsigned Value = 0;
+ const std::vector<RecordVal> &Vals = R->getValues();
+
+ DEBUG(o << " // prefilling: ");
+ // Start by filling in fixed values...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
+ Value |= B->getValue() << (e-i-1);
+ DEBUG(o << B->getValue());
+ } else {
+ DEBUG(o << "0");
+ }
+ }
+ DEBUG(o << "\n");
+
+ DEBUG(o << " // " << *R->getValue("Inst") << "\n");
+ o << " Value = " << Value << "U;\n\n";
+
+ // Loop over all of the fields in the instruction determining which are the
+ // operands to the instruction.
+ //
+ unsigned op = 0;
+ std::map<std::string, unsigned> OpOrder;
+ std::map<std::string, bool> OpContinuous;
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
+ // Is the operand continuous? If so, we can just mask and OR it in
+ // instead of doing it bit-by-bit, saving a lot in runtime cost.
+ const BitsInit *InstInit = BI;
+ int beginBitInVar = -1, endBitInVar = -1;
+ int beginBitInInst = -1, endBitInInst = -1;
+ bool continuous = true;
+
+ for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
+ if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ // only process the current variable
+ if (VI->getName() != Vals[i].getName())
+ continue;
+
+ if (beginBitInVar == -1)
+ beginBitInVar = VBI->getBitNum();
+
+ if (endBitInVar == -1)
+ endBitInVar = VBI->getBitNum();
+ else {
+ if (endBitInVar == (int)VBI->getBitNum() + 1)
+ endBitInVar = VBI->getBitNum();
+ else {
+ continuous = false;
+ break;
+ }
+ }
+
+ if (beginBitInInst == -1)
+ beginBitInInst = bit;
+ if (endBitInInst == -1)
+ endBitInInst = bit;
+ else {
+ if (endBitInInst == bit + 1)
+ endBitInInst = bit;
+ else {
+ continuous = false;
+ break;
+ }
+ }
+
+ // maintain same distance between bits in field and bits in
+ // instruction. if the relative distances stay the same
+ // throughout,
+ if (beginBitInVar - (int)VBI->getBitNum() !=
+ beginBitInInst - bit) {
+ continuous = false;
+ break;
+ }
+ }
+ }
+ }
+
+ // If we have found no bit in "Inst" which comes from this field, then
+ // this is not an operand!!
+ if (beginBitInInst != -1) {
+ o << " // op" << op << ": " << Vals[i].getName() << "\n"
+ << " int64_t op" << op
+ <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
+ //<< " MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
+ OpOrder[Vals[i].getName()] = op++;
+
+ DEBUG(o << " // Var: begin = " << beginBitInVar
+ << ", end = " << endBitInVar
+ << "; Inst: begin = " << beginBitInInst
+ << ", end = " << endBitInInst << "\n");
+
+ if (continuous) {
+ DEBUG(o << " // continuous: op" << OpOrder[Vals[i].getName()]
+ << "\n");
+
+ // Mask off the right bits
+ // Low mask (ie. shift, if necessary)
+ assert(endBitInVar >= 0 && "Negative shift amount in masking!");
+ if (endBitInVar != 0) {
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " >>= " << endBitInVar << ";\n";
+ beginBitInVar -= endBitInVar;
+ endBitInVar = 0;
+ }
+
+ // High mask
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";
+
+ // Shift the value to the correct place (according to place in inst)
+ assert(endBitInInst >= 0 && "Negative shift amount in inst position!");
+ if (endBitInInst != 0)
+ o << " op" << OpOrder[Vals[i].getName()]
+ << " <<= " << endBitInInst << ";\n";
+
+ // Just OR in the result
+ o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
+ }
+
+ // otherwise, will be taken care of in the loop below using this
+ // value:
+ OpContinuous[Vals[i].getName()] = continuous;
+ }
+ }
+ }
+
+ for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
+ if (Vals[f].getPrefix()) {
+ BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
+
+ // Scan through the field looking for bit initializers of the current
+ // variable...
+ for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
+ if (BitInit *BI = dynamic_cast<BitInit*>(FieldInitializer->getBit(i)))
+ {
+ DEBUG(o << " // bit init: f: " << f << ", i: " << i << "\n");
+ } else if (UnsetInit *UI =
+ dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) {
+ DEBUG(o << " // unset init: f: " << f << ", i: " << i << "\n");
+ } else if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ // If the bits of the field are laid out consecutively in the
+ // instruction, then instead of separately ORing in bits, just
+ // mask and shift the entire field for efficiency.
+ if (OpContinuous[VI->getName()]) {
+ // already taken care of in the loop above, thus there is no
+ // need to individually OR in the bits
+
+ // for debugging, output the regular version anyway, commented
+ DEBUG(o << " // Value |= getValueBit(op"
+ << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
+ << ")" << " << " << i << ";\n");
+ } else {
+ o << " Value |= getValueBit(op" << OpOrder[VI->getName()]
+ << ", " << VBI->getBitNum()
+ << ")" << " << " << i << ";\n";
+ }
+ } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
+ // FIXME: implement this!
+ o << "FIELD INIT not implemented yet!\n";
+ } else {
+ o << "Error: UNIMPLEMENTED\n";
+ }
+ }
+ }
+ }
+ }
+
+ o << " break;\n"
+ << " }\n";
+ }
+
+ o << " default:\n"
+ << " std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
+ << " abort();\n"
+ << " }\n"
+ << " return Value;\n"
+ << "}\n";
+}
diff --git a/llvm/utils/TableGen/CodeEmitterGen.h b/llvm/utils/TableGen/CodeEmitterGen.h
new file mode 100644
index 00000000000..4b87da5067e
--- /dev/null
+++ b/llvm/utils/TableGen/CodeEmitterGen.h
@@ -0,0 +1,24 @@
+//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===//
+//
+// FIXME: document
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEMITTERGEN_H
+#define CODEMITTERGEN_H
+
+#include "TableGenBackend.h"
+
+class CodeEmitterGen : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ CodeEmitterGen(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the code emitter
+ void run(std::ostream &o);
+private:
+ void emitMachineOpEmitter(std::ostream &o, const std::string &Namespace);
+ void emitGetValueBit(std::ostream &o, const std::string &Namespace);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/CodeGenWrappers.cpp b/llvm/utils/TableGen/CodeGenWrappers.cpp
new file mode 100644
index 00000000000..61c3abc2971
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenWrappers.cpp
@@ -0,0 +1,89 @@
+//===- CodeGenWrappers.cpp - Code Generation Class Wrappers -----*- C++ -*-===//
+//
+// These classes wrap target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes throw exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenWrappers.h"
+#include "Record.h"
+
+/// getValueType - Return the MCV::ValueType that the specified TableGen record
+/// corresponds to.
+MVT::ValueType getValueType(Record *Rec) {
+ return (MVT::ValueType)Rec->getValueAsInt("Value");
+}
+
+std::string getName(MVT::ValueType T) {
+ switch (T) {
+ case MVT::Other: return "UNKNOWN";
+ case MVT::i1: return "i1";
+ case MVT::i8: return "i8";
+ case MVT::i16: return "i16";
+ case MVT::i32: return "i32";
+ case MVT::i64: return "i64";
+ case MVT::i128: return "i128";
+ case MVT::f32: return "f32";
+ case MVT::f64: return "f64";
+ case MVT::f80: return "f80";
+ case MVT::f128: return "f128";
+ case MVT::isVoid:return "void";
+ default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ }
+}
+
+std::string getEnumName(MVT::ValueType T) {
+ switch (T) {
+ case MVT::Other: return "Other";
+ case MVT::i1: return "i1";
+ case MVT::i8: return "i8";
+ case MVT::i16: return "i16";
+ case MVT::i32: return "i32";
+ case MVT::i64: return "i64";
+ case MVT::i128: return "i128";
+ case MVT::f32: return "f32";
+ case MVT::f64: return "f64";
+ case MVT::f80: return "f80";
+ case MVT::f128: return "f128";
+ case MVT::isVoid:return "isVoid";
+ default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ }
+}
+
+
+std::ostream &operator<<(std::ostream &OS, MVT::ValueType T) {
+ return OS << getName(T);
+}
+
+
+
+/// getTarget - Return the current instance of the Target class.
+///
+CodeGenTarget::CodeGenTarget() {
+ std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
+ if (Targets.size() != 1)
+ throw std::string("ERROR: Multiple subclasses of Target defined!");
+ TargetRec = Targets[0];
+
+ // Read in all of the CalleeSavedRegisters...
+ ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters");
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)))
+ CalleeSavedRegisters.push_back(DI->getDef());
+ else
+ throw "Target: " + TargetRec->getName() +
+ " expected register definition in CalleeSavedRegisters list!";
+
+ PointerType = getValueType(TargetRec->getValueAsDef("PointerType"));
+}
+
+
+const std::string &CodeGenTarget::getName() const {
+ return TargetRec->getName();
+}
+
+Record *CodeGenTarget::getInstructionSet() const {
+ return TargetRec->getValueAsDef("InstructionSet");
+}
diff --git a/llvm/utils/TableGen/CodeGenWrappers.h b/llvm/utils/TableGen/CodeGenWrappers.h
new file mode 100644
index 00000000000..00ca3fcc603
--- /dev/null
+++ b/llvm/utils/TableGen/CodeGenWrappers.h
@@ -0,0 +1,56 @@
+//===- CodeGenWrappers.h - Code Generation Class Wrappers -------*- C++ -*-===//
+//
+// These classes wrap target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes throw exceptions on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGENWRAPPERS_H
+#define CODEGENWRAPPERS_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include <iosfwd>
+#include <string>
+#include <vector>
+class Record;
+class RecordKeeper;
+
+/// getValueType - Return the MVT::ValueType that the specified TableGen record
+/// corresponds to.
+MVT::ValueType getValueType(Record *Rec);
+
+std::ostream &operator<<(std::ostream &OS, MVT::ValueType T);
+std::string getName(MVT::ValueType T);
+std::string getEnumName(MVT::ValueType T);
+
+
+/// CodeGenTarget - This class corresponds to the Target class in the .td files.
+///
+class CodeGenTarget {
+ Record *TargetRec;
+ std::vector<Record*> CalleeSavedRegisters;
+ MVT::ValueType PointerType;
+
+public:
+ CodeGenTarget();
+
+ Record *getTargetRecord() const { return TargetRec; }
+ const std::string &getName() const;
+
+ const std::vector<Record*> &getCalleeSavedRegisters() const {
+ return CalleeSavedRegisters;
+ }
+
+ MVT::ValueType getPointerType() const { return PointerType; }
+
+ // getInstructionSet - Return the InstructionSet object...
+ Record *getInstructionSet() const;
+
+ // getInstructionSet - Return the CodeGenInstructionSet object for this
+ // target, lazily reading it from the record keeper as needed.
+ // CodeGenInstructionSet *getInstructionSet -
+};
+
+#endif
diff --git a/llvm/utils/TableGen/FileLexer.l b/llvm/utils/TableGen/FileLexer.l
new file mode 100644
index 00000000000..64ed4c625a9
--- /dev/null
+++ b/llvm/utils/TableGen/FileLexer.l
@@ -0,0 +1,222 @@
+/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===//
+//
+// This file defines a simple flex scanner for TableGen files. This is pretty
+// straight-forward, except for the magic to handle file inclusion.
+//
+//===----------------------------------------------------------------------===*/
+
+%option prefix="File"
+%option yylineno
+%option nostdinit
+%option never-interactive
+%option batch
+%option nodefault
+%option 8bit
+%option outfile="Lexer.cpp"
+%option ecs
+%option noreject
+%option noyymore
+
+%x comment
+
+%{
+#include "Record.h"
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+#include "FileParser.h"
+
+// Global variable recording the location of the include directory
+std::string IncludeDirectory;
+
+// ParseInt - This has to handle the special case of binary numbers 0b0101
+static int ParseInt(const char *Str) {
+ if (Str[0] == '0' && Str[1] == 'b')
+ return strtol(Str+2, 0, 2);
+ return strtol(Str, 0, 0);
+}
+
+static int CommentDepth = 0;
+
+struct IncludeRec {
+ std::string Filename;
+ FILE *File;
+ unsigned LineNo;
+ YY_BUFFER_STATE Buffer;
+
+ IncludeRec(const std::string &FN, FILE *F)
+ : Filename(FN), File(F), LineNo(0){
+ }
+};
+
+static std::vector<IncludeRec> IncludeStack;
+
+
+std::ostream &err() {
+ if (IncludeStack.empty())
+ return std::cerr << "At end of input: ";
+
+ for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i)
+ std::cerr << "Included from " << IncludeStack[i].Filename << ":"
+ << IncludeStack[i].LineNo << ":\n";
+ return std::cerr << "Parsing " << IncludeStack.back().Filename << ":"
+ << Filelineno << ": ";
+}
+
+
+int Fileparse();
+
+//
+// Function: ParseFile()
+//
+// Description:
+// This function begins the parsing of the specified tablegen file.
+//
+// Inputs:
+// Filename - A string containing the name of the file to parse.
+// IncludeDir - A string containing the directory from which include
+// files can be found.
+//
+void ParseFile(const std::string &Filename, const std::string & IncludeDir) {
+ FILE *F = stdin;
+ if (Filename != "-") {
+ F = fopen(Filename.c_str(), "r");
+
+ if (F == 0) {
+ std::cerr << "Could not open input file '" + Filename + "'!\n";
+ exit (1);
+ }
+ IncludeStack.push_back(IncludeRec(Filename, F));
+ } else {
+ IncludeStack.push_back(IncludeRec("<stdin>", stdin));
+ }
+
+ //
+ // Record the location of the include directory so that the lexer can find
+ // it later.
+ //
+ IncludeDirectory = IncludeDir;
+
+ Filein = F;
+ Filelineno = 1;
+ Fileparse();
+ Filein = stdin;
+}
+
+// HandleInclude - This function is called when an include directive is
+// encountered in the input stream...
+static void HandleInclude(const char *Buffer) {
+ unsigned Length = yyleng;
+ assert(Buffer[Length-1] == '"');
+ Buffer += strlen("include ");
+ Length -= strlen("include ");
+ while (*Buffer != '"') {
+ ++Buffer;
+ --Length;
+ }
+ assert(Length >= 2 && "Double quotes not found?");
+ std::string Filename(Buffer+1, Buffer+Length-1);
+ //std::cerr << "Filename = '" << Filename << "'\n";
+
+ // Save the line number and lex buffer of the includer...
+ IncludeStack.back().LineNo = Filelineno;
+ IncludeStack.back().Buffer = YY_CURRENT_BUFFER;
+
+ // Open the new input file...
+ yyin = fopen(Filename.c_str(), "r");
+ if (yyin == 0) {
+ //
+ // If we couldn't find the file in the current directory, look for it in
+ // the include directories.
+ //
+ // NOTE:
+ // Right now, there is only one directory. We need to eventually add
+ // support for more.
+ //
+ Filename = IncludeDirectory + "/" + Filename;
+ yyin = fopen(Filename.c_str(), "r");
+ if (yyin == 0) {
+ err() << "Could not find include file '" << Filename << "'!\n";
+ abort();
+ }
+ }
+
+ // Add the file to our include stack...
+ IncludeStack.push_back(IncludeRec(Filename, yyin));
+ Filelineno = 1; // Reset line numbering...
+ //yyrestart(yyin); // Start lexing the new file...
+
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+}
+
+
+// yywrap - This is called when the lexer runs out of input in one of the files.
+// Switch back to an includer if an includee has run out of input.
+//
+extern "C"
+int yywrap() {
+ if (IncludeStack.back().File != stdin)
+ fclose(IncludeStack.back().File);
+ IncludeStack.pop_back();
+ if (IncludeStack.empty()) return 1; // Top-level file is done.
+
+ // Otherwise, we need to switch back to a file which included the current one.
+ Filelineno = IncludeStack.back().LineNo; // Restore current line number
+ yy_switch_to_buffer(IncludeStack.back().Buffer);
+ return 0;
+}
+
+%}
+
+Comment \/\/.*
+
+Identifier [a-zA-Z_][0-9a-zA-Z_]*
+Integer [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+
+CodeFragment \[\{([^}]+|\}[^\]])*\}\]
+StringVal \"[^"]*\"
+IncludeStr include[ \t\n]+\"[^"]*\"
+
+%%
+
+{Comment} { /* Ignore comments */ }
+
+{IncludeStr} { HandleInclude(yytext); }
+{CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2);
+ return CODEFRAGMENT; }
+
+int { return INT; }
+bit { return BIT; }
+bits { return BITS; }
+string { return STRING; }
+list { return LIST; }
+code { return CODE; }
+dag { return DAG; }
+
+class { return CLASS; }
+def { return DEF; }
+field { return FIELD; }
+let { return LET; }
+in { return IN; }
+
+{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng);
+ return ID; }
+${Identifier} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng);
+ return VARNAME; }
+
+{StringVal} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1);
+ return STRVAL; }
+
+{Integer} { Filelval.IntVal = ParseInt(Filetext); return INTVAL; }
+
+[ \t\n]+ { /* Ignore whitespace */ }
+
+
+"/*" { BEGIN(comment); CommentDepth++; }
+<comment>[^*/]* /* eat anything that's not a '*' or '/' */
+<comment>"*"+[^*/]* /* eat up '*'s not followed by '/'s */
+<comment>"/*" { ++CommentDepth; }
+<comment>"/"+[^*]* /* eat up /'s not followed by *'s */
+<comment>"*"+"/" { if (!--CommentDepth) { BEGIN(INITIAL); } }
+<comment><<EOF>> { err() << "Unterminated comment!\n"; abort(); }
+
+. { return Filetext[0]; }
+
+%%
diff --git a/llvm/utils/TableGen/FileParser.y b/llvm/utils/TableGen/FileParser.y
new file mode 100644
index 00000000000..728fcf222c6
--- /dev/null
+++ b/llvm/utils/TableGen/FileParser.y
@@ -0,0 +1,510 @@
+//===-- FileParser.y - Parser for TableGen files ----------------*- C++ -*-===//
+//
+// This file implements the bison parser for Table Generator files...
+//
+//===------------------------------------------------------------------------=//
+
+%{
+#include "Record.h"
+#include "Support/StringExtras.h"
+#include <algorithm>
+#include <cstdio>
+#define YYERROR_VERBOSE 1
+
+int yyerror(const char *ErrorMsg);
+int yylex();
+extern int Filelineno;
+static Record *CurRec = 0;
+
+typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy;
+
+struct LetRecord {
+ std::string Name;
+ std::vector<unsigned> Bits;
+ Init *Value;
+ bool HasBits;
+ LetRecord(const std::string &N, std::vector<unsigned> *B, Init *V)
+ : Name(N), Value(V), HasBits(B != 0) {
+ if (HasBits) Bits = *B;
+ }
+};
+
+static std::vector<std::vector<LetRecord> > LetStack;
+
+
+extern std::ostream &err();
+
+static void addValue(const RecordVal &RV) {
+ if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
+ // The value already exists in the class, treat this as a set...
+ if (ERV->setValue(RV.getValue())) {
+ err() << "New definition of '" << RV.getName() << "' of type '"
+ << *RV.getType() << "' is incompatible with previous "
+ << "definition of type '" << *ERV->getType() << "'!\n";
+ abort();
+ }
+ } else {
+ CurRec->addValue(RV);
+ }
+}
+
+static void addSuperClass(Record *SC) {
+ if (CurRec->isSubClassOf(SC)) {
+ err() << "Already subclass of '" << SC->getName() << "'!\n";
+ abort();
+ }
+ CurRec->addSuperClass(SC);
+}
+
+static void setValue(const std::string &ValName,
+ std::vector<unsigned> *BitList, Init *V) {
+ if (!V) return ;
+
+ RecordVal *RV = CurRec->getValue(ValName);
+ if (RV == 0) {
+ err() << "Value '" << ValName << "' unknown!\n";
+ abort();
+ }
+
+ // If we are assigning to a subset of the bits in the value... then we must be
+ // assigning to a field of BitsRecTy, which must have a BitsInit
+ // initializer...
+ //
+ if (BitList) {
+ BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
+ if (CurVal == 0) {
+ err() << "Value '" << ValName << "' is not a bits type!\n";
+ abort();
+ }
+
+ // Convert the incoming value to a bits type of the appropriate size...
+ Init *BI = V->convertInitializerTo(new BitsRecTy(BitList->size()));
+ if (BI == 0) {
+ V->convertInitializerTo(new BitsRecTy(BitList->size()));
+ err() << "Initializer '" << *V << "' not compatible with bit range!\n";
+ abort();
+ }
+
+ // We should have a BitsInit type now...
+ assert(dynamic_cast<BitsInit*>(BI) != 0 || &(std::cerr << *BI) == 0);
+ BitsInit *BInit = (BitsInit*)BI;
+
+ BitsInit *NewVal = new BitsInit(CurVal->getNumBits());
+
+ // Loop over bits, assigning values as appropriate...
+ for (unsigned i = 0, e = BitList->size(); i != e; ++i) {
+ unsigned Bit = (*BitList)[i];
+ if (NewVal->getBit(Bit)) {
+ err() << "Cannot set bit #" << Bit << " of value '" << ValName
+ << "' more than once!\n";
+ abort();
+ }
+ NewVal->setBit(Bit, BInit->getBit(i));
+ }
+
+ for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
+ if (NewVal->getBit(i) == 0)
+ NewVal->setBit(i, CurVal->getBit(i));
+
+ V = NewVal;
+ }
+
+ if (RV->setValue(V)) {
+ err() << "Value '" << ValName << "' of type '" << *RV->getType()
+ << "' is incompatible with initializer '" << *V << "'!\n";
+ abort();
+ }
+}
+
+static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) {
+ // Add all of the values in the subclass into the current class...
+ const std::vector<RecordVal> &Vals = SC->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ addValue(Vals[i]);
+
+ const std::vector<std::string> &TArgs = SC->getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are specified...
+ if (TArgs.size() < TemplateArgs.size()) {
+ err() << "ERROR: More template args specified than expected!\n";
+ abort();
+ } else { // This class expects template arguments...
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default as necessary.
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i < TemplateArgs.size()) { // A value is specified for this temp-arg?
+ // Set it now.
+ setValue(TArgs[i], 0, TemplateArgs[i]);
+ } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+ err() << "ERROR: Value not specified for template argument #"
+ << i << " (" << TArgs[i] << ") of subclass '" << SC->getName()
+ << "'!\n";
+ abort();
+ }
+ }
+ }
+
+
+ // Since everything went well, we can now set the "superclass" list for the
+ // current record.
+ const std::vector<Record*> &SCs = SC->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i)
+ addSuperClass(SCs[i]);
+ addSuperClass(SC);
+}
+
+
+%}
+
+%union {
+ std::string *StrVal;
+ int IntVal;
+ RecTy *Ty;
+ Init *Initializer;
+ std::vector<Init*> *FieldList;
+ std::vector<unsigned>*BitList;
+ Record *Rec;
+ SubClassRefTy *SubClassRef;
+ std::vector<SubClassRefTy> *SubClassList;
+ std::vector<std::pair<Init*, std::string> > *DagValueList;
+};
+
+%token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN
+%token <IntVal> INTVAL
+%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT
+
+%type <Ty> Type
+%type <Rec> ClassInst DefInst Object ObjectBody ClassID
+
+%type <SubClassRef> SubClassRef
+%type <SubClassList> ClassList ClassListNE
+%type <IntVal> OptPrefix
+%type <Initializer> Value OptValue
+%type <DagValueList> DagArgList DagArgListNE
+%type <FieldList> ValueList ValueListNE
+%type <BitList> BitList OptBitList RBitList
+%type <StrVal> Declaration OptID OptVarName
+
+%start File
+%%
+
+ClassID : ID {
+ $$ = Records.getClass(*$1);
+ if ($$ == 0) {
+ err() << "Couldn't find class '" << *$1 << "'!\n";
+ abort();
+ }
+ delete $1;
+ };
+
+
+// TableGen types...
+Type : STRING { // string type
+ $$ = new StringRecTy();
+ } | BIT { // bit type
+ $$ = new BitRecTy();
+ } | BITS '<' INTVAL '>' { // bits<x> type
+ $$ = new BitsRecTy($3);
+ } | INT { // int type
+ $$ = new IntRecTy();
+ } | LIST '<' Type '>' { // list<x> type
+ $$ = new ListRecTy($3);
+ } | CODE { // code type
+ $$ = new CodeRecTy();
+ } | DAG { // dag type
+ $$ = new DagRecTy();
+ } | ClassID { // Record Type
+ $$ = new RecordRecTy($1);
+ };
+
+OptPrefix : /*empty*/ { $$ = 0; } | FIELD { $$ = 1; };
+
+OptValue : /*empty*/ { $$ = 0; } | '=' Value { $$ = $2; };
+
+Value : INTVAL {
+ $$ = new IntInit($1);
+ } | STRVAL {
+ $$ = new StringInit(*$1);
+ delete $1;
+ } | CODEFRAGMENT {
+ $$ = new CodeInit(*$1);
+ delete $1;
+ } | '?' {
+ $$ = new UnsetInit();
+ } | '{' ValueList '}' {
+ BitsInit *Init = new BitsInit($2->size());
+ for (unsigned i = 0, e = $2->size(); i != e; ++i) {
+ struct Init *Bit = (*$2)[i]->convertInitializerTo(new BitRecTy());
+ if (Bit == 0) {
+ err() << "Element #" << i << " (" << *(*$2)[i]
+ << ") is not convertable to a bit!\n";
+ abort();
+ }
+ Init->setBit($2->size()-i-1, Bit);
+ }
+ $$ = Init;
+ delete $2;
+ } | ID {
+ if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) {
+ $$ = new VarInit(*$1, RV->getType());
+ } else if (Record *D = Records.getDef(*$1)) {
+ $$ = new DefInit(D);
+ } else {
+ err() << "Variable not defined: '" << *$1 << "'!\n";
+ abort();
+ }
+
+ delete $1;
+ } | Value '{' BitList '}' {
+ $$ = $1->convertInitializerBitRange(*$3);
+ if ($$ == 0) {
+ err() << "Invalid bit range for value '" << *$1 << "'!\n";
+ abort();
+ }
+ delete $3;
+ } | '[' ValueList ']' {
+ $$ = new ListInit(*$2);
+ delete $2;
+ } | Value '.' ID {
+ if (!$1->getFieldType(*$3)) {
+ err() << "Cannot access field '" << *$3 << "' of value '" << *$1 << "!\n";
+ abort();
+ }
+ $$ = new FieldInit($1, *$3);
+ delete $3;
+ } | '(' ID DagArgList ')' {
+ Record *D = Records.getDef(*$2);
+ if (D == 0) {
+ err() << "Invalid def '" << *$2 << "'!\n";
+ abort();
+ }
+ $$ = new DagInit(D, *$3);
+ delete $2; delete $3;
+ };
+
+OptVarName : /* empty */ {
+ $$ = new std::string();
+ }
+ | ':' VARNAME {
+ $$ = $2;
+ };
+
+DagArgListNE : Value OptVarName {
+ $$ = new std::vector<std::pair<Init*, std::string> >();
+ $$->push_back(std::make_pair($1, *$2));
+ delete $2;
+ }
+ | DagArgListNE ',' Value OptVarName {
+ $1->push_back(std::make_pair($3, *$4));
+ delete $4;
+ $$ = $1;
+ };
+
+DagArgList : /*empty*/ {
+ $$ = new std::vector<std::pair<Init*, std::string> >();
+ }
+ | DagArgListNE { $$ = $1; };
+
+
+RBitList : INTVAL {
+ $$ = new std::vector<unsigned>();
+ $$->push_back($1);
+ } | INTVAL '-' INTVAL {
+ if ($1 < $3 || $1 < 0 || $3 < 0) {
+ err() << "Invalid bit range: " << $1 << "-" << $3 << "!\n";
+ abort();
+ }
+ $$ = new std::vector<unsigned>();
+ for (int i = $1; i >= $3; --i)
+ $$->push_back(i);
+ } | INTVAL INTVAL {
+ $2 = -$2;
+ if ($1 < $2 || $1 < 0 || $2 < 0) {
+ err() << "Invalid bit range: " << $1 << "-" << $2 << "!\n";
+ abort();
+ }
+ $$ = new std::vector<unsigned>();
+ for (int i = $1; i >= $2; --i)
+ $$->push_back(i);
+ } | RBitList ',' INTVAL {
+ ($$=$1)->push_back($3);
+ } | RBitList ',' INTVAL '-' INTVAL {
+ if ($3 < $5 || $3 < 0 || $5 < 0) {
+ err() << "Invalid bit range: " << $3 << "-" << $5 << "!\n";
+ abort();
+ }
+ $$ = $1;
+ for (int i = $3; i >= $5; --i)
+ $$->push_back(i);
+ } | RBitList ',' INTVAL INTVAL {
+ $4 = -$4;
+ if ($3 < $4 || $3 < 0 || $4 < 0) {
+ err() << "Invalid bit range: " << $3 << "-" << $4 << "!\n";
+ abort();
+ }
+ $$ = $1;
+ for (int i = $3; i >= $4; --i)
+ $$->push_back(i);
+ };
+
+BitList : RBitList { $$ = $1; std::reverse($1->begin(), $1->end()); };
+
+OptBitList : /*empty*/ { $$ = 0; } | '{' BitList '}' { $$ = $2; };
+
+
+
+ValueList : /*empty*/ {
+ $$ = new std::vector<Init*>();
+ } | ValueListNE {
+ $$ = $1;
+ };
+
+ValueListNE : Value {
+ $$ = new std::vector<Init*>();
+ $$->push_back($1);
+ } | ValueListNE ',' Value {
+ ($$ = $1)->push_back($3);
+ };
+
+Declaration : OptPrefix Type ID OptValue {
+ addValue(RecordVal(*$3, $2, $1));
+ setValue(*$3, 0, $4);
+ $$ = $3;
+};
+
+BodyItem : Declaration ';' {
+ delete $1;
+} | LET ID OptBitList '=' Value ';' {
+ setValue(*$2, $3, $5);
+ delete $2;
+ delete $3;
+};
+
+BodyList : /*empty*/ | BodyList BodyItem;
+Body : ';' | '{' BodyList '}';
+
+SubClassRef : ClassID {
+ $$ = new SubClassRefTy($1, new std::vector<Init*>());
+ } | ClassID '<' ValueListNE '>' {
+ $$ = new SubClassRefTy($1, $3);
+ };
+
+ClassListNE : SubClassRef {
+ $$ = new std::vector<SubClassRefTy>();
+ $$->push_back(*$1);
+ delete $1;
+ }
+ | ClassListNE ',' SubClassRef {
+ ($$=$1)->push_back(*$3);
+ delete $3;
+ };
+
+ClassList : /*empty */ {
+ $$ = new std::vector<SubClassRefTy>();
+ }
+ | ':' ClassListNE {
+ $$ = $2;
+ };
+
+DeclListNE : Declaration {
+ CurRec->addTemplateArg(*$1);
+ delete $1;
+} | DeclListNE ',' Declaration {
+ CurRec->addTemplateArg(*$3);
+ delete $3;
+};
+
+TemplateArgList : '<' DeclListNE '>' {};
+OptTemplateArgList : /*empty*/ | TemplateArgList;
+
+OptID : ID { $$ = $1; } | /*empty*/ { $$ = new std::string(); };
+
+ObjectBody : OptID {
+ static unsigned AnonCounter = 0;
+ if ($1->empty())
+ *$1 = "anonymous."+utostr(AnonCounter++);
+ CurRec = new Record(*$1);
+ delete $1;
+ } OptTemplateArgList ClassList {
+ for (unsigned i = 0, e = $4->size(); i != e; ++i) {
+ addSubClass((*$4)[i].first, *(*$4)[i].second);
+ // Delete the template arg values for the class
+ delete (*$4)[i].second;
+ }
+
+ // Process any variables on the set stack...
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ setValue(LetStack[i][j].Name,
+ LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0,
+ LetStack[i][j].Value);
+ } Body {
+ CurRec->resolveReferences();
+
+ // Now that all of the references have been resolved, we can delete template
+ // arguments for superclasses, so they don't pollute our record, and so that
+ // their names won't conflict with later uses of the name...
+ for (unsigned i = 0, e = $4->size(); i != e; ++i) {
+ Record *SuperClass = (*$4)[i].first;
+ for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i)
+ CurRec->removeValue(SuperClass->getTemplateArgs()[i]);
+ }
+ delete $4; // Delete the class list...
+
+ $$ = CurRec;
+ CurRec = 0;
+};
+
+ClassInst : CLASS ObjectBody {
+ if (Records.getClass($2->getName())) {
+ err() << "Class '" << $2->getName() << "' already defined!\n";
+ abort();
+ }
+ Records.addClass($$ = $2);
+};
+
+DefInst : DEF ObjectBody {
+ if (!$2->getTemplateArgs().empty()) {
+ err() << "Def '" << $2->getName()
+ << "' is not permitted to have template arguments!\n";
+ abort();
+ }
+ // If ObjectBody has template arguments, it's an error.
+ if (Records.getDef($2->getName())) {
+ err() << "Def '" << $2->getName() << "' already defined!\n";
+ abort();
+ }
+ Records.addDef($$ = $2);
+};
+
+
+Object : ClassInst | DefInst;
+
+LETItem : ID OptBitList '=' Value {
+ LetStack.back().push_back(LetRecord(*$1, $2, $4));
+ delete $1; delete $2;
+};
+
+LETList : LETItem | LETList ',' LETItem;
+
+// LETCommand - A 'LET' statement start...
+LETCommand : LET { LetStack.push_back(std::vector<LetRecord>()); } LETList IN;
+
+// Support Set commands wrapping objects... both with and without braces.
+Object : LETCommand '{' ObjectList '}' {
+ LetStack.pop_back();
+ }
+ | LETCommand Object {
+ LetStack.pop_back();
+ };
+
+ObjectList : Object {} | ObjectList Object {};
+
+File : ObjectList {};
+
+%%
+
+int yyerror(const char *ErrorMsg) {
+ err() << "Error parsing: " << ErrorMsg << "\n";
+ abort();
+}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
new file mode 100644
index 00000000000..c794cd04418
--- /dev/null
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -0,0 +1,160 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrInfoEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+
+// runEnums - Print out enum values for all of the instructions.
+void InstrInfoEmitter::runEnums(std::ostream &OS) {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ if (Insts.size() == 0)
+ throw std::string("No 'Instruction' subclasses defined!");
+
+ std::string Namespace = Insts[0]->getValueAsString("Namespace");
+
+ EmitSourceFileHeader("Target Instruction Enum Values", OS);
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n";
+
+ CodeGenTarget Target;
+
+ // We must emit the PHI opcode first...
+ Record *InstrInfo = Target.getInstructionSet();
+ Record *PHI = InstrInfo->getValueAsDef("PHIInst");
+
+ OS << " " << PHI->getName() << ", \t// 0 (fixed for all targets)\n";
+
+ // Print out the rest of the instructions now...
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ if (Insts[i] != PHI)
+ OS << " " << Insts[i]->getName() << ", \t// " << i+1 << "\n";
+
+ OS << " };\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+}
+
+void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name,
+ std::ostream &OS) const {
+ OS << "static const unsigned " << Name << "[] = { ";
+ for (unsigned j = 0, e = LI->getSize(); j != e; ++j)
+ if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j)))
+ OS << getQualifiedName(DI->getDef()) << ", ";
+ else
+ throw "Illegal value in '" + Name + "' list!";
+ OS << "0 };\n";
+}
+
+
+// run - Emit the main instruction description records for the target...
+void InstrInfoEmitter::run(std::ostream &OS) {
+ EmitSourceFileHeader("Target Instruction Descriptors", OS);
+ CodeGenTarget Target;
+ const std::string &TargetName = Target.getName();
+ Record *InstrInfo = Target.getInstructionSet();
+ Record *PHI = InstrInfo->getValueAsDef("PHIInst");
+
+ std::vector<Record*> Instructions =
+ Records.getAllDerivedDefinitions("Instruction");
+
+ // Emit all of the instruction's implicit uses and defs...
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ Record *Inst = Instructions[i];
+ ListInit *LI = Inst->getValueAsListInit("Uses");
+ if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS);
+ LI = Inst->getValueAsListInit("Defs");
+ if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS);
+ }
+
+ OS << "\nstatic const TargetInstrDescriptor " << TargetName
+ << "Insts[] = {\n";
+ emitRecord(PHI, 0, InstrInfo, OS);
+
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
+ if (Instructions[i] != PHI)
+ emitRecord(Instructions[i], i+1, InstrInfo, OS);
+ OS << "};\n";
+}
+
+void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo,
+ std::ostream &OS) {
+ OS << " { \"" << R->getValueAsString("Name")
+ << "\",\t-1, -1, 0, false, 0, 0, 0, 0";
+
+ // Emit all of the target indepedent flags...
+ if (R->getValueAsBit("isReturn")) OS << "|M_RET_FLAG";
+ if (R->getValueAsBit("isBranch")) OS << "|M_BRANCH_FLAG";
+ if (R->getValueAsBit("isCall" )) OS << "|M_CALL_FLAG";
+ if (R->getValueAsBit("isTwoAddress")) OS << "|M_2_ADDR_FLAG";
+ if (R->getValueAsBit("isTerminator")) OS << "|M_TERMINATOR_FLAG";
+ OS << ", 0";
+
+ // Emit all of the target-specific flags...
+ ListInit *LI = InstrInfo->getValueAsListInit("TSFlagsFields");
+ ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
+ if (LI->getSize() != Shift->getSize())
+ throw "Lengths of " + InstrInfo->getName() +
+ ":(TargetInfoFields, TargetInfoPositions) must be equal!";
+
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ emitShiftedValue(R, dynamic_cast<StringInit*>(LI->getElement(i)),
+ dynamic_cast<IntInit*>(Shift->getElement(i)), OS);
+
+ OS << ", ";
+
+ // Emit the implicit uses and defs lists...
+ LI = R->getValueAsListInit("Uses");
+ if (!LI->getSize())
+ OS << "0, ";
+ else
+ OS << R->getName() << "ImpUses, ";
+
+ LI = R->getValueAsListInit("Defs");
+ if (!LI->getSize())
+ OS << "0 ";
+ else
+ OS << R->getName() << "ImpDefs ";
+
+ OS << " }, // Inst #" << Num << " = " << R->getName() << "\n";
+}
+
+void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
+ IntInit *ShiftInt, std::ostream &OS) {
+ if (Val == 0 || ShiftInt == 0)
+ throw std::string("Illegal value or shift amount in TargetInfo*!");
+ RecordVal *RV = R->getValue(Val->getValue());
+ int Shift = ShiftInt->getValue();
+
+ if (RV == 0 || RV->getValue() == 0)
+ throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!";
+
+ Init *Value = RV->getValue();
+ if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
+ if (BI->getValue()) OS << "|(1<<" << Shift << ")";
+ return;
+ } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
+ // Convert the Bits to an integer to print...
+ Init *I = BI->convertInitializerTo(new IntRecTy());
+ if (I)
+ if (IntInit *II = dynamic_cast<IntInit*>(I)) {
+ if (II->getValue())
+ OS << "|(" << II->getValue() << "<<" << Shift << ")";
+ return;
+ }
+
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
+ if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")";
+ return;
+ }
+
+ std::cerr << "Unhandled initializer: " << *Val << "\n";
+ throw "In record '" + R->getName() + "' for TSFlag emission.";
+}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.h b/llvm/utils/TableGen/InstrInfoEmitter.h
new file mode 100644
index 00000000000..400c0db16c6
--- /dev/null
+++ b/llvm/utils/TableGen/InstrInfoEmitter.h
@@ -0,0 +1,34 @@
+//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRINFO_EMITTER_H
+#define INSTRINFO_EMITTER_H
+
+#include "TableGenBackend.h"
+class StringInit;
+class IntInit;
+class ListInit;
+
+class InstrInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ InstrInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(std::ostream &OS);
+
+ // runEnums - Print out enum values for all of the instructions.
+ void runEnums(std::ostream &OS);
+private:
+ void printDefList(ListInit *LI, const std::string &Name,
+ std::ostream &OS) const;
+ void emitRecord(Record *R, unsigned Num, Record *InstrInfo, std::ostream &OS);
+ void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift,
+ std::ostream &OS);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/InstrSelectorEmitter.cpp b/llvm/utils/TableGen/InstrSelectorEmitter.cpp
new file mode 100644
index 00000000000..a3c535cad4e
--- /dev/null
+++ b/llvm/utils/TableGen/InstrSelectorEmitter.cpp
@@ -0,0 +1,1287 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InstrSelectorEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+#include "Support/Debug.h"
+#include "Support/StringExtras.h"
+#include <set>
+
+NodeType::ArgResultTypes NodeType::Translate(Record *R) {
+ const std::string &Name = R->getName();
+ if (Name == "DNVT_any") return Any;
+ if (Name == "DNVT_void") return Void;
+ if (Name == "DNVT_val" ) return Val;
+ if (Name == "DNVT_arg0") return Arg0;
+ if (Name == "DNVT_arg1") return Arg1;
+ if (Name == "DNVT_ptr" ) return Ptr;
+ if (Name == "DNVT_i8" ) return I8;
+ throw "Unknown DagNodeValType '" + Name + "'!";
+}
+
+
+//===----------------------------------------------------------------------===//
+// TreePatternNode implementation
+//
+
+/// getValueRecord - Returns the value of this tree node as a record. For now
+/// we only allow DefInit's as our leaf values, so this is used.
+Record *TreePatternNode::getValueRecord() const {
+ DefInit *DI = dynamic_cast<DefInit*>(getValue());
+ assert(DI && "Instruction Selector does not yet support non-def leaves!");
+ return DI->getDef();
+}
+
+
+// updateNodeType - Set the node type of N to VT if VT contains information. If
+// N already contains a conflicting type, then throw an exception
+//
+bool TreePatternNode::updateNodeType(MVT::ValueType VT,
+ const std::string &RecName) {
+ if (VT == MVT::Other || getType() == VT) return false;
+ if (getType() == MVT::Other) {
+ setType(VT);
+ return true;
+ }
+
+ throw "Type inferfence contradiction found for pattern " + RecName;
+}
+
+/// InstantiateNonterminals - If this pattern refers to any nonterminals which
+/// are not themselves completely resolved, clone the nonterminal and resolve it
+/// with the using context we provide.
+///
+void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
+ if (!isLeaf()) {
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->InstantiateNonterminals(ISE);
+ return;
+ }
+
+ // If this is a leaf, it might be a reference to a nonterminal! Check now.
+ Record *R = getValueRecord();
+ if (R->isSubClassOf("Nonterminal")) {
+ Pattern *NT = ISE.getPattern(R);
+ if (!NT->isResolved()) {
+ // We found an unresolved nonterminal reference. Ask the ISE to clone
+ // it for us, then update our reference to the fresh, new, resolved,
+ // nonterminal.
+
+ Value = new DefInit(ISE.InstantiateNonterminal(NT, getType()));
+ }
+ }
+}
+
+
+/// clone - Make a copy of this tree and all of its children.
+///
+TreePatternNode *TreePatternNode::clone() const {
+ TreePatternNode *New;
+ if (isLeaf()) {
+ New = new TreePatternNode(Value);
+ } else {
+ std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
+ CChildren.reserve(Children.size());
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i)));
+ New = new TreePatternNode(Operator, CChildren);
+ }
+ New->setType(Type);
+ return New;
+}
+
+std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) {
+ if (N.isLeaf())
+ return OS << N.getType() << ":" << *N.getValue();
+ OS << "(" << N.getType() << ":";
+ OS << N.getOperator()->getName();
+
+ if (N.getNumChildren() != 0) {
+ OS << " " << *N.getChild(0);
+ for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
+ OS << ", " << *N.getChild(i);
+ }
+ return OS << ")";
+}
+
+void TreePatternNode::dump() const { std::cerr << *this; }
+
+//===----------------------------------------------------------------------===//
+// Pattern implementation
+//
+
+// Parse the specified DagInit into a TreePattern which we can use.
+//
+Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
+ InstrSelectorEmitter &ise)
+ : PTy(pty), ResultNode(0), TheRecord(TheRec), ISE(ise) {
+
+ // First, parse the pattern...
+ Tree = ParseTreePattern(RawPat);
+
+ // Run the type-inference engine...
+ InferAllTypes();
+
+ if (PTy == Instruction || PTy == Expander) {
+ // Check to make sure there is not any unset types in the tree pattern...
+ if (!isResolved()) {
+ std::cerr << "In pattern: " << *Tree << "\n";
+ error("Could not infer all types!");
+ }
+
+ // Check to see if we have a top-level (set) of a register.
+ if (Tree->getOperator()->getName() == "set") {
+ assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?");
+ if (!Tree->getChild(0)->isLeaf())
+ error("Arg #0 of set should be a register or register class!");
+ ResultNode = Tree->getChild(0);
+ ResultName = Tree->getChildName(0);
+ Tree = Tree->getChild(1);
+ }
+ }
+
+ calculateArgs(Tree, "");
+}
+
+void Pattern::error(const std::string &Msg) const {
+ std::string M = "In ";
+ switch (PTy) {
+ case Nonterminal: M += "nonterminal "; break;
+ case Instruction: M += "instruction "; break;
+ case Expander : M += "expander "; break;
+ }
+ throw M + TheRecord->getName() + ": " + Msg;
+}
+
+/// calculateArgs - Compute the list of all of the arguments to this pattern,
+/// which are the non-void leaf nodes in this pattern.
+///
+void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) {
+ if (N->isLeaf() || N->getNumChildren() == 0) {
+ if (N->getType() != MVT::isVoid)
+ Args.push_back(std::make_pair(N, Name));
+ } else {
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ calculateArgs(N->getChild(i), N->getChildName(i));
+ }
+}
+
+/// getIntrinsicType - Check to see if the specified record has an intrinsic
+/// type which should be applied to it. This infer the type of register
+/// references from the register file information, for example.
+///
+MVT::ValueType Pattern::getIntrinsicType(Record *R) const {
+ // Check to see if this is a register or a register class...
+ if (R->isSubClassOf("RegisterClass"))
+ return getValueType(R->getValueAsDef("RegType"));
+ else if (R->isSubClassOf("Nonterminal"))
+ return ISE.ReadNonterminal(R)->getTree()->getType();
+ else if (R->isSubClassOf("Register")) {
+ std::cerr << "WARNING: Explicit registers not handled yet!\n";
+ return MVT::Other;
+ }
+
+ error("Unknown value used: " + R->getName());
+ return MVT::Other;
+}
+
+TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
+ Record *Operator = Dag->getNodeType();
+
+ if (Operator->isSubClassOf("ValueType")) {
+ // If the operator is a ValueType, then this must be "type cast" of a leaf
+ // node.
+ if (Dag->getNumArgs() != 1)
+ error("Type cast only valid for a leaf node!");
+
+ Init *Arg = Dag->getArg(0);
+ TreePatternNode *New;
+ if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
+ New = new TreePatternNode(DI);
+ // If it's a regclass or something else known, set the type.
+ New->setType(getIntrinsicType(DI->getDef()));
+ } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
+ New = ParseTreePattern(DI);
+ } else {
+ Arg->dump();
+ error("Unknown leaf value for tree pattern!");
+ return 0;
+ }
+
+ // Apply the type cast...
+ New->updateNodeType(getValueType(Operator), TheRecord->getName());
+ return New;
+ }
+
+ if (!ISE.getNodeTypes().count(Operator))
+ error("Unrecognized node '" + Operator->getName() + "'!");
+
+ std::vector<std::pair<TreePatternNode*, std::string> > Children;
+
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ Init *Arg = Dag->getArg(i);
+ if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
+ Children.push_back(std::make_pair(ParseTreePattern(DI),
+ Dag->getArgName(i)));
+ } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
+ Record *R = DefI->getDef();
+ // Direct reference to a leaf DagNode? Turn it into a DagNode if its own.
+ if (R->isSubClassOf("DagNode")) {
+ Dag->setArg(i, new DagInit(R,
+ std::vector<std::pair<Init*, std::string> >()));
+ --i; // Revisit this node...
+ } else {
+ Children.push_back(std::make_pair(new TreePatternNode(DefI),
+ Dag->getArgName(i)));
+ // If it's a regclass or something else known, set the type.
+ Children.back().first->setType(getIntrinsicType(R));
+ }
+ } else {
+ Arg->dump();
+ error("Unknown leaf value for tree pattern!");
+ }
+ }
+
+ return new TreePatternNode(Operator, Children);
+}
+
+void Pattern::InferAllTypes() {
+ bool MadeChange, AnyUnset;
+ do {
+ MadeChange = false;
+ AnyUnset = InferTypes(Tree, MadeChange);
+ } while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange));
+ Resolved = !AnyUnset;
+}
+
+
+// InferTypes - Perform type inference on the tree, returning true if there
+// are any remaining untyped nodes and setting MadeChange if any changes were
+// made.
+bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) {
+ if (N->isLeaf()) return N->getType() == MVT::Other;
+
+ bool AnyUnset = false;
+ Record *Operator = N->getOperator();
+ const NodeType &NT = ISE.getNodeType(Operator);
+
+ // Check to see if we can infer anything about the argument types from the
+ // return types...
+ if (N->getNumChildren() != NT.ArgTypes.size())
+ error("Incorrect number of children for " + Operator->getName() + " node!");
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ AnyUnset |= InferTypes(Child, MadeChange);
+
+ switch (NT.ArgTypes[i]) {
+ case NodeType::Any: break;
+ case NodeType::I8:
+ MadeChange |= Child->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
+ case NodeType::Arg0:
+ MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= Child->updateNodeType(N->getChild(1)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Val:
+ if (Child->getType() == MVT::isVoid)
+ error("Inferred a void node in an illegal place!");
+ break;
+ case NodeType::Ptr:
+ MadeChange |= Child->updateNodeType(ISE.getTarget().getPointerType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Void:
+ MadeChange |= Child->updateNodeType(MVT::isVoid, TheRecord->getName());
+ break;
+ default: assert(0 && "Invalid argument ArgType!");
+ }
+ }
+
+ // See if we can infer anything about the return type now...
+ switch (NT.ResultType) {
+ case NodeType::Any: break;
+ case NodeType::Void:
+ MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
+ break;
+ case NodeType::I8:
+ MadeChange |= N->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
+ case NodeType::Arg0:
+ MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= N->updateNodeType(N->getChild(1)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Ptr:
+ MadeChange |= N->updateNodeType(ISE.getTarget().getPointerType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Val:
+ if (N->getType() == MVT::isVoid)
+ error("Inferred a void node in an illegal place!");
+ break;
+ default:
+ assert(0 && "Unhandled type constraint!");
+ break;
+ }
+
+ return AnyUnset | N->getType() == MVT::Other;
+}
+
+/// clone - This method is used to make an exact copy of the current pattern,
+/// then change the "TheRecord" instance variable to the specified record.
+///
+Pattern *Pattern::clone(Record *R) const {
+ assert(PTy == Nonterminal && "Can only clone nonterminals");
+ return new Pattern(Tree->clone(), R, Resolved, ISE);
+}
+
+
+
+std::ostream &operator<<(std::ostream &OS, const Pattern &P) {
+ switch (P.getPatternType()) {
+ case Pattern::Nonterminal: OS << "Nonterminal pattern "; break;
+ case Pattern::Instruction: OS << "Instruction pattern "; break;
+ case Pattern::Expander: OS << "Expander pattern "; break;
+ }
+
+ OS << P.getRecord()->getName() << ":\t";
+
+ if (Record *Result = P.getResult())
+ OS << Result->getName() << " = ";
+ OS << *P.getTree();
+
+ if (!P.isResolved())
+ OS << " [not completely resolved]";
+ return OS;
+}
+
+void Pattern::dump() const { std::cerr << *this; }
+
+
+
+/// getSlotName - If this is a leaf node, return the slot name that the operand
+/// will update.
+std::string Pattern::getSlotName() const {
+ if (getPatternType() == Pattern::Nonterminal) {
+ // Just use the nonterminal name, which will already include the type if
+ // it has been cloned.
+ return getRecord()->getName();
+ } else {
+ std::string SlotName;
+ if (getResult())
+ SlotName = getResult()->getName()+"_";
+ else
+ SlotName = "Void_";
+ return SlotName + getName(getTree()->getType());
+ }
+}
+
+/// getSlotName - If this is a leaf node, return the slot name that the
+/// operand will update.
+std::string Pattern::getSlotName(Record *R) {
+ if (R->isSubClassOf("Nonterminal")) {
+ // Just use the nonterminal name, which will already include the type if
+ // it has been cloned.
+ return R->getName();
+ } else if (R->isSubClassOf("RegisterClass")) {
+ MVT::ValueType Ty = getValueType(R->getValueAsDef("RegType"));
+ return R->getName() + "_" + getName(Ty);
+ } else {
+ assert(0 && "Don't know how to get a slot name for this!");
+ }
+ return "";
+}
+
+//===----------------------------------------------------------------------===//
+// PatternOrganizer implementation
+//
+
+/// addPattern - Add the specified pattern to the appropriate location in the
+/// collection.
+void PatternOrganizer::addPattern(Pattern *P) {
+ NodesForSlot &Nodes = AllPatterns[P->getSlotName()];
+ if (!P->getTree()->isLeaf())
+ Nodes[P->getTree()->getOperator()].push_back(P);
+ else {
+ // Right now we only support DefInit's with node types...
+ Nodes[P->getTree()->getValueRecord()].push_back(P);
+ }
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// InstrSelectorEmitter implementation
+//
+
+/// ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
+/// turning them into the more accessible NodeTypes data structure.
+///
+void InstrSelectorEmitter::ReadNodeTypes() {
+ std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("DagNode");
+ DEBUG(std::cerr << "Getting node types: ");
+ for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+ Record *Node = Nodes[i];
+
+ // Translate the return type...
+ NodeType::ArgResultTypes RetTy =
+ NodeType::Translate(Node->getValueAsDef("RetType"));
+
+ // Translate the arguments...
+ ListInit *Args = Node->getValueAsListInit("ArgTypes");
+ std::vector<NodeType::ArgResultTypes> ArgTypes;
+
+ for (unsigned a = 0, e = Args->getSize(); a != e; ++a) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Args->getElement(a)))
+ ArgTypes.push_back(NodeType::Translate(DI->getDef()));
+ else
+ throw "In node " + Node->getName() + ", argument is not a Def!";
+
+ if (a == 0 && ArgTypes.back() == NodeType::Arg0)
+ throw "In node " + Node->getName() + ", arg 0 cannot have type 'arg0'!";
+ if (a == 1 && ArgTypes.back() == NodeType::Arg1)
+ throw "In node " + Node->getName() + ", arg 1 cannot have type 'arg1'!";
+ }
+ if ((RetTy == NodeType::Arg0 && Args->getSize() == 0) ||
+ (RetTy == NodeType::Arg1 && Args->getSize() < 2))
+ throw "In node " + Node->getName() +
+ ", invalid return type for node with this many operands!";
+
+ // Add the node type mapping now...
+ NodeTypes[Node] = NodeType(RetTy, ArgTypes);
+ DEBUG(std::cerr << Node->getName() << ", ");
+ }
+ DEBUG(std::cerr << "DONE!\n");
+}
+
+Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) {
+ Pattern *&P = Patterns[R];
+ if (P) return P; // Don't reread it!
+
+ DagInit *DI = R->getValueAsDag("Pattern");
+ P = new Pattern(Pattern::Nonterminal, DI, R, *this);
+ DEBUG(std::cerr << "Parsed " << *P << "\n");
+ return P;
+}
+
+
+// ReadNonTerminals - Read in all nonterminals and incorporate them into our
+// pattern database.
+void InstrSelectorEmitter::ReadNonterminals() {
+ std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal");
+ for (unsigned i = 0, e = NTs.size(); i != e; ++i)
+ ReadNonterminal(NTs[i]);
+}
+
+
+/// ReadInstructionPatterns - Read in all subclasses of Instruction, and process
+/// those with a useful Pattern field.
+///
+void InstrSelectorEmitter::ReadInstructionPatterns() {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
+ Record *Inst = Insts[i];
+ if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) {
+ Patterns[Inst] = new Pattern(Pattern::Instruction, DI, Inst, *this);
+ DEBUG(std::cerr << "Parsed " << *Patterns[Inst] << "\n");
+ }
+ }
+}
+
+/// ReadExpanderPatterns - Read in all expander patterns...
+///
+void InstrSelectorEmitter::ReadExpanderPatterns() {
+ std::vector<Record*> Expanders = Records.getAllDerivedDefinitions("Expander");
+ for (unsigned i = 0, e = Expanders.size(); i != e; ++i) {
+ Record *Expander = Expanders[i];
+ DagInit *DI = Expander->getValueAsDag("Pattern");
+ Patterns[Expander] = new Pattern(Pattern::Expander, DI, Expander, *this);
+ DEBUG(std::cerr << "Parsed " << *Patterns[Expander] << "\n");
+ }
+}
+
+
+// InstantiateNonterminals - Instantiate any unresolved nonterminals with
+// information from the context that they are used in.
+//
+void InstrSelectorEmitter::InstantiateNonterminals() {
+ DEBUG(std::cerr << "Instantiating nonterminals:\n");
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved())
+ I->second->InstantiateNonterminals();
+}
+
+/// InstantiateNonterminal - This method takes the nonterminal specified by
+/// NT, which should not be completely resolved, clones it, applies ResultTy
+/// to its root, then runs the type inference stuff on it. This should
+/// produce a newly resolved nonterminal, which we make a record for and
+/// return. To be extra fancy and efficient, this only makes one clone for
+/// each type it is instantiated with.
+Record *InstrSelectorEmitter::InstantiateNonterminal(Pattern *NT,
+ MVT::ValueType ResultTy) {
+ assert(!NT->isResolved() && "Nonterminal is already resolved!");
+
+ // Check to see if we have already instantiated this pair...
+ Record* &Slot = InstantiatedNTs[std::make_pair(NT, ResultTy)];
+ if (Slot) return Slot;
+
+ Record *New = new Record(NT->getRecord()->getName()+"_"+getName(ResultTy));
+
+ // Copy over the superclasses...
+ const std::vector<Record*> &SCs = NT->getRecord()->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i)
+ New->addSuperClass(SCs[i]);
+
+ DEBUG(std::cerr << " Nonterminal '" << NT->getRecord()->getName()
+ << "' for type '" << getName(ResultTy) << "', producing '"
+ << New->getName() << "'\n");
+
+ // Copy the pattern...
+ Pattern *NewPat = NT->clone(New);
+
+ // Apply the type to the root...
+ NewPat->getTree()->updateNodeType(ResultTy, New->getName());
+
+ // Infer types...
+ NewPat->InferAllTypes();
+
+ // Make sure everything is good to go now...
+ if (!NewPat->isResolved())
+ NewPat->error("Instantiating nonterminal did not resolve all types!");
+
+ // Add the pattern to the patterns map, add the record to the RecordKeeper,
+ // return the new record.
+ Patterns[New] = NewPat;
+ Records.addDef(New);
+ return Slot = New;
+}
+
+// CalculateComputableValues - Fill in the ComputableValues map through
+// analysis of the patterns we are playing with.
+void InstrSelectorEmitter::CalculateComputableValues() {
+ // Loop over all of the patterns, adding them to the ComputableValues map
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved()) {
+ // We don't want to add patterns like R32 = R32. This is a hack working
+ // around a special case of a general problem, but for now we explicitly
+ // forbid these patterns. They can never match anyway.
+ Pattern *P = I->second;
+ if (!P->getResult() || !P->getTree()->isLeaf() ||
+ P->getResult() != P->getTree()->getValueRecord())
+ ComputableValues.addPattern(P);
+ }
+}
+
+#if 0
+// MoveIdenticalPatterns - Given a tree pattern 'P', move all of the tree
+// patterns which have the same top-level structure as P from the 'From' list to
+// the 'To' list.
+static void MoveIdenticalPatterns(TreePatternNode *P,
+ std::vector<std::pair<Pattern*, TreePatternNode*> > &From,
+ std::vector<std::pair<Pattern*, TreePatternNode*> > &To) {
+ assert(!P->isLeaf() && "All leaves are identical!");
+
+ const std::vector<TreePatternNode*> &PChildren = P->getChildren();
+ for (unsigned i = 0; i != From.size(); ++i) {
+ TreePatternNode *N = From[i].second;
+ assert(P->getOperator() == N->getOperator() &&"Differing operators?");
+ assert(PChildren.size() == N->getChildren().size() &&
+ "Nodes with different arity??");
+ bool isDifferent = false;
+ for (unsigned c = 0, e = PChildren.size(); c != e; ++c) {
+ TreePatternNode *PC = PChildren[c];
+ TreePatternNode *NC = N->getChild(c);
+ if (PC->isLeaf() != NC->isLeaf()) {
+ isDifferent = true;
+ break;
+ }
+
+ if (!PC->isLeaf()) {
+ if (PC->getOperator() != NC->getOperator()) {
+ isDifferent = true;
+ break;
+ }
+ } else { // It's a leaf!
+ if (PC->getValueRecord() != NC->getValueRecord()) {
+ isDifferent = true;
+ break;
+ }
+ }
+ }
+ // If it's the same as the reference one, move it over now...
+ if (!isDifferent) {
+ To.push_back(std::make_pair(From[i].first, N));
+ From.erase(From.begin()+i);
+ --i; // Don't skip an entry...
+ }
+ }
+}
+#endif
+
+static std::string getNodeName(Record *R) {
+ RecordVal *RV = R->getValue("EnumName");
+ if (RV)
+ if (Init *I = RV->getValue())
+ if (StringInit *SI = dynamic_cast<StringInit*>(I))
+ return SI->getValue();
+ return R->getName();
+}
+
+
+static void EmitPatternPredicates(TreePatternNode *Tree,
+ const std::string &VarName, std::ostream &OS){
+ OS << " && " << VarName << "->getNodeType() == ISD::"
+ << getNodeName(Tree->getOperator());
+
+ for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c)
+ if (!Tree->getChild(c)->isLeaf())
+ EmitPatternPredicates(Tree->getChild(c),
+ VarName + "->getUse(" + utostr(c)+")", OS);
+}
+
+static void EmitPatternCosts(TreePatternNode *Tree, const std::string &VarName,
+ std::ostream &OS) {
+ for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c)
+ if (Tree->getChild(c)->isLeaf()) {
+ OS << " + Match_"
+ << Pattern::getSlotName(Tree->getChild(c)->getValueRecord()) << "("
+ << VarName << "->getUse(" << c << "))";
+ } else {
+ EmitPatternCosts(Tree->getChild(c),
+ VarName + "->getUse(" + utostr(c) + ")", OS);
+ }
+}
+
+
+// EmitMatchCosters - Given a list of patterns, which all have the same root
+// pattern operator, emit an efficient decision tree to decide which one to
+// pick. This is structured this way to avoid reevaluations of non-obvious
+// subexpressions.
+void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS,
+ const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
+ const std::string &VarPrefix,
+ unsigned IndentAmt) {
+ assert(!Patterns.empty() && "No patterns to emit matchers for!");
+ std::string Indent(IndentAmt, ' ');
+
+ // Load all of the operands of the root node into scalars for fast access
+ const NodeType &ONT = getNodeType(Patterns[0].second->getOperator());
+ for (unsigned i = 0, e = ONT.ArgTypes.size(); i != e; ++i)
+ OS << Indent << "SelectionDAGNode *" << VarPrefix << "_Op" << i
+ << " = N->getUse(" << i << ");\n";
+
+ // Compute the costs of computing the various nonterminals/registers, which
+ // are directly used at this level.
+ OS << "\n" << Indent << "// Operand matching costs...\n";
+ std::set<std::string> ComputedValues; // Avoid duplicate computations...
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ TreePatternNode *NParent = Patterns[i].second;
+ for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
+ TreePatternNode *N = NParent->getChild(c);
+ if (N->isLeaf()) {
+ Record *VR = N->getValueRecord();
+ const std::string &LeafName = VR->getName();
+ std::string OpName = VarPrefix + "_Op" + utostr(c);
+ std::string ValName = OpName + "_" + LeafName + "_Cost";
+ if (!ComputedValues.count(ValName)) {
+ OS << Indent << "unsigned " << ValName << " = Match_"
+ << Pattern::getSlotName(VR) << "(" << OpName << ");\n";
+ ComputedValues.insert(ValName);
+ }
+ }
+ }
+ }
+ OS << "\n";
+
+
+ std::string LocCostName = VarPrefix + "_Cost";
+ OS << Indent << "unsigned " << LocCostName << "Min = ~0U >> 1;\n"
+ << Indent << "unsigned " << VarPrefix << "_PatternMin = NoMatchPattern;\n";
+
+#if 0
+ // Separate out all of the patterns into groups based on what their top-level
+ // signature looks like...
+ std::vector<std::pair<Pattern*, TreePatternNode*> > PatternsLeft(Patterns);
+ while (!PatternsLeft.empty()) {
+ // Process all of the patterns that have the same signature as the last
+ // element...
+ std::vector<std::pair<Pattern*, TreePatternNode*> > Group;
+ MoveIdenticalPatterns(PatternsLeft.back().second, PatternsLeft, Group);
+ assert(!Group.empty() && "Didn't at least pick the source pattern?");
+
+#if 0
+ OS << "PROCESSING GROUP:\n";
+ for (unsigned i = 0, e = Group.size(); i != e; ++i)
+ OS << " " << *Group[i].first << "\n";
+ OS << "\n\n";
+#endif
+
+ OS << Indent << "{ // ";
+
+ if (Group.size() != 1) {
+ OS << Group.size() << " size group...\n";
+ OS << Indent << " unsigned " << VarPrefix << "_Pattern = NoMatch;\n";
+ } else {
+ OS << *Group[0].first << "\n";
+ OS << Indent << " unsigned " << VarPrefix << "_Pattern = "
+ << Group[0].first->getRecord()->getName() << "_Pattern;\n";
+ }
+
+ OS << Indent << " unsigned " << LocCostName << " = ";
+ if (Group.size() == 1)
+ OS << "1;\n"; // Add inst cost if at individual rec
+ else
+ OS << "0;\n";
+
+ // Loop over all of the operands, adding in their costs...
+ TreePatternNode *N = Group[0].second;
+ const std::vector<TreePatternNode*> &Children = N->getChildren();
+
+ // If necessary, emit conditionals to check for the appropriate tree
+ // structure here...
+ for (unsigned i = 0, e = Children.size(); i != e; ++i) {
+ TreePatternNode *C = Children[i];
+ if (C->isLeaf()) {
+ // We already calculated the cost for this leaf, add it in now...
+ OS << Indent << " " << LocCostName << " += "
+ << VarPrefix << "_Op" << utostr(i) << "_"
+ << C->getValueRecord()->getName() << "_Cost;\n";
+ } else {
+ // If it's not a leaf, we have to check to make sure that the current
+ // node has the appropriate structure, then recurse into it...
+ OS << Indent << " if (" << VarPrefix << "_Op" << i
+ << "->getNodeType() == ISD::" << getNodeName(C->getOperator())
+ << ") {\n";
+ std::vector<std::pair<Pattern*, TreePatternNode*> > SubPatterns;
+ for (unsigned n = 0, e = Group.size(); n != e; ++n)
+ SubPatterns.push_back(std::make_pair(Group[n].first,
+ Group[n].second->getChild(i)));
+ EmitMatchCosters(OS, SubPatterns, VarPrefix+"_Op"+utostr(i),
+ IndentAmt + 4);
+ OS << Indent << " }\n";
+ }
+ }
+
+ // If the cost for this match is less than the minimum computed cost so far,
+ // update the minimum cost and selected pattern.
+ OS << Indent << " if (" << LocCostName << " < " << LocCostName << "Min) { "
+ << LocCostName << "Min = " << LocCostName << "; " << VarPrefix
+ << "_PatternMin = " << VarPrefix << "_Pattern; }\n";
+
+ OS << Indent << "}\n";
+ }
+#endif
+
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ Pattern *P = Patterns[i].first;
+ TreePatternNode *PTree = P->getTree();
+ unsigned PatternCost = 1;
+
+ // Check to see if there are any non-leaf elements in the pattern. If so,
+ // we need to emit a predicate for this match.
+ bool AnyNonLeaf = false;
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (!PTree->getChild(c)->isLeaf()) {
+ AnyNonLeaf = true;
+ break;
+ }
+
+ if (!AnyNonLeaf) { // No predicate necessary, just output a scope...
+ OS << " {// " << *P << "\n";
+ } else {
+ // We need to emit a predicate to make sure the tree pattern matches, do
+ // so now...
+ OS << " if (1";
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (!PTree->getChild(c)->isLeaf())
+ EmitPatternPredicates(PTree->getChild(c),
+ VarPrefix + "_Op" + utostr(c), OS);
+
+ OS << ") {\n // " << *P << "\n";
+ }
+
+ OS << " unsigned PatCost = " << PatternCost;
+
+ for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c)
+ if (PTree->getChild(c)->isLeaf()) {
+ OS << " + " << VarPrefix << "_Op" << c << "_"
+ << PTree->getChild(c)->getValueRecord()->getName() << "_Cost";
+ } else {
+ EmitPatternCosts(PTree->getChild(c), VarPrefix + "_Op" + utostr(c), OS);
+ }
+ OS << ";\n";
+ OS << " if (PatCost < MinCost) { MinCost = PatCost; Pattern = "
+ << P->getRecord()->getName() << "_Pattern; }\n"
+ << " }\n";
+ }
+}
+
+static void ReduceAllOperands(TreePatternNode *N, const std::string &Name,
+ std::vector<std::pair<TreePatternNode*, std::string> > &Operands,
+ std::ostream &OS) {
+ if (N->isLeaf()) {
+ // If this is a leaf, register or nonterminal reference...
+ std::string SlotName = Pattern::getSlotName(N->getValueRecord());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = Reduce_"
+ << SlotName << "(" << Name << ", MBB);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ } else if (N->getNumChildren() == 0) {
+ // This is a reference to a leaf tree node, like an immediate or frame
+ // index.
+ if (N->getType() != MVT::isVoid) {
+ std::string SlotName =
+ getNodeName(N->getOperator()) + "_" + getName(N->getType());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = "
+ << Name << "->getValue<ReducedValue_" << SlotName << ">(ISD::"
+ << SlotName << "_Slot);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ }
+ } else {
+ // Otherwise this is an interior node...
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ std::string ChildName = Name + "_Op" + utostr(i);
+ OS << " SelectionDAGNode *" << ChildName << " = " << Name
+ << "->getUse(" << i << ");\n";
+ ReduceAllOperands(N->getChild(i), ChildName, Operands, OS);
+ }
+ }
+}
+
+/// PrintExpanderOperand - Print out Arg as part of the instruction emission
+/// process for the expander pattern P. This argument may be referencing some
+/// values defined in P, or may just be physical register references or
+/// something like that. If PrintArg is true, we are printing out arguments to
+/// the BuildMI call. If it is false, we are printing the result register
+/// name.
+void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg,
+ const std::string &NameVar,
+ TreePatternNode *ArgDeclNode,
+ Pattern *P, bool PrintArg,
+ std::ostream &OS) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
+ Record *Arg = DI->getDef();
+ if (!ArgDeclNode->isLeaf() && ArgDeclNode->getNumChildren() != 0)
+ P->error("Expected leaf node as argument!");
+ Record *ArgDecl = ArgDeclNode->isLeaf() ? ArgDeclNode->getValueRecord() :
+ ArgDeclNode->getOperator();
+ if (Arg->isSubClassOf("Register")) {
+ // This is a physical register reference... make sure that the instruction
+ // requested a register!
+ if (!ArgDecl->isSubClassOf("RegisterClass"))
+ P->error("Argument mismatch for instruction pattern!");
+
+ // FIXME: This should check to see if the register is in the specified
+ // register class!
+ if (PrintArg) OS << ".addReg(";
+ OS << getQualifiedName(Arg);
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->isSubClassOf("RegisterClass")) {
+ // If this is a symbolic register class reference, we must be using a
+ // named value.
+ if (NameVar.empty()) P->error("Did not specify WHICH register to pass!");
+ if (Arg != ArgDecl) P->error("Instruction pattern mismatch!");
+
+ if (PrintArg) OS << ".addReg(";
+ OS << NameVar;
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->getName() == "frameidx") {
+ if (!PrintArg) P->error("Cannot define a new frameidx value!");
+ OS << ".addFrameIndex(" << NameVar << ")";
+ return;
+ } else if (Arg->getName() == "basicblock") {
+ if (!PrintArg) P->error("Cannot define a new basicblock value!");
+ OS << ".addMBB(" << NameVar << ")";
+ return;
+ }
+ P->error("Unknown operand type '" + Arg->getName() + "' to expander!");
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+ if (!NameVar.empty())
+ P->error("Illegal to specify a name for a constant initializer arg!");
+
+ // Hack this check to allow R32 values with 0 as the initializer for memory
+ // references... FIXME!
+ if (ArgDeclNode->isLeaf() && II->getValue() == 0 &&
+ ArgDeclNode->getValueRecord()->getName() == "R32") {
+ OS << ".addReg(0)";
+ } else {
+ if (ArgDeclNode->isLeaf() || ArgDeclNode->getOperator()->getName()!="imm")
+ P->error("Illegal immediate int value '" + itostr(II->getValue()) +
+ "' operand!");
+ OS << ".addZImm(" << II->getValue() << ")";
+ }
+ return;
+ }
+ P->error("Unknown operand type to expander!");
+}
+
+static std::string getArgName(Pattern *P, const std::string &ArgName,
+ const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) {
+ assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!");
+ if (ArgName.empty()) return "";
+
+ for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i)
+ if (P->getArgName(i) == ArgName)
+ return Operands[i].second + "->Val";
+
+ if (ArgName == P->getResultName())
+ return "NewReg";
+ P->error("Pattern does not define a value named $" + ArgName + "!");
+ return "";
+}
+
+
+void InstrSelectorEmitter::run(std::ostream &OS) {
+ // Type-check all of the node types to ensure we "understand" them.
+ ReadNodeTypes();
+
+ // Read in all of the nonterminals, instructions, and expanders...
+ ReadNonterminals();
+ ReadInstructionPatterns();
+ ReadExpanderPatterns();
+
+ // Instantiate any unresolved nonterminals with information from the context
+ // that they are used in.
+ InstantiateNonterminals();
+
+ // Clear InstantiatedNTs, we don't need it anymore...
+ InstantiatedNTs.clear();
+
+ DEBUG(std::cerr << "Patterns acquired:\n");
+ for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
+ E = Patterns.end(); I != E; ++I)
+ if (I->second->isResolved())
+ DEBUG(std::cerr << " " << *I->second << "\n");
+
+ CalculateComputableValues();
+
+ EmitSourceFileHeader("Instruction Selector for the " + Target.getName() +
+ " target", OS);
+ OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
+
+ // Output the slot number enums...
+ OS << "\nenum { // Slot numbers...\n"
+ << " LastBuiltinSlot = ISD::NumBuiltinSlots-1, // Start numbering here\n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " " << I->first << "_Slot,\n";
+ OS << " NumSlots\n};\n\n// Reduction value typedefs...\n";
+
+ // Output the reduction value typedefs...
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+
+ OS << "typedef ReducedValue<unsigned, " << I->first
+ << "_Slot> ReducedValue_" << I->first << ";\n";
+ }
+
+ // Output the pattern enums...
+ OS << "\n\n"
+ << "enum { // Patterns...\n"
+ << " NotComputed = 0,\n"
+ << " NoMatchPattern, \n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ OS << " // " << I->first << " patterns...\n";
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i)
+ OS << " " << J->second[i]->getRecord()->getName() << "_Pattern,\n";
+ }
+ OS << "};\n\n";
+
+ //===--------------------------------------------------------------------===//
+ // Emit the class definition...
+ //
+ OS << "namespace {\n"
+ << " class " << Target.getName() << "ISel {\n"
+ << " SelectionDAG &DAG;\n"
+ << " public:\n"
+ << " X86ISel(SelectionDAG &D) : DAG(D) {}\n"
+ << " void generateCode();\n"
+ << " private:\n"
+ << " unsigned makeAnotherReg(const TargetRegisterClass *RC) {\n"
+ << " return DAG.getMachineFunction().getSSARegMap()->createVirt"
+ "ualRegister(RC);\n"
+ << " }\n\n"
+ << " // DAG matching methods for classes... all of these methods"
+ " return the cost\n"
+ << " // of producing a value of the specified class and type, which"
+ " also gets\n"
+ << " // added to the DAG node.\n";
+
+ // Output all of the matching prototypes for slots...
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " unsigned Match_" << I->first << "(SelectionDAGNode *N);\n";
+ OS << "\n // DAG matching methods for DAG nodes...\n";
+
+ // Output all of the matching prototypes for slot/node pairs
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ OS << " unsigned Match_" << I->first << "_" << getNodeName(J->first)
+ << "(SelectionDAGNode *N);\n";
+
+ // Output all of the dag reduction methods prototypes...
+ OS << "\n // DAG reduction methods...\n";
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I)
+ OS << " ReducedValue_" << I->first << " *Reduce_" << I->first
+ << "(SelectionDAGNode *N,\n" << std::string(27+2*I->first.size(), ' ')
+ << "MachineBasicBlock *MBB);\n";
+ OS << " };\n}\n\n";
+
+ // Emit the generateCode entry-point...
+ OS << "void X86ISel::generateCode() {\n"
+ << " SelectionDAGNode *Root = DAG.getRoot();\n"
+ << " assert(Root->getValueType() == MVT::isVoid && "
+ "\"Root of DAG produces value??\");\n\n"
+ << " std::cerr << \"\\n\";\n"
+ << " unsigned Cost = Match_Void_void(Root);\n"
+ << " if (Cost >= ~0U >> 1) {\n"
+ << " std::cerr << \"Match failed!\\n\";\n"
+ << " Root->dump();\n"
+ << " abort();\n"
+ << " }\n\n"
+ << " std::cerr << \"Total DAG Cost: \" << Cost << \"\\n\\n\";\n\n"
+ << " Reduce_Void_void(Root, 0);\n"
+ << "}\n\n"
+ << "//===" << std::string(70, '-') << "===//\n"
+ << "// Matching methods...\n"
+ << "//\n\n";
+
+ //===--------------------------------------------------------------------===//
+ // Emit all of the matcher methods...
+ //
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ const std::string &SlotName = I->first;
+ OS << "unsigned " << Target.getName() << "ISel::Match_" << SlotName
+ << "(SelectionDAGNode *N) {\n"
+ << " assert(N->getValueType() == MVT::"
+ << getEnumName((*I->second.begin()).second[0]->getTree()->getType())
+ << ");\n" << " // If we already have a cost available for " << SlotName
+ << " use it!\n"
+ << " if (N->getPatternFor(" << SlotName << "_Slot))\n"
+ << " return N->getCostFor(" << SlotName << "_Slot);\n\n"
+ << " unsigned Cost;\n"
+ << " switch (N->getNodeType()) {\n"
+ << " default: Cost = ~0U >> 1; // Match failed\n"
+ << " N->setPatternCostFor(" << SlotName << "_Slot, NoMatchPattern, Cost, NumSlots);\n"
+ << " break;\n";
+
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ if (!J->first->isSubClassOf("Nonterminal"))
+ OS << " case ISD::" << getNodeName(J->first) << ":\tCost = Match_"
+ << SlotName << "_" << getNodeName(J->first) << "(N); break;\n";
+ OS << " }\n"; // End of the switch statement
+
+ // Emit any patterns which have a nonterminal leaf as the RHS. These may
+ // match multiple root nodes, so they cannot be handled with the switch...
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J)
+ if (J->first->isSubClassOf("Nonterminal")) {
+ OS << " unsigned " << J->first->getName() << "_Cost = Match_"
+ << getNodeName(J->first) << "(N);\n"
+ << " if (" << getNodeName(J->first) << "_Cost < Cost) Cost = "
+ << getNodeName(J->first) << "_Cost;\n";
+ }
+
+ OS << " return Cost;\n}\n\n";
+
+ for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
+ E = I->second.end(); J != E; ++J) {
+ Record *Operator = J->first;
+ bool isNonterm = Operator->isSubClassOf("Nonterminal");
+ if (!isNonterm) {
+ OS << "unsigned " << Target.getName() << "ISel::Match_";
+ if (!isNonterm) OS << SlotName << "_";
+ OS << getNodeName(Operator) << "(SelectionDAGNode *N) {\n"
+ << " unsigned Pattern = NoMatchPattern;\n"
+ << " unsigned MinCost = ~0U >> 1;\n";
+
+ std::vector<std::pair<Pattern*, TreePatternNode*> > Patterns;
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i)
+ Patterns.push_back(std::make_pair(J->second[i],
+ J->second[i]->getTree()));
+ EmitMatchCosters(OS, Patterns, "N", 2);
+
+ OS << "\n N->setPatternCostFor(" << SlotName
+ << "_Slot, Pattern, MinCost, NumSlots);\n"
+ << " return MinCost;\n"
+ << "}\n";
+ }
+ }
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Emit all of the reducer methods...
+ //
+ OS << "\n\n//===" << std::string(70, '-') << "===//\n"
+ << "// Reducer methods...\n"
+ << "//\n";
+
+ for (PatternOrganizer::iterator I = ComputableValues.begin(),
+ E = ComputableValues.end(); I != E; ++I) {
+ const std::string &SlotName = I->first;
+ OS << "ReducedValue_" << SlotName << " *" << Target.getName()
+ << "ISel::Reduce_" << SlotName
+ << "(SelectionDAGNode *N, MachineBasicBlock *MBB) {\n"
+ << " ReducedValue_" << SlotName << " *Val = N->hasValue<ReducedValue_"
+ << SlotName << ">(" << SlotName << "_Slot);\n"
+ << " if (Val) return Val;\n"
+ << " if (N->getBB()) MBB = N->getBB();\n\n"
+ << " switch (N->getPatternFor(" << SlotName << "_Slot)) {\n";
+
+ // Loop over all of the patterns that can produce a value for this slot...
+ PatternOrganizer::NodesForSlot &NodesForSlot = I->second;
+ for (PatternOrganizer::NodesForSlot::iterator J = NodesForSlot.begin(),
+ E = NodesForSlot.end(); J != E; ++J)
+ for (unsigned i = 0, e = J->second.size(); i != e; ++i) {
+ Pattern *P = J->second[i];
+ OS << " case " << P->getRecord()->getName() << "_Pattern: {\n"
+ << " // " << *P << "\n";
+ // Loop over the operands, reducing them...
+ std::vector<std::pair<TreePatternNode*, std::string> > Operands;
+ ReduceAllOperands(P->getTree(), "N", Operands, OS);
+
+ // Now that we have reduced all of our operands, and have the values
+ // that reduction produces, perform the reduction action for this
+ // pattern.
+ std::string Result;
+
+ // If the pattern produces a register result, generate a new register
+ // now.
+ if (Record *R = P->getResult()) {
+ assert(R->isSubClassOf("RegisterClass") &&
+ "Only handle register class results so far!");
+ OS << " unsigned NewReg = makeAnotherReg(" << Target.getName()
+ << "::" << R->getName() << "RegisterClass);\n";
+ Result = "NewReg";
+ DEBUG(OS << " std::cerr << \"%reg\" << NewReg << \" =\t\";\n");
+ } else {
+ DEBUG(OS << " std::cerr << \"\t\t\";\n");
+ Result = "0";
+ }
+
+ // Print out the pattern that matched...
+ DEBUG(OS << " std::cerr << \" " << P->getRecord()->getName() <<'"');
+ DEBUG(for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].first->isLeaf()) {
+ Record *RV = Operands[i].first->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << " << \" %reg\" << " << Operands[i].second
+ << "->Val";
+ } else {
+ OS << " << ' ' << " << Operands[i].second
+ << "->Val";
+ });
+ DEBUG(OS << " << \"\\n\";\n");
+
+ // Generate the reduction code appropriate to the particular type of
+ // pattern that this is...
+ switch (P->getPatternType()) {
+ case Pattern::Instruction:
+ // Instruction patterns just emit a single MachineInstr, using BuildMI
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << P->getRecord()->getName() << ", " << Operands.size();
+ if (P->getResult()) OS << ", NewReg";
+ OS << ")";
+
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ TreePatternNode *Op = Operands[i].first;
+ if (Op->isLeaf()) {
+ Record *RV = Op->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << ".addReg(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "imm") {
+ OS << ".addZImm(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "basicblock") {
+ OS << ".addMBB(" << Operands[i].second << "->Val)";
+ } else {
+ assert(0 && "Unknown value type!");
+ }
+ }
+ OS << ";\n";
+ break;
+ case Pattern::Expander: {
+ // Expander patterns emit one machine instr for each instruction in
+ // the list of instructions expanded to.
+ ListInit *Insts = P->getRecord()->getValueAsListInit("Result");
+ for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) {
+ DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN));
+ if (!DIInst) P->error("Result list must contain instructions!");
+ Record *InstRec = DIInst->getNodeType();
+ Pattern *InstPat = getPattern(InstRec);
+ if (!InstPat || InstPat->getPatternType() != Pattern::Instruction)
+ P->error("Instruction list must contain Instruction patterns!");
+
+ bool hasResult = InstPat->getResult() != 0;
+ if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) {
+ P->error("Incorrect number of arguments specified for inst '" +
+ InstPat->getRecord()->getName() + "' in result list!");
+ }
+
+ // Start emission of the instruction...
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << InstRec->getName() << ", "
+ << DIInst->getNumArgs()-hasResult;
+ // Emit register result if necessary..
+ if (hasResult) {
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(0), Operands);
+ PrintExpanderOperand(DIInst->getArg(0), ArgNameVal,
+ InstPat->getResultNode(), P, false,
+ OS << ", ");
+ }
+ OS << ")";
+
+ for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(i), Operands);
+
+ PrintExpanderOperand(DIInst->getArg(i), ArgNameVal,
+ InstPat->getArg(i-hasResult), P, true, OS);
+ }
+
+ OS << ";\n";
+ }
+ break;
+ }
+ default:
+ assert(0 && "Reduction of this type of pattern not implemented!");
+ }
+
+ OS << " Val = new ReducedValue_" << SlotName << "(" << Result<<");\n"
+ << " break;\n"
+ << " }\n";
+ }
+
+
+ OS << " default: assert(0 && \"Unknown " << SlotName << " pattern!\");\n"
+ << " }\n\n N->addValue(Val); // Do not ever recalculate this\n"
+ << " return Val;\n}\n\n";
+ }
+}
+
diff --git a/llvm/utils/TableGen/InstrSelectorEmitter.h b/llvm/utils/TableGen/InstrSelectorEmitter.h
new file mode 100644
index 00000000000..922aa79dfa1
--- /dev/null
+++ b/llvm/utils/TableGen/InstrSelectorEmitter.h
@@ -0,0 +1,387 @@
+//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INSTRSELECTOR_EMITTER_H
+#define INSTRSELECTOR_EMITTER_H
+
+#include "TableGenBackend.h"
+#include "CodeGenWrappers.h"
+#include <vector>
+#include <map>
+#include <cassert>
+
+class DagInit;
+class Init;
+class InstrSelectorEmitter;
+
+/// NodeType - Represents Information parsed from the DagNode entries.
+///
+struct NodeType {
+ enum ArgResultTypes {
+ Any, // No constraint on type
+ Val, // A non-void type
+ Arg0, // Value matches the type of Arg0
+ Arg1, // Value matches the type of Arg1
+ Ptr, // Tree node is the type of the target pointer
+ I8, // Always bool
+ Void, // Tree node always returns void
+ };
+
+ ArgResultTypes ResultType;
+ std::vector<ArgResultTypes> ArgTypes;
+
+ NodeType(ArgResultTypes RT, std::vector<ArgResultTypes> &AT) : ResultType(RT){
+ AT.swap(ArgTypes);
+ }
+
+ NodeType() : ResultType(Val) {}
+ NodeType(const NodeType &N) : ResultType(N.ResultType), ArgTypes(N.ArgTypes){}
+
+ static ArgResultTypes Translate(Record *R);
+};
+
+
+
+/// TreePatternNode - Represent a node of the tree patterns.
+///
+class TreePatternNode {
+ /// Operator - The operation that this node represents... this is null if this
+ /// is a leaf.
+ Record *Operator;
+
+ /// Type - The inferred value type...
+ ///
+ MVT::ValueType Type;
+
+ /// Children - If this is not a leaf (Operator != 0), this is the subtrees
+ /// that we contain.
+ std::vector<std::pair<TreePatternNode*, std::string> > Children;
+
+ /// Value - If this node is a leaf, this indicates what the thing is.
+ ///
+ Init *Value;
+public:
+ TreePatternNode(Record *o, const std::vector<std::pair<TreePatternNode*,
+ std::string> > &c)
+ : Operator(o), Type(MVT::Other), Children(c), Value(0) {}
+ TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {}
+
+ Record *getOperator() const {
+ assert(Operator && "This is a leaf node!");
+ return Operator;
+ }
+ MVT::ValueType getType() const { return Type; }
+ void setType(MVT::ValueType T) { Type = T; }
+
+ bool isLeaf() const { return Operator == 0; }
+
+ unsigned getNumChildren() const { return Children.size(); }
+ TreePatternNode *getChild(unsigned c) const {
+ assert(Operator != 0 && "This is a leaf node!");
+ assert(c < Children.size() && "Child access out of range!");
+ return Children[c].first;
+ }
+ const std::string &getChildName(unsigned c) const {
+ assert(Operator != 0 && "This is a leaf node!");
+ assert(c < Children.size() && "Child access out of range!");
+ return Children[c].second;
+ }
+
+ Init *getValue() const {
+ assert(Operator == 0 && "This is not a leaf node!");
+ return Value;
+ }
+
+ /// getValueRecord - Returns the value of this tree node as a record. For now
+ /// we only allow DefInit's as our leaf values, so this is used.
+ Record *getValueRecord() const;
+
+ /// clone - Make a copy of this tree and all of its children.
+ ///
+ TreePatternNode *clone() const;
+
+ void dump() const;
+
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals(InstrSelectorEmitter &ISE);
+
+ /// UpdateNodeType - Set the node type of N to VT if VT contains information.
+ /// If N already contains a conflicting type, then throw an exception. This
+ /// returns true if any information was updated.
+ ///
+ bool updateNodeType(MVT::ValueType VT, const std::string &RecName);
+};
+
+std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N);
+
+
+
+/// Pattern - Represent a pattern of one form or another. Currently, three
+/// types of patterns are possible: Instruction's, Nonterminals, and Expanders.
+///
+struct Pattern {
+ enum PatternType {
+ Nonterminal, Instruction, Expander
+ };
+private:
+ /// PTy - The type of pattern this is.
+ ///
+ PatternType PTy;
+
+ /// Tree - The tree pattern which corresponds to this pattern. Note that if
+ /// there was a (set) node on the outside level that it has been stripped off.
+ ///
+ TreePatternNode *Tree;
+
+ /// Result - If this is an instruction or expander pattern, this is the
+ /// register result, specified with a (set) in the pattern.
+ ///
+ std::string ResultName; // The name of the result value...
+ TreePatternNode *ResultNode; // The leaf node for the result register...
+
+ /// TheRecord - The actual TableGen record corresponding to this pattern.
+ ///
+ Record *TheRecord;
+
+ /// Resolved - This is true of the pattern is useful in practice. In
+ /// particular, some non-terminals will have non-resolvable types. When a
+ /// user of the non-terminal is later found, they will have inferred a type
+ /// for the result of the non-terminal, which cause a clone of an unresolved
+ /// nonterminal to be made which is "resolved".
+ ///
+ bool Resolved;
+
+ /// Args - This is a list of all of the arguments to this pattern, which are
+ /// the non-void leaf nodes in this pattern.
+ std::vector<std::pair<TreePatternNode*, std::string> > Args;
+
+ /// ISE - the instruction selector emitter coordinating this madness.
+ ///
+ InstrSelectorEmitter &ISE;
+public:
+
+ /// Pattern constructor - Parse the specified DagInitializer into the current
+ /// record.
+ Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
+ InstrSelectorEmitter &ise);
+
+ /// Pattern - Constructor used for cloning nonterminal patterns
+ Pattern(TreePatternNode *tree, Record *rec, bool res,
+ InstrSelectorEmitter &ise)
+ : PTy(Nonterminal), Tree(tree), ResultNode(0), TheRecord(rec),
+ Resolved(res), ISE(ise) {
+ calculateArgs(Tree, "");
+ }
+
+ /// getPatternType - Return what flavor of Record this pattern originated from
+ ///
+ PatternType getPatternType() const { return PTy; }
+
+ /// getTree - Return the tree pattern which corresponds to this pattern.
+ ///
+ TreePatternNode *getTree() const { return Tree; }
+
+ Record *getResult() const {
+ return ResultNode ? ResultNode->getValueRecord() : 0;
+ }
+ const std::string &getResultName() const { return ResultName; }
+ TreePatternNode *getResultNode() const { return ResultNode; }
+
+ /// getRecord - Return the actual TableGen record corresponding to this
+ /// pattern.
+ ///
+ Record *getRecord() const { return TheRecord; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ TreePatternNode *getArg(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i].first;
+ }
+ Record *getArgRec(unsigned i) const {
+ return getArg(i)->getValueRecord();
+ }
+ Init *getArgVal(unsigned i) const {
+ return getArg(i)->getValue();
+ }
+ const std::string &getArgName(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i].second;
+ }
+
+ bool isResolved() const { return Resolved; }
+
+ /// InferAllTypes - Runs the type inference engine on the current pattern,
+ /// stopping when nothing can be inferred, then updating the Resolved field.
+ void InferAllTypes();
+
+ /// InstantiateNonterminals - If this pattern refers to any nonterminals which
+ /// are not themselves completely resolved, clone the nonterminal and resolve
+ /// it with the using context we provide.
+ void InstantiateNonterminals() {
+ Tree->InstantiateNonterminals(ISE);
+ }
+
+ /// clone - This method is used to make an exact copy of the current pattern,
+ /// then change the "TheRecord" instance variable to the specified record.
+ ///
+ Pattern *clone(Record *R) const;
+
+ /// error - Throw an exception, prefixing it with information about this
+ /// pattern.
+ void error(const std::string &Msg) const;
+
+ /// getSlotName - If this is a leaf node, return the slot name that the
+ /// operand will update.
+ std::string getSlotName() const;
+ static std::string getSlotName(Record *R);
+
+ void dump() const;
+
+private:
+ void calculateArgs(TreePatternNode *N, const std::string &Name);
+ MVT::ValueType getIntrinsicType(Record *R) const;
+ TreePatternNode *ParseTreePattern(DagInit *DI);
+ bool InferTypes(TreePatternNode *N, bool &MadeChange);
+};
+
+std::ostream &operator<<(std::ostream &OS, const Pattern &P);
+
+
+/// PatternOrganizer - This class represents all of the patterns which are
+/// useful for the instruction selector, neatly catagorized in a hierarchical
+/// structure.
+struct PatternOrganizer {
+ /// PatternsForNode - The list of patterns which can produce a value of a
+ /// particular slot type, given a particular root node in the tree. All of
+ /// the patterns in this vector produce the same value type and have the same
+ /// root DAG node.
+ typedef std::vector<Pattern*> PatternsForNode;
+
+ /// NodesForSlot - This map keeps track of all of the root DAG nodes which can
+ /// lead to the production of a value for this slot. All of the patterns in
+ /// this data structure produces values of the same slot.
+ typedef std::map<Record*, PatternsForNode> NodesForSlot;
+
+ /// AllPatterns - This data structure contains all patterns in the instruction
+ /// selector.
+ std::map<std::string, NodesForSlot> AllPatterns;
+
+ // Forwarding functions...
+ typedef std::map<std::string, NodesForSlot>::iterator iterator;
+ iterator begin() { return AllPatterns.begin(); }
+ iterator end() { return AllPatterns.end(); }
+
+
+ /// addPattern - Add the specified pattern to the appropriate location in the
+ /// collection.
+ void addPattern(Pattern *P);
+};
+
+
+/// InstrSelectorEmitter - The top-level class which coordinates construction
+/// and emission of the instruction selector.
+///
+class InstrSelectorEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+
+ std::map<Record*, NodeType> NodeTypes;
+
+ /// Patterns - a list of all of the patterns defined by the target description
+ ///
+ std::map<Record*, Pattern*> Patterns;
+
+ /// InstantiatedNTs - A data structure to keep track of which nonterminals
+ /// have been instantiated already...
+ ///
+ std::map<std::pair<Pattern*,MVT::ValueType>, Record*> InstantiatedNTs;
+
+ /// ComputableValues - This map indicates which patterns can be used to
+ /// generate a value that is used by the selector. The keys of this map
+ /// implicitly define the values that are used by the selector.
+ ///
+ PatternOrganizer ComputableValues;
+
+public:
+ InstrSelectorEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the instruction set description, returning true on failure.
+ void run(std::ostream &OS);
+
+ const CodeGenTarget &getTarget() const { return Target; }
+ std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; }
+ const NodeType &getNodeType(Record *R) const {
+ std::map<Record*, NodeType>::const_iterator I = NodeTypes.find(R);
+ assert(I != NodeTypes.end() && "Unknown node type!");
+ return I->second;
+ }
+
+ /// getPattern - return the pattern corresponding to the specified record, or
+ /// null if there is none.
+ Pattern *getPattern(Record *R) const {
+ std::map<Record*, Pattern*>::const_iterator I = Patterns.find(R);
+ return I != Patterns.end() ? I->second : 0;
+ }
+
+ /// ReadNonterminal - This method parses the specified record as a
+ /// nonterminal, but only if it hasn't been read in already.
+ Pattern *ReadNonterminal(Record *R);
+
+ /// InstantiateNonterminal - This method takes the nonterminal specified by
+ /// NT, which should not be completely resolved, clones it, applies ResultTy
+ /// to its root, then runs the type inference stuff on it. This should
+ /// produce a newly resolved nonterminal, which we make a record for and
+ /// return. To be extra fancy and efficient, this only makes one clone for
+ /// each type it is instantiated with.
+ Record *InstantiateNonterminal(Pattern *NT, MVT::ValueType ResultTy);
+
+private:
+ // ReadNodeTypes - Read in all of the node types in the current RecordKeeper,
+ // turning them into the more accessible NodeTypes data structure.
+ void ReadNodeTypes();
+
+ // ReadNonTerminals - Read in all nonterminals and incorporate them into our
+ // pattern database.
+ void ReadNonterminals();
+
+ // ReadInstructionPatterns - Read in all subclasses of Instruction, and
+ // process those with a useful Pattern field.
+ void ReadInstructionPatterns();
+
+ // ReadExpanderPatterns - Read in all of the expanded patterns.
+ void ReadExpanderPatterns();
+
+ // InstantiateNonterminals - Instantiate any unresolved nonterminals with
+ // information from the context that they are used in.
+ void InstantiateNonterminals();
+
+ // CalculateComputableValues - Fill in the ComputableValues map through
+ // analysis of the patterns we are playing with.
+ void CalculateComputableValues();
+
+ // EmitMatchCosters - Given a list of patterns, which all have the same root
+ // pattern operator, emit an efficient decision tree to decide which one to
+ // pick. This is structured this way to avoid reevaluations of non-obvious
+ // subexpressions.
+ void EmitMatchCosters(std::ostream &OS,
+ const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns,
+ const std::string &VarPrefix, unsigned Indent);
+
+ /// PrintExpanderOperand - Print out Arg as part of the instruction emission
+ /// process for the expander pattern P. This argument may be referencing some
+ /// values defined in P, or may just be physical register references or
+ /// something like that. If PrintArg is true, we are printing out arguments
+ /// to the BuildMI call. If it is false, we are printing the result register
+ /// name.
+ void PrintExpanderOperand(Init *Arg, const std::string &NameVar,
+ TreePatternNode *ArgDecl, Pattern *P,
+ bool PrintArg, std::ostream &OS);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/Makefile b/llvm/utils/TableGen/Makefile
new file mode 100644
index 00000000000..89a956d9dde
--- /dev/null
+++ b/llvm/utils/TableGen/Makefile
@@ -0,0 +1,18 @@
+LEVEL = ../..
+TOOLNAME = tblgen
+USEDLIBS = support.a
+
+.PRECIOUS: FileLexer.cpp FileParser.cpp
+
+include $(LEVEL)/Makefile.common
+
+#
+# Make the source file depend on the header file. In this way, dependencies
+# (which depend on the source file) won't get generated until bison is done
+# generating the C source and header files for the parser.
+#
+FileLexer.cpp: FileParser.h
+
+clean::
+ -rm -f FileParser.cpp FileParser.h FileLexer.cpp CommandLine.cpp
+ -rm -f FileParser.output
diff --git a/llvm/utils/TableGen/Record.cpp b/llvm/utils/TableGen/Record.cpp
new file mode 100644
index 00000000000..384005081e7
--- /dev/null
+++ b/llvm/utils/TableGen/Record.cpp
@@ -0,0 +1,676 @@
+//===- Record.cpp - Record implementation ---------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "Record.h"
+
+//===----------------------------------------------------------------------===//
+// Type implementations
+//===----------------------------------------------------------------------===//
+
+void RecTy::dump() const { print(std::cerr); }
+
+Init *BitRecTy::convertValue(BitsInit *BI) {
+ if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
+ return BI->getBit(0);
+}
+
+bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->getNumBits() == 1;
+}
+
+Init *BitRecTy::convertValue(IntInit *II) {
+ int Val = II->getValue();
+ if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
+
+ return new BitInit(Val != 0);
+}
+
+Init *BitRecTy::convertValue(TypedInit *VI) {
+ if (dynamic_cast<BitRecTy*>(VI->getType()))
+ return VI; // Accept variable if it is already of bit type!
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(UnsetInit *UI) {
+ BitsInit *Ret = new BitsInit(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new UnsetInit());
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitInit *UI) {
+ if (Size != 1) return 0; // Can only convert single bit...
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, UI);
+ return Ret;
+}
+
+// convertValue from Int initializer to bits type: Split the integer up into the
+// appropriate bits...
+//
+Init *BitsRecTy::convertValue(IntInit *II) {
+ int Value = II->getValue();
+ // Make sure this bitfield is large enough to hold the integer value...
+ if (Value >= 0) {
+ if (Value & ~((1 << Size)-1))
+ return 0;
+ } else {
+ if ((Value >> Size) != -1 || ((Value & (1 << Size-1)) == 0))
+ return 0;
+ }
+
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new BitInit(Value & (1 << i)));
+
+ return Ret;
+}
+
+Init *BitsRecTy::convertValue(BitsInit *BI) {
+ // If the number of bits is right, return it. Otherwise we need to expand or
+ // truncate...
+ if (BI->getNumBits() == Size) return BI;
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(TypedInit *VI) {
+ if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
+ if (BRT->Size == Size) {
+ BitsInit *Ret = new BitsInit(Size);
+ for (unsigned i = 0; i != Size; ++i)
+ Ret->setBit(i, new VarBitInit(VI, i));
+ return Ret;
+ }
+ if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
+ BitsInit *Ret = new BitsInit(1);
+ Ret->setBit(0, VI);
+ return Ret;
+ }
+
+ return 0;
+}
+
+Init *IntRecTy::convertValue(BitInit *BI) {
+ return new IntInit(BI->getValue());
+}
+
+Init *IntRecTy::convertValue(BitsInit *BI) {
+ int Result = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return 0;
+ }
+ return new IntInit(Result);
+}
+
+Init *IntRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+Init *StringRecTy::convertValue(TypedInit *TI) {
+ if (dynamic_cast<StringRecTy*>(TI->getType()))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+void ListRecTy::print(std::ostream &OS) const {
+ OS << "list<" << *Ty << ">";
+}
+
+Init *ListRecTy::convertValue(ListInit *LI) {
+ std::vector<Init*> Elements;
+
+ // Verify that all of the elements of the list are subclasses of the
+ // appropriate class!
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
+ Elements.push_back(CI);
+ else
+ return 0;
+
+ return new ListInit(Elements);
+}
+
+Init *ListRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with our class.
+ if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
+ if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
+ return TI;
+ return 0;
+}
+
+Init *CodeRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+
+void RecordRecTy::print(std::ostream &OS) const {
+ OS << Rec->getName();
+}
+
+Init *RecordRecTy::convertValue(DefInit *DI) {
+ // Ensure that DI is a subclass of Rec.
+ if (!DI->getDef()->isSubClassOf(Rec))
+ return 0;
+ return DI;
+}
+
+Init *RecordRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with Rec.
+ if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
+ if (RRT->getRecord()->isSubClassOf(getRecord()) ||
+ RRT->getRecord() == getRecord())
+ return TI;
+ return 0;
+}
+
+bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
+ return Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Initializer implementations
+//===----------------------------------------------------------------------===//
+
+void Init::dump() const { return print(std::cerr); }
+
+Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= getNumBits()) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, getBit(Bits[i]));
+ }
+ return BI;
+}
+
+void BitsInit::print(std::ostream &OS) const {
+ //if (!printInHex(OS)) return;
+ //if (!printAsVariable(OS)) return;
+ //if (!printAsUnset(OS)) return;
+
+ OS << "{ ";
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ if (i) OS << ", ";
+ if (Init *Bit = getBit(e-i-1))
+ Bit->print(OS);
+ else
+ OS << "*";
+ }
+ OS << " }";
+}
+
+bool BitsInit::printInHex(std::ostream &OS) const {
+ // First, attempt to convert the value into an integer value...
+ int Result = 0;
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return true;
+ }
+
+ OS << "0x" << std::hex << Result << std::dec;
+ return false;
+}
+
+bool BitsInit::printAsVariable(std::ostream &OS) const {
+ // Get the variable that we may be set equal to...
+ assert(getNumBits() != 0);
+ VarBitInit *FirstBit = dynamic_cast<VarBitInit*>(getBit(0));
+ if (FirstBit == 0) return true;
+ TypedInit *Var = FirstBit->getVariable();
+
+ // Check to make sure the types are compatible.
+ BitsRecTy *Ty = dynamic_cast<BitsRecTy*>(FirstBit->getVariable()->getType());
+ if (Ty == 0) return true;
+ if (Ty->getNumBits() != getNumBits()) return true; // Incompatible types!
+
+ // Check to make sure all bits are referring to the right bits in the variable
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ VarBitInit *Bit = dynamic_cast<VarBitInit*>(getBit(i));
+ if (Bit == 0 || Bit->getVariable() != Var || Bit->getBitNum() != i)
+ return true;
+ }
+
+ Var->print(OS);
+ return false;
+}
+
+bool BitsInit::printAsUnset(std::ostream &OS) const {
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i)
+ if (!dynamic_cast<UnsetInit*>(getBit(i)))
+ return true;
+ OS << "?";
+ return false;
+}
+
+// resolveReferences - If there are any field references that refer to fields
+// that have been filled in, we can propagate the values now.
+//
+Init *BitsInit::resolveReferences(Record &R) {
+ bool Changed = false;
+ BitsInit *New = new BitsInit(getNumBits());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ Init *B;
+ Init *CurBit = getBit(i);
+
+ do {
+ B = CurBit;
+ CurBit = CurBit->resolveReferences(R);
+ Changed |= B != CurBit;
+ } while (B != CurBit);
+ New->setBit(i, CurBit);
+ }
+
+ if (Changed)
+ return New;
+ delete New;
+ return this;
+}
+
+Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsInit *BI = new BitsInit(Bits.size());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= 32) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new BitInit(Value & (1 << Bits[i])));
+ }
+ return BI;
+}
+
+void ListInit::print(std::ostream &OS) const {
+ OS << "[";
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << *Values[i];
+ }
+ OS << "]";
+}
+
+Init *VarInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-bits variable...
+ unsigned NumBits = T->getNumBits();
+
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= NumBits) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new VarBitInit(this, Bits[i]));
+ }
+ return BI;
+}
+
+Init *VarInit::resolveBitReference(Record &R, unsigned Bit) {
+ if (R.isTemplateArg(getName()))
+ return this;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existant variable?");
+ assert(dynamic_cast<BitsInit*>(RV->getValue()));
+ BitsInit *BI = (BitsInit*)RV->getValue();
+
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (!dynamic_cast<UnsetInit*>(B)) // If the bit is not set...
+ return B; // Replace the VarBitInit with it.
+ return this;
+}
+
+RecTy *VarInit::getFieldType(const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = R.getValue(VarName))
+ if (Init *I = RV->getValue()->getFieldInit(R, FieldName))
+ return I;
+ else
+ return 0;
+ return 0;
+}
+
+/// resolveReferences - This method is used by classes that refer to other
+/// variables which may not be defined at the time they expression is formed.
+/// If a value is set for the variable later, this method will be called on
+/// users of the value to allow the value to propagate out.
+///
+Init *VarInit::resolveReferences(Record &R) {
+ if (RecordVal *Val = R.getValue(VarName))
+ if (!dynamic_cast<UnsetInit*>(Val->getValue()))
+ return Val->getValue();
+ return this;
+}
+
+
+Init *VarBitInit::resolveReferences(Record &R) {
+ Init *I = getVariable()->resolveBitReference(R, getBitNum());
+ if (I != getVariable())
+ return I;
+ return this;
+}
+
+RecTy *DefInit::getFieldType(const std::string &FieldName) const {
+ if (const RecordVal *RV = Def->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const {
+ return Def->getValue(FieldName)->getValue();
+}
+
+
+void DefInit::print(std::ostream &OS) const {
+ OS << Def->getName();
+}
+
+Init *FieldInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-bits field...
+ unsigned NumBits = T->getNumBits();
+
+ BitsInit *BI = new BitsInit(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= NumBits) {
+ delete BI;
+ return 0;
+ }
+ BI->setBit(i, new VarBitInit(this, Bits[i]));
+ }
+ return BI;
+}
+
+Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) {
+ Init *BitsVal = Rec->getFieldInit(R, FieldName);
+ if (BitsVal)
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (dynamic_cast<BitInit*>(B)) // If the bit is set...
+ return B; // Replace the VarBitInit with it.
+ }
+ return this;
+}
+
+Init *FieldInit::resolveReferences(Record &R) {
+ Init *BitsVal = Rec->getFieldInit(R, FieldName);
+ if (BitsVal) {
+ Init *BVR = BitsVal->resolveReferences(R);
+ return BVR->isComplete() ? BVR : this;
+ }
+ return this;
+}
+
+
+void DagInit::print(std::ostream &OS) const {
+ OS << "(" << NodeTypeDef->getName();
+ if (Args.size()) {
+ OS << " " << *Args[0];
+ if (!ArgNames[0].empty()) OS << ":$" << ArgNames[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ OS << ", " << *Args[i];
+ if (!ArgNames[i].empty()) OS << ":$" << ArgNames[i];
+ }
+ }
+ OS << ")";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Other implementations
+//===----------------------------------------------------------------------===//
+
+RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
+ : Name(N), Ty(T), Prefix(P) {
+ Value = Ty->convertValue(new UnsetInit());
+ assert(Value && "Cannot create unset value for current type!");
+}
+
+void RecordVal::dump() const { std::cerr << *this; }
+
+void RecordVal::print(std::ostream &OS, bool PrintSem) const {
+ if (getPrefix()) OS << "field ";
+ OS << *getType() << " " << getName();
+ if (getValue()) {
+ OS << " = " << *getValue();
+ }
+ if (PrintSem) OS << ";\n";
+}
+
+// resolveReferences - If there are any field references that refer to fields
+// that have been filled in, we can propagate the values now.
+//
+void Record::resolveReferences() {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ Values[i].setValue(Values[i].getValue()->resolveReferences(*this));
+}
+
+void Record::dump() const { std::cerr << *this; }
+
+std::ostream &operator<<(std::ostream &OS, const Record &R) {
+ OS << R.getName();
+
+ const std::vector<std::string> &TArgs = R.getTemplateArgs();
+ if (!TArgs.empty()) {
+ OS << "<";
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ const RecordVal *RV = R.getValue(TArgs[i]);
+ assert(RV && "Template argument record not found??");
+ RV->print(OS, false);
+ }
+ OS << ">";
+ }
+
+ OS << " {";
+ const std::vector<Record*> &SC = R.getSuperClasses();
+ if (!SC.empty()) {
+ OS << "\t//";
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ OS << " " << SC[i]->getName();
+ }
+ OS << "\n";
+
+ const std::vector<RecordVal> &Vals = R.getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+
+ return OS << "}\n";
+}
+
+/// getValueInit - Return the initializer for a value with the specified name,
+/// or throw an exception if the field does not exist.
+///
+Init *Record::getValueInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+ return R->getValue();
+}
+
+
+/// getValueAsString - This method looks up the specified field and returns its
+/// value as a string, throwing an exception if the field does not exist or if
+/// the value is not a string.
+///
+std::string Record::getValueAsString(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
+ return SI->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a string initializer!";
+}
+
+/// getValueAsBitsInit - This method looks up the specified field and returns
+/// its value as a BitsInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+BitsInit *Record::getValueAsBitsInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
+ return BI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a BitsInit initializer!";
+}
+
+/// getValueAsListInit - This method looks up the specified field and returns
+/// its value as a ListInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+ListInit *Record::getValueAsListInit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
+ return LI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsInt - This method looks up the specified field and returns its
+/// value as an int, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+int Record::getValueAsInt(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
+ return II->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsDef - This method looks up the specified field and returns its
+/// value as a Record, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+Record *Record::getValueAsDef(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
+ return DI->getDef();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsBit - This method looks up the specified field and returns its
+/// value as a bit, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+bool Record::getValueAsBit(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
+ return BI->getValue();
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a bit initializer!";
+}
+
+/// getValueAsDag - This method looks up the specified field and returns its
+/// value as an Dag, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+DagInit *Record::getValueAsDag(const std::string &FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record '" + getName() + "' does not have a field named '" +
+ FieldName + "!\n";
+
+ if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
+ return DI;
+ throw "Record '" + getName() + "', field '" + FieldName +
+ "' does not have a dag initializer!";
+}
+
+
+void RecordKeeper::dump() const { std::cerr << *this; }
+
+std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK) {
+ OS << "------------- Classes -----------------\n";
+ const std::map<std::string, Record*> &Classes = RK.getClasses();
+ for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ OS << "class " << *I->second;
+
+ OS << "------------- Defs -----------------\n";
+ const std::map<std::string, Record*> &Defs = RK.getDefs();
+ for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ OS << "def " << *I->second;
+ return OS;
+}
+
+
+/// getAllDerivedDefinitions - This method returns all concrete definitions
+/// that derive from the specified class name. If a class with the specified
+/// name does not exist, an error is printed and true is returned.
+std::vector<Record*>
+RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
+ Record *Class = Records.getClass(ClassName);
+ if (!Class)
+ throw "ERROR: Couldn't find the '" + ClassName + "' class!\n";
+
+ std::vector<Record*> Defs;
+ for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
+ E = getDefs().end(); I != E; ++I)
+ if (I->second->isSubClassOf(Class))
+ Defs.push_back(I->second);
+
+ return Defs;
+}
diff --git a/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h
new file mode 100644
index 00000000000..4a2fa057cfd
--- /dev/null
+++ b/llvm/utils/TableGen/Record.h
@@ -0,0 +1,849 @@
+//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===//
+//
+// This file defines the main TableGen data structures, including the TableGen
+// types, values, and high-level data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+#include <cassert>
+
+// RecTy subclasses...
+class BitRecTy;
+class BitsRecTy;
+class IntRecTy;
+class StringRecTy;
+class ListRecTy;
+class CodeRecTy;
+class DagRecTy;
+class RecordRecTy;
+
+// Init subclasses...
+class Init;
+class UnsetInit;
+class BitInit;
+class BitsInit;
+class IntInit;
+class StringInit;
+class CodeInit;
+class ListInit;
+class DefInit;
+class DagInit;
+class TypedInit;
+class VarInit;
+class FieldInit;
+class VarBitInit;
+
+// Other classes...
+class Record;
+
+//===----------------------------------------------------------------------===//
+// Type Classes
+//===----------------------------------------------------------------------===//
+
+struct RecTy {
+ virtual ~RecTy() {}
+
+ virtual void print(std::ostream &OS) const = 0;
+ void dump() const;
+
+ /// typeIsConvertibleTo - Return true if all values of 'this' type can be
+ /// converted to the specified type.
+ virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
+
+public: // These methods should only be called from subclasses of Init
+ virtual Init *convertValue( UnsetInit *UI) { return 0; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI) { return 0; }
+ virtual Init *convertValue( VarInit *VI) {
+ return convertValue((TypedInit*)VI);
+ }
+ virtual Init *convertValue( FieldInit *FI) {
+ return convertValue((TypedInit*)FI);
+ }
+
+public: // These methods should only be called by subclasses of RecTy.
+ // baseClassOf - These virtual methods should be overloaded to return true iff
+ // all values of type 'RHS' can be converted to the 'this' type.
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const RecTy &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+
+/// BitRecTy - 'bit' - Represent a single bit
+///
+struct BitRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(BitInit *BI) { return (Init*)BI; }
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(IntInit *II);
+ Init *convertValue(TypedInit *VI);
+ Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
+
+ void print(std::ostream &OS) const { OS << "bit"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const;
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+};
+
+
+/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
+///
+class BitsRecTy : public RecTy {
+ unsigned Size;
+public:
+ BitsRecTy(unsigned Sz) : Size(Sz) {}
+
+ unsigned getNumBits() const { return Size; }
+
+ Init *convertValue(UnsetInit *UI);
+ Init *convertValue(BitInit *UI);
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(IntInit *II);
+ Init *convertValue(TypedInit *VI);
+
+ void print(std::ostream &OS) const { OS << "bits<" << Size << ">"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->Size == Size;
+ }
+};
+
+
+/// IntRecTy - 'int' - Represent an integer value of no particular size
+///
+struct IntRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(IntInit *II) { return (Init*)II; }
+ Init *convertValue(BitInit *BI);
+ Init *convertValue(BitsInit *BI);
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "int"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
+};
+
+/// StringRecTy - 'string' - Represent an string value
+///
+struct StringRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(StringInit *SI) { return (Init*)SI; }
+ Init *convertValue(TypedInit *TI);
+ void print(std::ostream &OS) const { OS << "string"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
+};
+
+/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
+/// the specified type.
+///
+class ListRecTy : public RecTy {
+ RecTy *Ty;
+public:
+ ListRecTy(RecTy *T) : Ty(T) {}
+
+ RecTy *getElementType() const { return Ty; }
+
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue(ListInit *LI);
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const ListRecTy *RHS) const {
+ return RHS->getElementType()->typeIsConvertibleTo(Ty);
+ }
+};
+
+/// CodeRecTy - 'code' - Represent an code fragment, function or method.
+///
+struct CodeRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( CodeInit *CI) { return (Init*)CI; }
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "code"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
+};
+
+/// DagRecTy - 'dag' - Represent a dag fragment
+///
+struct DagRecTy : public RecTy {
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( DagInit *CI) { return (Init*)CI; }
+ Init *convertValue(TypedInit *TI);
+
+ void print(std::ostream &OS) const { OS << "dag"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
+};
+
+
+/// RecordRecTy - '<classname>' - Represent an instance of a class, such as:
+/// (R32 X = EAX).
+///
+class RecordRecTy : public RecTy {
+ Record *Rec;
+public:
+ RecordRecTy(Record *R) : Rec(R) {}
+
+ Record *getRecord() const { return Rec; }
+
+ Init *convertValue(UnsetInit *UI) { return (Init*)UI; }
+ Init *convertValue( DefInit *DI);
+ Init *convertValue(TypedInit *VI);
+
+ void print(std::ostream &OS) const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const;
+};
+
+
+
+//===----------------------------------------------------------------------===//
+// Initializer Classes
+//===----------------------------------------------------------------------===//
+
+struct Init {
+ virtual ~Init() {}
+
+ /// isComplete - This virtual method should be overridden by values that may
+ /// not be completely specified yet.
+ virtual bool isComplete() const { return true; }
+
+ /// print - Print out this value.
+ virtual void print(std::ostream &OS) const = 0;
+
+ /// dump - Debugging method that may be called through a debugger, just
+ /// invokes print on cerr.
+ void dump() const;
+
+ /// convertInitializerTo - This virtual function is a simple call-back
+ /// function that should be overridden to call the appropriate
+ /// RecTy::convertValue method.
+ ///
+ virtual Init *convertInitializerTo(RecTy *Ty) = 0;
+
+ /// convertInitializerBitRange - This method is used to implement the bitrange
+ /// selection operator. Given an initializer, it selects the specified bits
+ /// out, returning them as a new init of bits type. If it is not legal to use
+ /// the bit subscript operator on this initializer, return null.
+ ///
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits) {
+ return 0;
+ }
+
+ /// getFieldType - This method is used to implement the FieldInit class.
+ /// Implementors of this method should return the type of the named field if
+ /// they are of record type.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
+
+ /// getFieldInit - This method complements getFieldType to return the
+ /// initializer for the specified field. If getFieldType returns non-null
+ /// this method should return non-null, otherwise it returns null.
+ ///
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const {
+ return 0;
+ }
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// If a value is set for the variable later, this method will be called on
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R) { return this; }
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const Init &I) {
+ I.print(OS); return OS;
+}
+
+
+/// UnsetInit - ? - Represents an uninitialized value
+///
+struct UnsetInit : public Init {
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual bool isComplete() const { return false; }
+ virtual void print(std::ostream &OS) const { OS << "?"; }
+};
+
+
+/// BitInit - true/false - Represent a concrete initializer for a bit.
+///
+class BitInit : public Init {
+ bool Value;
+public:
+ BitInit(bool V) : Value(V) {}
+
+ bool getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << (Value ? "1" : "0"); }
+};
+
+/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
+/// It contains a vector of bits, whose size is determined by the type.
+///
+class BitsInit : public Init {
+ std::vector<Init*> Bits;
+public:
+ BitsInit(unsigned Size) : Bits(Size) {}
+
+ unsigned getNumBits() const { return Bits.size(); }
+
+ Init *getBit(unsigned Bit) const {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ return Bits[Bit];
+ }
+ void setBit(unsigned Bit, Init *V) {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ assert(Bits[Bit] == 0 && "Bit already set!");
+ Bits[Bit] = V;
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual bool isComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (!getBit(i)->isComplete()) return false;
+ return true;
+ }
+ virtual void print(std::ostream &OS) const;
+
+ virtual Init *resolveReferences(Record &R);
+
+ // printXX - Print this bitstream with the specified format, returning true if
+ // it is not possible.
+ bool printInHex(std::ostream &OS) const;
+ bool printAsVariable(std::ostream &OS) const;
+ bool printAsUnset(std::ostream &OS) const;
+};
+
+
+/// IntInit - 7 - Represent an initalization by a literal integer value.
+///
+class IntInit : public Init {
+ int Value;
+public:
+ IntInit(int V) : Value(V) {}
+
+ int getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual void print(std::ostream &OS) const { OS << Value; }
+};
+
+
+/// StringInit - "foo" - Represent an initialization by a string value.
+///
+class StringInit : public Init {
+ std::string Value;
+public:
+ StringInit(const std::string &V) : Value(V) {}
+
+ const std::string &getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << "\"" << Value << "\""; }
+};
+
+/// CodeInit - "[{...}]" - Represent a code fragment.
+///
+class CodeInit : public Init {
+ std::string Value;
+public:
+ CodeInit(const std::string &V) : Value(V) {}
+
+ const std::string getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const { OS << "[{" << Value << "}]"; }
+};
+
+/// ListInit - [AL, AH, CL] - Represent a list of defs
+///
+class ListInit : public Init {
+ std::vector<Init*> Values;
+public:
+ ListInit(std::vector<Init*> &Vs) {
+ Values.swap(Vs);
+ }
+
+ unsigned getSize() const { return Values.size(); }
+ Init *getElement(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ return Values[i];
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual void print(std::ostream &OS) const;
+};
+
+
+/// TypedInit - This is the common super-class of types that have a specific,
+/// explicit, type.
+///
+class TypedInit : public Init {
+ RecTy *Ty;
+public:
+ TypedInit(RecTy *T) : Ty(T) {}
+
+ RecTy *getType() const { return Ty; }
+
+ /// resolveBitReference - This method is used to implement
+ /// VarBitInit::resolveReferences. If the bit is able to be resolved, we
+ /// simply return the resolved value, otherwise we return this.
+ ///
+ virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0;
+};
+
+/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
+///
+class VarInit : public TypedInit {
+ std::string VarName;
+public:
+ VarInit(const std::string &VN, RecTy *T) : TypedInit(T), VarName(VN) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ const std::string &getName() const { return VarName; }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual Init *resolveBitReference(Record &R, unsigned Bit);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// If a value is set for the variable later, this method will be called on
+ /// users of the value to allow the value to propagate out.
+ ///
+ virtual Init *resolveReferences(Record &R);
+
+ virtual void print(std::ostream &OS) const { OS << VarName; }
+};
+
+
+/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
+///
+class VarBitInit : public Init {
+ TypedInit *TI;
+ unsigned Bit;
+public:
+ VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
+ assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
+ ((BitsRecTy*)T->getType())->getNumBits() > B &&
+ "Illegal VarBitInit expression!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getBitNum() const { return Bit; }
+
+ virtual void print(std::ostream &OS) const {
+ TI->print(OS); OS << "{" << Bit << "}";
+ }
+ virtual Init *resolveReferences(Record &R);
+};
+
+
+/// DefInit - AL - Represent a reference to a 'def' in the description
+///
+class DefInit : public Init {
+ Record *Def;
+public:
+ DefInit(Record *D) : Def(D) {}
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Record *getDef() const { return Def; }
+
+ //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const std::string &FieldName) const;
+
+ virtual void print(std::ostream &OS) const;
+};
+
+
+/// FieldInit - X.Y - Represent a reference to a subfield of a variable
+///
+class FieldInit : public TypedInit {
+ Init *Rec; // Record we are referring to
+ std::string FieldName; // Field we are accessing
+public:
+ FieldInit(Init *R, const std::string &FN)
+ : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
+ assert(getType() && "FieldInit with non-record type!");
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual Init *resolveBitReference(Record &R, unsigned Bit);
+
+ virtual Init *resolveReferences(Record &R);
+
+ virtual void print(std::ostream &OS) const {
+ Rec->print(OS); OS << "." << FieldName;
+ }
+};
+
+/// DagInit - (def a, b) - Represent a DAG tree value. DAG inits are required
+/// to have Records for their first value, after that, any legal Init is
+/// possible.
+///
+class DagInit : public Init {
+ Record *NodeTypeDef;
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+public:
+ DagInit(Record *D, const std::vector<std::pair<Init*, std::string> > &args)
+ : NodeTypeDef(D) {
+ Args.reserve(args.size());
+ ArgNames.reserve(args.size());
+ for (unsigned i = 0, e = args.size(); i != e; ++i) {
+ Args.push_back(args[i].first);
+ ArgNames.push_back(args[i].second);
+ }
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) {
+ return Ty->convertValue(this);
+ }
+
+ Record *getNodeType() const { return NodeTypeDef; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ Init *getArg(unsigned Num) const {
+ assert(Num < Args.size() && "Arg number out of range!");
+ return Args[Num];
+ }
+ const std::string &getArgName(unsigned Num) const {
+ assert(Num < ArgNames.size() && "Arg number out of range!");
+ return ArgNames[Num];
+ }
+
+ void setArg(unsigned Num, Init *I) {
+ assert(Num < Args.size() && "Arg number out of range!");
+ Args[Num] = I;
+ }
+
+ virtual void print(std::ostream &OS) const;
+};
+
+//===----------------------------------------------------------------------===//
+// High-Level Classes
+//===----------------------------------------------------------------------===//
+
+class RecordVal {
+ std::string Name;
+ RecTy *Ty;
+ unsigned Prefix;
+ Init *Value;
+public:
+ RecordVal(const std::string &N, RecTy *T, unsigned P);
+
+ const std::string &getName() const { return Name; }
+
+ unsigned getPrefix() const { return Prefix; }
+ RecTy *getType() const { return Ty; }
+ Init *getValue() const { return Value; }
+
+ bool setValue(Init *V) {
+ if (V) {
+ Value = V->convertInitializerTo(Ty);
+ return Value == 0;
+ }
+ Value = 0;
+ return false;
+ }
+
+ void dump() const;
+ void print(std::ostream &OS, bool PrintSem = true) const;
+};
+
+inline std::ostream &operator<<(std::ostream &OS, const RecordVal &RV) {
+ RV.print(OS << " ");
+ return OS;
+}
+
+struct Record {
+ const std::string Name;
+ std::vector<std::string> TemplateArgs;
+ std::vector<RecordVal> Values;
+ std::vector<Record*> SuperClasses;
+public:
+
+ Record(const std::string &N) : Name(N) {}
+ ~Record() {}
+
+ const std::string &getName() const { return Name; }
+ const std::vector<std::string> &getTemplateArgs() const {
+ return TemplateArgs;
+ }
+ const std::vector<RecordVal> &getValues() const { return Values; }
+ const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
+
+ bool isTemplateArg(const std::string &Name) const {
+ for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
+ if (TemplateArgs[i] == Name) return true;
+ return false;
+ }
+
+ const RecordVal *getValue(const std::string &Name) const {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+ RecordVal *getValue(const std::string &Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+
+ void addTemplateArg(const std::string &Name) {
+ assert(!isTemplateArg(Name) && "Template arg already defined!");
+ TemplateArgs.push_back(Name);
+ }
+
+ void addValue(const RecordVal &RV) {
+ assert(getValue(RV.getName()) == 0 && "Value already added!");
+ Values.push_back(RV);
+ }
+
+ void removeValue(const std::string &Name) {
+ assert(getValue(Name) && "Cannot remove an entry that does not exist!");
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) {
+ Values.erase(Values.begin()+i);
+ return;
+ }
+ assert(0 && "Name does not exist in record!");
+ }
+
+ bool isSubClassOf(Record *R) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i] == R)
+ return true;
+ return false;
+ }
+
+ bool isSubClassOf(const std::string &Name) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i]->getName() == Name)
+ return true;
+ return false;
+ }
+
+ void addSuperClass(Record *R) {
+ assert(!isSubClassOf(R) && "Already subclassing record!");
+ SuperClasses.push_back(R);
+ }
+
+ // resolveReferences - If there are any field references that refer to fields
+ // that have been filled in, we can propagate the values now.
+ //
+ void resolveReferences();
+
+ void dump() const;
+
+ //===--------------------------------------------------------------------===//
+ // High-level methods useful to tablegen back-ends
+ //
+
+ /// getValueInit - Return the initializer for a value with the specified name,
+ /// or throw an exception if the field does not exist.
+ ///
+ Init *getValueInit(const std::string &FieldName) const;
+
+ /// getValueAsString - This method looks up the specified field and returns
+ /// its value as a string, throwing an exception if the field does not exist
+ /// or if the value is not a string.
+ ///
+ std::string getValueAsString(const std::string &FieldName) const;
+
+ /// getValueAsBitsInit - This method looks up the specified field and returns
+ /// its value as a BitsInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ BitsInit *getValueAsBitsInit(const std::string &FieldName) const;
+
+ /// getValueAsListInit - This method looks up the specified field and returns
+ /// its value as a ListInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ ListInit *getValueAsListInit(const std::string &FieldName) const;
+
+ /// getValueAsDef - This method looks up the specified field and returns its
+ /// value as a Record, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ Record *getValueAsDef(const std::string &FieldName) const;
+
+ /// getValueAsBit - This method looks up the specified field and returns its
+ /// value as a bit, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ bool getValueAsBit(const std::string &FieldName) const;
+
+ /// getValueAsInt - This method looks up the specified field and returns its
+ /// value as an int, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ int getValueAsInt(const std::string &FieldName) const;
+
+ /// getValueAsDag - This method looks up the specified field and returns its
+ /// value as an Dag, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ DagInit *getValueAsDag(const std::string &FieldName) const;
+};
+
+std::ostream &operator<<(std::ostream &OS, const Record &R);
+
+class RecordKeeper {
+ std::map<std::string, Record*> Classes, Defs;
+public:
+ ~RecordKeeper() {
+ for (std::map<std::string, Record*>::iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ delete I->second;
+ for (std::map<std::string, Record*>::iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ delete I->second;
+ }
+
+ const std::map<std::string, Record*> &getClasses() const { return Classes; }
+ const std::map<std::string, Record*> &getDefs() const { return Defs; }
+
+ Record *getClass(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
+ return I == Classes.end() ? 0 : I->second;
+ }
+ Record *getDef(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
+ return I == Defs.end() ? 0 : I->second;
+ }
+ void addClass(Record *R) {
+ assert(getClass(R->getName()) == 0 && "Class already exists!");
+ Classes.insert(std::make_pair(R->getName(), R));
+ }
+ void addDef(Record *R) {
+ assert(getDef(R->getName()) == 0 && "Def already exists!");
+ Defs.insert(std::make_pair(R->getName(), R));
+ }
+
+ //===--------------------------------------------------------------------===//
+ // High-level helper methods, useful for tablegen backends...
+
+ /// getAllDerivedDefinitions - This method returns all concrete definitions
+ /// that derive from the specified class name. If a class with the specified
+ /// name does not exist, an exception is thrown.
+ std::vector<Record*>
+ getAllDerivedDefinitions(const std::string &ClassName) const;
+
+
+ void dump() const;
+};
+
+std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK);
+
+extern RecordKeeper Records;
+
+#endif
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
new file mode 100644
index 00000000000..af3efe3a9c4
--- /dev/null
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -0,0 +1,234 @@
+//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterInfoEmitter.h"
+#include "CodeGenWrappers.h"
+#include "Record.h"
+#include "Support/StringExtras.h"
+#include <set>
+
+// runEnums - Print out enum values for all of the registers.
+void RegisterInfoEmitter::runEnums(std::ostream &OS) {
+ std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register");
+
+ if (Registers.size() == 0)
+ throw std::string("No 'Register' subclasses defined!");
+
+ std::string Namespace = Registers[0]->getValueAsString("Namespace");
+
+ EmitSourceFileHeader("Target Register Enum Values", OS);
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n NoRegister,\n";
+
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ OS << " " << Registers[i]->getName() << ", \t// " << i+1 << "\n";
+
+ OS << " };\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+}
+
+void RegisterInfoEmitter::runHeader(std::ostream &OS) {
+ EmitSourceFileHeader("Register Information Header Fragment", OS);
+ const std::string &TargetName = CodeGenTarget().getName();
+ std::string ClassName = TargetName + "GenRegisterInfo";
+
+ OS << "#include \"llvm/Target/MRegisterInfo.h\"\n\n";
+
+ OS << "struct " << ClassName << " : public MRegisterInfo {\n"
+ << " " << ClassName
+ << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
+ << " const unsigned* getCalleeSaveRegs() const;\n"
+ << "};\n\n";
+
+ std::vector<Record*> RegisterClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+
+ OS << "namespace " << TargetName << " { // Register classes\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (RegisterClasses[i]->getValueAsBit("isDummyClass"))
+ continue; // Ignore dummies
+
+ const std::string &Name = RegisterClasses[i]->getName();
+ if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes
+ OS << " extern TargetRegisterClass *" << Name << "RegisterClass;\n";
+ }
+ OS << "} // end of namespace " << TargetName << "\n\n";
+}
+
+// RegisterInfoEmitter::run - Main register file description emitter.
+//
+void RegisterInfoEmitter::run(std::ostream &OS) {
+ EmitSourceFileHeader("Register Information Source Fragment", OS);
+
+ // Start out by emitting each of the register classes... to do this, we build
+ // a set of registers which belong to a register class, this is to ensure that
+ // each register is only in a single register class.
+ //
+ std::vector<Record*> RegisterClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+
+ std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register");
+
+ std::set<Record*> RegistersFound;
+ std::vector<std::string> RegClassNames;
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ Record *RC = RegisterClasses[rc];
+ if (RC->getValueAsBit("isDummyClass")) continue; // Ignore dummies
+
+ std::string Name = RC->getName();
+ if (Name.size() > 9 && Name[9] == '.') {
+ static unsigned AnonCounter = 0;
+ Name = "AnonRegClass_"+utostr(AnonCounter++);
+ }
+
+ RegClassNames.push_back(Name);
+
+ // Emit the register list now...
+ OS << " // " << Name << " Register Class...\n const unsigned " << Name
+ << "[] = {\n ";
+ ListInit *RegList = RC->getValueAsListInit("MemberList");
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i));
+ if (!RegDef) throw "Register class member is not a record!";
+ Record *Reg = RegDef->getDef();
+ if (!Reg->isSubClassOf("Register"))
+ throw "Register Class member '" + Reg->getName() +
+ " does not derive from the Register class!";
+ if (RegistersFound.count(Reg))
+ throw "Register '" + Reg->getName() +
+ "' included in multiple register classes!";
+ RegistersFound.insert(Reg);
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
+ << " " << Name << "Class() : TargetRegisterClass("
+ << RC->getValueAsInt("Size")/8 << ", " << RC->getValueAsInt("Alignment")
+ << ", " << Name << ", " << Name << " + " << RegList->getSize()
+ << ") {}\n";
+
+ if (CodeInit *CI = dynamic_cast<CodeInit*>(RC->getValueInit("Methods")))
+ OS << CI->getValue();
+ else
+ throw "Expected 'code' fragment for 'Methods' value in register class '"+
+ RC->getName() + "'!";
+
+ OS << " } " << Name << "Instance;\n\n";
+ }
+
+ OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
+ for (unsigned i = 0, e = RegClassNames.size(); i != e; ++i)
+ OS << " &" << RegClassNames[i] << "Instance,\n";
+ OS << " };\n";
+
+ // Emit register class aliases...
+ std::vector<Record*> RegisterAliasesRecs =
+ Records.getAllDerivedDefinitions("RegisterAliases");
+ std::map<Record*, std::set<Record*> > RegisterAliases;
+
+ for (unsigned i = 0, e = RegisterAliasesRecs.size(); i != e; ++i) {
+ Record *AS = RegisterAliasesRecs[i];
+ Record *R = AS->getValueAsDef("Reg");
+ ListInit *LI = AS->getValueAsListInit("Aliases");
+
+ // Add information that R aliases all of the elements in the list... and
+ // that everything in the list aliases R.
+ for (unsigned j = 0, e = LI->getSize(); j != e; ++j) {
+ DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j));
+ if (!Reg) throw "ERROR: Alias list element is not a def!";
+ if (RegisterAliases[R].count(Reg->getDef()))
+ std::cerr << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg->getDef())
+ << " specified multiple times!\n";
+ RegisterAliases[R].insert(Reg->getDef());
+
+ if (RegisterAliases[Reg->getDef()].count(R))
+ std::cerr << "Warning: register alias between " << getQualifiedName(R)
+ << " and " << getQualifiedName(Reg->getDef())
+ << " specified multiple times!\n";
+ RegisterAliases[Reg->getDef()].insert(R);
+ }
+ }
+
+ if (!RegisterAliases.empty())
+ OS << "\n\n // Register Alias Sets...\n";
+
+ // Loop over all of the registers which have aliases, emitting the alias list
+ // to memory.
+ for (std::map<Record*, std::set<Record*> >::iterator
+ I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
+ OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { ";
+ for (std::set<Record*>::iterator ASI = I->second.begin(),
+ E = I->second.end(); ASI != E; ++ASI)
+ OS << getQualifiedName(*ASI) << ", ";
+ OS << "0 };\n";
+ }
+
+ OS << "\n const MRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
+ OS << " { \"NOREG\",\t0,\t\t0,\t0 },\n";
+ // Now that register alias sets have been emitted, emit the register
+ // descriptors now.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ Record *Reg = Registers[i];
+ OS << " { \"";
+ if (!Reg->getValueAsString("Name").empty())
+ OS << Reg->getValueAsString("Name");
+ else
+ OS << Reg->getName();
+ OS << "\",\t";
+ if (RegisterAliases.count(Reg))
+ OS << Reg->getName() << "_AliasSet,\t";
+ else
+ OS << "0,\t\t";
+ OS << "0, 0 },\n";
+ }
+ OS << " };\n"; // End of register descriptors...
+ OS << "}\n\n"; // End of anonymous namespace...
+
+ CodeGenTarget Target;
+
+ OS << "namespace " << Target.getName() << " { // Register classes\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (RegisterClasses[i]->getValueAsBit("isDummyClass"))
+ continue; // Ignore dummies
+
+ const std::string &Name = RegisterClasses[i]->getName();
+ if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes
+ OS << " TargetRegisterClass *" << Name << "RegisterClass = &"
+ << Name << "Instance;\n";
+ }
+ OS << "} // end of namespace " << Target.getName() << "\n\n";
+
+
+
+ std::string ClassName = Target.getName() + "GenRegisterInfo";
+
+ // Emit the constructor of the class...
+ OS << ClassName << "::" << ClassName
+ << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
+ << " : MRegisterInfo(RegisterDescriptors, " << Registers.size()+1
+ << ", RegisterClasses, RegisterClasses+" << RegClassNames.size() << ",\n "
+ << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {}\n\n";
+
+ // Emit the getCalleeSaveRegs method...
+ OS << "const unsigned* " << ClassName << "::getCalleeSaveRegs() const {\n"
+ << " static const unsigned CalleeSaveRegs[] = {\n ";
+
+ const std::vector<Record*> &CSR = Target.getCalleeSavedRegisters();
+ for (unsigned i = 0, e = CSR.size(); i != e; ++i)
+ OS << getQualifiedName(CSR[i]) << ", ";
+ OS << " 0\n };\n return CalleeSaveRegs;\n}\n\n";
+}
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.h b/llvm/utils/TableGen/RegisterInfoEmitter.h
new file mode 100644
index 00000000000..65a03303cdd
--- /dev/null
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.h
@@ -0,0 +1,29 @@
+//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REGISTER_INFO_EMITTER_H
+#define REGISTER_INFO_EMITTER_H
+
+#include "TableGenBackend.h"
+
+class RegisterInfoEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // run - Output the register file description, returning true on failure.
+ void run(std::ostream &o);
+
+ // runHeader - Emit a header fragment for the register info emitter.
+ void runHeader(std::ostream &o);
+
+ // runEnums - Print out enum values for all of the registers.
+ void runEnums(std::ostream &o);
+};
+
+#endif
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
new file mode 100644
index 00000000000..971ac9081aa
--- /dev/null
+++ b/llvm/utils/TableGen/TableGen.cpp
@@ -0,0 +1,482 @@
+//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//
+// TableGen is a tool which can be used to build up a description of something,
+// then invoke one or more "tablegen backends" to emit information about the
+// description in some predefined format. In practice, this is used by the LLVM
+// code generators to automate generation of a code generator through a
+// high-level description of the target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Record.h"
+#include "Support/CommandLine.h"
+#include "Support/Signals.h"
+#include "Support/FileUtilities.h"
+#include "CodeEmitterGen.h"
+#include "RegisterInfoEmitter.h"
+#include "InstrInfoEmitter.h"
+#include "InstrSelectorEmitter.h"
+#include <algorithm>
+#include <cstdio>
+#include <fstream>
+
+enum ActionType {
+ PrintRecords,
+ GenEmitter,
+ GenRegisterEnums, GenRegister, GenRegisterHeader,
+ GenInstrEnums, GenInstrs, GenInstrSelector,
+ PrintEnums,
+ Parse,
+};
+
+namespace {
+ cl::opt<ActionType>
+ Action(cl::desc("Action to perform:"),
+ cl::values(clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(GenEmitter, "gen-emitter",
+ "Generate machine code emitter"),
+ clEnumValN(GenRegisterEnums, "gen-register-enums",
+ "Generate enum values for registers"),
+ clEnumValN(GenRegister, "gen-register-desc",
+ "Generate a register info description"),
+ clEnumValN(GenRegisterHeader, "gen-register-desc-header",
+ "Generate a register info description header"),
+ clEnumValN(GenInstrEnums, "gen-instr-enums",
+ "Generate enum values for instructions"),
+ clEnumValN(GenInstrs, "gen-instr-desc",
+ "Generate instruction descriptions"),
+ clEnumValN(GenInstrSelector, "gen-instr-selector",
+ "Generate an instruction selector"),
+ clEnumValN(PrintEnums, "print-enums",
+ "Print enum values for a class"),
+ clEnumValN(Parse, "parse",
+ "Interpret machine code (testing only)"),
+ 0));
+
+ cl::opt<std::string>
+ Class("class", cl::desc("Print Enum list for this class"),
+ cl::value_desc("class name"));
+
+ cl::opt<std::string>
+ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
+ cl::init("-"));
+
+ cl::opt<std::string>
+ InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ cl::opt<std::string>
+ IncludeDir("I", cl::desc("Directory of include files"),
+ cl::value_desc("directory"), cl::init(""));
+}
+
+
+void ParseFile(const std::string &Filename, const std::string & IncludeDir);
+
+RecordKeeper Records;
+
+static Init *getBit(Record *R, unsigned BitNo) {
+ const std::vector<RecordVal> &V = R->getValues();
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (V[i].getPrefix()) {
+ assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
+ "Can only handle fields of bits<> type!");
+ BitsInit *I = (BitsInit*)V[i].getValue();
+ if (BitNo < I->getNumBits())
+ return I->getBit(BitNo);
+ BitNo -= I->getNumBits();
+ }
+
+ std::cerr << "Cannot find requested bit!\n";
+ abort();
+ return 0;
+}
+
+static unsigned getNumBits(Record *R) {
+ const std::vector<RecordVal> &V = R->getValues();
+ unsigned Num = 0;
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (V[i].getPrefix()) {
+ assert(dynamic_cast<BitsInit*>(V[i].getValue()) &&
+ "Can only handle fields of bits<> type!");
+ Num += ((BitsInit*)V[i].getValue())->getNumBits();
+ }
+ return Num;
+}
+
+static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) {
+ return dynamic_cast<BitInit*>(getBit(I1, BitNo)) &&
+ dynamic_cast<BitInit*>(getBit(I2, BitNo));
+}
+
+static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) {
+ BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo));
+ BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo));
+
+ return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue();
+}
+
+static bool BitRangesEqual(Record *I1, Record *I2,
+ unsigned Start, unsigned End) {
+ for (unsigned i = Start; i != End; ++i)
+ if (!BitsAreEqual(I1, I2, i))
+ return false;
+ return true;
+}
+
+static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) {
+ // Look for the first bit of the pair that are required to be 0 or 1.
+ while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit)))
+ ++FirstFixedBit;
+ return FirstFixedBit;
+}
+
+static void FindInstDifferences(Record *I1, Record *I2,
+ unsigned FirstFixedBit, unsigned MaxBits,
+ unsigned &FirstVaryingBitOverall,
+ unsigned &LastFixedBitOverall) {
+ // Compare the first instruction to the rest of the instructions, looking for
+ // fields that differ.
+ //
+ unsigned FirstVaryingBit = FirstFixedBit;
+ while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit))
+ ++FirstVaryingBit;
+
+ unsigned LastFixedBit = FirstVaryingBit;
+ while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit))
+ ++LastFixedBit;
+
+ if (FirstVaryingBit < FirstVaryingBitOverall)
+ FirstVaryingBitOverall = FirstVaryingBit;
+ if (LastFixedBit < LastFixedBitOverall)
+ LastFixedBitOverall = LastFixedBit;
+}
+
+static bool getBitValue(Record *R, unsigned BitNo) {
+ Init *I = getBit(R, BitNo);
+ assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!");
+ return ((BitInit*)I)->getValue();
+}
+
+struct BitComparator {
+ unsigned BitBegin, BitEnd;
+ BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {}
+
+ bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2
+ for (unsigned i = BitBegin; i != BitEnd; ++i) {
+ bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i);
+ if (V1 < V2)
+ return true;
+ else if (V2 < V1)
+ return false;
+ }
+ return false;
+ }
+};
+
+static void PrintRange(std::vector<Record*>::iterator I,
+ std::vector<Record*>::iterator E) {
+ while (I != E) std::cerr << **I++;
+}
+
+static bool getMemoryBit(unsigned char *M, unsigned i) {
+ return (M[i/8] & (1 << (i&7))) != 0;
+}
+
+static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB,
+ std::vector<Record*>::iterator IE,
+ unsigned StartBit) {
+ unsigned FirstFixedBit = 0;
+ for (std::vector<Record*>::iterator I = IB; I != IE; ++I)
+ FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit));
+ return FirstFixedBit;
+}
+
+// ParseMachineCode - Try to split the vector of instructions (which is
+// intentionally taken by-copy) in half, narrowing down the possible
+// instructions that we may have found. Eventually, this list will get pared
+// down to zero or one instruction, in which case we have a match or failure.
+//
+static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB,
+ std::vector<Record*>::iterator InstsE,
+ unsigned char *M) {
+ assert(InstsB != InstsE && "Empty range?");
+ if (InstsB+1 == InstsE) {
+ // Only a single instruction, see if we match it...
+ Record *Inst = *InstsB;
+ for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i)
+ if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i)))
+ if (getMemoryBit(M, i) != BI->getValue())
+ throw std::string("Parse failed!\n");
+ return Inst;
+ }
+
+ unsigned MaxBits = ~0;
+ for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I)
+ MaxBits = std::min(MaxBits, getNumBits(*I));
+
+ unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0);
+ unsigned FirstVaryingBit, LastFixedBit;
+ do {
+ FirstVaryingBit = ~0;
+ LastFixedBit = ~0;
+ for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I)
+ FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits,
+ FirstVaryingBit, LastFixedBit);
+ if (FirstVaryingBit == MaxBits) {
+ std::cerr << "ERROR: Could not find bit to distinguish between "
+ << "the following entries!\n";
+ PrintRange(InstsB, InstsE);
+ }
+
+#if 0
+ std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
+ << ": " << InstsE-InstsB << "\n";
+#endif
+
+ FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit);
+ } while (FirstVaryingBit != FirstFixedBit);
+
+ //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n";
+ //PrintRange(InstsB, InstsE);
+
+ // Sort the Insts list so that the entries have all of the bits in the range
+ // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be
+ // set to either 0 or 1 (BitInit values), which simplifies things.
+ //
+ std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit));
+
+ // Once the list is sorted by these bits, split the bit list into smaller
+ // lists, and recurse on each one.
+ //
+ std::vector<Record*>::iterator RangeBegin = InstsB;
+ Record *Match = 0;
+ while (RangeBegin != InstsE) {
+ std::vector<Record*>::iterator RangeEnd = RangeBegin+1;
+ while (RangeEnd != InstsE &&
+ BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit))
+ ++RangeEnd;
+
+ // We just identified a range of equal instructions. If this range is the
+ // input range, we were not able to distinguish between the instructions in
+ // the set. Print an error and exit!
+ //
+ if (RangeBegin == InstsB && RangeEnd == InstsE) {
+ std::cerr << "Error: Could not distinguish among the following insts!:\n";
+ PrintRange(InstsB, InstsE);
+ abort();
+ }
+
+#if 0
+ std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit
+ << ": [" << RangeEnd-RangeBegin << "] - ";
+ for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i)
+ std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " ";
+ std::cerr << "\n";
+#endif
+
+ if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) {
+ if (Match) {
+ std::cerr << "Error: Multiple matches found:\n";
+ PrintRange(InstsB, InstsE);
+ }
+
+ assert(Match == 0 && "Multiple matches??");
+ Match = R;
+ }
+ RangeBegin = RangeEnd;
+ }
+
+ return Match;
+}
+
+static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) {
+ assert(dynamic_cast<BitsInit*>(Val.getValue()) &&
+ "Can only handle undefined bits<> types!");
+ BitsInit *BI = (BitsInit*)Val.getValue();
+ assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!");
+
+ unsigned Value = 0;
+ const std::vector<RecordVal> &Vals = I->getValues();
+
+ // Start by filling in fixed values...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i)))
+ Value |= B->getValue() << i;
+
+ // Loop over all of the fields in the instruction adding in any
+ // contributions to this value (due to bit references).
+ //
+ unsigned Offset = 0;
+ for (unsigned f = 0, e = Vals.size(); f != e; ++f)
+ if (Vals[f].getPrefix()) {
+ BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
+ if (&Vals[f] == &Val) {
+ // Read the bits directly now...
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ Value |= getMemoryBit(Ptr, Offset+i) << i;
+ break;
+ }
+
+ // Scan through the field looking for bit initializers of the current
+ // variable...
+ for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i)
+ if (VarBitInit *VBI =
+ dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
+ TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
+ if (VI->getName() == Val.getName())
+ Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum();
+ } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
+ // FIXME: implement this!
+ std::cerr << "FIELD INIT not implemented yet!\n";
+ }
+ }
+ Offset += FieldInitializer->getNumBits();
+ }
+
+ std::cout << "0x" << std::hex << Value << std::dec;
+}
+
+static void PrintInstruction(Record *I, unsigned char *Ptr) {
+ std::cout << "Inst " << getNumBits(I)/8 << " bytes: "
+ << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue()
+ << "\t";
+
+ const std::vector<RecordVal> &Vals = I->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getValue()->isComplete()) {
+ std::cout << Vals[i].getName() << "=";
+ PrintValue(I, Ptr, Vals[i]);
+ std::cout << "\t";
+ }
+
+ std::cout << "\n";// << *I;
+}
+
+static void ParseMachineCode() {
+ // X86 code
+ unsigned char Buffer[] = {
+ 0x55, // push EBP
+ 0x89, 0xE5, // mov EBP, ESP
+ //0x83, 0xEC, 0x08, // sub ESP, 0x8
+ 0xE8, 1, 2, 3, 4, // call +0x04030201
+ 0x89, 0xEC, // mov ESP, EBP
+ 0x5D, // pop EBP
+ 0xC3, // ret
+ 0x90, // nop
+ 0xC9, // leave
+ 0x89, 0xF6, // mov ESI, ESI
+ 0x68, 1, 2, 3, 4, // push 0x04030201
+ 0x5e, // pop ESI
+ 0xFF, 0xD0, // call EAX
+ 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201
+ 0x85, 0xC0, // test EAX, EAX
+ 0xF4, // hlt
+ };
+
+#if 0
+ // SparcV9 code
+ unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17
+ };
+#endif
+
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ unsigned char *BuffPtr = Buffer;
+ while (1) {
+ Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr);
+ PrintInstruction(R, BuffPtr);
+
+ unsigned Bits = getNumBits(R);
+ assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!");
+ BuffPtr += Bits/8;
+ }
+}
+
+
+int main(int argc, char **argv) {
+ cl::ParseCommandLineOptions(argc, argv);
+ ParseFile(InputFilename, IncludeDir);
+
+ std::ostream *Out = &std::cout;
+ if (OutputFilename != "-") {
+ // Output to a .tmp file, because we don't actually want to overwrite the
+ // output file unless the generated file is different or the specified file
+ // does not exist.
+ Out = new std::ofstream((OutputFilename+".tmp").c_str());
+
+ if (!Out->good()) {
+ std::cerr << argv[0] << ": error opening " << OutputFilename << ".tmp!\n";
+ return 1;
+ }
+
+ // Make sure the file gets removed if *gasp* tablegen crashes...
+ RemoveFileOnSignal(OutputFilename+".tmp");
+ }
+
+ try {
+ switch (Action) {
+ case PrintRecords:
+ *Out << Records; // No argument, dump all contents
+ break;
+ case Parse:
+ ParseMachineCode();
+ break;
+ case GenEmitter:
+ CodeEmitterGen(Records).run(*Out);
+ break;
+
+ case GenRegisterEnums:
+ RegisterInfoEmitter(Records).runEnums(*Out);
+ break;
+ case GenRegister:
+ RegisterInfoEmitter(Records).run(*Out);
+ break;
+ case GenRegisterHeader:
+ RegisterInfoEmitter(Records).runHeader(*Out);
+ break;
+
+ case GenInstrEnums:
+ InstrInfoEmitter(Records).runEnums(*Out);
+ break;
+ case GenInstrs:
+ InstrInfoEmitter(Records).run(*Out);
+ break;
+ case GenInstrSelector:
+ InstrSelectorEmitter(Records).run(*Out);
+ break;
+ case PrintEnums:
+ std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
+ for (unsigned i = 0, e = Recs.size(); i != e; ++i)
+ *Out << Recs[i] << ", ";
+ *Out << "\n";
+ break;
+ }
+ } catch (const std::string &Error) {
+ std::cerr << Error << "\n";
+ if (Out != &std::cout) {
+ delete Out; // Close the file
+ std::remove(OutputFilename.c_str()); // Remove the file, it's broken
+ }
+ return 1;
+ }
+
+ if (Out != &std::cout) {
+ delete Out; // Close the file
+
+ // Now that we have generated the result, check to see if we either don't
+ // have the requested file, or if the requested file is different than the
+ // file we generated. If so, move the generated file over the requested
+ // file. Otherwise, just remove the file we just generated, so 'make'
+ // doesn't try to regenerate tons of dependencies.
+ //
+ MoveFileOverIfUpdated(OutputFilename+".tmp", OutputFilename);
+ }
+ return 0;
+}
diff --git a/llvm/utils/TableGen/TableGenBackend.cpp b/llvm/utils/TableGen/TableGenBackend.cpp
new file mode 100644
index 00000000000..b86ae72ce9d
--- /dev/null
+++ b/llvm/utils/TableGen/TableGenBackend.cpp
@@ -0,0 +1,27 @@
+//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
+//
+// This file provides useful services for TableGen backends...
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackend.h"
+#include "Record.h"
+#include <iostream>
+
+void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
+ std::ostream &OS) const {
+ OS << "//===- TableGen'erated file -------------------------------------*-"
+ " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
+ "d file, do not edit!\n//\n//===------------------------------------"
+ "----------------------------------===//\n\n";
+}
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+///
+std::string TableGenBackend::getQualifiedName(Record *R) const {
+ std::string Namespace = R->getValueAsString("Namespace");
+ if (Namespace.empty()) return R->getName();
+ return Namespace + "::" + R->getName();
+}
+
diff --git a/llvm/utils/TableGen/TableGenBackend.h b/llvm/utils/TableGen/TableGenBackend.h
new file mode 100644
index 00000000000..8dfbaddad16
--- /dev/null
+++ b/llvm/utils/TableGen/TableGenBackend.h
@@ -0,0 +1,34 @@
+//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===//
+//
+// The TableGenBackend class is provided as a common interface for all TableGen
+// backends. It provides useful services and an standardized interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TABLEGENBACKEND_H
+#define TABLEGENBACKEND_H
+
+#include <string>
+#include <iosfwd>
+class Record;
+class RecordKeeper;
+
+struct TableGenBackend {
+ virtual ~TableGenBackend() {}
+
+ // run - All TableGen backends should implement the run method, which should
+ // be the main entry point.
+ virtual void run(std::ostream &OS) = 0;
+
+
+public: // Useful helper routines...
+ /// EmitSourceFileHeader - Output a LLVM style file header to the specified
+ /// ostream.
+ void EmitSourceFileHeader(const std::string &Desc, std::ostream &OS) const;
+
+ /// getQualifiedName - Return the name of the specified record, with a
+ /// namespace qualifier if the record contains one.
+ std::string getQualifiedName(Record *R) const;
+};
+
+#endif
OpenPOWER on IntegriCloud