* [PATCH 0/8] Implement a new DTS Source Language
@ 2008-09-23 19:04 Jon Loeliger
[not found] ` <1222196652-13811-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
0 siblings, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
This series of patches enhances the DTS source language to
support a fullly interpreted language for generating nodes
and properties. It is backward compatible with V1 sources.
The main features implemented by this patch set support
function definitions, 'if', 'for', 'return' and assignment
statements. Local variables, global constants and
almost complete C-like expressions are also supported.
Enhancements to the source position and error/warning
reporting now support source column positions too.
Jon Loeliger (8):
Remove support for the legacy DTS source file format.
Add conditionalized debug() print macro.
Enhance source position implementation.
Add header files for new Internal Representation form.
Add most of the new IR implementation files.
Add the main IR evaluation implementation
Introduce new DTS language.
Add documentation for the new DTS language.
Documentation/manual.txt | 500 ++++++++++++++--
Makefile | 2 +-
Makefile.dtc | 18 +-
dtc-lexer.l | 299 +++++++---
dtc-parser.y | 726 +++++++++++++++++------
dtc.c | 7 +-
dtc.h | 9 +
ir.c | 197 ++++++
ir.h | 161 +++++
ir_builtin.c | 178 ++++++
ir_builtin.h | 41 ++
ir_dump.c | 220 +++++++
ir_emit.c | 492 +++++++++++++++
ir_eval.c | 1504 +++++++++++++++++++++++++++++++++++++++++++++
ir_scope.c | 319 ++++++++++
ir_scope.h | 114 ++++
livetree.c | 16 +
nv.c | 108 ++++
nv.h | 34 +
srcpos.c | 136 ++++-
srcpos.h | 25 +-
tests/base01.dts | 24 +-
tests/empty.dts | 2 +
tests/escapes.dts | 2 +
tests/label01.dts | 38 +-
tests/references_dts0.dts | 12 +-
tests/run_tests.sh | 27 +-
tests/test01.dts | 38 +-
tests/test_tree1_dts0.dts | 18 +-
treesource.c | 3 +
30 files changed, 4872 insertions(+), 398 deletions(-)
create mode 100644 ir.c
create mode 100644 ir.h
create mode 100644 ir_builtin.c
create mode 100644 ir_builtin.h
create mode 100644 ir_dump.c
create mode 100644 ir_emit.c
create mode 100644 ir_eval.c
create mode 100644 ir_scope.c
create mode 100644 ir_scope.h
create mode 100644 nv.c
create mode 100644 nv.h
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/8] Remove support for the legacy DTS source file format.
[not found] ` <1222196652-13811-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-24 2:34 ` [PATCH 0/8] Implement a new DTS Source Language Kumar Gala
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Now that all in-kernel-tree DTS files are properly /dts-v1/,
remove direct support for the older, un-numbered DTS
source file format.
Convert existing tests to /dts-v1/ and remove support
for the conversion tests themselves.
For now, though, the conversion tool still exists.
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
dtc-lexer.l | 40 +-------------------------------------
dtc-parser.y | 46 ---------------------------------------------
tests/base01.dts | 24 ++++++++++++----------
tests/empty.dts | 2 +
tests/escapes.dts | 2 +
tests/label01.dts | 38 +++++++++++++++++++-----------------
tests/references_dts0.dts | 12 ++++++----
tests/run_tests.sh | 27 +-------------------------
tests/test01.dts | 38 +++++++++++++++++++-----------------
tests/test_tree1_dts0.dts | 18 +++++++++-------
10 files changed, 77 insertions(+), 170 deletions(-)
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 6f8b7dd..6b862d2 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -47,15 +47,10 @@ LINECOMMENT "//".*\n
#define DPRINT(fmt, ...) do { } while (0)
#endif
-static int dts_version; /* = 0 */
+static int dts_version = 1;
-#define BEGIN_DEFAULT() if (dts_version == 0) { \
- DPRINT("<INITIAL>\n"); \
- BEGIN(INITIAL); \
- } else { \
- DPRINT("<V1>\n"); \
+#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \
BEGIN(V1); \
- }
static void push_input_file(const char *filename);
static int pop_input_file(void);
@@ -110,29 +105,6 @@ static int pop_input_file(void);
return DT_LABEL;
}
-<INITIAL>[bodh]# {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- if (*yytext == 'b')
- yylval.cbase = 2;
- else if (*yytext == 'o')
- yylval.cbase = 8;
- else if (*yytext == 'd')
- yylval.cbase = 10;
- else
- yylval.cbase = 16;
- DPRINT("Base: %d\n", yylval.cbase);
- return DT_BASE;
- }
-
-<INITIAL>[0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LEGACYLITERAL;
- }
-
<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
@@ -158,14 +130,6 @@ static int pop_input_file(void);
return DT_REF;
}
-<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
- return DT_REF;
- }
-
<BYTESTRING>[0-9a-fA-F]{2} {
yylloc.file = srcpos_file;
yylloc.first_line = yylineno;
diff --git a/dtc-parser.y b/dtc-parser.y
index b2ab562..3762181 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -55,7 +55,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%token DT_MEMRESERVE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
-%token <literal> DT_LEGACYLITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -67,11 +66,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
-%type <re> v0_memreserve
-%type <re> v0_memreserves
%type <addr> addr
%type <data> celllist
-%type <cbase> cellbase
%type <cell> cellval
%type <data> bytestring
%type <prop> propdef
@@ -90,10 +86,6 @@ sourcefile:
{
the_boot_info = build_boot_info($3, $4, 0);
}
- | v0_memreserves devicetree
- {
- the_boot_info = build_boot_info($1, $2, 0);
- }
;
memreserves:
@@ -114,37 +106,11 @@ memreserve:
}
;
-v0_memreserves:
- /* empty */
- {
- $$ = NULL;
- }
- | v0_memreserve v0_memreserves
- {
- $$ = chain_reserve_entry($1, $2);
- };
- ;
-
-v0_memreserve:
- memreserve
- {
- $$ = $1;
- }
- | label DT_MEMRESERVE addr '-' addr ';'
- {
- $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
- }
- ;
-
addr:
DT_LITERAL
{
$$ = eval_literal($1, 0, 64);
}
- | DT_LEGACYLITERAL
- {
- $$ = eval_literal($1, 16, 64);
- }
;
devicetree:
@@ -269,23 +235,11 @@ celllist:
}
;
-cellbase:
- /* empty */
- {
- $$ = 16;
- }
- | DT_BASE
- ;
-
cellval:
DT_LITERAL
{
$$ = eval_literal($1, 0, 32);
}
- | cellbase DT_LEGACYLITERAL
- {
- $$ = eval_literal($2, $1, 32);
- }
;
bytestring:
diff --git a/tests/base01.dts b/tests/base01.dts
index f84bc49..97a5dd5 100644
--- a/tests/base01.dts
+++ b/tests/base01.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
/ {
model = "SomeModel";
compatible = "Nothing";
@@ -6,26 +8,26 @@
memory@0 {
device_type = "memory";
- reg = <00000000 00000000 00000000 20000000>;
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
- d10 = <d# 10>; // hex: 0xa
- d23 = <d# 23>; // hex: 0x17
- b101 = <b# 101>; // hex: 0x5
- o17 = <o# 17>; // hex: 0xf
- hd00d = <h# d00d>; // hex: 0xd00d
+ d10 = < 10>; // hex: 0xa
+ d23 = < 23>; // hex: 0x17
+ b101 = < 0x5>; // hex: 0x5
+ o17 = < 017>; // hex: 0xf
+ hd00d = < 0xd00d>; // hex: 0xd00d
// hex: 0x4d2 0x163e 0x2334 0xd80
- stuff = <d# 1234 d# 5678 d# 9012 d# 3456>;
+ stuff = < 1234 5678 9012 3456>;
- bad-d-1 = <d# abc123>; // Hrm. 0
- bad-d-2 = <d# 123456789012345>;
- bad-o-1 = <o# 891>;
- bad-o-2 = <o# 123456123456>;
+ bad-d-1 = < 0>; // Hrm. 0
+ bad-d-2 = < 123456789012345>;
+ bad-o-1 = < 00>;
+ bad-o-2 = < 0123456123456>;
};
};
diff --git a/tests/empty.dts b/tests/empty.dts
index 336d7a2..e160dad 100644
--- a/tests/empty.dts
+++ b/tests/empty.dts
@@ -1,2 +1,4 @@
+/dts-v1/;
+
/ {
};
diff --git a/tests/escapes.dts b/tests/escapes.dts
index f1b8dbc..e05ab46 100644
--- a/tests/escapes.dts
+++ b/tests/escapes.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
/ {
compatible = "test_string_escapes";
escape-str = "nastystring: \a\b\t\n\v\f\r\\\"";
diff --git a/tests/label01.dts b/tests/label01.dts
index 372b17a..a895803 100644
--- a/tests/label01.dts
+++ b/tests/label01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
/ {
model = "MyBoardName";
@@ -9,28 +11,28 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
#size-cells = <2>;
cpus {
- linux,phandle = <1>;
+ linux,phandle = <0x1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,970@0 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <0>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
linux,boot-cpu;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
PowerPC,970@1 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <1>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
};
@@ -38,8 +40,8 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
node: randomnode {
prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ;
blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ];
- ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >;
- mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>;
+ ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >;
+ mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>;
tricky1 = [61 lt1: 62 63 00];
subnode: child {
};
@@ -49,12 +51,12 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
memory@0 {
device_type = "memory";
- memreg: reg = <00000000 00000000 00000000 20000000>;
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
chosen {
bootargs = "root=/dev/sda2";
- linux,platform = <00000600>;
+ linux,platform = <0x600>;
};
};
diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts
index df82c23..36b6f51 100644
--- a/tests/references_dts0.dts
+++ b/tests/references_dts0.dts
@@ -1,19 +1,21 @@
+/dts-v1/;
+
/ {
/* Explicit phandles */
n1: node1 {
- linux,phandle = <2000>;
- ref = <&/node2>; /* reference precedes target */
+ linux,phandle = <0x2000>;
+ ref = <&{/node2}>; /* reference precedes target */
lref = <&n2>;
};
n2: node2 {
- linux,phandle = <1>;
- ref = <&/node1>; /* reference after target */
+ linux,phandle = <0x1>;
+ ref = <&{/node1}>; /* reference after target */
lref = <&n1>;
};
/* Implicit phandles */
n3: node3 {
- ref = <&/node4>;
+ ref = <&{/node4}>;
lref = <&n4>;
};
n4: node4 {
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index eb29462..30cd9a1 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -71,13 +71,6 @@ run_dtc_test () {
base_run_test wrap_test $VALGRIND $DTC "$@"
}
-CONVERT=../convert-dtsv0
-
-run_convert_test () {
- echo -n "convert-dtsv0 $@: "
- base_run_test wrap_test $VALGRIND $CONVERT "$@"
-}
-
tree1_tests () {
TREE=$1
@@ -287,21 +280,6 @@ dtc_tests () {
run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile
}
-convert_tests () {
- V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \
- test01.dts label01.dts"
- for dts in $V0_DTS; do
- run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts
- run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts
- run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts
- run_convert_test $dts
- run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1
-
- run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb
- run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb
- done
-}
-
while getopts "vt:m" ARG ; do
case $ARG in
"v")
@@ -317,7 +295,7 @@ while getopts "vt:m" ARG ; do
done
if [ -z "$TESTSETS" ]; then
- TESTSETS="libfdt dtc convert"
+ TESTSETS="libfdt dtc"
fi
# Make sure we don't have stale blobs lying around
@@ -331,9 +309,6 @@ for set in $TESTSETS; do
"dtc")
dtc_tests
;;
- "convert")
- convert_tests
- ;;
esac
done
diff --git a/tests/test01.dts b/tests/test01.dts
index ed2b178..f9fd165 100644
--- a/tests/test01.dts
+++ b/tests/test01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-/memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+/memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
/ {
model = "MyBoardName";
@@ -9,28 +11,28 @@
#size-cells = <2>;
cpus {
- linux,phandle = <1>;
+ linux,phandle = <0x1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,970@0 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <0>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
linux,boot-cpu;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
PowerPC,970@1 {
name = "PowerPC,970";
device_type = "cpu";
- reg = <1>;
- clock-frequency = <5f5e1000>;
- timebase-frequency = <1FCA055>;
- i-cache-size = <10000>;
- d-cache-size = <8000>;
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
};
};
@@ -38,18 +40,18 @@
randomnode {
string = "\xff\0stuffstuff\t\t\t\n\n\n";
blob = [0a 0b 0c 0d de ea ad be ef];
- ref = < &/memory@0 >;
- mixed = "abc", [1234], <a b c>;
+ ref = < &{/memory@0} >;
+ mixed = "abc", [1234], <0xa 0xb 0xc>;
};
memory@0 {
device_type = "memory";
- memreg: reg = <00000000 00000000 00000000 20000000>;
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
chosen {
bootargs = "root=/dev/sda2";
- linux,platform = <00000600>;
+ linux,platform = <0x600>;
};
};
diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts
index bc65819..6b40cf5 100644
--- a/tests/test_tree1_dts0.dts
+++ b/tests/test_tree1_dts0.dts
@@ -1,9 +1,11 @@
-/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ 75bcd15 1000;
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x0000000000100000;
+/memreserve/ 0x00000000075bcd15 0x0000000000001000;
/ {
compatible = "test_tree1";
- prop-int = <deadbeef>;
+ prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
@@ -12,18 +14,18 @@
subsubnode {
compatible = "subsubnode1", "subsubnode";
- prop-int = <h# deadbeef>;
+ prop-int = < 0xdeadbeef>;
};
};
subnode@2 {
- linux,phandle = <2000>;
- prop-int = <d# 123456789>;
+ linux,phandle = <0x2000>;
+ prop-int = < 123456789>;
subsubnode@0 {
- linux,phandle = <2001>;
+ linux,phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
- prop-int = <o# 0726746425>;
+ prop-int = < 0726746425>;
};
};
};
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 2/8] Add conditionalized debug() print macro.
[not found] ` <1222196652-13811-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
0 siblings, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
dtc.h | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/dtc.h b/dtc.h
index 08d54c8..ec636f8 100644
--- a/dtc.h
+++ b/dtc.h
@@ -34,7 +34,15 @@
#include <libfdt_env.h>
#include <fdt.h>
+#ifdef DEBUG
+#define debug(fmt,args...) printf(fmt, ##args)
+#else
+#define debug(fmt,args...)
+#endif
+
+
#define DEFAULT_FDT_VERSION 17
+
/*
* Command line options
*/
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 3/8] Enhance source position implementation.
[not found] ` <1222196652-13811-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-25 12:42 ` [PATCH 2/8] Add conditionalized debug() print macro Josh Boyer
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Implemented some print and copy routines.
Made empty srcpos objects that will be used later.
Protected .h file from multiple #include's.
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
srcpos.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
srcpos.h | 19 ++++++++++++
2 files changed, 107 insertions(+), 7 deletions(-)
diff --git a/srcpos.c b/srcpos.c
index 9641b76..59d1835 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -23,12 +23,29 @@
/*
* Like yylineno, this is the current open file pos.
*/
-
struct dtc_file *srcpos_file;
-static int dtc_open_one(struct dtc_file *file,
- const char *search,
- const char *fname)
+/*
+ * The empty source position.
+ */
+
+struct dtc_file dtc_empty_file = {
+ .dir = NULL,
+ .name = "<no file>",
+ .file = NULL
+};
+
+srcpos srcpos_empty = {
+ .first_line = 0,
+ .first_column = 0,
+ .last_line = 0,
+ .last_column = 0,
+ .file = &dtc_empty_file
+};
+
+
+static int
+dtc_open_one(struct dtc_file *file, const char *search, const char *fname)
{
char *fullname;
@@ -53,8 +70,8 @@ static int dtc_open_one(struct dtc_file *file,
}
-struct dtc_file *dtc_open_file(const char *fname,
- const struct search_path *search)
+struct dtc_file *
+dtc_open_file(const char *fname, const struct search_path *search)
{
static const struct search_path default_search = { NULL, NULL, NULL };
@@ -106,7 +123,9 @@ fail:
die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
}
-void dtc_close_file(struct dtc_file *file)
+
+void
+dtc_close_file(struct dtc_file *file)
{
if (fclose(file->file))
die("Error closing \"%s\": %s\n", file->name, strerror(errno));
@@ -114,3 +133,65 @@ void dtc_close_file(struct dtc_file *file)
free(file->dir);
free(file);
}
+
+
+srcpos *
+srcpos_copy(srcpos *pos)
+{
+ srcpos *pos_new;
+
+ pos_new = xmalloc(sizeof(srcpos));
+ memcpy(pos_new, pos, sizeof(srcpos));
+
+ return pos_new;
+}
+
+
+
+void
+srcpos_dump(srcpos *pos)
+{
+ printf("file : \"%s\"\n",
+ pos->file ? (char *) pos->file : "<no file>");
+ printf("first_line : %d\n", pos->first_line);
+ printf("first_column: %d\n", pos->first_column);
+ printf("last_line : %d\n", pos->last_line);
+ printf("last_column : %d\n", pos->last_column);
+ printf("file : %s\n", pos->file->name);
+}
+
+
+char *
+srcpos_string(srcpos *pos)
+{
+# define POS_BUF_SIZE (100)
+
+ const char *fname;
+ char buf[POS_BUF_SIZE];
+
+ if (pos->file && pos->file->name)
+ fname = pos->file->name;
+ else
+ fname = "<no-file>";
+
+ if (pos->first_line == pos->last_line) {
+ if (pos->first_column == pos->last_column) {
+ snprintf(buf, POS_BUF_SIZE, "%s %d:%d",
+ fname, pos->first_line, pos->first_column);
+ } else {
+ snprintf(buf, POS_BUF_SIZE, "%s %d:%d-%d",
+ fname, pos->first_line,
+ pos->first_column, pos->last_column);
+ }
+
+ } else {
+ snprintf(buf, POS_BUF_SIZE, "%s %d:%d - %d:%d",
+ fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ }
+
+ return strdup(buf);
+
+# undef POS_BUF_SIZE
+}
diff --git a/srcpos.h b/srcpos.h
index e17c7c0..de55b18 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -17,6 +17,9 @@
* USA
*/
+#ifndef _SRCPOS_H_
+#define _SRCPOS_H_
+
/*
* Augment the standard YYLTYPE with a filenum index into an
* array of all opened filenames.
@@ -69,6 +72,16 @@ typedef struct YYLTYPE {
while (YYID (0))
+typedef YYLTYPE srcpos;
+
+/*
+ * Fictional source position used for IR nodes that are
+ * created without otherwise knowing a true source position.
+ * For example,constant definitions from the command line.
+ */
+extern srcpos srcpos_empty;
+
+
extern void yyerror(char const *);
extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
@@ -83,3 +96,9 @@ struct search_path {
extern struct dtc_file *dtc_open_file(const char *fname,
const struct search_path *search);
extern void dtc_close_file(struct dtc_file *file);
+
+extern srcpos *srcpos_copy(srcpos *pos);
+extern char *srcpos_string(srcpos *pos);
+extern void srcpos_dump(srcpos *pos);
+
+#endif /* _SRCPOS_H_ */
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 4/8] Add header files for new Internal Representation form.
[not found] ` <1222196652-13811-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-24 17:07 ` [PATCH 3/8] Enhance source position implementation Scott Wood
2008-09-24 17:23 ` Scott Wood
2 siblings, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
ir.h | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ir_builtin.h | 41 +++++++++++++++
ir_scope.h | 114 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 316 insertions(+), 0 deletions(-)
create mode 100644 ir.h
create mode 100644 ir_builtin.h
create mode 100644 ir_scope.h
diff --git a/ir.h b/ir.h
new file mode 100644
index 0000000..7d27fe7
--- /dev/null
+++ b/ir.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _IR_H_
+#define _IR_H_
+
+#include "srcpos.h"
+#include "ir_builtin.h"
+
+
+#define IR_UNDEF 0
+#define IR_ROOT 1
+#define IR_MEM_RESERVE 2
+#define IR_ASSIGN 3
+#define IR_PROP_DEF 4
+#define IR_REF_PHANDLE 5
+#define IR_REF_PATH 6
+#define IR_CELL 7
+#define IR_LITERAL 8
+#define IR_LIT_STR 9
+#define IR_LIT_BYTE 10
+#define IR_LABEL 11
+#define IR_LIST 12
+#define IR_INCBIN 13
+#define IR_BUILTIN 14
+#define IR_SELECT 15
+#define IR_OR 16
+#define IR_AND 17
+#define IR_BIT_OR 18
+#define IR_BIT_XOR 19
+#define IR_BIT_AND 20
+#define IR_EQ 21
+#define IR_LT 22
+#define IR_LE 23
+#define IR_GT 24
+#define IR_GE 25
+#define IR_NE 26
+#define IR_LSHIFT 27
+#define IR_RSHIFT 28
+#define IR_ADD 29
+#define IR_MINUS 30
+#define IR_MULT 31
+#define IR_DIV 32
+#define IR_MOD 33
+#define IR_UMINUS 34
+#define IR_BIT_COMPL 35
+#define IR_NOT 36
+#define IR_FUNC_DEF 37
+#define IR_FOR 38
+#define IR_RETURN 39
+#define IR_RANGE 40
+#define IR_ID 41
+#define IR_IF 42
+#define IR_PARAMDECL 43
+#define IR_FUNC_CALL 44
+#define IR_NODE 45
+#define IR_PROPNODENAME 46
+#define IR_LIT_CELL 47
+#define IR_LIT_ADDR 48
+#define IR_CVT_PROPNODENAME 49
+#define IR_CVT_STRING 50
+#define IR_CONST_DEF 51
+
+#define IR_NUM_TYPES 52
+
+
+typedef unsigned int ir_type;
+
+extern char const *ir_type_string(ir_type ir_type);
+
+
+struct ir {
+ ir_type ir_type;
+ srcpos *ir_srcpos;
+
+ long long ir_literal;
+ char *ir_lit_str;
+ char *ir_label_name;
+ irb_id ir_builtin_id;
+
+ struct ir *ir_name;
+ struct ir *ir_label;
+ struct ir *ir_expr1;
+ struct ir *ir_expr2;
+ struct ir *ir_expr3;
+
+ struct ir *ir_mem_reserves;
+ struct ir *ir_statements;
+ struct ir *ir_statements2;
+ struct ir *ir_declarations;
+
+ struct ir *ir_first;
+ struct ir *ir_last;
+ struct ir *ir_prev;
+ struct ir *ir_next;
+};
+
+
+extern struct ir *the_ir_tree;
+
+extern struct ir *ir_alloc(ir_type ir_type, srcpos *);
+extern struct ir *ir_copy(struct ir *ir); /* shallow copy */
+extern void ir_free(struct ir *ir);
+extern void ir_free_all(struct ir *ir);
+
+extern struct ir *ir_alloc_unop(ir_type ir_type,
+ struct ir *ir1,
+ srcpos *pos);
+extern struct ir *ir_alloc_binop(ir_type ir_type,
+ struct ir *ir1,
+ struct ir *ir2,
+ srcpos *pos);
+extern struct ir *ir_alloc_triop(ir_type ir_type,
+ struct ir *ir1,
+ struct ir *ir2,
+ struct ir *ir3,
+ srcpos *pos);
+extern struct ir *ir_list_append(struct ir *ir_list, struct ir *ir_node);
+extern void ir_dump(struct ir *ir);
+extern struct ir *ir_eval(struct ir *ir);
+extern struct ir_scope *ir_eval_func_body(struct ir *ir_func);
+
+extern void ir_process(void);
+extern struct ir *ir_simplify(struct ir *ir, unsigned int ctxt);
+extern void ir_emit(struct ir *ir);
+extern void ir_emit_statement_list(struct ir *ir_list);
+
+
+#define IR_EVAL_CTXT_ANY 0
+#define IR_EVAL_CTXT_CELL 1
+
+extern int ir_is_constant(struct ir *ir);
+extern int ir_is_string(struct ir *ir);
+extern char *ir_eval_for_label(struct ir *ir);
+extern char *ir_eval_for_name(struct ir *ir);
+extern uint64_t ir_eval_for_addr(struct ir *ir);
+extern void ir_eval_for_data(struct ir *ir, struct data *d);
+extern char *ir_eval_for_c_string(struct ir *ir);
+
+extern void ir_warn(struct ir *ir, char const *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+extern void ir_error(struct ir *ir, char const *, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#endif /* _IR_H_ */
diff --git a/ir_builtin.h b/ir_builtin.h
new file mode 100644
index 0000000..c4e1b18
--- /dev/null
+++ b/ir_builtin.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _IR_BUILTIN_H_
+#define _IR_BUILTIN_H_
+
+
+#define IRB_UNDEF 0
+#define IRB_JOIN 1
+
+typedef unsigned int irb_id;
+
+typedef struct ir * (*irb_impl_func)(struct ir *ir_params);
+
+struct irb_entry {
+ irb_id irb_id;
+ char *irb_name;
+ irb_impl_func irb_implementation;
+};
+
+
+extern irb_id ir_lookup_builtin_by_name(char *str_name);
+extern struct ir *ir_eval_builtin(struct ir *ir);
+
+#endif /* _IR_BUILTIN_H_ */
diff --git a/ir_scope.h b/ir_scope.h
new file mode 100644
index 0000000..4529d50
--- /dev/null
+++ b/ir_scope.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _IR_SCOPE_H_
+#define _IR_SCOPE_H_
+
+/*
+ * IR Symbols and Symbol Tables
+ *
+ * Each ir_scope structure can have its own Symbol Table, represented
+ * as a simple linked list of symbols.
+ *
+ * As the number of symbols and scopes is expected to be relatively
+ * small (dozens total), and not large (hundreds or more), the
+ * current implementation is a dead-simple brute force linear search
+ * of a Symbol Table.
+ *
+ * Symbol Table operations (add, lookup) are implicitly performed
+ * relative to the IR Scope Stack.
+ *
+ * During evaluation of the IR form, each symbol can have at most
+ * one value, represented as an IR expression. In the case of
+ * variables (or constants), the IR expression should be a
+ * literal of some type. For function definitions, the expression
+ * is the complete IR representation of the function definition.
+ */
+
+#define IRSYM_NONE 0
+#define IRSYM_VAR 1
+#define IRSYM_FUNCDEF 2
+#define IRSYM_PARAM 3
+#define IRSYM_CONST 4
+
+#define IRSYM_NUM_TYPES 5
+
+typedef unsigned int irsym_type;
+
+struct ir_symbol {
+ irsym_type irsym_type;
+ char *irsym_name;
+ struct ir *irsym_value;
+ struct ir_symbol *irsym_next;
+};
+
+
+
+/*
+ * IR Evaluation Scope
+ */
+
+#define IRS_NONE 0x00
+#define IRS_ROOT 0x01
+#define IRS_NODE 0x02
+#define IRS_FOR_LOOP 0x04
+#define IRS_FUNC_CALL 0x08
+
+#define IRS_MAX_BIT IRS_FUNC_CALL
+#define IRS_ANY 0xFF
+
+typedef unsigned int irs_type;
+
+struct ir_scope {
+ irs_type irs_type;
+ struct ir_symbol *irs_symtab;
+ struct ir *irs_expr;
+ struct reserve_info *irs_reserve_list;
+ struct property *irs_prop_list;
+ struct node *irs_node_list;
+
+ struct ir_scope *irs_next;
+};
+
+/*
+ * Each entry on this stack provides an evaluation environment.
+ */
+extern struct ir_scope *irs_scope_stack;
+
+extern void irs_push_scope(irs_type irs_type);
+extern struct ir_scope *irs_pop_scope(void);
+
+extern void irs_append_reserve(struct reserve_info *ri);
+extern void irs_append_property(struct property *p);
+extern void irs_append_node(struct node *n);
+extern void irs_scope_append_node_list(struct node *nl);
+extern void irs_scope_append_property_list(struct property *pl);
+extern void irs_set_return_value(struct ir *ir_ret);
+
+extern struct ir_symbol *irs_alloc_symbol(char *name, irsym_type irsym_type);
+extern struct ir_symbol *irs_lookup_in_scope(struct ir_scope *irs, char *name);
+extern struct ir_symbol *irs_lookup(char *name, irs_type irs_type);
+extern struct ir_symbol *irs_lookup_local(char *name);
+extern struct ir_symbol *irs_create_local(char *name, irsym_type irsym_type);
+extern struct ir_symbol *irs_create_symbol(irs_type irs_type,
+ char *name,
+ irsym_type irsym_type);
+extern void irs_dump_symbols(void);
+
+#endif /* _IR_SCOPE_H_ */
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 5/8] Add most of the new IR implementation files.
[not found] ` <1222196652-13811-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-24 19:17 ` [PATCH 4/8] Add header files for new Internal Representation form Scott Wood
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
ir.c | 197 +++++++++++++++++++++++
ir_builtin.c | 178 +++++++++++++++++++++
ir_dump.c | 220 ++++++++++++++++++++++++++
ir_emit.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ir_scope.c | 319 +++++++++++++++++++++++++++++++++++++
5 files changed, 1406 insertions(+), 0 deletions(-)
create mode 100644 ir.c
create mode 100644 ir_builtin.c
create mode 100644 ir_dump.c
create mode 100644 ir_emit.c
create mode 100644 ir_scope.c
diff --git a/ir.c b/ir.c
new file mode 100644
index 0000000..7e5fce6
--- /dev/null
+++ b/ir.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "dtc.h"
+#include "ir.h"
+
+extern int treesource_error;
+
+
+struct ir *the_ir_tree;
+
+
+extern struct ir *
+ir_alloc(ir_type ir_type, srcpos *pos)
+{
+ struct ir *ir;
+
+ ir = xmalloc(sizeof(struct ir));
+ memset(ir, 0, sizeof(struct ir));
+
+ ir->ir_type = ir_type;
+ ir->ir_srcpos = srcpos_copy(pos);
+
+ return ir;
+}
+
+
+/*
+ * Shallow copy, mostly.
+ *
+ * Note that things like the immediate strings and source position
+ * are copied, but the sub-IR-expressions are not.
+ */
+extern struct ir *
+ir_copy(struct ir *ir)
+{
+ struct ir *ir_new;
+
+ if (!ir)
+ return NULL;
+
+ ir_new = ir_alloc(ir->ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = ir->ir_literal;
+ if (ir->ir_lit_str)
+ ir_new->ir_lit_str = strdup(ir->ir_lit_str);
+ if (ir->ir_label_name)
+ ir_new->ir_label_name = strdup(ir->ir_label_name);
+
+ return ir_new;
+}
+
+
+void
+ir_free(struct ir *ir)
+{
+}
+
+
+void
+ir_free_all(struct ir *ir)
+{
+}
+
+
+extern struct ir *
+ir_alloc_unop(ir_type ir_type, struct ir *ir1, srcpos *pos)
+{
+ struct ir *ir;
+
+ ir = ir_alloc(ir_type, pos);
+ ir->ir_expr1 = ir1;
+
+ return ir;
+}
+
+
+extern struct ir *
+ir_alloc_binop(ir_type ir_type,
+ struct ir *ir1, struct ir *ir2,
+ srcpos *pos)
+{
+ struct ir *ir;
+
+ ir = ir_alloc(ir_type, pos);
+ ir->ir_expr1 = ir1;
+ ir->ir_expr2 = ir2;
+
+ return ir;
+}
+
+
+extern struct ir *
+ir_alloc_triop(ir_type ir_type,
+ struct ir *ir1, struct ir *ir2, struct ir *ir3,
+ srcpos *pos)
+{
+ struct ir *ir;
+
+ ir = ir_alloc(ir_type, pos);
+ ir->ir_expr1 = ir1;
+ ir->ir_expr2 = ir2;
+ ir->ir_expr3 = ir3;
+
+ return ir;
+}
+
+
+extern struct ir *
+ir_list_append(struct ir *ir_list, struct ir *ir_node)
+{
+ if (ir_node == NULL) {
+ return ir_list;
+ }
+
+ if (ir_list == NULL) {
+ ir_list = ir_alloc(IR_LIST, ir_node->ir_srcpos);
+ }
+
+ ir_node->ir_prev = ir_list->ir_last;
+
+ if (ir_list->ir_last) {
+ ir_list->ir_last->ir_next = ir_node;
+ } else {
+ ir_list->ir_first = ir_node;
+ }
+
+ ir_list->ir_last = ir_node;
+
+ return ir_list;
+}
+
+
+void
+ir_process(void)
+{
+ /*
+ * FIXME: Fix leaking the whole orginal IR tree here.
+ */
+ the_ir_tree = ir_simplify(the_ir_tree, IR_EVAL_CTXT_ANY);
+
+ ir_emit(the_ir_tree);
+}
+
+
+void
+ir_warn(struct ir *ir, char const *fmt, ...)
+{
+ srcpos *pos;
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ pos = ir ? ir->ir_srcpos : &srcpos_empty;
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Error: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ va_end(va);
+}
+
+
+void
+ir_error(struct ir *ir, char const *fmt, ...)
+{
+ srcpos *pos;
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ pos = ir ? ir->ir_srcpos : &srcpos_empty;
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Warn: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ treesource_error = 1;
+ va_end(va);
+}
diff --git a/ir_builtin.c b/ir_builtin.c
new file mode 100644
index 0000000..2f33440
--- /dev/null
+++ b/ir_builtin.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "ir.h"
+
+struct ir *ir_builtin_join(struct ir *ir_params);
+struct ir *ir_builtin_hexstr(struct ir *ir_params);
+
+static const struct irb_entry irb_builtins[] = {
+ { 0, NULL, NULL },
+ { 1, "join", ir_builtin_join },
+ { 2, "hexstr", ir_builtin_hexstr },
+};
+
+#define IRB_NUM_BUILTINS ARRAY_SIZE(irb_builtins)
+
+
+irb_id
+ir_lookup_builtin_by_name(char *str_name)
+{
+ irb_id irb;
+
+ for (irb = 1; irb < IRB_NUM_BUILTINS; irb++) {
+ if (strcmp(irb_builtins[irb].irb_name, str_name) == 0) {
+ return irb;
+ }
+ }
+
+ return IRB_UNDEF;
+}
+
+
+struct ir *
+ir_eval_builtin(struct ir *ir)
+{
+ irb_id irb;
+ const struct irb_entry *irbe;
+ struct ir *ir_new;
+
+ if (ir == NULL)
+ return NULL;
+
+ if (ir->ir_type != IR_BUILTIN)
+ return NULL;
+
+ irb = ir->ir_builtin_id;
+
+ if (irb <= IRB_UNDEF || irb >= IRB_NUM_BUILTINS)
+ return NULL;
+
+ irbe = &irb_builtins[irb];
+
+ ir_new = (*irbe->irb_implementation)(ir);
+
+ return ir_new;
+}
+
+
+struct ir *
+ir_builtin_join(struct ir *ir_builtin)
+{
+ struct ir *ir_new;
+ struct ir *irp;
+ struct ir *ir;
+ char *s;
+ char *str;
+ int len;
+ char buf[30];
+
+ debug("ir_builtin_impl_join():\n");
+
+ irp = ir_builtin->ir_expr1;
+ if (irp->ir_type == IR_LIST)
+ irp = irp->ir_first;
+
+ len = 1;
+ str = xmalloc(1);
+ *str = 0;
+
+ while (irp != NULL) {
+ ir = ir_eval(irp);
+
+ if (ir_is_string(ir)) {
+ s = ir_eval_for_c_string(ir);
+ } else if (ir_is_constant(ir)) {
+ unsigned long long a;
+ a = ir_eval_for_addr(ir);
+ snprintf(buf, 30, "%llu", a);
+ s = buf;
+ } else {
+ ir_error(ir,
+ "Can't handle %s in join()\n",
+ ir_type_string(ir->ir_type));
+ s = 0;
+ }
+
+ len += strlen(s);
+
+ str = xrealloc(str, len);
+ strcat(str, s);
+
+ irp = irp->ir_next;
+ }
+
+ ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos);
+ ir_new->ir_lit_str = str;
+
+ return ir_new;
+}
+
+
+
+struct ir *
+ir_builtin_hexstr(struct ir *ir_builtin)
+{
+ struct ir *ir_new;
+ struct ir *irp;
+ struct ir *ir;
+ char *s;
+ char *str;
+ int len;
+ char buf[30];
+
+ irp = ir_builtin->ir_expr1;
+ if (irp->ir_type == IR_LIST)
+ irp = irp->ir_first;
+
+ len = 1;
+ str = xmalloc(1);
+ *str = 0;
+
+ while (irp != NULL) {
+ ir = ir_eval(irp);
+ if (ir_is_constant(ir)) {
+ unsigned long long a;
+ a = ir_eval_for_addr(ir);
+ snprintf(buf, 30, "%llx", a);
+ s = buf;
+ } else {
+ ir_error(ir,
+ "Can't handle %s in hexstr()\n",
+ ir_type_string(ir->ir_type));
+ s = 0;
+ }
+ len += strlen(s);
+
+ str = xrealloc(str, len);
+ strcat(str, s);
+
+ irp = irp->ir_next;
+ }
+
+ ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos);
+ ir_new->ir_lit_str = str;
+
+ return ir_new;
+}
+
+
diff --git a/ir_dump.c b/ir_dump.c
new file mode 100644
index 0000000..c818e2a
--- /dev/null
+++ b/ir_dump.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "ir.h"
+
+
+static const char *ir_type_str[IR_NUM_TYPES] = {
+ "IR_UNDEF",
+ "IR_ROOT",
+ "IR_MEM_RESERVE",
+ "IR_ASSIGN",
+ "IR_PROP_DEF",
+ "IR_REF_PHANDLE",
+ "IR_REF_PATH",
+ "IR_CELL",
+ "IR_LITERAL",
+ "IR_LIT_STR",
+ "IR_LIT_BYTE",
+ "IR_LABEL",
+ "IR_LIST",
+ "IR_INCBIN",
+ "IR_BUILTIN",
+ "IR_SELECT",
+ "IR_OR",
+ "IR_AND",
+ "IR_BIT_OR",
+ "IR_BIT_XOR",
+ "IR_BIT_AND",
+ "IR_EQ",
+ "IR_LT",
+ "IR_LE",
+ "IR_GT",
+ "IR_GE",
+ "IR_NE",
+ "IR_LSHIFT",
+ "IR_RSHIFT",
+ "IR_ADD",
+ "IR_MINUS",
+ "IR_MULT",
+ "IR_DIV",
+ "IR_MOD",
+ "IR_UMINUS",
+ "IR_BIT_COMPL",
+ "IR_NOT",
+ "IR_FUNC_DEF",
+ "IR_FOR",
+ "IR_RETURN",
+ "IR_RANGE",
+ "IR_ID",
+ "IR_IF",
+ "IR_PARAMDECL",
+ "IR_FUNC_CALL",
+ "IR_NODE",
+ "IR_PROPNODENAME",
+ "IR_LIT_CELL",
+ "IR_LIT_ADDR",
+ "IR_CVT_PROPNODENAME",
+ "IR_CVT_STRING",
+ "IR_CONST_DEF",
+};
+
+
+const char *
+ir_type_string(ir_type ir_type)
+{
+ if (0 <= ir_type && ir_type < IR_NUM_TYPES)
+ return ir_type_str[ir_type];
+ else
+ return "<unknown>";
+}
+
+
+static void
+ir_dump_node(struct ir *ir, unsigned int level)
+{
+ int indent = 4 * level;
+ struct ir *iri;
+
+ if (ir == NULL)
+ return;
+
+ /*
+ * Print node values
+ */
+ printf("%*sNODE : %p\n",
+ indent, "", ir);
+
+ printf("%*sir_type : %s\n",
+ indent, "", ir_type_string(ir->ir_type));
+
+ printf("%*sir_srcpos : %s\n",
+ indent, "", srcpos_string(ir->ir_srcpos));
+
+
+ printf("%*sir_literal : %lld\n", indent, "", ir->ir_literal);
+
+ if (ir->ir_builtin_id != IRB_UNDEF) {
+ printf("%*sir_builtin_id : %d\n",
+ indent, "", ir->ir_builtin_id);
+ }
+ if (ir->ir_lit_str) {
+ printf("%*sir_lit_str : %s\n",
+ indent, "", ir->ir_lit_str);
+ }
+ if (ir->ir_label_name) {
+ printf("%*sir_label_name : %s\n",
+ indent, "", ir->ir_label_name);
+ }
+
+ if (ir->ir_name) {
+ printf("%*sir_name : %p\n",
+ indent, "", ir->ir_name);
+ ir_dump_node(ir->ir_name, level + 1);
+ }
+
+ if (ir->ir_label) {
+ printf("%*sir_label : %p\n",
+ indent, "", ir->ir_label);
+ ir_dump_node(ir->ir_label, level + 1);
+ }
+
+ if (ir->ir_first)
+ printf("%*sir_first : %p\n",
+ indent, "", ir->ir_first);
+ if (ir->ir_last)
+ printf("%*sir_last : %p\n",
+ indent, "", ir->ir_last);
+ if (ir->ir_next)
+ printf("%*sir_next : %p\n",
+ indent, "", ir->ir_next);
+ if (ir->ir_prev)
+ printf("%*sir_prev : %p\n",
+ indent, "", ir->ir_prev);
+
+ /*
+ * Dump mem-reserves.
+ */
+ if (ir->ir_mem_reserves) {
+ printf("%*sir_mem_reserves: %p\n",
+ indent, "", ir->ir_mem_reserves);
+ ir_dump_node(ir->ir_mem_reserves, level + 1);
+ }
+
+ /*
+ * Dump sub-expressions
+ */
+ if (ir->ir_expr1) {
+ printf("%*sir_expr1 : %p\n",
+ indent, "", ir->ir_expr1);
+ ir_dump_node(ir->ir_expr1, level + 1);
+ }
+
+ if (ir->ir_expr2) {
+ printf("%*sir_expr2 : %p\n",
+ indent, "", ir->ir_expr2);
+ ir_dump_node(ir->ir_expr2, level + 1);
+ }
+
+ if (ir->ir_expr3) {
+ printf("%*sir_expr3 : %p\n",
+ indent, "", ir->ir_expr3);
+ ir_dump_node(ir->ir_expr3, level + 1);
+ }
+
+ /*
+ * Recursively dump declarations.
+ */
+ if (ir->ir_declarations) {
+ printf("%*sir_declarations: %p\n",
+ indent, "", ir->ir_declarations);
+ ir_dump_node(ir->ir_declarations, level + 1);
+ }
+
+ /*
+ * Recursively dump statements.
+ */
+ if (ir->ir_statements) {
+ printf("%*sir_statements: %p\n",
+ indent, "", ir->ir_statements);
+ ir_dump_node(ir->ir_statements, level + 1);
+ }
+ if (ir->ir_statements2) {
+ printf("%*sir_statements2: %p\n",
+ indent, "", ir->ir_statements2);
+ ir_dump_node(ir->ir_statements2, level + 1);
+ }
+
+ /*
+ * Recursively dump LIST chain.
+ */
+ for (iri = ir->ir_first; iri != NULL; iri = iri->ir_next) {
+ ir_dump_node(iri, level + 1);
+ }
+}
+
+
+extern void
+ir_dump(struct ir *ir)
+{
+ ir_dump_node(ir, 0);
+}
diff --git a/ir_emit.c b/ir_emit.c
new file mode 100644
index 0000000..dc94c71
--- /dev/null
+++ b/ir_emit.c
@@ -0,0 +1,492 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+#include "ir.h"
+#include "ir_scope.h"
+#include "nv.h"
+
+extern struct boot_info *the_boot_info;
+
+
+void ir_emit_node(struct ir *ir);
+
+
+void
+ir_emit_prop_def(struct ir *irp)
+{
+ struct ir *ir_lhs;
+ struct property *p;
+ char *prop_name;
+ char *lab;
+ struct data d;
+
+ debug("ir_emit_prop_def(");
+
+ lab = ir_eval_for_label(irp->ir_label);
+ if (lab) {
+ debug("%s : ", lab);
+ }
+
+ ir_lhs = ir_eval(irp->ir_expr1);
+ prop_name = ir_eval_for_name(ir_lhs);
+ debug("%s = <expr>)\n", prop_name);
+
+ if (prop_name) {
+ d = empty_data;
+ ir_eval_for_data(irp->ir_expr2, &d);
+ p = build_property(prop_name, d, lab);
+ irs_append_property(p);
+ }
+
+ debug("ir_emit_prop_def(): Done\n");
+}
+
+
+void
+ir_emit_assign(struct ir *ir_assign)
+{
+ char *var_name;
+ struct ir_symbol *irsym;
+ struct ir *ir_val;
+ struct ir *ir_pos;
+
+ ir_pos = ir_assign->ir_expr1 ? ir_assign->ir_expr1 : ir_assign;
+
+ var_name = ir_eval_for_name(ir_assign->ir_expr1);
+
+ debug("ir_emit_assign(%s)\n", var_name);
+
+ if (!var_name) {
+ ir_error(ir_pos, "Can't determine LHS name\n");
+ return;
+ }
+
+ irsym = irs_lookup_local(var_name);
+ if (irsym != NULL) {
+ if (irsym->irsym_type == IRSYM_CONST) {
+ ir_error(ir_pos,
+ "Can't assign to constant \"%s\"\n",
+ var_name);
+ }
+ } else {
+ /*
+ * FIXME: Debate on-the-fly creation or pre-declaration.
+ */
+ irsym = irs_create_local(var_name, IRSYM_VAR);
+ }
+
+ ir_val = ir_eval(ir_assign->ir_expr2);
+ irsym->irsym_value = ir_val;
+}
+
+
+void
+ir_emit_for(struct ir *ir_for)
+{
+ char *var_name;
+ struct ir_symbol *irsym;
+ struct ir *ir_id;
+ struct ir *ir_val;
+ struct ir *ir_range;
+ unsigned long long var;
+ unsigned long long start;
+ unsigned long long stop;
+
+ irs_push_scope(IRS_FOR_LOOP);
+
+ /*
+ * Introduce for-loop variable into FOR_LOOP scope.
+ */
+ ir_id = ir_for->ir_expr1;
+ var_name = ir_eval_for_name(ir_id);
+ irsym = irs_create_local(var_name, IRSYM_VAR);
+
+ ir_val = ir_alloc(IR_LIT_ADDR, ir_id->ir_srcpos);
+ irsym->irsym_value = ir_val;
+
+ ir_range = ir_for->ir_expr2;
+ start = ir_eval_for_addr(ir_range->ir_expr1);
+ stop = ir_eval_for_addr(ir_range->ir_expr2);
+
+ debug("Range appears to be %llu to %llu\n", start, stop);
+
+ var = start;
+ while (var <= stop ) {
+ ir_val->ir_literal = var;
+ ir_emit_statement_list(ir_for->ir_statements);
+ var++;
+ }
+
+ irs_pop_scope();
+}
+
+
+void
+ir_emit_if(struct ir *ir_if)
+{
+ uint64_t lit;
+
+ debug("ir_if()\n");
+ lit = ir_eval_for_addr(ir_if->ir_expr1);
+ if (lit) {
+ ir_emit_statement_list(ir_if->ir_statements);
+ } else {
+ ir_emit_statement_list(ir_if->ir_statements2);
+ }
+}
+
+
+void
+ir_emit_return(struct ir *ir_return)
+{
+ struct ir *ir_ret_expr;
+
+ ir_ret_expr = ir_eval(ir_return->ir_expr1);
+ irs_set_return_value(ir_ret_expr);
+}
+
+
+void
+ir_emit_func_call(struct ir *ir_func)
+{
+ struct ir_scope *irs_scope;
+
+ /*
+ * Perform function body.
+ *
+ * Returned scope has node and property "side effects".
+ * Function return value is thrown to /dev/null.
+ */
+ irs_scope = ir_eval_func_body(ir_func);
+
+ /*
+ * Propagate any nodes or properties into parent scope.
+ */
+ irs_scope_append_property_list(irs_scope->irs_prop_list);
+ irs_scope_append_node_list(irs_scope->irs_node_list);
+}
+
+
+void
+ir_emit_statement(struct ir *ir)
+{
+ if (ir == NULL)
+ return;
+
+ switch (ir->ir_type) {
+ case IR_NODE:
+ ir_emit_node(ir);
+ break;
+
+ case IR_PROP_DEF:
+ ir_emit_prop_def(ir);
+ break;
+
+ case IR_FOR:
+ ir_emit_for(ir);
+ break;
+
+ case IR_IF:
+ ir_emit_if(ir);
+ break;
+
+ case IR_RETURN:
+ ir_emit_return(ir);
+ break;
+
+ case IR_ASSIGN:
+ ir_emit_assign(ir);
+ break;
+
+ case IR_FUNC_CALL:
+ ir_emit_func_call(ir);
+ break;
+
+ case IR_LIST:
+ /*
+ * FIXME: LIST within a LIST. Optimize out earlier?
+ */
+ ir_emit_statement_list(ir);
+ break;
+
+ default:
+ ir_error(ir, "Unknown statement with ir_type %s\n",
+ ir_type_string(ir->ir_type));
+ }
+}
+
+
+void
+ir_emit_statement_list(struct ir *ir_list)
+{
+ struct ir *ir;
+
+ if (ir_list == NULL)
+ return;
+
+ if (ir_list->ir_type != IR_LIST)
+ return;
+
+ for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) {
+ ir_emit_statement(ir);
+ }
+}
+
+
+/*
+ * Enter a /define/ function definitin into IRS_ROOT symtab.
+ */
+void
+ir_emit_func_def(struct ir *ir_func_def)
+{
+ char *func_name;
+ struct ir_symbol *irsym;
+ struct ir *ir_pos;
+
+ ir_pos = ir_func_def->ir_expr1
+ ? ir_func_def->ir_expr1 : ir_func_def;
+
+ func_name = ir_eval_for_name(ir_func_def->ir_name);
+
+
+ irsym = irs_lookup(func_name, IRS_ROOT);
+ if (irsym != NULL) {
+ ir_warn(ir_pos,
+ "Redefinintion of \"%s\" ignored\n",
+ func_name);
+ return;
+ }
+
+ irsym = irs_create_symbol(IRS_ROOT, func_name, IRSYM_FUNCDEF);
+
+ irsym->irsym_value = ir_func_def;
+
+ debug("ir_emit_func_def(): Defined %s\n", func_name);
+}
+
+
+/*
+ * Enter a /define/ function definitin into IRS_ROOT symtab.
+ */
+void
+ir_emit_const_def(struct ir *ir_const_def)
+{
+ char *const_name;
+ struct ir_symbol *irsym;
+ struct ir *ir_val;
+ struct ir *ir_pos;
+
+ ir_pos = ir_const_def->ir_expr1
+ ? ir_const_def->ir_expr1 : ir_const_def;
+
+ const_name = ir_eval_for_name(ir_const_def->ir_expr1);
+
+ debug("ir_const_def(%s)\n", const_name);
+
+ if (!const_name) {
+ ir_error(ir_pos, "Can't determine LHS constant name\n");
+ return;
+ }
+
+ irsym = irs_lookup(const_name, IRS_ANY);
+ if (irsym != NULL) {
+ ir_warn(ir_pos,
+ "Redefinintion of \"%s\" ignored\n",
+ const_name);
+ return;
+ }
+
+ irsym = irs_create_symbol(IRS_ROOT, const_name, IRSYM_CONST);
+
+ ir_val = ir_eval(ir_const_def->ir_expr2);
+ irsym->irsym_value = ir_val;
+}
+
+
+void
+ir_emit_declaration_list(struct ir *ir_list)
+{
+ struct ir *ir;
+
+ if (ir_list == NULL)
+ return;
+
+ if (ir_list->ir_type != IR_LIST)
+ return;
+
+ for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) {
+ switch (ir->ir_type) {
+ case IR_CONST_DEF:
+ ir_emit_const_def(ir);
+ break;
+
+ case IR_FUNC_DEF:
+ ir_emit_func_def(ir);
+ break;
+
+ default:
+ ir_error(ir,
+ "Unknown devlaration type %s\n",
+ ir_type_string(ir->ir_type));
+ break;
+ }
+ }
+}
+
+
+void
+ir_emit_node(struct ir *ir)
+{
+ struct ir *ir_name;
+ struct ir *ir_label;
+ char *name;
+ char *label;
+ struct node *node;
+ struct node *node_list;
+ struct ir_scope *irs_scope;
+
+ if (ir == NULL)
+ return;
+
+ if (ir->ir_type != IR_NODE)
+ return;
+
+ ir_name = ir_eval(ir->ir_name);
+ name = ir_eval_for_name(ir_name);
+
+ ir_label = ir_eval(ir->ir_label);
+ label = ir_eval_for_label(ir_label);
+
+ debug("ir_emit_node(): Making node %s : %s\n", label, name);
+
+ irs_push_scope(IRS_NODE);
+ ir_emit_statement_list(ir->ir_statements);
+ irs_scope = irs_pop_scope();
+
+ node_list = reverse_nodes(irs_scope->irs_node_list);
+ node = build_node(irs_scope->irs_prop_list, node_list);
+ name_node(node, name, label);
+
+ irs_append_node(node);
+}
+
+
+void
+ir_emit_mem_reserves(struct ir *ir_mem)
+{
+ struct ir *ir;
+ struct reserve_info *ri;
+ uint64_t addr;
+ uint64_t size;
+ char *lab;
+
+ if (ir_mem == NULL)
+ return;
+
+ for (ir = ir_mem->ir_first; ir != NULL; ir = ir->ir_next) {
+ addr = ir_eval_for_addr(ir->ir_expr1);
+ size = ir_eval_for_addr(ir->ir_expr2);
+ lab = ir_eval_for_label(ir->ir_label);
+
+ debug("emit: build_reserve_entry(0x%llx, 0x%llx, ",
+ (unsigned long long)addr, (unsigned long long)size);
+ if (lab) {
+ debug("%s)\n", lab);
+ } else {
+ debug("<no-label>)\n");
+ }
+
+ ri = build_reserve_entry(addr, size, lab);
+ irs_append_reserve(ri);
+ }
+}
+
+
+void
+ir_add_cmd_line_constant_defs(void)
+{
+ struct nv_pair *nv;
+ struct ir_symbol *irsym;
+ struct ir *ir_const;
+
+ for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+ irsym = irs_create_symbol(IRS_ROOT, nv->nv_name, IRSYM_CONST);
+ if (nv->nv_value) {
+ ir_const = ir_alloc(IR_LITERAL, &srcpos_empty);
+ ir_const->ir_lit_str = strdup(nv->nv_value);
+ irsym->irsym_value = ir_const;
+ }
+ }
+}
+
+
+void
+ir_emit_root(struct ir *ir)
+{
+ struct reserve_info *ri_list;
+ struct node *node_list;
+
+ if (ir == NULL)
+ return;
+
+ if (ir->ir_type != IR_ROOT) {
+ debug("emit: Bad root node\n");
+ return;
+ }
+
+ irs_push_scope(IRS_ROOT);
+
+ /*
+ * Establish constant definitions from command line.
+ */
+ ir_add_cmd_line_constant_defs();
+
+ ir_emit_mem_reserves(ir->ir_mem_reserves);
+
+ /*
+ * Fast-and-loose... These are definitions, not declarations!
+ */
+ ir_emit_declaration_list(ir->ir_declarations);
+
+ /*
+ * Emit the root IR_NODE.
+ */
+ ir_emit_node(ir->ir_statements);
+
+ /*
+ * Build the_boot_info.
+ */
+ ri_list = irs_scope_stack->irs_reserve_list;
+ node_list = irs_scope_stack->irs_node_list;
+ the_boot_info = build_boot_info(ri_list, node_list, 0);
+
+ irs_pop_scope();
+}
+
+
+extern void
+ir_emit(struct ir *ir)
+{
+ ir_emit_root(ir);
+ fflush(stdout);
+}
diff --git a/ir_scope.c b/ir_scope.c
new file mode 100644
index 0000000..c9a52e8
--- /dev/null
+++ b/ir_scope.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+#include "ir.h"
+#include "ir_scope.h"
+
+
+struct ir_scope *irs_scope_stack;
+
+static const char *irs_scope_bits_str[] = {
+ "ROOT",
+ "NODE",
+ "FOR_LOOP",
+ "FUNC_CALL",
+};
+
+
+static const char *irsym_type_str[IRSYM_NUM_TYPES] = {
+ "NONE",
+ "VAR",
+ "FUNCDEF",
+ "PARAM",
+ "CONST",
+};
+
+
+void
+irs_push_scope(irs_type irs_type)
+{
+ struct ir_scope *irs_new;
+
+ irs_new = xmalloc(sizeof(struct ir_scope));
+ memset(irs_new, 0, sizeof(struct ir_scope));
+
+ irs_new->irs_type = irs_type;
+ irs_new->irs_next = irs_scope_stack;
+
+ irs_scope_stack = irs_new;
+}
+
+
+struct ir_scope *
+irs_pop_scope()
+{
+ struct ir_scope *irs_top = irs_scope_stack;
+
+ irs_scope_stack = irs_top->irs_next;
+ irs_top->irs_next = NULL;
+
+ return irs_top;
+}
+
+
+void
+irs_free_scope(struct ir_scope *irs)
+{
+ free(irs);
+}
+
+
+struct ir_scope *
+irs_find_scope(irs_type irs_match)
+{
+ struct ir_scope *irs;
+
+ for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+ if (irs->irs_type & irs_match)
+ return irs;
+ }
+ return NULL;
+}
+
+
+void
+irs_append_reserve(struct reserve_info *ri)
+{
+ struct ir_scope *irs;
+
+ irs = irs_find_scope(IRS_ROOT);
+ irs->irs_reserve_list = chain_reserve_entry(ri,
+ irs->irs_reserve_list);
+}
+
+
+void
+irs_scope_append_property_list(struct property *pl)
+{
+ struct ir_scope *irs;
+ struct property *p;
+
+ irs = irs_find_scope(IRS_NODE);
+ for (p = pl; p != NULL; p = p->next) {
+ irs->irs_prop_list = chain_property(p, irs->irs_prop_list);
+ }
+}
+
+void
+irs_scope_append_node_list(struct node *nl)
+{
+ struct ir_scope *irs;
+ struct node *n;
+
+ irs = irs_find_scope(IRS_NODE);
+ for (n = nl; n != NULL; n = n->parent) {
+ irs->irs_node_list = chain_node(n, irs->irs_node_list);
+ }
+}
+
+
+void
+irs_append_property(struct property *p)
+{
+ struct ir_scope *irs;
+
+ irs = irs_find_scope(IRS_NODE);
+ irs->irs_prop_list = chain_property(p, irs->irs_prop_list);
+}
+
+
+void
+irs_append_node(struct node *n)
+{
+ struct ir_scope *irs;
+
+ irs = irs_find_scope(IRS_NODE | IRS_ROOT);
+ irs->irs_node_list = chain_node(n, irs->irs_node_list);
+}
+
+
+void
+irs_set_return_value(struct ir *ir_ret)
+{
+ struct ir_scope *irs;
+
+ /*
+ * FIXME: If a previous irs_expr existed, it just leaked.
+ */
+ irs = irs_find_scope(IRS_FUNC_CALL);
+ irs->irs_expr = ir_ret;
+}
+
+
+
+struct ir_symbol *
+irs_alloc_symbol(char *name, irsym_type irsym_type)
+{
+ struct ir_symbol *irsym;
+
+ irsym = xmalloc(sizeof(struct ir_symbol));
+ memset(irsym, 0, sizeof(struct ir_symbol));
+
+ irsym->irsym_type = irsym_type;
+ irsym->irsym_name = strdup(name);
+
+ return irsym;
+}
+
+
+void
+irs_add_symbol(struct ir_scope *irs, struct ir_symbol *irsym)
+{
+ irsym->irsym_next = irs->irs_symtab;
+ irs->irs_symtab = irsym;
+}
+
+
+struct ir_symbol *
+irs_lookup_in_scope(struct ir_scope *irs, char *name)
+{
+ struct ir_symbol *irsym;
+
+ for (irsym = irs->irs_symtab; irsym; irsym = irsym->irsym_next)
+ if (strcmp(irsym->irsym_name, name) == 0)
+ return irsym;
+
+ return NULL;
+}
+
+
+struct ir_symbol *
+irs_lookup(char *name, irs_type irs_type)
+{
+ struct ir_scope *irs;
+ struct ir_symbol *irsym;
+
+ /*
+ * Look through scope stack finding matching scopes.
+ */
+ for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next)
+ if (irs->irs_type & irs_type) {
+ irsym = irs_lookup_in_scope(irs, name);
+ if (irsym != NULL)
+ return irsym;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Try to find a symbol that is local to the innermost function.
+ *
+ * Look through scope stack finding matching scopes.
+ * Peer into FUNC_CALL, FOR_LOOP and IR_ROOT symbol tables,
+ * but bail at first FUNC_CALL to make them be "local".
+ */
+struct ir_symbol *
+irs_lookup_local(char *name)
+{
+ struct ir_scope *irs;
+ struct ir_symbol *irsym;
+
+ for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+ if (irs->irs_type & (IRS_FUNC_CALL|IRS_FOR_LOOP|IRS_ROOT)) {
+ irsym = irs_lookup_in_scope(irs, name);
+ if (irsym != NULL)
+ return irsym;
+ if (irs->irs_type & IRS_FUNC_CALL)
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+
+struct ir_symbol *
+irs_create_local(char *name, irsym_type irsym_type)
+{
+ struct ir_scope *irs;
+ struct ir_symbol *irsym;
+
+ for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+ if (irs->irs_type & (IRS_FUNC_CALL|IRS_ROOT)) {
+ break;
+ }
+ }
+
+ irsym = irs_alloc_symbol(name, irsym_type);
+ irs_add_symbol(irs_scope_stack, irsym);
+
+ return irsym;
+}
+
+
+struct ir_symbol *
+irs_create_symbol(irs_type irs_type, char *name, irsym_type irsym_type)
+{
+ struct ir_scope *irs;
+ struct ir_symbol *irsym;
+
+ /*
+ * Check for prior existence of symbol first.
+ */
+ irsym = irs_lookup(name, irs_type);
+ if (irsym != NULL)
+ return irsym;
+
+ /*
+ * Create the symbol.
+ */
+ irsym = irs_alloc_symbol(name, irsym_type);
+
+ /*
+ * Locate the right scope and add symbol.
+ */
+ irs = irs_find_scope(irs_type);
+ irs_add_symbol(irs, irsym);
+
+ return irsym;
+}
+
+
+void
+irs_dump_symbols(void)
+{
+ struct ir_scope *irs;
+ struct ir_symbol *irsym;
+ int i;
+
+ /*
+ * Look through scope stack.
+ */
+ for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+ printf("Type: 0x%02x : ", irs->irs_type);
+ for (i = 0; i < IRS_MAX_BIT; i++) {
+ if (irs->irs_type & (1 << i))
+ printf("%s ", irs_scope_bits_str[i]);
+ }
+ printf("\n");
+ for (irsym = irs->irs_symtab;
+ irsym != NULL;
+ irsym = irsym->irsym_next) {
+ printf(" %s : %s\n",
+ irsym_type_str[irsym->irsym_type],
+ irsym->irsym_name);
+ }
+ }
+}
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 6/8] Add the main IR evaluation implementation
[not found] ` <1222196652-13811-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-24 22:25 ` [PATCH 5/8] Add most of the new IR implementation files Scott Wood
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
ir_eval.c | 1504 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1504 insertions(+), 0 deletions(-)
create mode 100644 ir_eval.c
diff --git a/ir_eval.c b/ir_eval.c
new file mode 100644
index 0000000..bd667cb
--- /dev/null
+++ b/ir_eval.c
@@ -0,0 +1,1504 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+#include "ir.h"
+#include "ir_scope.h"
+
+
+/*
+ * Returns:
+ * 0 on success, with *val filled in
+ * -1 == bad characters in literal number
+ * -2 == literal out of range
+ * -3 == bad literal
+ */
+
+int
+ir_eval_literal_guessing(const char *s, int base, int bits,
+ unsigned long long *val)
+{
+ char *e;
+
+ errno = 0;
+ *val = strtoull(s, &e, base);
+
+ if (*e)
+ return -1;
+ else if ((errno == ERANGE)
+ || ((bits < 64) && (*val >= (1ULL << bits))))
+ return -2;
+ else if (errno != 0)
+ return -3;
+
+ return 0;
+}
+
+unsigned long long
+ir_eval_literal_str(const char *s, int base, int bits)
+{
+ unsigned long long val;
+ char *e;
+
+ errno = 0;
+ val = strtoull(s, &e, base);
+
+ if (*e)
+ die("bad characters in literal");
+ else if ((errno == ERANGE)
+ || ((bits < 64) && (val >= (1ULL << bits))))
+ die("literal out of range");
+ else if (errno != 0)
+ die("bad literal");
+
+ return val;
+}
+
+
+struct ir *
+ir_eval_cvt_to_string(struct ir *ir)
+{
+ char buf[30];
+ unsigned long long lit1;
+ struct ir *ir_new;
+
+ ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+ if (ir_is_constant(ir)) {
+ lit1 = ir_eval_for_addr(ir);
+ snprintf(buf, 30, "%llu", lit1);
+ ir_new->ir_lit_str = strdup(buf);
+ } else {
+ ir_error(ir,
+ "Can't convert %s to a string\n",
+ ir_type_string(ir->ir_type));
+ }
+
+ return ir_new;
+}
+
+
+/*
+ * FIXME: This should be named ir_is_constant_number()
+ */
+int
+ir_is_constant(struct ir *ir)
+{
+ return ir &&
+ (ir->ir_type == IR_LITERAL
+ || ir->ir_type == IR_LIT_BYTE
+ || ir->ir_type == IR_LIT_CELL
+ || ir->ir_type == IR_LIT_ADDR);
+}
+
+
+int
+ir_is_string(struct ir *ir)
+{
+ return ir && ir->ir_type == IR_LIT_STR;
+}
+
+
+char *
+ir_eval_for_label(struct ir *ir)
+{
+ char *str;
+
+ if (ir == NULL)
+ return NULL;
+
+ if (ir->ir_type == IR_LABEL
+ || ir->ir_type == IR_REF_PATH
+ || ir->ir_type == IR_REF_PHANDLE) {
+ str = strdup(ir->ir_label_name);
+ } else if (ir->ir_type == IR_LIT_STR) {
+ str = strdup(ir->ir_lit_str);
+ } else {
+ str = NULL;
+ }
+
+ return str;
+}
+
+
+char *
+ir_eval_for_name(struct ir *ir)
+{
+ struct ir *ir_val;
+ char *str;
+
+ if (ir == NULL)
+ return NULL;
+
+ ir_val = ir;
+
+ if (ir_val == NULL) {
+ ir_error(ir, "Expected a name\n");
+ return NULL;
+ }
+
+ if (ir_val->ir_type != IR_PROPNODENAME
+ && ir_val->ir_type != IR_ID
+ && ir_val->ir_type != IR_LIT_STR)
+ return NULL;
+
+ str = strdup(ir->ir_lit_str);
+
+ return str;
+}
+
+
+/*
+ * FIXME: This is misnamed. Should be more like ir_eval_for_const()
+ */
+uint64_t
+ir_eval_for_addr(struct ir *ir)
+{
+ unsigned long long a = 0;
+
+ struct ir *ir_val;
+
+ ir_val = ir_eval(ir);
+ if (ir_val == NULL) {
+ ir_error(ir, "Expected a const expression\n");
+ return 0;
+ }
+
+ /*
+ * FIXME: UH, ir_is_constant() check or something?
+ */
+
+ a = ir_val->ir_literal;
+ ir_free(ir_val);
+ debug("eval_for_addr() is 0x%08llx\n", a);
+
+ return a;
+}
+
+
+char *
+ir_eval_for_c_string(struct ir *ir)
+{
+ struct data dtmp;
+ char *p;
+
+ if (ir == NULL)
+ return NULL;
+
+
+ if (!ir_is_string(ir))
+ return NULL;
+
+ p = ir->ir_lit_str;
+ dtmp = data_copy_escape_string(p, strlen(p));
+
+ return strdup(dtmp.val);
+}
+
+
+void
+ir_eval_for_data(struct ir *ir, struct data *d)
+{
+ struct ir *ir_val;
+ struct ir *iri;
+ struct data dtmp;
+ char *lab;
+ cell_t c;
+ unsigned long long ulit64;
+
+ if (ir == NULL)
+ return;
+
+ ir_val = ir_eval(ir);
+
+ switch (ir_val->ir_type) {
+ case IR_LIST:
+ for (iri = ir_val->ir_first; iri != NULL; iri = iri->ir_next) {
+ ir_eval_for_data(iri, d);
+ }
+ break;
+
+ case IR_LIT_STR:
+ dtmp = data_copy_escape_string(ir_val->ir_lit_str,
+ strlen(ir_val->ir_lit_str));
+ *d = data_merge(*d, dtmp);
+ break;
+
+ case IR_LIT_BYTE:
+ *d = data_append_byte(*d, ir_val->ir_literal);
+ break;
+
+ case IR_LIT_ADDR:
+ ulit64 = ir_val->ir_literal;
+ *d = data_append_addr(*d, ulit64);
+ break;
+
+ case IR_LIT_CELL:
+ c = (cell_t) ir_val->ir_literal;
+ *d = data_append_cell(*d, c);
+ break;
+
+ case IR_CELL:
+ ir_eval_for_data(ir_val->ir_expr1, d);
+ break;
+
+ case IR_LABEL:
+ lab = ir_eval_for_label(ir);
+ *d = data_add_marker(*d, LABEL, lab);
+ break;
+
+ case IR_REF_PATH:
+ lab = ir_eval_for_label(ir);
+ *d = data_add_marker(*d, REF_PATH, lab);
+ break;
+
+ case IR_REF_PHANDLE:
+ lab = ir_eval_for_label(ir);
+ *d = data_add_marker(*d, REF_PHANDLE, lab);
+ *d = data_append_cell(*d, -1);
+ break;
+
+ case IR_INCBIN: {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct data dinc = empty_data;
+ char *file_name;
+ struct dtc_file *file;
+ unsigned long long start;
+ unsigned long long len;
+ struct ir *ir_pos;
+
+ /*
+ * expr1 is file_name
+ * expr2 is start, NULL implies start of file
+ * expr3 is length, NULL implies whole file
+ */
+ file_name = ir_eval_for_c_string(ir_val->ir_expr1);
+ file = dtc_open_file(file_name, &path);
+
+ ir_pos = ir_val->ir_expr2;
+ start = ir_eval_for_addr(ir_val->ir_expr2);
+ if (ir_val->ir_expr3)
+ len = ir_eval_for_addr(ir_val->ir_expr3);
+ else
+ len = -1;
+
+ if (start != 0) {
+ if (fseek(file->file, start, SEEK_SET) != 0) {
+ ir_error(ir_pos,
+ "Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)start,
+ file_name,
+ strerror(errno));
+ }
+ }
+
+ dinc = data_copy_file(file->file, len);
+ *d = data_merge(*d, dinc);
+ dtc_close_file(file);
+ break;
+ }
+
+ default:
+ ir_error(ir,
+ "Can't convert IR type %s to data\n",
+ ir_type_string(ir_val->ir_type));
+ break;
+ }
+}
+
+
+struct ir_scope *
+ir_eval_func_body(struct ir *ir_func)
+{
+ char *func_name;
+ struct ir *ir_func_def;
+ struct ir *ir_parameters;
+ struct ir *ir_statements;
+ struct ir_symbol *irsym;
+ struct ir *ir_p;
+ struct ir *ir_f;
+ char *param_name;
+ struct ir_scope *irs_scope;
+ struct ir *ir_next;
+ struct ir *ir_pos;
+
+ if (ir_func == NULL)
+ return NULL;
+
+ if (ir_func->ir_type != IR_FUNC_CALL)
+ return NULL;
+
+ /*
+ * Lookup the function definition.
+ */
+ ir_pos = ir_func->ir_expr1;
+ func_name = ir_eval_for_name(ir_func->ir_expr1);
+ debug("ir_eval_func_body(): Looking up %s\n", func_name);
+
+ irsym = irs_lookup(func_name, IRS_ANY);
+ if (irsym == NULL || irsym->irsym_type != IRSYM_FUNCDEF) {
+ ir_error(ir_pos,
+ "%s isn't a function definition\n",
+ func_name);
+ return NULL;
+ }
+
+ ir_func_def = irsym->irsym_value;
+ ir_statements = ir_func_def->ir_statements;
+ ir_parameters = ir_func_def->ir_declarations;
+
+ debug("ir_eval_func_body(): Found definition for %s\n",
+ irsym->irsym_name);
+
+ /*
+ * Set up parameter binding via eval-and-copy-in.
+ *
+ * First pass evaluates each parameter expression and
+ * builds a temporary list of each eval() parameter.
+ * These evaluations need to be done before the function
+ * scope is opened.
+ *
+ * Remember to dodge a possible parent IR_LIST node.
+ */
+ debug("ir_eval_func_body(): Evaluating parameters\n");
+ ir_p = ir_eval(ir_func->ir_expr2);
+ if (ir_p != NULL && ir_p->ir_type == IR_LIST) {
+ ir_p = ir_p->ir_first;
+ }
+
+ /*
+ * Open an evaluation scope and symbol table for
+ * the function.
+ */
+ irs_push_scope(IRS_FUNC_CALL);
+
+ /*
+ * Second pass loops over each formal parameter
+ * and each actual expression simultaneously.
+ *
+ * Again remember to dodge a possible parent IR_LIST node.
+ */
+ ir_f = ir_parameters;
+ if (ir_f != NULL && ir_f->ir_type == IR_LIST) {
+ ir_f = ir_f->ir_first;
+ }
+
+ debug("ir_eval_func_body(): Binding parameter to formals\n");
+
+ ir_pos = ir_p;
+ while (ir_f != NULL && ir_p != NULL) {
+ param_name = ir_f->ir_lit_str;
+
+ debug("ir_eval_func_body(): Binding parameter %s\n",
+ param_name);
+
+ irsym = irs_create_local(param_name, IRSYM_VAR);
+
+ irsym->irsym_value = ir_p;
+ ir_next = ir_p->ir_next;
+ ir_p->ir_next = ir_p->ir_prev = NULL;
+
+ ir_f = ir_f->ir_next;
+ ir_p = ir_next;
+ ir_pos = ir_p;
+ }
+
+ if (ir_f != NULL && ir_p == NULL) {
+ ir_error(ir_pos,
+ "Not enough parameters to %s (%s)\n",
+ func_name,
+ srcpos_string(ir_func_def->ir_srcpos));
+ }
+
+ if (ir_f == NULL && ir_p != NULL) {
+ ir_error(ir_pos,
+ "Too many parameters to %s (%s)\n",
+ func_name,
+ srcpos_string(ir_func_def->ir_srcpos));
+ }
+
+ /*
+ * And "invoke" it.
+ */
+ ir_emit_statement_list(ir_statements);
+
+ /*
+ * FIXME: Do parameter copy-out here?
+ */
+ irs_scope = irs_pop_scope();
+
+ /*
+ * FIXME: This is a bit dodgy perhaps.
+ */
+ return irs_scope;
+}
+
+
+struct ir *
+ir_eval_func_call(struct ir *ir_func)
+{
+ struct ir_scope *irs_scope;
+
+ /*
+ * Perform function body.
+ * Returned scope has "side effects".
+ *
+ * This context really just wants the return value,
+ * but we could debate using nodes and properties too?
+ */
+ irs_scope = ir_eval_func_body(ir_func);
+
+ if (!irs_scope)
+ return NULL;
+
+ return irs_scope->irs_expr;
+}
+
+
+struct ir *
+ir_eval(struct ir *ir)
+{
+ struct ir *ir_new;
+ struct ir *iri;
+ struct ir *ir1;
+ struct ir *ir2;
+ struct ir_symbol *irsym;
+ unsigned long long lit1;
+ unsigned long long lit2;
+ char *str;
+ int len;
+
+ if (ir == NULL)
+ return NULL;
+
+ ir_new = NULL;
+
+ /*
+ * Perform IR node-specific evaluations.
+ */
+ switch (ir->ir_type) {
+ case IR_LIT_STR:
+ case IR_LIT_BYTE:
+ case IR_LIT_CELL:
+ case IR_LIT_ADDR:
+ case IR_PROPNODENAME:
+ case IR_REF_PATH:
+ /*
+ * Values already present in the IR node.
+ */
+ ir_new = ir_copy(ir);
+ break;
+
+ case IR_REF_PHANDLE:
+ /*
+ * Promote a REF_PHANDLE of a LIT_STR to a
+ * direct REF_PHANDLE.
+ */
+ ir_new = ir_copy(ir);
+ if (ir->ir_label) {
+ iri = ir_eval(ir->ir_label);
+ if (ir_is_string(iri)) {
+ ir_new->ir_label_name = iri->ir_lit_str;
+ }
+ }
+ break;
+
+ case IR_LABEL:
+ ir_new = ir_copy(ir);
+ break;
+
+ case IR_CVT_PROPNODENAME:
+ iri = ir_eval(ir->ir_expr1);
+ str = ir_eval_for_name(iri);
+ if (str) {
+ ir_new = ir_alloc(IR_PROPNODENAME, ir->ir_srcpos);
+ ir_new->ir_lit_str = str;
+ }
+ break;
+
+ case IR_CVT_STRING:
+ iri = ir_eval(ir->ir_expr1);
+ ir_new = ir_eval_cvt_to_string(iri);
+ break;
+
+ case IR_ID:
+ irsym = irs_lookup(ir->ir_lit_str, IRS_ANY);
+ if (irsym != NULL) {
+ ir_new = ir_eval(irsym->irsym_value);
+ } else {
+ ir_error(ir,
+ "Unknown value for \"%s\"\n",
+ ir->ir_lit_str);
+ }
+ break;
+
+ case IR_LIST:
+ ir_new = ir_alloc(IR_LIST, ir->ir_srcpos);
+ for (iri = ir->ir_first; iri != NULL; iri = iri->ir_next) {
+ ir_list_append(ir_new, ir_eval(iri));
+ }
+ break;
+
+ case IR_SELECT:
+ /*
+ * Pick the ? or the : side.
+ */
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ if (lit1) {
+ ir_new = ir_eval(ir->ir_expr2);
+ } else {
+ ir_new = ir_eval(ir->ir_expr3);
+ }
+ break;
+
+ case IR_OR:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ if (!lit1) {
+ lit1 = ir_eval_for_addr(ir->ir_expr2);
+ }
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = (lit1 != 0);
+ break;
+
+ case IR_AND:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ if (lit1) {
+ lit1 = ir_eval_for_addr(ir->ir_expr2);
+ }
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = (lit1 != 0);
+
+ break;
+
+ case IR_BIT_OR:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 | lit2;
+ break;
+
+ case IR_BIT_XOR:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 ^ lit2;
+ break;
+
+ case IR_BIT_AND:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 & lit2;
+ break;
+
+ case IR_EQ:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 == lit2;
+ break;
+
+ case IR_LT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 < lit2;
+ break;
+
+ case IR_LE:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 <= lit2;
+ break;
+
+ case IR_GT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 > lit2;
+ break;
+
+ case IR_GE:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 >= lit2;
+ break;
+
+ case IR_NE:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 != lit2;
+ break;
+
+ case IR_LSHIFT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 << lit2;
+ break;
+
+ case IR_RSHIFT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 >> lit2;
+ break;
+
+ case IR_ADD:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 + lit2;
+ break;
+
+ case IR_MINUS:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 - lit2;
+ break;
+
+ case IR_MULT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 * lit2;
+ break;
+
+ case IR_DIV:
+ /* FIXME: check for division by const 0 */
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 / lit2;
+ break;
+
+ case IR_MOD:
+ /*
+ * This is really a bit upside down due to not having
+ * a real typing system. Cope for now.
+ */
+ ir1 = ir_eval(ir->ir_expr1);
+ ir2 = ir_eval(ir->ir_expr2);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ /*
+ * FIXME: check for division by const 0.
+ */
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ lit2 = ir_eval_for_addr(ir->ir_expr2);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 % lit2;
+
+ } else if (ir_is_string(ir1) || ir_is_string(ir2)) {
+ if (!ir_is_string(ir1))
+ ir1 = ir_eval_cvt_to_string(ir1);
+ if (!ir_is_string(ir2))
+ ir2 = ir_eval_cvt_to_string(ir2);
+ len = strlen(ir1->ir_lit_str)
+ + strlen(ir2->ir_lit_str) + 1;
+ str = xmalloc(len);
+ strcpy(str, ir1->ir_lit_str);
+ strcat(str, ir2->ir_lit_str);
+ str[len - 1] = 0;
+ ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+ ir_new->ir_lit_str = str;
+ }
+ break;
+
+ case IR_BIT_COMPL:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = ~lit1;
+ break;
+
+ case IR_NOT:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = !lit1;
+ break;
+
+ case IR_UMINUS:
+ lit1 = ir_eval_for_addr(ir->ir_expr1);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = -lit1;
+ break;
+
+ case IR_FUNC_CALL:
+ ir_new = ir_eval_func_call(ir);
+ break;
+
+ case IR_BUILTIN:
+ ir_new = ir_eval_builtin(ir);
+ break;
+
+ case IR_RANGE:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_eval(ir->ir_expr1);
+ ir_new->ir_expr2 = ir_eval(ir->ir_expr2);
+ break;
+
+ case IR_CELL:
+ ir_new = ir_eval(ir->ir_expr1);
+ if (ir_is_constant(ir_new)) {
+ /* FIXME: Check for 32-bit range here? */
+ ir_new->ir_type = IR_LIT_CELL;
+ } else if (ir_is_string(ir_new)) {
+ /* empty */
+ } else {
+ ir_error(ir, "Can't determine CELL value\n");
+ }
+ break;
+
+ case IR_LITERAL:
+ lit1 = 0;
+ if (ir_eval_literal_guessing(ir->ir_lit_str,
+ 0, 64, &lit1) == 0) {
+ /*
+ * Smells like an number.
+ */
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ ir_new->ir_literal = lit1;
+ } else {
+ /*
+ * Dunno what it is. Must be a string.
+ * FIXME: ir_eval_for_c_string() here?
+ */
+ ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+ ir_new->ir_lit_str = strdup(ir->ir_lit_str);
+ }
+ break;
+
+ case IR_INCBIN:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_eval(ir->ir_expr1);
+ ir_new->ir_expr2 = ir_eval(ir->ir_expr2);
+ ir_new->ir_expr3 = ir_eval(ir->ir_expr3);
+ break;
+
+ case IR_PROP_DEF:
+ ir_error(ir, "Can't evaluate IR_PROP_DEF here.\n");
+ break;
+
+ case IR_ROOT:
+ case IR_RETURN:
+ case IR_IF:
+ case IR_FOR:
+ case IR_ASSIGN:
+ case IR_MEM_RESERVE:
+ case IR_FUNC_DEF:
+ case IR_PARAMDECL:
+ case IR_NODE:
+ ir_error(ir,
+ "Can't evaluate %s statements in expressions\n",
+ ir_type_string(ir->ir_type));
+ break;
+
+ default:
+ ir_error(ir,
+ "Unknown expression ir_type %s\n",
+ ir_type_string(ir->ir_type));
+ }
+
+ return ir_new;
+}
+
+
+struct ir *
+ir_simplify(struct ir *ir, unsigned int ctxt)
+{
+ struct ir *ir1;
+ struct ir *ir2;
+ ir_type ir_type;
+ struct ir *ir_new;
+ unsigned long long lit1;
+ unsigned long long lit2;
+ unsigned long long ulit64;
+
+ if (ir == NULL)
+ return NULL;
+
+ /*
+ * First determine what the evaluation context will be
+ * for any sub-expression based on the current IR node.
+ */
+ switch (ir->ir_type) {
+ case IR_CELL:
+ /*
+ * Pass new context down.
+ */
+ ctxt = IR_EVAL_CTXT_CELL;
+ break;
+
+ case IR_INCBIN:
+ case IR_IF:
+ case IR_FOR:
+ case IR_MEM_RESERVE:
+ /*
+ * These are always done in an ANY context.
+ */
+ ctxt = IR_EVAL_CTXT_ANY;
+ break;
+
+ default:
+ /*
+ * Use the supplied (parameter) context.
+ */
+ break;
+ }
+
+
+ /*
+ * Perform IR node-specific optimizations.
+ */
+ switch (ir->ir_type) {
+ case IR_ID:
+ case IR_LIT_STR:
+ case IR_LIT_BYTE:
+ case IR_LIT_CELL:
+ case IR_LIT_ADDR:
+ case IR_PROPNODENAME:
+ case IR_LABEL:
+ case IR_REF_PATH:
+ /*
+ * Already as simple as they can be.
+ */
+ ir_new = ir_copy(ir);
+ break;
+
+ case IR_REF_PHANDLE:
+ ir_new = ir_copy(ir);
+ ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+ break;
+
+ case IR_RETURN:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ break;
+
+ case IR_MEM_RESERVE:
+ case IR_RANGE:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ break;
+
+ case IR_CELL:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir1 && ir1->ir_type == IR_LIT_CELL) {
+ ir_new = ir1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_PROP_DEF:
+ ir_new = ir_copy(ir);
+ ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ break;
+
+ case IR_LITERAL:
+ /*
+ * Based on context, evaluate literal into 32 or 64 bits.
+ * LIT_ADDR could be a lie; it just means 64-bit. Feh.
+ */
+ if (ctxt == IR_EVAL_CTXT_CELL) {
+ ulit64 = ir_eval_literal_str(ir->ir_lit_str, 0, 32);
+ ir_new = ir_alloc(IR_LIT_CELL, ir->ir_srcpos);
+ } else {
+ ulit64 = ir_eval_literal_str(ir->ir_lit_str, 0, 64);
+ ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+ }
+ ir_new->ir_literal = ulit64;
+ break;
+
+ case IR_FUNC_CALL:
+ {
+ char *name;
+ irb_id irb;
+
+ ir_new = ir_copy(ir);
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ name = ir_eval_for_name(ir1);
+ if (name) {
+ irb = ir_lookup_builtin_by_name(name);
+ if (irb != IRB_UNDEF) {
+ debug("ir_simplify(): Use builtin %s\n",
+ name);
+ ir_new->ir_type = IR_BUILTIN;
+ ir_new->ir_builtin_id = irb;
+ ir_new->ir_expr1 = ir2;
+ } else {
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ } else {
+ ir_error(ir1, "Unknown function %s\n", name);
+ }
+ }
+ break;
+
+ case IR_BUILTIN:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ break;
+
+ case IR_LIST:
+ ir_new = ir_alloc(IR_LIST, ir->ir_srcpos);
+ for (ir1 = ir->ir_first; ir1 != NULL; ir1 = ir1->ir_next) {
+ ir_list_append(ir_new,
+ ir_simplify(ir1, ctxt));
+ }
+ break;
+
+ case IR_INCBIN:
+ /*
+ * Ponder loading and caching files?
+ */
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+ break;
+
+ case IR_ASSIGN:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ break;
+
+ case IR_IF:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ /*
+ * Eliminate the IR_IF.
+ * Pick the THEN or ELSE statements only.
+ * FIXME: Fix leaking ir1 here.
+ */
+ ulit64 = ir_eval_for_addr(ir1);
+ if (ulit64) {
+ /*
+ * Keep the THEN statements.
+ */
+ ir_new = ir_simplify(ir->ir_statements, ctxt);
+ } else {
+ /*
+ * Keep the ELSE statements.
+ */
+ ir_new = ir_simplify(ir->ir_statements2, ctxt);
+ }
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir1 = ir_simplify(ir->ir_statements, ctxt);
+ ir_new->ir_statements = ir1;
+ ir1 = ir_simplify(ir->ir_statements2, ctxt);
+ ir_new->ir_statements2 = ir1;
+ }
+ break;
+
+ case IR_FOR:
+ /*
+ * Lots of optimizations possible here based on
+ * empty statements and trivial ranges. Later.
+ * FIXME: Do "for" simplification optimizations.
+ */
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+ ir_new->ir_statements = ir_simplify(ir->ir_statements, ctxt);
+ break;
+
+ case IR_SELECT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ /*
+ * Pick the ? or the : side.
+ * FIXME: Fix leaking ir1.
+ */
+ ulit64 = ir_eval_for_addr(ir1);
+ if (ulit64) {
+ ir_new = ir_simplify(ir->ir_expr2, ctxt);
+ } else {
+ ir_new = ir_simplify(ir->ir_expr3, ctxt);
+ }
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+ }
+ break;
+
+ case IR_CVT_PROPNODENAME:
+ /*
+ * IR_CVT_PROPNODENAME(IR_PROPNODENAME) == IR_PROPNODENAME,
+ * so drop the CVT.
+ */
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir1 && ir1->ir_type == IR_PROPNODENAME) {
+ ir_new = ir1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_CVT_STRING:
+ /*
+ * IR_CVT_STRING(IR_LIT_STR) == IR_LIT_STR,
+ * so drop the CVT.
+ */
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir1 && ir1->ir_type == IR_LIT_STR) {
+ ir_new = ir1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_OR:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ ulit64 = ir_eval_for_addr(ir1);
+ if (ulit64) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = 1;
+ break;
+ }
+ }
+
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new->ir_literal = lit1 || lit2;
+
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir2, ctxt);
+ }
+ break;
+
+ case IR_AND:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ ulit64 = ir_eval_for_addr(ir1);
+ if (ulit64 == 0) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = 0;
+ break;
+ }
+ }
+
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new->ir_literal = lit1 && lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_BIT_OR:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 | lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_BIT_XOR:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 ^ lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_BIT_AND:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 & lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_EQ:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 == lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_LT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 < lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_LE:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 <= lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_GT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 > lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_GE:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 >= lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_NE:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 != lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_LSHIFT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 << lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_RSHIFT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 >> lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_ADD:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 + lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_MINUS:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 - lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_MULT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 * lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_DIV:
+ /* FIXME: check for division by const 0 */
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 / lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_MOD:
+ /* FIXME: check for division by const 0 */
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir2 = ir_simplify(ir->ir_expr2, ctxt);
+ if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ lit2 = ir_eval_for_addr(ir2);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = lit1 % lit2;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ ir_new->ir_expr2 = ir2;
+ }
+ break;
+
+ case IR_BIT_COMPL:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = ~lit1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_NOT:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = !lit1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_UMINUS:
+ ir1 = ir_simplify(ir->ir_expr1, ctxt);
+ if (ir_is_constant(ir1)) {
+ ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+ ? IR_LIT_CELL : IR_LIT_ADDR;
+ lit1 = ir_eval_for_addr(ir1);
+ ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+ ir_new->ir_literal = -lit1;
+ } else {
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir1;
+ }
+ break;
+
+ case IR_ROOT:
+ ir_new = ir_copy(ir);
+ ir_new->ir_mem_reserves =
+ ir_simplify(ir->ir_mem_reserves, ctxt);
+ ir_new->ir_declarations =
+ ir_simplify(ir->ir_declarations, ctxt);
+ ir_new->ir_statements =
+ ir_simplify(ir->ir_statements, ctxt);
+ break;
+
+ case IR_NODE:
+ ir_new = ir_copy(ir);
+ ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+ ir_new->ir_name = ir_simplify(ir->ir_name, ctxt);
+ ir_new->ir_statements =
+ ir_simplify(ir->ir_statements, ctxt);
+ break;
+
+ case IR_CONST_DEF:
+ ir_new = ir_copy(ir);
+ ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+ ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+ break;
+
+ case IR_FUNC_DEF:
+ ir_new = ir_copy(ir);
+ ir_new->ir_name = ir_simplify(ir->ir_name, ctxt);
+ ir_new->ir_declarations =
+ ir_simplify(ir->ir_declarations, ctxt);
+ ir_new->ir_statements =
+ ir_simplify(ir->ir_statements, ctxt);
+ break;
+
+ case IR_PARAMDECL:
+ default:
+ ir_new = NULL;
+ ir_error(ir,
+ "Can't simplify unknown ir_type %s\n",
+ ir_type_string(ir->ir_type));
+ }
+
+ return ir_new;
+}
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 7/8] Introduce new DTS language.
[not found] ` <1222196652-13811-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
0 siblings, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Introduce function defs and statements.
Added support for expressions.
Added if, for, assign and return statements.
Added support for BUILTIN functions.
Added support for /const/ definitions.
Added support for command line defines, eg: -D x=1
Add lexical support for column source position information.
Notably, this involved identifying all the newline
characters to reset the column count. Had to rewrite
the C comment rules, and break \n out of the {WS} set.
Add lexical source positions to all IR nodes.
Change error reporting to use IR source positions.
Passes test suite.
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
Makefile | 2 +-
Makefile.dtc | 18 ++-
dtc-lexer.l | 259 +++++++++++++++++----
dtc-parser.y | 720 ++++++++++++++++++++++++++++++++++++++++++++++------------
dtc.c | 7 +-
dtc.h | 1 +
livetree.c | 16 ++
nv.c | 108 +++++++++
nv.h | 34 +++
srcpos.c | 47 ++++-
srcpos.h | 10 +-
treesource.c | 3 +
12 files changed, 1016 insertions(+), 209 deletions(-)
create mode 100644 nv.c
create mode 100644 nv.h
diff --git a/Makefile b/Makefile
index 5ad0189..1ae5577 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ CONFIG_LOCALVERSION =
CPPFLAGS = -I libfdt
CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual
-BISON = bison
+BISON = bison -v
LEX = flex
INSTALL = /usr/bin/install
diff --git a/Makefile.dtc b/Makefile.dtc
index 6ddf9ec..dd53276 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -3,7 +3,21 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
- checks.c
+DTC_SRCS = \
+ checks.c \
+ data.c \
+ dtc.c \
+ flattree.c \
+ fstree.c \
+ ir.c \
+ ir_builtin.c \
+ ir_dump.c \
+ ir_emit.c \
+ ir_eval.c \
+ ir_scope.c \
+ livetree.c \
+ nv.c \
+ srcpos.c \
+ treesource.c
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 6b862d2..4465462 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -18,19 +18,19 @@
* USA
*/
-%option noyywrap nounput noinput yylineno
+%option noyywrap nounput noinput yylineno stack
-%x INCLUDE
%x BYTESTRING
%x PROPNODENAME
+%x COMMENT
%s V1
PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
+ID \\[a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
-WS [[:space:]]
-COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
+WS [[:blank:]]
LINECOMMENT "//".*\n
%{
@@ -49,6 +49,22 @@ LINECOMMENT "//".*\n
static int dts_version = 1;
+/*
+ * Track column positions too. Brute force.
+ */
+int yycolno = 1;
+
+#define SET_SRCPOS(yylloc) do { \
+ yylloc.file = srcpos_file; \
+ yylloc.first_line = yylineno; \
+ yylloc.last_line = yylineno; \
+ yylloc.first_column = yycolno; \
+ yycolno += yyleng; \
+ yylloc.last_column = yycolno - 1; \
+ DPRINT("Set srcpos: %s\n", \
+ srcpos_string(&yylloc)); \
+ } while (0)
+
#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \
BEGIN(V1); \
@@ -59,29 +75,27 @@ static int pop_input_file(void);
%%
<*>"/include/"{WS}*{STRING} {
char *name = strchr(yytext, '\"') + 1;
+ SET_SRCPOS(yylloc);
yytext[yyleng-1] = '\0';
push_input_file(name);
}
-<*><<EOF>> {
+<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
}
}
<*>{STRING} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("String: %s\n", yytext);
- yylval.data = data_copy_escape_string(yytext+1,
- yyleng-2);
- yylloc.first_line = yylineno;
+ yytext[yyleng-1] = 0; /* remove close quote */
+ yylval.litstr = strdup(yytext + 1);
return DT_STRING;
}
<*>"/dts-v1/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
BEGIN_DEFAULT();
@@ -89,41 +103,31 @@ static int pop_input_file(void);
}
<*>"/memreserve/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
<*>{LABEL}: {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("Label: %s\n", yytext);
yylval.labelref = strdup(yytext);
yylval.labelref[yyleng-1] = '\0';
return DT_LABEL;
}
-<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LITERAL;
- }
-
-\&{LABEL} { /* label reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+<*>\&{LABEL} {
+ /* label reference */
+ SET_SRCPOS(yylloc);
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1);
return DT_REF;
}
-"&{/"{PATHCHAR}+\} { /* new-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+<*>"&{/"{PATHCHAR}+\} {
+ /* new-style path reference */
+ SET_SRCPOS(yylloc);
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = strdup(yytext+2);
@@ -131,44 +135,199 @@ static int pop_input_file(void);
}
<BYTESTRING>[0-9a-fA-F]{2} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
<BYTESTRING>"]" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
+<*>[0-9]+|0[xX][0-9a-fA-F]+ {
+ SET_SRCPOS(yylloc);
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LITERAL;
+ }
+
+<*>"for" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: for\n");
+ BEGIN_DEFAULT();
+ return DT_FOR;
+ }
+
+<*>"if" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: if\n");
+ BEGIN_DEFAULT();
+ return DT_IF;
+ }
+
+<*>"void" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: void\n");
+ return DT_VOID;
+ }
+
+<*>"in" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: in\n");
+ BEGIN_DEFAULT();
+ return DT_IN;
+ }
+
+<*>"else" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: else\n");
+ BEGIN_DEFAULT();
+ return DT_ELSE;
+ }
+
+<*>"return" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: return\n");
+ return DT_RETURN;
+ }
+
+<*>"/define/" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: define\n");
+ return DT_DEFINE;
+ }
+
+<*>"/const/" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: const\n");
+ return DT_CONST;
+}
+
+<*>"/incbin/" {
+ SET_SRCPOS(yylloc);
+ DPRINT("Binary Include\n");
+ return DT_INCBIN;
+ }
+
+<*>{ID} {
+ SET_SRCPOS(yylloc);
+ DPRINT("Id: %s\n", yytext);
+ yylval.id = strdup(yytext + 1); /* drop \ */
+ BEGIN_DEFAULT();
+ return DT_ID;
+ }
+
<PROPNODENAME>{PROPNODECHAR}+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = strdup(yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
-"/incbin/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Binary Include\n");
- return DT_INCBIN;
+
+<*>{WS}+ {
+ /* eat whitespace, but not newline */
+ SET_SRCPOS(yylloc);
+ }
+
+<*>"/*" {
+ SET_SRCPOS(yylloc);
+ yy_push_state(COMMENT);
+ }
+
+<COMMENT>{
+[^*\n]* {
+ /* munch */
+ SET_SRCPOS(yylloc);
}
-<*>{WS}+ /* eat whitespace */
-<*>{COMMENT}+ /* eat C-style comments */
-<*>{LINECOMMENT}+ /* eat C++-style comments */
+[^*\n]*\n {
+ yycolno = 1;
+ }
+
+"*"+[^*/\n]* {
+ /* munch */
+ SET_SRCPOS(yylloc);
+ }
+
+"*"+[^*/\n]*\n {
+ yycolno = 1;
+ }
+
+"*"+"/" {
+ SET_SRCPOS(yylloc);
+ yy_pop_state();
+ }
+}
+
+
+<*>{LINECOMMENT}+ {
+ /* eat C++-style comments including newline */
+ yycolno = 1;
+ }
+
+<*>":=" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: <<\n");
+ return DT_ASSIGN;
+ }
+<*>"<<" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: <<\n");
+ return DT_LSHIFT;
+ }
+<*>">>" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: >>\n");
+ return DT_RSHIFT;
+ }
+<*>"<=" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: <=\n");
+ return DT_LE;
+ }
+<*>">=" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: >=\n");
+ return DT_GE;
+ }
+<*>"==" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: ==\n");
+ return DT_EQ;
+ }
+<*>"!=" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: !=\n");
+ return DT_NE;
+ }
+<*>"&&" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: &&\n");
+ return DT_AND;
+ }
+<*>"||" {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: ||\n");
+ return DT_OR;
+ }
+<*>".." {
+ SET_SRCPOS(yylloc);
+ DPRINT("token: ..\n");
+ return DT_RANGE;
+ }
+
+<*>\n {
+ yycolno = 1;
+ }
<*>. {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
+ SET_SRCPOS(yylloc);
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
if (yytext[0] == '[') {
@@ -176,7 +335,9 @@ static int pop_input_file(void);
BEGIN(BYTESTRING);
}
if ((yytext[0] == '{')
- || (yytext[0] == ';')) {
+ || (yytext[0] == ';')
+ || (yytext[0] == ':')
+ ) {
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
}
@@ -194,6 +355,7 @@ struct incl_file {
struct dtc_file *file;
YY_BUFFER_STATE yy_prev_buf;
int yy_prev_lineno;
+ int yy_prev_colno;
struct incl_file *prev;
};
@@ -235,6 +397,7 @@ static void push_input_file(const char *filename)
*/
incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
incl_file->yy_prev_lineno = yylineno;
+ incl_file->yy_prev_lineno = yycolno;
incl_file->file = srcpos_file;
incl_file->prev = incl_file_stack;
@@ -245,6 +408,7 @@ static void push_input_file(const char *filename)
*/
srcpos_file = newfile;
yylineno = 1;
+ yycolno = 1;
yyin = newfile->file;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
}
@@ -272,6 +436,7 @@ static int pop_input_file(void)
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(incl_file->yy_prev_buf);
yylineno = incl_file->yy_prev_lineno;
+ yycolno = incl_file->yy_prev_colno;
srcpos_file = incl_file->file;
yyin = incl_file->file ? incl_file->file->file : NULL;
diff --git a/dtc-parser.y b/dtc-parser.y
index 3762181..77ccbb8 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -25,69 +25,129 @@
#include "dtc.h"
#include "srcpos.h"
+#include "ir.h"
extern int yylex(void);
+extern void yyerror(char const *s);
-extern struct boot_info *the_boot_info;
extern int treesource_error;
-static unsigned long long eval_literal(const char *s, int base, int bits);
+#define YYERROR_VERBOSE
+
%}
%union {
+ struct ir *ir;
char *propnodename;
+ char *id;
+ char *litstr;
char *literal;
char *labelref;
- unsigned int cbase;
uint8_t byte;
- struct data data;
-
- uint64_t addr;
- cell_t cell;
- struct property *prop;
- struct property *proplist;
- struct node *node;
- struct node *nodelist;
- struct reserve_info *re;
}
%token DT_V1
%token DT_MEMRESERVE
+%token DT_INCBIN
+%token DT_DEFINE
+%token DT_CONST
+%token DT_FOR
+%token DT_IN
+%token DT_RANGE
+%token DT_VOID
+%token DT_IF
+%token DT_ELSE
+%token DT_RETURN
+
%token <propnodename> DT_PROPNODENAME
+%token <id> DT_ID
%token <literal> DT_LITERAL
-%token <cbase> DT_BASE
%token <byte> DT_BYTE
-%token <data> DT_STRING
+%token <litstr> DT_STRING
%token <labelref> DT_LABEL
%token <labelref> DT_REF
-%token DT_INCBIN
-%type <data> propdata
-%type <data> propdataprefix
-%type <re> memreserve
-%type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
-%type <data> bytestring
-%type <prop> propdef
-%type <proplist> proplist
-
-%type <node> devicetree
-%type <node> nodedef
-%type <node> subnode
-%type <nodelist> subnodes
-%type <labelref> label
+%token DT_OR
+%token DT_AND
+%token DT_EQ DT_NE
+%token DT_LE DT_GE
+%token DT_LSHIFT DT_RSHIFT
+%token DT_ASSIGN
+
+%type <ir> sourcefile
+%type <ir> memreserves
+%type <ir> memreserve
+%type <ir> devicetree
+%type <ir> declaration_list
+%type <ir> declaration
+%type <ir> funcdef
+%type <ir> constdef
+%type <ir> errordef
+%type <ir> subnode
+%type <ir> paramdecl_list
+%type <ir> paramdecls
+%type <ir> paramdecl
+
+%type <ir> statement_block
+%type <ir> statement_list
+%type <ir> statement
+%type <ir> for_statement
+%type <ir> if_statement
+%type <ir> return_statement
+%type <ir> assign_statement
+%type <ir> trivial_statement
+%type <ir> error_statement
+
+%type <ir> propdef
+%type <ir> celllist
+%type <ir> cellval
+%type <ir> literal
+%type <ir> string
+%type <ir> addr
+%type <ir> byte
+%type <ir> propnodename
+%type <ir> label
+%type <ir> opt_label
+%type <ir> node_label
+%type <ir> propdata
+%type <ir> propdataitem
+%type <ir> propdataprefix
+%type <ir> bytestring
+
+%type <ir> param_list
+
+%type <ir> expr
+%type <ir> expr_primary
+%type <ir> expr_postfix
+%type <ir> expr_unary
+%type <ir> expr_mul
+%type <ir> expr_add
+%type <ir> expr_shift
+%type <ir> expr_rela
+%type <ir> expr_eq
+%type <ir> expr_bitand
+%type <ir> expr_bitxor
+%type <ir> expr_bitor
+%type <ir> expr_and
+%type <ir> expr_or
+%type <ir> expr_conditional
+
+%type <ir> range
+%type <ir> identifier
%%
sourcefile:
- DT_V1 ';' memreserves devicetree
+ DT_V1 ';' memreserves declaration_list devicetree
{
- the_boot_info = build_boot_info($3, $4, 0);
+ the_ir_tree = ir_alloc(IR_ROOT, &@5);
+ the_ir_tree->ir_mem_reserves = $3;
+ the_ir_tree->ir_declarations = $4;
+ the_ir_tree->ir_statements = $5;
}
;
+/* FIXME: make left recursive */
memreserves:
/* empty */
{
@@ -95,239 +155,605 @@ memreserves:
}
| memreserve memreserves
{
- $$ = chain_reserve_entry($1, $2);
+ $$ = ir_list_append($2, $1);
}
;
memreserve:
- label DT_MEMRESERVE addr addr ';'
+ opt_label DT_MEMRESERVE addr addr ';'
{
- $$ = build_reserve_entry($3, $4, $1);
+ $$ = ir_alloc_binop(IR_MEM_RESERVE, $3, $4, &@2);
+ $$->ir_label = $1;
}
;
-addr:
- DT_LITERAL
+
+declaration_list:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | declaration_list declaration
{
- $$ = eval_literal($1, 0, 64);
+ $$ = ir_list_append($1, $2);
}
- ;
+ ;
-devicetree:
- '/' nodedef
+declaration:
+ constdef
+ | funcdef
+ | errordef
+ ;
+
+constdef:
+ DT_CONST identifier '=' expr ';'
{
- $$ = name_node($2, "", NULL);
+ $$ = ir_alloc_binop(IR_CONST_DEF, $2, $4, &@1);
}
;
-nodedef:
- '{' proplist subnodes '}' ';'
+funcdef:
+ DT_DEFINE propnodename paramdecls statement_block
{
- $$ = build_node($2, $3);
+ $$ = ir_alloc(IR_FUNC_DEF, &@1);
+ $$->ir_name = $2;
+ $$->ir_declarations = $3;
+ $$->ir_statements = $4;
}
;
-proplist:
+errordef:
+ error
+ {
+ $$ = NULL
+ }
+ ;
+
+paramdecls:
+ '(' paramdecl_list ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+paramdecl_list:
/* empty */
{
$$ = NULL;
}
- | proplist propdef
+ | paramdecl
+ {
+ $$ = ir_list_append(NULL, $1);
+ }
+ | paramdecl_list ',' paramdecl
{
- $$ = chain_property($2, $1);
+ $$ = ir_list_append($1, $3);
}
;
-propdef:
- label DT_PROPNODENAME '=' propdata ';'
+paramdecl:
+ identifier
+ ;
+
+
+devicetree:
+ '/' statement_block ';'
{
- $$ = build_property($2, $4, $1);
+ $$ = ir_alloc(IR_NODE, &@2);
+ $$->ir_statements = $2;
+ $$->ir_name = ir_alloc(IR_PROPNODENAME, &@1);
+ $$->ir_name->ir_lit_str = "";
+ $$->ir_label = NULL;
}
- | label DT_PROPNODENAME ';'
+ ;
+
+
+statement_block:
+ '{' statement_list '}'
{
- $$ = build_property($2, empty_data, $1);
+ $$ = $2;
}
;
-propdata:
- propdataprefix DT_STRING
+statement_list:
+ /* empty */
{
- $$ = data_merge($1, $2);
+ $$ = NULL;
}
- | propdataprefix '<' celllist '>'
+ | statement_list statement
{
- $$ = data_merge($1, $3);
+ $$ = ir_list_append($1, $2);
}
- | propdataprefix '[' bytestring ']'
+ ;
+
+statement:
+ for_statement
+ | if_statement
+ | return_statement
+ | assign_statement
+ | propdef
+ | subnode
+ | statement_block
+ | trivial_statement
+ | error_statement
+ ;
+
+
+subnode:
+ node_label expr statement_block ';'
{
- $$ = data_merge($1, $3);
+ $$ = ir_alloc(IR_NODE, &@3);
+ $$->ir_statements = $3;
+ $$->ir_label = $1;
+ $$->ir_name = $2;
}
- | propdataprefix DT_REF
+ | label expr statement_block ';'
{
- $$ = data_add_marker($1, REF_PATH, $2);
+ $$ = ir_alloc(IR_NODE, &@3);
+ $$->ir_statements = $3;
+ $$->ir_label = $1;
+ $$->ir_name = $2;
}
- | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+ | expr statement_block ';'
{
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file($4.val, &path);
- struct data d = empty_data;
+ $$ = ir_alloc(IR_NODE, &@2);
+ $$->ir_statements = $2;
+ $$->ir_label = NULL;
+ $$->ir_name = $1;
+ }
+ ;
- if ($6 != 0)
- if (fseek(file->file, $6, SEEK_SET) != 0)
- yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)$6,
- $4.val, strerror(errno));
+for_statement:
+ DT_FOR identifier DT_IN range statement_block
+ {
+ $$ = ir_alloc_binop(IR_FOR, $2, $4, &@1);
+ $$->ir_statements = $5;
+ }
+ ;
- d = data_copy_file(file->file, $8);
+range:
+ expr DT_RANGE expr
+ {
+ $$ = ir_alloc_binop(IR_RANGE, $1, $3, &@2);
+ }
+ ;
- $$ = data_merge($1, d);
- dtc_close_file(file);
+if_statement:
+ DT_IF '(' expr ')' statement_block
+ {
+ $$ = ir_alloc_unop(IR_IF, $3, &@1);
+ $$->ir_statements = $5;
}
- | propdataprefix DT_INCBIN '(' DT_STRING ')'
+ | DT_IF '(' expr ')' statement_block DT_ELSE statement_block
{
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file($4.val, &path);
- struct data d = empty_data;
+ $$ = ir_alloc_unop(IR_IF, $3, &@1);
+ $$->ir_statements = $5;
+ $$->ir_statements2 = $7;
+ }
+ ;
- d = data_copy_file(file->file, -1);
+return_statement:
+ DT_RETURN expr ';'
+ {
+ $$ = ir_alloc_unop(IR_RETURN, $2, &@1);
+ }
+ ;
+
+assign_statement:
+ identifier DT_ASSIGN expr ';'
+ {
+ $$ = ir_alloc_binop(IR_ASSIGN, $1, $3, &@2);
+ }
+ ;
+
+trivial_statement:
+ ';'
+ {
+ $$ = NULL;
+ }
+ ;
+
+error_statement:
+ error
+ {
+ $$ = NULL;
+ }
+ ;
+
+propdef:
+ expr ';'
+ {
+ $$ = ir_alloc_unop(IR_PROP_DEF,
+ ir_alloc_unop(IR_CVT_PROPNODENAME,
+ $1,
+ &@1),
+ &@1);
+ $$->ir_label = NULL;
+ }
+ | expr '=' propdata ';'
+ {
+ $$ = ir_alloc_binop(IR_PROP_DEF,
+ ir_alloc_unop(IR_CVT_PROPNODENAME,
+ $1,
+ &@1),
+ $3,
+ &@2);
+ $$->ir_label = NULL;
+ }
+ | label expr ';'
+ {
+ $$ = ir_alloc_unop(IR_PROP_DEF,
+ ir_alloc_unop(IR_CVT_PROPNODENAME,
+ $2,
+ &@2),
+ &@2);
+ $$->ir_label = $1;
+ }
+ | label expr '=' propdata ';'
+ {
+ $$ = ir_alloc_binop(IR_PROP_DEF,
+ ir_alloc_unop(IR_CVT_PROPNODENAME,
+ $2,
+ &@2),
+ $4,
+ &@3);
+ $$->ir_label = $1;
+ }
+ ;
+
+propdata:
+ propdataprefix propdataitem
+ {
+ $$ = ir_list_append($1, $2);
+ }
+ | propdata label
+ {
+ $$ = ir_list_append($1, $2);
+ }
+ ;
- $$ = data_merge($1, d);
- dtc_close_file(file);
+propdataitem:
+ string
+ {
+ $$ = $1;
+ }
+ | '<' celllist '>'
+ {
+ $$ = $2;
}
- | propdata DT_LABEL
+ | '[' bytestring ']'
{
- $$ = data_add_marker($1, LABEL, $2);
+ $$ = $2;
+ }
+ | DT_REF
+ {
+ $$ = ir_alloc(IR_REF_PATH, &@1);
+ $$->ir_label_name = $1;
+ }
+ | DT_INCBIN '(' expr ')'
+ {
+ $$ = ir_alloc_unop(IR_INCBIN, $3, &@1);
+ }
+ | DT_INCBIN '(' expr ',' expr ',' expr ')'
+ {
+ $$ = ir_alloc_triop(IR_INCBIN, $3, $5, $7, &@1);
}
;
propdataprefix:
/* empty */
{
- $$ = empty_data;
+ $$ = NULL;
}
| propdata ','
{
$$ = $1;
}
- | propdataprefix DT_LABEL
+ | propdataprefix label
{
- $$ = data_add_marker($1, LABEL, $2);
+ $$ = ir_list_append($1, $2);
}
;
celllist:
/* empty */
{
- $$ = empty_data;
+ $$ = NULL;
}
| celllist cellval
{
- $$ = data_append_cell($1, $2);
+ $$ = ir_list_append($1, $2);
+ }
+ | celllist '&' '(' expr ')'
+ {
+ $$ = ir_alloc(IR_REF_PHANDLE, &@2);
+ $$->ir_label = $4;
+ $$ = ir_list_append($1, $$);
+
}
| celllist DT_REF
{
- $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
- $2), -1);
+ $$ = ir_alloc(IR_REF_PHANDLE, &@2);
+ $$->ir_label_name = $2;
+ $$ = ir_list_append($1, $$);
}
- | celllist DT_LABEL
+ | celllist label
{
- $$ = data_add_marker($1, LABEL, $2);
+ $$ = ir_list_append($1, $2);
}
;
cellval:
- DT_LITERAL
+ expr_primary
{
- $$ = eval_literal($1, 0, 32);
+ $$ = ir_alloc_unop(IR_CELL, $1, &@1);
}
;
-bytestring:
- /* empty */
+
+expr:
+ expr_conditional
+ ;
+
+expr_conditional:
+ expr_or
+ | expr_or '?' expr_or ':' expr_conditional
+ {
+ $$ = ir_alloc_triop(IR_SELECT, $1, $3, $5, &@2);
+ }
+ ;
+
+expr_or:
+ expr_and
+ | expr_or DT_OR expr_and
+ {
+ $$ = ir_alloc_binop(IR_OR, $1, $3, &@2);
+ };
+
+expr_and:
+ expr_bitor
+ | expr_and DT_AND expr_bitor
+ {
+ $$ = ir_alloc_binop(IR_AND, $1, $3, &@2);
+ };
+ ;
+
+expr_bitor:
+ expr_bitxor
+ | expr_bitor '|' expr_bitxor
+ {
+ $$ = ir_alloc_binop(IR_BIT_OR, $1, $3, &@2);
+ };
+ ;
+
+expr_bitxor:
+ expr_bitand
+ | expr_bitxor '^' expr_bitand
{
- $$ = empty_data;
+ $$ = ir_alloc_binop(IR_BIT_XOR, $1, $3, &@2);
+ };
+ ;
+
+expr_bitand:
+ expr_eq
+ | expr_bitand '&' expr_eq
+ {
+ $$ = ir_alloc_binop(IR_BIT_AND, $1, $3, &@2);
+ };
+ ;
+
+expr_eq:
+ expr_rela
+ | expr_eq DT_EQ expr_rela
+ {
+ $$ = ir_alloc_binop(IR_EQ, $1, $3, &@2);
}
- | bytestring DT_BYTE
+ | expr_eq DT_NE expr_rela
+ {
+ $$ = ir_alloc_binop(IR_NE, $1, $3, &@2);
+ }
+ ;
+
+expr_rela:
+ expr_shift
+ | expr_rela '<' expr_shift
+ {
+ $$ = ir_alloc_binop(IR_LT, $1, $3, &@2);
+ }
+ | expr_rela '>' expr_shift
+ {
+ $$ = ir_alloc_binop(IR_GT, $1, $3, &@2);
+ }
+ | expr_rela DT_LE expr_shift
+ {
+ $$ = ir_alloc_binop(IR_LE, $1, $3, &@2);
+ }
+ | expr_rela DT_GE expr_shift
+ {
+ $$ = ir_alloc_binop(IR_GE, $1, $3, &@2);
+ }
+ ;
+
+expr_shift:
+ expr_add
+ | expr_shift DT_LSHIFT expr_add
{
- $$ = data_append_byte($1, $2);
+ $$ = ir_alloc_binop(IR_LSHIFT, $1, $3, &@2);
}
- | bytestring DT_LABEL
+ | expr_shift DT_RSHIFT expr_add
{
- $$ = data_add_marker($1, LABEL, $2);
+ $$ = ir_alloc_binop(IR_RSHIFT, $1, $3, &@2);
}
;
-subnodes:
+expr_add:
+ expr_mul
+ | expr_add '+' expr_mul
+ {
+ $$ = ir_alloc_binop(IR_ADD, $1, $3, &@2);
+ }
+ | expr_add '-' expr_mul
+ {
+ $$ = ir_alloc_binop(IR_MINUS, $1, $3, &@2);
+ }
+ ;
+
+expr_mul:
+ expr_unary
+ | expr_mul '*' expr_unary
+ {
+ $$ = ir_alloc_binop(IR_MULT, $1, $3, &@2);
+ }
+ | expr_mul '/' expr_unary
+ {
+ $$ = ir_alloc_binop(IR_DIV, $1, $3, &@2);
+ }
+ | expr_mul '%' expr_unary
+ {
+ $$ = ir_alloc_binop(IR_MOD, $1, $3, &@2);
+ }
+ ;
+
+expr_unary:
+ expr_postfix
+ | '-' expr_unary
+ {
+ $$ = ir_alloc_unop(IR_UMINUS, $2, &@1);
+ }
+ | '~' expr_unary
+ {
+ $$ = ir_alloc_unop(IR_BIT_COMPL, $2, &@1);
+ }
+ | '!' expr_unary
+ {
+ $$ = ir_alloc_unop(IR_NOT, $2, &@1);
+ }
+ ;
+
+expr_postfix:
+ expr_primary
+ | expr_postfix '(' ')'
+ {
+ $$ = ir_alloc_binop(IR_FUNC_CALL, $1, NULL, &@2);
+ }
+ | expr_postfix '(' param_list ')'
+ {
+ $$ = ir_alloc_binop(IR_FUNC_CALL, $1, $3, &@2);
+ }
+ ;
+
+param_list:
+ expr
+ {
+ $$ = ir_list_append(NULL, $1);
+ }
+ | param_list ',' expr
+ {
+ $$ = ir_list_append($1, $3);
+ }
+ ;
+
+
+
+expr_primary:
+ literal
+ | string
+ | propnodename
+ | identifier
+ | '(' expr ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+addr:
+ expr_primary
+ ;
+
+
+bytestring:
/* empty */
{
$$ = NULL;
}
- | subnode subnodes
+ | bytestring byte
{
- $$ = chain_node($1, $2);
+ $$ = ir_list_append($1, $2);
}
- | subnode propdef
+ | bytestring label
{
- yyerror("syntax error: properties must precede subnodes");
- YYERROR;
+ $$ = ir_list_append($1, $2);
}
;
-subnode:
- label DT_PROPNODENAME nodedef
+propnodename:
+ DT_PROPNODENAME
{
- $$ = name_node($3, $2, $1);
+ $$ = ir_alloc(IR_PROPNODENAME, &@1);
+ $$->ir_lit_str = $1;
}
;
-label:
+identifier:
+ DT_ID
+ {
+ $$ = ir_alloc(IR_ID, &@1);
+ $$->ir_lit_str = $1;
+ }
+ ;
+
+literal:
+ DT_LITERAL
+ {
+ $$ = ir_alloc(IR_LITERAL, &@1);
+ $$->ir_lit_str = $1;
+ }
+ ;
+
+byte:
+ DT_BYTE
+ {
+ $$ = ir_alloc(IR_LIT_BYTE, &@1);
+ $$->ir_literal = $1;
+ }
+ ;
+
+string:
+ DT_STRING
+ {
+ $$ = ir_alloc(IR_LIT_STR, &@1);
+ $$->ir_lit_str = $1;
+ }
+ ;
+
+opt_label:
/* empty */
{
$$ = NULL;
}
- | DT_LABEL
+ | label
{
$$ = $1;
}
;
-%%
-
-void yyerrorf(char const *s, ...)
-{
- const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
- va_list va;
- va_start(va, s);
+label:
+ DT_LABEL
+ {
+ $$ = ir_alloc(IR_LABEL, &@1);
+ $$->ir_label_name = $1;
+ }
+ ;
- if (strcmp(fname, "-") == 0)
- fname = "stdin";
+node_label:
+ expr ':'
+ ;
- fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
- vfprintf(stderr, s, va);
- fprintf(stderr, "\n");
- treesource_error = 1;
- va_end(va);
-}
-
-void yyerror (char const *s)
-{
- yyerrorf("%s", s);
-}
+%%
-static unsigned long long eval_literal(const char *s, int base, int bits)
+void yyerror(char const *s)
{
- unsigned long long val;
- char *e;
-
- errno = 0;
- val = strtoull(s, &e, base);
- if (*e)
- yyerror("bad characters in literal");
- else if ((errno == ERANGE)
- || ((bits < 64) && (val >= (1ULL << bits))))
- yyerror("literal out of range");
- else if (errno != 0)
- yyerror("bad literal");
- return val;
+ srcpos_error(&yylloc, "%s", s);
+ treesource_error = 1;
}
diff --git a/dtc.c b/dtc.c
index 84bee2d..ccaf89c 100644
--- a/dtc.c
+++ b/dtc.c
@@ -20,6 +20,7 @@
#include "dtc.h"
#include "srcpos.h"
+#include "nv.h"
#include "version_gen.h"
@@ -127,7 +128,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
+ while ((opt = getopt(argc, argv, "hD:I:O:o:V:R:S:p:fcqb:v")) != EOF) {
switch (opt) {
case 'I':
inform = optarg;
@@ -162,6 +163,9 @@ int main(int argc, char *argv[])
case 'b':
cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break;
+ case 'D':
+ nv_note_define(optarg);
+ break;
case 'v':
printf("Version: %s\n", DTC_VERSION);
exit(0);
@@ -203,7 +207,6 @@ int main(int argc, char *argv[])
fill_fullpaths(bi->dt, "");
process_checks(force, bi);
-
if (streq(outname, "-")) {
outf = stdout;
} else {
diff --git a/dtc.h b/dtc.h
index ec636f8..327fc15 100644
--- a/dtc.h
+++ b/dtc.h
@@ -187,6 +187,7 @@ struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children);
struct node *name_node(struct node *node, char *name, char *label);
struct node *chain_node(struct node *first, struct node *list);
+struct node *reverse_nodes(struct node *first);
void add_property(struct node *node, struct property *prop);
void add_child(struct node *parent, struct node *child);
diff --git a/livetree.c b/livetree.c
index 0ca3de5..fec33b4 100644
--- a/livetree.c
+++ b/livetree.c
@@ -97,6 +97,22 @@ struct node *chain_node(struct node *first, struct node *list)
return first;
}
+struct node *reverse_nodes(struct node *first)
+{
+ struct node *p = first;
+ struct node *head = NULL;
+ struct node *next;
+
+ while (p) {
+ next = p->next_sibling;
+ p->next_sibling = head;
+ head = p;
+ p = next;
+ }
+ return head;
+}
+
+
void add_property(struct node *node, struct property *prop)
{
struct property **p;
diff --git a/nv.c b/nv.c
new file mode 100644
index 0000000..f02b8bc
--- /dev/null
+++ b/nv.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "dtc.h"
+#include "nv.h"
+
+struct nv_pair *nv_list;
+
+
+struct nv_pair *
+nv_alloc(void)
+{
+ struct nv_pair *nv;
+
+ nv = xmalloc(sizeof(struct nv_pair));
+ memset(nv, 0, sizeof(struct nv_pair));
+
+ return nv;
+}
+
+
+int
+nv_is_present(char *name)
+{
+ struct nv_pair *nv;
+
+ for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+ if (strcmp(nv->nv_name, name) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+void
+nv_dump(void)
+{
+ struct nv_pair *nv;
+
+ for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+ printf("NV: %s = \"%s\"\n", nv->nv_name, nv->nv_value);
+ }
+}
+
+
+/*
+ * Accept a string like "foo=123", or "cpu=mpc8548".
+ * Split it on the = for name and value parts.
+ * Record it in a name-value pairing list for later
+ * use when setting up the IR evaluation environment.
+ */
+
+void
+nv_note_define(char *defstr)
+{
+ struct nv_pair *nv;
+ char *name;
+ char *value;
+
+ if (!defstr || ! *defstr)
+ return;
+
+ name = strdup(defstr);
+
+ /*
+ * Separate name and value at equal sign.
+ */
+ value = strchr(name, '=');
+ if (value) {
+ *value = 0;
+ value++;
+ if (! *value) {
+ value = NULL;
+ }
+ }
+
+ if (nv_is_present(name)) {
+ printf("Warning: Ignored duplicate value %s for %s\n",
+ value, name);
+ return;
+ }
+
+ debug("nv_note_define(): %s = \"%s\"\n", name, value);
+
+ nv = nv_alloc();
+ nv->nv_name = name;
+ nv->nv_value = value;
+
+ nv->nv_next = nv_list;
+ nv_list = nv;
+}
diff --git a/nv.h b/nv.h
new file mode 100644
index 0000000..70ed718
--- /dev/null
+++ b/nv.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _NV_H_
+#define _NV_H_
+
+
+struct nv_pair {
+ char *nv_name;
+ char *nv_value;
+ struct nv_pair *nv_next;
+};
+
+extern struct nv_pair *nv_list;
+
+extern void nv_note_define(char *defstr);
+
+#endif /* _NV_H_ */
diff --git a/srcpos.c b/srcpos.c
index 59d1835..c69487e 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -20,6 +20,7 @@
#include "dtc.h"
#include "srcpos.h"
+
/*
* Like yylineno, this is the current open file pos.
*/
@@ -129,9 +130,6 @@ dtc_close_file(struct dtc_file *file)
{
if (fclose(file->file))
die("Error closing \"%s\": %s\n", file->name, strerror(errno));
-
- free(file->dir);
- free(file);
}
@@ -169,10 +167,15 @@ srcpos_string(srcpos *pos)
const char *fname;
char buf[POS_BUF_SIZE];
- if (pos->file && pos->file->name)
+ if (!pos) {
+ fname = "<no-file>";
+ } else if (pos->file->name) {
fname = pos->file->name;
- else
+ if (strcmp(fname, "-") == 0)
+ fname = "stdin";
+ } else {
fname = "<no-file>";
+ }
if (pos->first_line == pos->last_line) {
if (pos->first_column == pos->last_column) {
@@ -195,3 +198,37 @@ srcpos_string(srcpos *pos)
# undef POS_BUF_SIZE
}
+
+
+void
+srcpos_error(srcpos *pos, char const *fmt, ...)
+{
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Error: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ va_end(va);
+}
+
+
+void
+srcpos_warn(srcpos *pos, char const *fmt, ...)
+{
+ const char *srcstr;
+ va_list va;
+ va_start(va, fmt);
+
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "Warning: %s ", srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ va_end(va);
+}
diff --git a/srcpos.h b/srcpos.h
index de55b18..5f9961b 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -81,11 +81,6 @@ typedef YYLTYPE srcpos;
*/
extern srcpos srcpos_empty;
-
-
-extern void yyerror(char const *);
-extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
-
extern struct dtc_file *srcpos_file;
struct search_path {
@@ -101,4 +96,9 @@ extern srcpos *srcpos_copy(srcpos *pos);
extern char *srcpos_string(srcpos *pos);
extern void srcpos_dump(srcpos *pos);
+extern void srcpos_error(srcpos *pos, char const *, ...)
+ __attribute__((format(printf, 2, 3)));
+extern void srcpos_warn(srcpos *pos, char const *, ...)
+ __attribute__((format(printf, 2, 3)));
+
#endif /* _SRCPOS_H_ */
diff --git a/treesource.c b/treesource.c
index 1521ff1..5d69878 100644
--- a/treesource.c
+++ b/treesource.c
@@ -20,6 +20,7 @@
#include "dtc.h"
#include "srcpos.h"
+#include "ir.h"
extern FILE *yyin;
extern int yyparse(void);
@@ -41,6 +42,8 @@ struct boot_info *dt_from_source(const char *fname)
if (treesource_error)
die("Syntax error parsing input tree\n");
+ ir_process();
+
return the_boot_info;
}
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 8/8] Add documentation for the new DTS language.
[not found] ` <1222196652-13811-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-23 19:04 ` Jon Loeliger
[not found] ` <1222196652-13811-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
0 siblings, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-23 19:04 UTC (permalink / raw)
To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 463 insertions(+), 37 deletions(-)
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index b957662..ac56309 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -105,13 +105,21 @@ Options:
-q
Quiet: -q suppress warnings, -qq errors, -qqq all
+ -D <id>
+ -D <id>=<value>
+ Introduce a constant definition for symbol <id> with
+ possible initial value given by <value>. The RHS
+ should be a literal number or string value.
+
+ -p <padsize>
+ Add at least <padsize> additional space to the DTB image.
+
-R <number>
Make space for <number> reserve map entries
Relevant for dtb and asm output only.
-S <bytes>
- Ensure the blob at least <bytes> long, adding additional
- space if needed.
+ Deprecated option.
-v
Print DTC version and exit.
@@ -131,47 +139,338 @@ Additionally, dtc performs various sanity checks on the tree.
4) Device Tree Source file
-4.1) Overview
-Here is a very rough overview of the layout of a DTS source file:
+4.1) DTS Lexical Components
+
+Property and node names [a-zA-Z0-9,._+*#?@-]+
+Identifiers \\[a-zA-Z_][a-zA-Z0-9_]*
+Labels [a-zA-Z_][a-zA-Z0-9_]*
+Strings <C-style-double-quoted-strings>
+Comments Both /* ... */ and // style are supported
+Numeric literals <C-style-integer-numbers>
+Bytes [0-9a-fA-F][0-9a-fA-F]
+
+Keywords:
+ else
+ for
+ if
+ in
+ return
+ void
+ /const/
+ /define/
+ /incbin/
+
+C-style expression operators:
+ <<
+ >>
+ <=
+ >=
+ ==
+ !=
+ &&
+ ||
+ +
+ -
+ *
+ /
+ %
+
+Additional tokens:
+ ..
+ :=
+ {
+ }
+ ,
+ &
+
+
+These constructs are handled and eliminated purely at the
+lexical level and do not appear in the grammar proper:
+
+ - Source files included using the syntax:
+
+ /include/ "filename"
+
+ - Both classic C style and C++ style comments are supported.
+ Comments don't nest.
+ For example, given:
+
+ 1 /*
+ 2 * asdasdasd // asdasdad
+ 3 // */
+ 4 asasd
+ 5 */
+ The // comment on line 3 is not effective and is ignored.
+ The original /* comment ends on line 3. Line 5 is in error.
+
+ And given:
+
+ 1 // /*
+ 2 * asdasdasd // asdasdad
+ 3 */
+
+ The // comment on line 1 hides the opening /*.
+ Line 2 is in error.
+
+
+4.2) DTS Grammar
+
+Here is a very rough overview of the grammar of a DTS source file:
+
+
+ sourcefile:
+ '/dts-v1/' ';' possibly_empty_list_of_declarations devicetree
+
+ declaration:
+ memreserve
+ | constdef
+ | funcdef
+
+ memreserve: label '/memreserve/' addr addr ';'
+
+ constdef: '/const/' identifier '=' expr ';'
+
+ funcdef: '/define/' propnodename paramdecls statement_block
+
+ paramdecls: '(' possibly_empty_paramdecl_list ')'
+
+ paramdecl: identifier
+
+ devicetree: '/' statement_block
+
+ statement_block: '{' possibly_empty_list_of_statements '}'
+
+ statement:
+ subnode
+ | for_statement
+ | if_statement
+ | return_statement
+ | assign_statement
+ | property_definition
+ | statement_block
+ | ';'
+
+ subnode:
+ node_label expr statement_block ';'
+ | label expr statement_block ';'
+ | expr statement_block ';'
+
+ for_statement:
+ 'for' identifier 'in' expr '..' expr statement_block
+
+ if_statement:
+ 'if' '(' expr ')' statement_block
+ | 'if' '(' expr ')' statement_block 'else' statement_block
+
+ return_statement: 'return' expr ';'
+
+ assign_statement: identifier ':=' expr ';'
+
+ property_definition:
+ optional_label expr ';'
+ | optional_label expr '=' list_of_property_data_and_labels ';'
+ list_of_property_data_and_labels:
+ STRING
+ | '<' possibly_empty_list_of_cell_values_and_labels '>'
+ | '[' possibly_empty_list_of_byte_values_and_labels ']'
+ | label
+ | '/incbin/' '(' expr ')'
+ | '/incbin/' '(' expr ',' expr ',' expr ')'
- sourcefile: list_of_memreserve devicetree
+ cell_value:
+ expr_primary
+ | '&' '(' expr ')'
+ | '&' phandle_reference
+ | label
- memreserve: label 'memreserve' ADDR ADDR ';'
- | label 'memreserve' ADDR '-' ADDR ';'
- devicetree: '/' nodedef
+ expr:
+ expr_primary
+ | expr '?' expr ':' expr
+ | expr expr_oper expr
- nodedef: '{' list_of_property list_of_subnode '}' ';'
+ expr_oper:
+ ||
+ &&
+ |
+ ^
+ &
+ ==
+ < | > | <= | >=
+ << | >>
+ + | -
+ * | / | %
+ - | ~ | !
+ '(' ')' | '(' non_empty_list_of_param_exprs ')'
- property: label PROPNAME '=' propdata ';'
+ expr_primary:
+ literal
+ | string
+ | propnodename
+ | identifier
+ | '(' expr ')'
- propdata: STRING
- | '<' list_of_cells '>'
- | '[' list_of_bytes ']'
+ addr: expr
- subnode: label nodename nodedef
+ node_label: expr ':'
-That structure forms a hierarchical layout of nodes and properties
-rooted at an initial node as:
+ propnodename: <1275-property-name>
+
+ identifier: '\'-<C style name>
+
+ literal: <C style number>
+ byte: <exactly two hex digits>
+ string: <C style string>
+ label: '&'-<label name>-':'
+
+
+4.2) Overview
+
+The DTS source file begins with the '/dts-v1/' token to state
+that it is using "Version 1" style source files.
+
+Any declarations are executed in order, and can use the
+effects of earlier declarations.
+
+All declarations must precede the required root node definition,
+which is introduced with the '/'-named node:
/ {
+ ...
}
-Both classic C style and C++ style comments are supported.
+The statement-block structure forms a hierarchical layout of nodes
+and properties along with some control-statements that allow for
+repeated and alternate statement blocks.
+
+
+4.3) Declarations
+
+An arbitrary list of declarations can be made between '/dts-v1/'
+and the beginning of the root node. These declarations are
+introduced in order.
+
+
+4.3.1) Memory Reservations
+
+A memory reservation is a declaration that a block of memory
+from the first address expression, with a size given by the
+second address expression, is to be "reserved" and not used
+by the kernel. These address ranges are passed through to
+the DTB to the kernel.
+
+
+4.3.2) Function Definitions
+
+A function definition can be introduced using /define/.
+These definitions are just "stored" and then later invoked as
+either a subroutine in a statement context, or as a function
+with a return value in an expression context.
-Source files may be directly included using the syntax:
+Functions declare the number of formal parameters which will
+be passed in at the call site, and must match one-to-one.
- /include/ "filename"
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the call.
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the call.
-4.2) Properties
-Properties are named, possibly labeled, values. Each value
-is one of:
+4.3.3) Constant Definitions
- - A null-teminated C-like string,
+Constant definitions introduce a named identifier into the outer-most
+symbol scope. The constants can not be changed by later assignment
+statements, though they can be hidden. (Be careful.)
+
+Constants may be expressions yielding constant numeric or strings
+values. It is an error for them not to be evaluatable at their
+point of definition.
+
+Constant definitions may also be introduced from the command line
+using the '-D var=value" options. They will be placed into the
+same outer-most scope. Constant definitions from the command line
+override the definitions within the source file, but with a warning.
+
+
+4.4) Statements
+
+A statement block is simply a list of sequentially executed
+statements introduced with a required opening brace and terminated
+with a required closing brace.
+
+4.4.1) Subnodes
+
+Node may contain sub-nodes to obtain a hierarchical structure.
+
+For example:
+
+ - A child node named "childnode" whose unit name is
+ "childnode at address". It it turn has a string property
+ called "childprop".
+
+ childnode@address {
+ childprop = "hello\n";
+ };
+
+
+4.4.2) 'for' Statement
+
+The 'for' statement provides iterative execution of a
+block of statements.
+
+The lower bound of the range is evaluated once, and the
+upper bound is evaluated once.
+
+A new scope that contains the loop variable is created
+and pushed onto the symbol table scope stack. The loop
+variable is initialized with the lower bound value.
+
+The statement block is executed once for each inclusive value
+in the given range in increasing order.
+
+After the loop terminates, the loop variable scope is popped.
+
+
+4.4.3) 'if' Statement
+
+The 'if' statement provides alternate execution flow paths.
+The expression is evaluated once, and if non-zero, the fist
+statement block is executed, otherwise the 'else' block of
+statements is executed if present.
+
+
+4.4.4) 'return' Statement
+
+Inside a function definition, the 'return' statement allows
+a value to be passed back to the caller. The return expression
+is evaluated once, in the context of the function's scope,
+and its resultant value is made available as the function's
+return result.
+
+
+4.4.5) Assign Statement
+
+The ':=' operator allows assignment to non-constant identifiers.
+
+The identifiers can be either formal parameters or variable as
+found by the searching using the dynamic symbol table scoping rules.
+
+An assignment to an otherwise unknown identifier causes that
+identifier to be introduced into the current scope.
+
+You can't assign to /constant/ identifiers (except in the initial
+definition of them).
+
+
+4.4.6) Property Definition
+
+Properties are named, possibly labeled, values.
+Each value within a property is one of:
+
+ - A null-terminated C-like string,
- A numeric value fitting in 32 bits,
- A list of 32-bit values
- A byte sequence
@@ -195,27 +494,126 @@ Here are some example property definitions:
property4 = [0a 0b 0c 0d de ea ad be ef];
-Node may contain sub-nodes to obtain a hierarchical structure.
-For example:
+4.4.7) Subroutine calls
- - A child node named "childnode" whose unit name is
- "childnode at address". It it turn has a string property
- called "childprop".
+An expression at the statement level should be a function call,
+though it might be considered as just a "subroutine call" as
+any return value is thrown away.
- childnode@addresss {
- childprop = "hello\n";
- };
+Invocation of the function introduces a symbol table scope
+in which the formal paramters are introduced and bound.
+Initial values for the formals are obtained by evaluating
+the actual parameters, in order, and using a copy-in binding.
+
+Any incidental (dynamically occurring) assignment to an
+otherwise unknown identifier will cause the introduction of
+a new variable in the function's execution scope.
+
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any return value from a return statement is thrown away.
+Execution control is returned to the point of the call.
-By default, all numeric values are hexadecimal. Alternate bases
-may be specified using a prefix "d#" for decimal, "b#" for binary,
-and "o#" for octal.
-Strings support common escape sequences from C: "\n", "\t", "\r",
-"\(octal value)", "\x(hex value)".
+4.5) Expressions
+Basically, expressions follow C conventions. However, there
+are no assignment operations such as +=, or pre-/post-
+increment/decrement.
-4.3) Labels and References
+The '%' operation is a modulus operation for integers, and
+a string concatenation operation if at least one of the operands
+is determined to be a string value.
+
+
+4.5.1) Expressions
+
+Pretend it is C and see how close we get.
+
+
+4.5.2) Function Invocations
+
+A previously defined function may be invoked from within an
+expression. A "return" statement should be used to return
+a resulting expression value to the caller's context.
+
+Invocation of the function introduces a symbol table scope
+in which the formal parameters are introduced and bound.
+Initial values for the formals are obtained by evaluating
+the actual parameters, in order, and using a copy-in binding.
+
+Any incidental (dynamically occurring) assignment to an
+otherwise unknown identifier will cause the introduciton of
+a new variable in the function's execution scope.
+
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any return value from a return statement is used as the result
+of the function call within the context of the original expression.
+
+Execution control is returned to the point of the call.
+
+
+4.5.3) Builtin Functions
+
+There are a few builtin function names;
+
+ join() Concatenate and return a list of expression
+ as a string. Non-string arguments are coerced
+ into being a string.
+
+ hexstr() Format and return a hex string representation
+ of the one parameter without a leading '0x'.
+
+While not here yet, /incbin/ should be converted into a builtin.
+
+
+4.5.4) Literal Numbers
+
+Literal numbers follow C conventions. Specifically, they are
+base-ten by default, but can be hexadecimal, binary or octal
+with a leading 0x or 0X, 0b or OB, or a simple leading zero,
+respectively.
+
+There is no support for floating point representations at all.
+
+Most math and expression handling is assumed to be 64-bit, but
+a cell-context may force a 32-bit container instead.
+
+
+4.5.5) Literal Strings
+
+Strings support common escape sequences from C:
+ "\n", "\t", "\r"
+ "\(octal value)"
+ "\x(hex value)"
+
+
+4.5.6) Identifiers
+
+Identifiers references are resolved using dynamic symbol table
+scoping rules. An identifier referenced on the right-hand-side
+of an expression must be resolvable or else it is an error.
+
+An identifier occurring on the left-hand-side of a ':=' assignment
+is first sought and used if found. If it is not found, it is
+introduced dynamically in the innermost, current scope.
+
+Sometimes identifiers can be used without the leading slash,
+other times they are required, especially if to disambiguate
+from property names. It's not ideal yet at all.
+
+
+4.6) Labels and References
Labels may be applied to nodes or properties. Labels appear
before a node name, and are referenced using an ampersand: &label.
@@ -239,6 +637,34 @@ And used in properties, lables may appear before or after any value:
...
};
+The names of some labels can be constructed in an expression
+context using the representation "&( <string_expr> )".
+
+
+4.7) Symbol Table
+
+During the execution of the program, the evaluation context for
+both statements and expressions is performed in the context of
+a dynamic scoping environment. That is, as each function,
+subroutine or for-loop is encountered, a new symbol table scope
+is pushed onto a dynamic run-time stack. When an identifier's
+name needs to be resolved and a value for it determined, a
+search is performed from the inner-most, current top of the
+scope-stack back through the dynamic scope stack towards the
+outer-most and earliest scope.
+
+At each scope, an attempt is made to locate the symbol. If it
+is found, that is the symbol that is used. If the symbol can not
+be found at any level, it may be an error, or it may be cause to
+introduce the symbol, as determined by the context in which the
+identifier occurs.
+
+Constants from the command line using the "-D id=value" construct
+are introduced into the outermost scope prior to beginning to
+execute the source file proper. This is the same outer-most scope
+into which the /const/ and /define/ function symbols are also
+introduced.
+
II - The DT block format
--
1.6.0.90.g436ed
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
[not found] ` <1222196652-13811-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 1/8] Remove support for the legacy DTS source file format Jon Loeliger
@ 2008-09-24 2:34 ` Kumar Gala
[not found] ` <097BFF8D-317F-4E85-AC2A-4C0A8D6C608B-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
1 sibling, 1 reply; 25+ messages in thread
From: Kumar Gala @ 2008-09-24 2:34 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
On Sep 23, 2008, at 2:04 PM, Jon Loeliger wrote:
> This series of patches enhances the DTS source language to
> support a fullly interpreted language for generating nodes
> and properties. It is backward compatible with V1 sources.
>
> The main features implemented by this patch set support
> function definitions, 'if', 'for', 'return' and assignment
> statements. Local variables, global constants and
> almost complete C-like expressions are also supported.
>
> Enhancements to the source position and error/warning
> reporting now support source column positions too.
>
> Jon Loeliger (8):
> Remove support for the legacy DTS source file format.
> Add conditionalized debug() print macro.
> Enhance source position implementation.
> Add header files for new Internal Representation form.
> Add most of the new IR implementation files.
> Add the main IR evaluation implementation
> Introduce new DTS language.
> Add documentation for the new DTS language.
Any examples/tests of all the cool new features?
- k
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
[not found] ` <097BFF8D-317F-4E85-AC2A-4C0A8D6C608B-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
@ 2008-09-24 16:51 ` Jon Loeliger
2008-09-24 18:48 ` Jon Loeliger
2008-09-25 4:26 ` David Gibson
2008-09-25 3:50 ` David Gibson
1 sibling, 2 replies; 25+ messages in thread
From: Jon Loeliger @ 2008-09-24 16:51 UTC (permalink / raw)
To: Kumar Gala; +Cc: devicetree-discuss
On Tue, 2008-09-23 at 21:34 -0500, Kumar Gala wrote:
> Any examples/tests of all the cool new features?
>
> - k
Here is a QAD example based on the MPC8641 DTS file
as found in the arch/powerpc/boot/dts directory today.
It is maybe not the best example, but it shows the
flavor of what can be done.
Enjoy,
jdl
/*
* MPC8641 HPCN Device Tree Source
*
* Copyright 2006 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/dts-v1/;
/define/ make_cpu(\cpu)
{
"PowerPC,8641@" % \cpu {
device_type = "cpu";
reg = < (\cpu) >;
d-cache-line-size = <32>;
i-cache-line-size = <32>;
d-cache-size = <32768>; // L1
i-cache-size = <32768>; // L1
timebase-frequency = <0>; // From uboot
bus-frequency = <0>; // From uboot
clock-frequency = <0>; // From uboot
};
}
/define/ make_i2c(\id, \addr)
{
"i2c@" % \hexstr(\addr) {
#address-cells = <1>;
#size-cells = <0>;
cell-index = <\id>;
compatible = "fsl-i2c";
reg = < (\addr) 0x100>;
interrupts = <43 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
}
/define/ make_ethernet(\id, \addr)
{
"enet" % \id : "ethernet@" % \hexstr(\addr) {
cell-index = <\id>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = < (\addr) 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
if (\id == 0) {
interrupts = <29 2 30 2 34 2>;
}
if (\id == 1) {
interrupts = <35 2 36 2 40 2>;
}
if (\id == 2) {
interrupts = <31 2 32 2 33 2>;
}
if (\id == 3) {
interrupts = <37 2 38 2 39 2>;
}
interrupt-parent = <&mpic>;
phy-handle = <&("phy" % \id)>;
phy-connection-type = "rgmii-id";
};
}
/define/ make_ethernet_phy(\id)
{
"phy" % \id : "ethernet-phy@" % \id {
interrupt-parent = <&mpic>;
interrupts = <10 1>;
reg = < (\id) >;
device_type = "ethernet-phy";
};
}
/define/ make_dma_channel(\id)
{
"dma-channel@" % hexstr(\id * 0x80) {
compatible = "fsl,mpc8641-dma-channel",
"fsl,eloplus-dma-channel";
reg = < (0x80 * \id) 0x80>;
cell-index = < (\id) >;
interrupt-parent = <&mpic>;
interrupts = < (20 + \id) 2>;
};
}
/define/ make_serial(\id, \addr)
{
"serial" % \id : "serial@" % hexstr(\addr) {
cell-index = < (\id) >;
device_type = "serial";
compatible = "ns16550";
reg = < (\addr) 0x100>;
clock-frequency = <0>;
if (\id == 0) {
interrupts = <42 2>;
} else {
interrupts = <28 2>;
}
interrupt-parent = <&mpic>;
};
}
/ {
model = "MPC8641HPCN";
compatible = "fsl,mpc8641hpcn";
#address-cells = <1>;
#size-cells = <1>;
aliases {
ethernet0 = &enet0;
ethernet1 = &enet1;
ethernet2 = &enet2;
ethernet3 = &enet3;
serial0 = &serial0;
serial1 = &serial1;
pci0 = &pci0;
pci1 = &pci1;
rapidio0 = &rapidio0;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
make_cpu(0);
make_cpu(1);
};
memory {
device_type = "memory";
reg = <0x00000000 0x40000000>; // 1G at 0x0
};
localbus@f8005000 {
#address-cells = <2>;
#size-cells = <1>;
compatible = "fsl,mpc8641-localbus", "simple-bus";
reg = <0xf8005000 0x1000>;
interrupts = <19 2>;
interrupt-parent = <&mpic>;
ranges = <0 0 0xff800000 0x00800000
1 0 0xfe000000 0x01000000
2 0 0xf8200000 0x00100000
3 0 0xf8100000 0x00100000>;
flash@0,0 {
compatible = "cfi-flash";
reg = <0 0 0x00800000>;
bank-width = <2>;
device-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel";
reg = <0x00000000 0x00300000>;
};
partition@300000 {
label = "firmware b";
reg = <0x00300000 0x00100000>;
read-only;
};
partition@400000 {
label = "fs";
reg = <0x00400000 0x00300000>;
};
partition@700000 {
label = "firmware a";
reg = <0x00700000 0x00100000>;
read-only;
};
};
};
soc8641@f8000000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "simple-bus";
ranges = <0x00000000 0xf8000000 0x00100000>;
reg = <0xf8000000 0x00001000>; // CCSRBAR
bus-frequency = <0>;
make_i2c(0, 0x3000);
make_i2c(1, 0x3100);
dma@21300 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
reg = <0x21300 0x4>;
ranges = <0x0 0x21100 0x200>;
cell-index = <0>;
for \i in 0 .. 3 {
make_dma_channel(\i);
}
};
mdio@24520 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,gianfar-mdio";
reg = <0x24520 0x20>;
for \i in 0 .. 3 {
make_ethernet_phy(\i);
}
};
for \i in 0 .. 3 {
make_ethernet(\i, 0x24000 + \i * 0x1000);
}
make_serial(0, 0x4500);
make_serial(1, 0x4600);
mpic: pic@40000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <0x40000 0x40000>;
compatible = "chrp,open-pic";
device_type = "open-pic";
};
global-utilities@e0000 {
compatible = "fsl,mpc8641-guts";
reg = <0xe0000 0x1000>;
fsl,has-rstcr;
};
};
pci0: pcie@f8008000 {
cell-index = <0>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0xf8008000 0x1000>;
bus-range = <0x0 0xff>;
ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <24 2>;
interrupt-map-mask = <0xff00 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 func 0 - PCI slot 1 */
0x8800 0 0 1 &mpic 2 1
0x8800 0 0 2 &mpic 3 1
0x8800 0 0 3 &mpic 4 1
0x8800 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 1 - PCI slot 1 */
0x8900 0 0 1 &mpic 2 1
0x8900 0 0 2 &mpic 3 1
0x8900 0 0 3 &mpic 4 1
0x8900 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 2 - PCI slot 1 */
0x8a00 0 0 1 &mpic 2 1
0x8a00 0 0 2 &mpic 3 1
0x8a00 0 0 3 &mpic 4 1
0x8a00 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 3 - PCI slot 1 */
0x8b00 0 0 1 &mpic 2 1
0x8b00 0 0 2 &mpic 3 1
0x8b00 0 0 3 &mpic 4 1
0x8b00 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 4 - PCI slot 1 */
0x8c00 0 0 1 &mpic 2 1
0x8c00 0 0 2 &mpic 3 1
0x8c00 0 0 3 &mpic 4 1
0x8c00 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 5 - PCI slot 1 */
0x8d00 0 0 1 &mpic 2 1
0x8d00 0 0 2 &mpic 3 1
0x8d00 0 0 3 &mpic 4 1
0x8d00 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 6 - PCI slot 1 */
0x8e00 0 0 1 &mpic 2 1
0x8e00 0 0 2 &mpic 3 1
0x8e00 0 0 3 &mpic 4 1
0x8e00 0 0 4 &mpic 1 1
/* IDSEL 0x11 func 7 - PCI slot 1 */
0x8f00 0 0 1 &mpic 2 1
0x8f00 0 0 2 &mpic 3 1
0x8f00 0 0 3 &mpic 4 1
0x8f00 0 0 4 &mpic 1 1
/* IDSEL 0x12 func 0 - PCI slot 2 */
0x9000 0 0 1 &mpic 3 1
0x9000 0 0 2 &mpic 4 1
0x9000 0 0 3 &mpic 1 1
0x9000 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 1 - PCI slot 2 */
0x9100 0 0 1 &mpic 3 1
0x9100 0 0 2 &mpic 4 1
0x9100 0 0 3 &mpic 1 1
0x9100 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 2 - PCI slot 2 */
0x9200 0 0 1 &mpic 3 1
0x9200 0 0 2 &mpic 4 1
0x9200 0 0 3 &mpic 1 1
0x9200 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 3 - PCI slot 2 */
0x9300 0 0 1 &mpic 3 1
0x9300 0 0 2 &mpic 4 1
0x9300 0 0 3 &mpic 1 1
0x9300 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 4 - PCI slot 2 */
0x9400 0 0 1 &mpic 3 1
0x9400 0 0 2 &mpic 4 1
0x9400 0 0 3 &mpic 1 1
0x9400 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 5 - PCI slot 2 */
0x9500 0 0 1 &mpic 3 1
0x9500 0 0 2 &mpic 4 1
0x9500 0 0 3 &mpic 1 1
0x9500 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 6 - PCI slot 2 */
0x9600 0 0 1 &mpic 3 1
0x9600 0 0 2 &mpic 4 1
0x9600 0 0 3 &mpic 1 1
0x9600 0 0 4 &mpic 2 1
/* IDSEL 0x12 func 7 - PCI slot 2 */
0x9700 0 0 1 &mpic 3 1
0x9700 0 0 2 &mpic 4 1
0x9700 0 0 3 &mpic 1 1
0x9700 0 0 4 &mpic 2 1
// IDSEL 0x1c USB
0xe000 0 0 1 &i8259 12 2
0xe100 0 0 2 &i8259 9 2
0xe200 0 0 3 &i8259 10 2
0xe300 0 0 4 &i8259 11 2
// IDSEL 0x1d Audio
0xe800 0 0 1 &i8259 6 2
// IDSEL 0x1e Legacy
0xf000 0 0 1 &i8259 7 2
0xf100 0 0 1 &i8259 7 2
// IDSEL 0x1f IDE/SATA
0xf800 0 0 1 &i8259 14 2
0xf900 0 0 1 &i8259 5 2
>;
pcie@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <0x02000000 0x0 0x80000000
0x02000000 0x0 0x80000000
0x0 0x20000000
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
0x0 0x00100000>;
uli1575@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
#address-cells = <3>;
ranges = <0x02000000 0x0 0x80000000
0x02000000 0x0 0x80000000
0x0 0x20000000
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
0x0 0x00100000>;
isa@1e {
device_type = "isa";
#interrupt-cells = <2>;
#size-cells = <1>;
#address-cells = <2>;
reg = <0xf000 0 0 0 0>;
ranges = <1 0 0x01000000 0 0
0x00001000>;
interrupt-parent = <&i8259>;
i8259: interrupt-controller@20 {
reg = <1 0x20 2
1 0xa0 2
1 0x4d0 2>;
interrupt-controller;
device_type = "interrupt-controller";
#address-cells = <0>;
#interrupt-cells = <2>;
compatible = "chrp,iic";
interrupts = <9 2>;
interrupt-parent = <&mpic>;
};
i8042@60 {
#size-cells = <0>;
#address-cells = <1>;
reg = <1 0x60 1 1 0x64 1>;
interrupts = <1 3 12 3>;
interrupt-parent =
<&i8259>;
keyboard@0 {
reg = <0>;
compatible = "pnpPNP,303";
};
mouse@1 {
reg = <1>;
compatible = "pnpPNP,f03";
};
};
rtc@70 {
compatible =
"pnpPNP,b00";
reg = <1 0x70 2>;
};
gpio@400 {
reg = <1 0x400 0x80>;
};
};
};
};
};
pci1: pcie@f8009000 {
cell-index = <1>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0xf8009000 0x1000>;
bus-range = <0 0xff>;
ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <25 2>;
interrupt-map-mask = <0xf800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0 */
0x0000 0 0 1 &mpic 4 1
0x0000 0 0 2 &mpic 5 1
0x0000 0 0 3 &mpic 6 1
0x0000 0 0 4 &mpic 7 1
>;
pcie@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <0x02000000 0x0 0xa0000000
0x02000000 0x0 0xa0000000
0x0 0x20000000
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
0x0 0x00100000>;
};
};
rapidio0: rapidio@f80c0000 {
#address-cells = <2>;
#size-cells = <2>;
compatible = "fsl,rapidio-delta";
reg = <0xf80c0000 0x20000>;
ranges = <0 0 0xc0000000 0 0x20000000>;
interrupt-parent = <&mpic>;
/* err_irq bell_outb_irq bell_inb_irq
msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>;
};
};
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/8] Enhance source position implementation.
[not found] ` <1222196652-13811-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 4/8] Add header files for new Internal Representation form Jon Loeliger
@ 2008-09-24 17:07 ` Scott Wood
[not found] ` <48DA73DA.5000603-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-09-24 17:23 ` Scott Wood
2 siblings, 1 reply; 25+ messages in thread
From: Scott Wood @ 2008-09-24 17:07 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Jon Loeliger wrote:
> @@ -106,7 +123,9 @@ fail:
> die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
> }
>
> -void dtc_close_file(struct dtc_file *file)
> +
> +void
> +dtc_close_file(struct dtc_file *file)
:-(
> +char *
> +srcpos_string(srcpos *pos)
> +{
> +# define POS_BUF_SIZE (100)
Local #defines make $YOUTHFUL_DEITY_OFFSPRING cry (and the whitespace
after the # doesn't help). Declare a "const int", or just use sizeof(buf).
> + const char *fname;
> + char buf[POS_BUF_SIZE];
> +
> + if (pos->file && pos->file->name)
> + fname = pos->file->name;
> + else
> + fname = "<no-file>";
> +
> + if (pos->first_line == pos->last_line) {
> + if (pos->first_column == pos->last_column) {
> + snprintf(buf, POS_BUF_SIZE, "%s %d:%d",
> + fname, pos->first_line, pos->first_column);
> + } else {
> + snprintf(buf, POS_BUF_SIZE, "%s %d:%d-%d",
> + fname, pos->first_line,
> + pos->first_column, pos->last_column);
> + }
> +
> + } else {
> + snprintf(buf, POS_BUF_SIZE, "%s %d:%d - %d:%d",
> + fname,
> + pos->first_line, pos->first_column,
> + pos->last_line, pos->last_column);
> + }
Seems a little elaborate; are there cases where reporting the
line/column of the first character of the token is not clear?
> + return strdup(buf);
Why not just dynamically allocate the buffer in the first place? Or if
you care about the memory wastage (which you probably don't, given that
you just leak the allocated string in the callers in later patches),
make this function take a FILE * to output to, rather than return an
allocated string.
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/8] Enhance source position implementation.
[not found] ` <48DA73DA.5000603-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2008-09-24 17:17 ` Jon Loeliger
2008-09-24 17:21 ` Scott Wood
2008-09-24 17:23 ` Warner Losh
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-24 17:17 UTC (permalink / raw)
To: Scott Wood; +Cc: devicetree-discuss
On Wed, 2008-09-24 at 12:07 -0500, Scott Wood wrote:
> > +char *
> > +srcpos_string(srcpos *pos)
> > +{
> > +# define POS_BUF_SIZE (100)
>
> Local #defines make $YOUTHFUL_DEITY_OFFSPRING cry (and the whitespace
> after the # doesn't help). Declare a "const int", or just use sizeof(buf).
Sigh.
>
> Seems a little elaborate;
...and yet clear.
> are there cases where reporting the
> line/column of the first character of the token is not clear?
Yes.
> > + return strdup(buf);
>
> Why not just dynamically allocate the buffer in the first place? Or if
> you care about the memory wastage (which you probably don't, given that
> you just leak the allocated string in the callers in later patches),
> make this function take a FILE * to output to, rather than return an
> allocated string.
Well, it was really a more general formatting routine.
It may not always directly be output directly to a FILE.
So, maybe there is some room for improvement or optimization
in the future...
jdl
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/8] Enhance source position implementation.
2008-09-24 17:17 ` Jon Loeliger
@ 2008-09-24 17:21 ` Scott Wood
0 siblings, 0 replies; 25+ messages in thread
From: Scott Wood @ 2008-09-24 17:21 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss
Jon Loeliger wrote:
> On Wed, 2008-09-24 at 12:07 -0500, Scott Wood wrote:
>> are there cases where reporting the
>> line/column of the first character of the token is not clear?
>
> Yes.
I was hoping for an example. :-)
> Well, it was really a more general formatting routine.
We already have *printf().
> It may not always directly be output directly to a FILE.
>
> So, maybe there is some room for improvement or optimization
> in the future...
There's also room for generalization in the future.
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/8] Enhance source position implementation.
[not found] ` <1222196652-13811-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 4/8] Add header files for new Internal Representation form Jon Loeliger
2008-09-24 17:07 ` [PATCH 3/8] Enhance source position implementation Scott Wood
@ 2008-09-24 17:23 ` Scott Wood
2 siblings, 0 replies; 25+ messages in thread
From: Scott Wood @ 2008-09-24 17:23 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Jon Loeliger wrote:
> +char *
> +srcpos_string(srcpos *pos)
> +{
> +# define POS_BUF_SIZE (100)
> +
> + const char *fname;
> + char buf[POS_BUF_SIZE];
> +
> + if (pos->file && pos->file->name)
> + fname = pos->file->name;
> + else
> + fname = "<no-file>";
> +
> + if (pos->first_line == pos->last_line) {
> + if (pos->first_column == pos->last_column) {
> + snprintf(buf, POS_BUF_SIZE, "%s %d:%d",
> + fname, pos->first_line, pos->first_column);
Oh, another thing -- if the filename is over 100 characters (due to
having directory components included, for example), this will cut off
the most useful information (the line/column info), and the second most
useful information (the end of the file name, rather than the leading
path components).
If we wrote directly to a FILE *, this would be a non-issue.
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 3/8] Enhance source position implementation.
[not found] ` <48DA73DA.5000603-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-09-24 17:17 ` Jon Loeliger
@ 2008-09-24 17:23 ` Warner Losh
1 sibling, 0 replies; 25+ messages in thread
From: Warner Losh @ 2008-09-24 17:23 UTC (permalink / raw)
To: scottwood-KZfg59tc24xl57MIdRCFDg
Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
From: Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Subject: Re: [PATCH 3/8] Enhance source position implementation.
Date: Wed, 24 Sep 2008 12:07:38 -0500
> Jon Loeliger wrote:
> > @@ -106,7 +123,9 @@ fail:
> > die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
> > }
> >
> > -void dtc_close_file(struct dtc_file *file)
> > +
> > +void
> > +dtc_close_file(struct dtc_file *file)
>
> :-(
>
> > +char *
> > +srcpos_string(srcpos *pos)
> > +{
> > +# define POS_BUF_SIZE (100)
>
> Local #defines make $YOUTHFUL_DEITY_OFFSPRING cry (and the whitespace
> after the # doesn't help). Declare a "const int", or just use sizeof(buf).
>
> > + const char *fname;
> > + char buf[POS_BUF_SIZE];
> > +
> > + if (pos->file && pos->file->name)
> > + fname = pos->file->name;
> > + else
> > + fname = "<no-file>";
> > +
> > + if (pos->first_line == pos->last_line) {
> > + if (pos->first_column == pos->last_column) {
> > + snprintf(buf, POS_BUF_SIZE, "%s %d:%d",
> > + fname, pos->first_line, pos->first_column);
> > + } else {
> > + snprintf(buf, POS_BUF_SIZE, "%s %d:%d-%d",
> > + fname, pos->first_line,
> > + pos->first_column, pos->last_column);
> > + }
> > +
> > + } else {
> > + snprintf(buf, POS_BUF_SIZE, "%s %d:%d - %d:%d",
> > + fname,
> > + pos->first_line, pos->first_column,
> > + pos->last_line, pos->last_column);
> > + }
>
> Seems a little elaborate; are there cases where reporting the
> line/column of the first character of the token is not clear?
>
> > + return strdup(buf);
>
> Why not just dynamically allocate the buffer in the first place? Or if
> you care about the memory wastage (which you probably don't, given that
> you just leak the allocated string in the callers in later patches),
> make this function take a FILE * to output to, rather than return an
> allocated string.
Wouldn't asprintf be more appropriate? That way you wouldn't have
trunctation issues either that you get with snprintf. While asprintf
is an extension, it is a common enough one...
Warner
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
2008-09-24 16:51 ` Jon Loeliger
@ 2008-09-24 18:48 ` Jon Loeliger
2008-09-25 4:31 ` David Gibson
2008-09-25 4:26 ` David Gibson
1 sibling, 1 reply; 25+ messages in thread
From: Jon Loeliger @ 2008-09-24 18:48 UTC (permalink / raw)
To: Kumar Gala; +Cc: devicetree-discuss
On Wed, 2008-09-24 at 11:51 -0500, Jon Loeliger wrote:
> On Tue, 2008-09-23 at 21:34 -0500, Kumar Gala wrote:
>
> > Any examples/tests of all the cool new features?
> >
> > - k
>
> Here is a QAD example based on the MPC8641 DTS file
> as found in the arch/powerpc/boot/dts directory today.
> It is maybe not the best example, but it shows the
> flavor of what can be done.
>
> Enjoy,
> jdl
Also, here is the same refactoring done on the
mpc8572ds.dts file too.
And, perhaps more important than doing this work
on this one file, it shows that the first section
of both this 8572 DTS file and the 8641 DTS file
are almost identical throughout the /define/ section.
Minor refactoring needed in the 8641 variant.
The only "real" difference is 8641 says "TSEC" and
the 8572 says "eTSEC", and one weird interrupt thing
in the serial node. Dunno.
Enjoy,
jdl
/*
* MPC8572 DS Device Tree Source
*
* Copyright 2007, 2008 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/dts-v1/;
/define/ make_cpu(\part, \cpu)
{
"PowerPC," % \part % "@" % \cpu {
device_type = "cpu";
reg = < (\cpu) >;
d-cache-line-size = <32>;
i-cache-line-size = <32>;
d-cache-size = <32768>; // L1
i-cache-size = <32768>; // L1
timebase-frequency = <0>; // From uboot
bus-frequency = <0>; // From uboot
clock-frequency = <0>; // From uboot
next-level-cache = <&L2>;
};
}
/define/ make_i2c(\id)
{
\addr := 0x3000 + \id * 0x100;
"i2c@" % \hexstr(\addr) {
#address-cells = <1>;
#size-cells = <0>;
cell-index = <\id>;
compatible = "fsl-i2c";
reg = < (\addr) 0x100>;
interrupts = <43 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
}
/define/ make_dma_channel(\part, \id, \intr_base)
{
"dma-channel@" % hexstr(\id * 0x80) {
compatible = < ("fsl,mpc" % \part % "-dma-channel")
("fsl,eloplus-dma-channel") >;
reg = < (0x80 * \id) 0x80>;
cell-index = < (\id) >;
interrupt-parent = <&mpic>;
interrupts = < (\intr_base + \id) 2>;
};
}
/define/ make_dma_controller(\part, \ctrl)
{
\addr := 0x21300 - \ctrl * 0x15000;
\intr_base := \ctrl * 56 + 20;
"dma@" % hexstr(\addr) {
#address-cells = <1>;
#size-cells = <1>;
compatible = < ("fsl,mpc" % \part % "-dma")
("fsl,eloplus-dma") >;
reg = < (\addr) 0x4>;
ranges = <0x0 (\addr - 0x200) 0x200>;
cell-index = < (\ctrl) >;
for \c in 0 .. 3 {
make_dma_channel(\part, \c, \intr_base);
}
};
}
/define/ make_ethernet_phy(\id)
{
"phy" % \id : "ethernet-phy@" % \id {
interrupt-parent = <&mpic>;
interrupts = <10 1>;
reg = < (\id) >;
};
}
/define/ make_ethernet(\id)
{
\addr := 0x24000 + \id * 0x1000;
"enet" % \id : "ethernet@" % \hexstr(\addr) {
cell-index = <\id>;
device_type = "network";
model = "eTSEC";
compatible = "gianfar";
reg = < (\addr) 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
if (\id == 0) {
interrupts = <29 2 30 2 34 2>;
}
if (\id == 1) {
interrupts = <35 2 36 2 40 2>;
}
if (\id == 2) {
interrupts = <31 2 32 2 33 2>;
}
if (\id == 3) {
interrupts = <37 2 38 2 39 2>;
}
interrupt-parent = <&mpic>;
phy-handle = <&("phy" % \id)>;
phy-connection-type = "rgmii-id";
};
}
/define/ make_serial(\id)
{
\addr := 0x4500 + \id * 0x100;
"serial" % \id : "serial@" % hexstr(\addr) {
cell-index = < (\id) >;
device_type = "serial";
compatible = "ns16550";
reg = < (\addr) 0x100>;
clock-frequency = <0>;
interrupts = <42 2>;
interrupt-parent = <&mpic>;
};
}
/define/ make_memory_controller(\id)
{
\addr := 0x2000 + \id * 0x4000;
"memory-controller@" % hexstr(\addr) {
compatible = "fsl,mpc8572-memory-controller";
reg = < (\addr) 0x1000>;
interrupt-parent = <&mpic>;
interrupts = <18 2>;
};
}
/ {
model = "fsl,MPC8572DS";
compatible = "fsl,MPC8572DS";
#address-cells = <1>;
#size-cells = <1>;
aliases {
ethernet0 = &enet0;
ethernet1 = &enet1;
ethernet2 = &enet2;
ethernet3 = &enet3;
serial0 = &serial0;
serial1 = &serial1;
pci0 = &pci0;
pci1 = &pci1;
pci2 = &pci2;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
make_cpu("8572", 0);
make_cpu("8572", 1);
};
memory {
device_type = "memory";
reg = <0x0 0x0>; // Filled by U-Boot
};
soc8572@ffe00000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "simple-bus";
ranges = <0x0 0xffe00000 0x100000>;
reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
bus-frequency = <0>; // Filled out by uboot.
make_memory_controller(0);
make_memory_controller(1);
L2: l2-cache-controller@20000 {
compatible = "fsl,mpc8572-l2-cache-controller";
reg = <0x20000 0x1000>;
cache-line-size = <32>; // 32 bytes
cache-size = <0x80000>; // L2, 512K
interrupt-parent = <&mpic>;
interrupts = <16 2>;
};
make_i2c(0);
make_i2c(1);
make_dma_controller("8572", 1);
make_dma_controller("8572", 0);
mdio@24520 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,gianfar-mdio";
reg = <0x24520 0x20>;
for \phy in 0 .. 3 {
make_ethernet_phy(\phy);
}
};
for \id in 0 .. 3 {
make_ethernet(\id);
}
make_serial(0);
make_serial(1);
global-utilities@e0000 { //global utilities block
compatible = "fsl,mpc8572-guts";
reg = <0xe0000 0x1000>;
fsl,has-rstcr;
};
msi@41600 {
compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
reg = <0x41600 0x80>;
msi-available-ranges = <0 0x100>;
interrupts = <
0xe0 0
0xe1 0
0xe2 0
0xe3 0
0xe4 0
0xe5 0
0xe6 0
0xe7 0>;
interrupt-parent = <&mpic>;
};
crypto@30000 {
compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
"fsl,sec2.1", "fsl,sec2.0";
reg = <0x30000 0x10000>;
interrupts = <45 2 58 2>;
interrupt-parent = <&mpic>;
fsl,num-channels = <4>;
fsl,channel-fifo-len = <24>;
fsl,exec-units-mask = <0x9fe>;
fsl,descriptor-types-mask = <0x3ab0ebf>;
};
mpic: pic@40000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <0x40000 0x40000>;
compatible = "chrp,open-pic";
device_type = "open-pic";
};
};
pci0: pcie@ffe08000 {
cell-index = <0>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0xffe08000 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <24 2>;
interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x11 func 0 - PCI slot 1 */
0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 1 - PCI slot 1 */
0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 2 - PCI slot 1 */
0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 3 - PCI slot 1 */
0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 4 - PCI slot 1 */
0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 5 - PCI slot 1 */
0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 6 - PCI slot 1 */
0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x11 func 7 - PCI slot 1 */
0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
/* IDSEL 0x12 func 0 - PCI slot 2 */
0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 1 - PCI slot 2 */
0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 2 - PCI slot 2 */
0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 3 - PCI slot 2 */
0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 4 - PCI slot 2 */
0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 5 - PCI slot 2 */
0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 6 - PCI slot 2 */
0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
/* IDSEL 0x12 func 7 - PCI slot 2 */
0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
// IDSEL 0x1c USB
0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
// IDSEL 0x1d Audio
0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
// IDSEL 0x1e Legacy
0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
// IDSEL 0x1f IDE/SATA
0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <0x2000000 0x0 0x80000000
0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
uli1575@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
ranges = <0x2000000 0x0 0x80000000
0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
isa@1e {
device_type = "isa";
#interrupt-cells = <2>;
#size-cells = <1>;
#address-cells = <2>;
reg = <0xf000 0x0 0x0 0x0 0x0>;
ranges = <0x1 0x0 0x1000000 0x0 0x0
0x1000>;
interrupt-parent = <&i8259>;
i8259: interrupt-controller@20 {
reg = <0x1 0x20 0x2
0x1 0xa0 0x2
0x1 0x4d0 0x2>;
interrupt-controller;
device_type = "interrupt-controller";
#address-cells = <0>;
#interrupt-cells = <2>;
compatible = "chrp,iic";
interrupts = <9 2>;
interrupt-parent = <&mpic>;
};
i8042@60 {
#size-cells = <0>;
#address-cells = <1>;
reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
interrupts = <1 3 12 3>;
interrupt-parent =
<&i8259>;
keyboard@0 {
reg = <0x0>;
compatible = "pnpPNP,303";
};
mouse@1 {
reg = <0x1>;
compatible = "pnpPNP,f03";
};
};
rtc@70 {
compatible = "pnpPNP,b00";
reg = <0x1 0x70 0x2>;
};
gpio@400 {
reg = <0x1 0x400 0x80>;
};
};
};
};
};
pci1: pcie@ffe09000 {
cell-index = <1>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0xffe09000 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
0000 0x0 0x0 0x1 &mpic 0x4 0x1
0000 0x0 0x0 0x2 &mpic 0x5 0x1
0000 0x0 0x0 0x3 &mpic 0x6 0x1
0000 0x0 0x0 0x4 &mpic 0x7 0x1
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <0x2000000 0x0 0xa0000000
0x2000000 0x0 0xa0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
pci2: pcie@ffe0a000 {
cell-index = <2>;
compatible = "fsl,mpc8548-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <0xffe0a000 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <27 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
0000 0x0 0x0 0x1 &mpic 0x0 0x1
0000 0x0 0x0 0x2 &mpic 0x1 0x1
0000 0x0 0x0 0x3 &mpic 0x2 0x1
0000 0x0 0x0 0x4 &mpic 0x3 0x1
>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ranges = <0x2000000 0x0 0xc0000000
0x2000000 0x0 0xc0000000
0x0 0x20000000
0x1000000 0x0 0x0
0x1000000 0x0 0x0
0x0 0x100000>;
};
};
};
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 4/8] Add header files for new Internal Representation form.
[not found] ` <1222196652-13811-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 5/8] Add most of the new IR implementation files Jon Loeliger
@ 2008-09-24 19:17 ` Scott Wood
1 sibling, 0 replies; 25+ messages in thread
From: Scott Wood @ 2008-09-24 19:17 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Jon Loeliger wrote:
> +struct ir {
> + ir_type ir_type;
> + srcpos *ir_srcpos;
> +
> + long long ir_literal;
> + char *ir_lit_str;
> + char *ir_label_name;
> + irb_id ir_builtin_id;
> +
> + struct ir *ir_name;
> + struct ir *ir_label;
> + struct ir *ir_expr1;
> + struct ir *ir_expr2;
> + struct ir *ir_expr3;
> +
> + struct ir *ir_mem_reserves;
> + struct ir *ir_statements;
> + struct ir *ir_statements2;
> + struct ir *ir_declarations;
> +
> + struct ir *ir_first;
> + struct ir *ir_last;
> + struct ir *ir_prev;
> + struct ir *ir_next;
> +};
Could we skip the redundant "ir_" prefix? Structs have had their own
namespaces for a *loooooong* time now.
> +extern struct ir *the_ir_tree;
s/the_//
> +struct irb_entry {
> + irb_id irb_id;
> + char *irb_name;
> + irb_impl_func irb_implementation;
> +};
How about "struct builtin_func" or similar? Let's not pack the
meaningful bits of the name into an obscure acronym.
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 5/8] Add most of the new IR implementation files.
[not found] ` <1222196652-13811-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 6/8] Add the main IR evaluation implementation Jon Loeliger
@ 2008-09-24 22:25 ` Scott Wood
1 sibling, 0 replies; 25+ messages in thread
From: Scott Wood @ 2008-09-24 22:25 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
Jon Loeliger wrote:
> Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> ---
> ir.c | 197 +++++++++++++++++++++++
> ir_builtin.c | 178 +++++++++++++++++++++
> ir_dump.c | 220 ++++++++++++++++++++++++++
> ir_emit.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ir_scope.c | 319 +++++++++++++++++++++++++++++++++++++
> 5 files changed, 1406 insertions(+), 0 deletions(-)
> create mode 100644 ir.c
> create mode 100644 ir_builtin.c
> create mode 100644 ir_dump.c
> create mode 100644 ir_emit.c
> create mode 100644 ir_scope.c
>
> +void
> +ir_free(struct ir *ir)
> +{
> +}
> +
> +
> +void
> +ir_free_all(struct ir *ir)
> +{
> +}
Hmm.
> +extern struct ir *
> +ir_alloc_unop(ir_type ir_type, struct ir *ir1, srcpos *pos)
> +{
> + struct ir *ir;
> +
> + ir = ir_alloc(ir_type, pos);
> + ir->ir_expr1 = ir1;
> +
> + return ir;
> +}
> +
> +
> +extern struct ir *
> +ir_alloc_binop(ir_type ir_type,
> + struct ir *ir1, struct ir *ir2,
> + srcpos *pos)
> +{
> + struct ir *ir;
> +
> + ir = ir_alloc(ir_type, pos);
> + ir->ir_expr1 = ir1;
> + ir->ir_expr2 = ir2;
> +
> + return ir;
> +}
> +
> +
> +extern struct ir *
> +ir_alloc_triop(ir_type ir_type,
> + struct ir *ir1, struct ir *ir2, struct ir *ir3,
> + srcpos *pos)
> +{
> + struct ir *ir;
> +
> + ir = ir_alloc(ir_type, pos);
> + ir->ir_expr1 = ir1;
> + ir->ir_expr2 = ir2;
> + ir->ir_expr3 = ir3;
> +
> + return ir;
> +}
Yay, constructors in C.
> + ir_node->ir_prev = ir_list->ir_last;
> +
> + if (ir_list->ir_last) {
> + ir_list->ir_last->ir_next = ir_node;
> + } else {
> + ir_list->ir_first = ir_node;
> + }
> +
> + ir_list->ir_last = ir_node;
Can't we use something a generic linked list implementation, as in the
kernel?
> +void
> +ir_process(void)
> +{
> + /*
> + * FIXME: Fix leaking the whole orginal IR tree here.
> + */
> + the_ir_tree = ir_simplify(the_ir_tree, IR_EVAL_CTXT_ANY);
> +
> + ir_emit(the_ir_tree);
> +}
You don't add ir_simplify until the next patch.
> +void
> +ir_warn(struct ir *ir, char const *fmt, ...)
> +{
> + srcpos *pos;
> + const char *srcstr;
> + va_list va;
> + va_start(va, fmt);
> +
> + pos = ir ? ir->ir_srcpos : &srcpos_empty;
> + srcstr = srcpos_string(pos);
> +
> + fprintf(stderr, "Error: %s ", srcstr);
> + vfprintf(stderr, fmt, va);
> + fprintf(stderr, "\n");
> +
> + va_end(va);
> +}
> +
> +
> +void
> +ir_error(struct ir *ir, char const *fmt, ...)
> +{
> + srcpos *pos;
> + const char *srcstr;
> + va_list va;
> + va_start(va, fmt);
> +
> + pos = ir ? ir->ir_srcpos : &srcpos_empty;
> + srcstr = srcpos_string(pos);
> +
> + fprintf(stderr, "Warn: %s ", srcstr);
> + vfprintf(stderr, fmt, va);
> + fprintf(stderr, "\n");
> +
> + treesource_error = 1;
> + va_end(va);
> +}
These should be one function with a parameter distinguishing them.
> diff --git a/ir_builtin.c b/ir_builtin.c
> new file mode 100644
> index 0000000..2f33440
> --- /dev/null
> +++ b/ir_builtin.c
> @@ -0,0 +1,178 @@
> +/*
> + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> + * USA
> + */
> +
> +#include <stdio.h>
> +
> +#include "dtc.h"
> +#include "ir.h"
> +
> +struct ir *ir_builtin_join(struct ir *ir_params);
> +struct ir *ir_builtin_hexstr(struct ir *ir_params);
> +
> +static const struct irb_entry irb_builtins[] = {
> + { 0, NULL, NULL },
> + { 1, "join", ir_builtin_join },
> + { 2, "hexstr", ir_builtin_hexstr },
> +};
What purpose does the initial NULL entry serve?
> +#define IRB_NUM_BUILTINS ARRAY_SIZE(irb_builtins)
...other than changing MAX_BUILTIN to NUM_BUILTINS (or, you could just
use ARRAY_SIZE in the loop itself).
Or if this weren't C, we could just use an existing dictionary
implementation without having to do all this crap from scratch every time.
> +struct ir *
> +ir_eval_builtin(struct ir *ir)
> +{
> + irb_id irb;
> + const struct irb_entry *irbe;
> + struct ir *ir_new;
> +
> + if (ir == NULL)
> + return NULL;
> +
> + if (ir->ir_type != IR_BUILTIN)
> + return NULL;
> +
> + irb = ir->ir_builtin_id;
> +
> + if (irb <= IRB_UNDEF || irb >= IRB_NUM_BUILTINS)
> + return NULL;
Shouldn't we fail rather more loudly if any of these conditions actually
happens?
> + ir_new = (*irbe->irb_implementation)(ir);
> +
> + return ir_new;
Why not just "return irbe->irb_implementation(ir);"?
> +struct ir *
> +ir_builtin_join(struct ir *ir_builtin)
> +{
How does this builtin differ from the concatenation operator, other than
that in the latter at least one argument must already be a string? I
noticed join() wasn't used in either of your example trees, can you give
an example when you would use it?
> + struct ir *ir_new;
> + struct ir *irp;
> + struct ir *ir;
> + char *s;
> + char *str;
> + int len;
> + char buf[30];
> +
> + debug("ir_builtin_impl_join():\n");
> +
> + irp = ir_builtin->ir_expr1;
> + if (irp->ir_type == IR_LIST)
> + irp = irp->ir_first;
> +
> + len = 1;
> + str = xmalloc(1);
> + *str = 0;
> +
> + while (irp != NULL) {
> + ir = ir_eval(irp);
> +
> + if (ir_is_string(ir)) {
> + s = ir_eval_for_c_string(ir);
> + } else if (ir_is_constant(ir)) {
> + unsigned long long a;
> + a = ir_eval_for_addr(ir);
> + snprintf(buf, 30, "%llu", a);
> + s = buf;
Use sizeof(buf).
> +#include "ir.h"
> +#include "ir_scope.h"
> +#include "nv.h"
> +
> +extern struct boot_info *the_boot_info;
This is already in ir.h.
> +void ir_emit_node(struct ir *ir);
Should either be static, or declared in a header file.
> +void
> +ir_emit_prop_def(struct ir *irp)
> +{
> + struct ir *ir_lhs;
> + struct property *p;
> + char *prop_name;
> + char *lab;
> + struct data d;
> +
> + debug("ir_emit_prop_def(");
> +
> + lab = ir_eval_for_label(irp->ir_label);
> + if (lab) {
> + debug("%s : ", lab);
> + }
> +
> + ir_lhs = ir_eval(irp->ir_expr1);
> + prop_name = ir_eval_for_name(ir_lhs);
> + debug("%s = <expr>)\n", prop_name);
> +
> + if (prop_name) {
> + d = empty_data;
> + ir_eval_for_data(irp->ir_expr2, &d);
ir_eval_for_data() is also not defined until patch 6. Breaking patches
up doesn't aid reviewability if they're not self-contained.
> + p = build_property(prop_name, d, lab);
> + irs_append_property(p);
> + }
> +
> + debug("ir_emit_prop_def(): Done\n");
> +}
> +
> +
> +void
> +ir_emit_assign(struct ir *ir_assign)
> +{
> + char *var_name;
> + struct ir_symbol *irsym;
> + struct ir *ir_val;
> + struct ir *ir_pos;
> +
> + ir_pos = ir_assign->ir_expr1 ? ir_assign->ir_expr1 : ir_assign;
> +
> + var_name = ir_eval_for_name(ir_assign->ir_expr1);
> +
> + debug("ir_emit_assign(%s)\n", var_name);
> +
> + if (!var_name) {
> + ir_error(ir_pos, "Can't determine LHS name\n");
> + return;
> + }
> +
> + irsym = irs_lookup_local(var_name);
> + if (irsym != NULL) {
> + if (irsym->irsym_type == IRSYM_CONST) {
> + ir_error(ir_pos,
> + "Can't assign to constant \"%s\"\n",
> + var_name);
> + }
> + } else {
> + /*
> + * FIXME: Debate on-the-fly creation or pre-declaration.
> + */
> + irsym = irs_create_local(var_name, IRSYM_VAR);
> + }
> +
> + ir_val = ir_eval(ir_assign->ir_expr2);
> + irsym->irsym_value = ir_val;
> +}
> +
> +
> +void
> +ir_emit_for(struct ir *ir_for)
> +{
> + char *var_name;
> + struct ir_symbol *irsym;
> + struct ir *ir_id;
> + struct ir *ir_val;
> + struct ir *ir_range;
> + unsigned long long var;
> + unsigned long long start;
> + unsigned long long stop;
> +
> + irs_push_scope(IRS_FOR_LOOP);
> +
> + /*
> + * Introduce for-loop variable into FOR_LOOP scope.
> + */
> + ir_id = ir_for->ir_expr1;
> + var_name = ir_eval_for_name(ir_id);
> + irsym = irs_create_local(var_name, IRSYM_VAR);
> +
> + ir_val = ir_alloc(IR_LIT_ADDR, ir_id->ir_srcpos);
> + irsym->irsym_value = ir_val;
> +
> + ir_range = ir_for->ir_expr2;
> + start = ir_eval_for_addr(ir_range->ir_expr1);
> + stop = ir_eval_for_addr(ir_range->ir_expr2);
> +
> + debug("Range appears to be %llu to %llu\n", start, stop);
> +
> + var = start;
> + while (var <= stop ) {
> + ir_val->ir_literal = var;
> + ir_emit_statement_list(ir_for->ir_statements);
> + var++;
> + }
> +
> + irs_pop_scope();
> +}
> +
> +
> +void
> +ir_emit_if(struct ir *ir_if)
> +{
> + uint64_t lit;
> +
> + debug("ir_if()\n");
> + lit = ir_eval_for_addr(ir_if->ir_expr1);
> + if (lit) {
> + ir_emit_statement_list(ir_if->ir_statements);
> + } else {
> + ir_emit_statement_list(ir_if->ir_statements2);
> + }
> +}
> +
> +
> +void
> +ir_emit_return(struct ir *ir_return)
> +{
> + struct ir *ir_ret_expr;
> +
> + ir_ret_expr = ir_eval(ir_return->ir_expr1);
> + irs_set_return_value(ir_ret_expr);
> +}
> +
> +
> +void
> +ir_emit_func_call(struct ir *ir_func)
> +{
> + struct ir_scope *irs_scope;
> +
> + /*
> + * Perform function body.
> + *
> + * Returned scope has node and property "side effects".
> + * Function return value is thrown to /dev/null.
> + */
> + irs_scope = ir_eval_func_body(ir_func);
> +
> + /*
> + * Propagate any nodes or properties into parent scope.
> + */
> + irs_scope_append_property_list(irs_scope->irs_prop_list);
> + irs_scope_append_node_list(irs_scope->irs_node_list);
> +}
> +
> +
> +void
> +ir_emit_statement(struct ir *ir)
> +{
> + if (ir == NULL)
> + return;
> +
> + switch (ir->ir_type) {
> + case IR_NODE:
> + ir_emit_node(ir);
> + break;
> +
> + case IR_PROP_DEF:
> + ir_emit_prop_def(ir);
> + break;
> +
> + case IR_FOR:
> + ir_emit_for(ir);
> + break;
> +
> + case IR_IF:
> + ir_emit_if(ir);
> + break;
> +
> + case IR_RETURN:
> + ir_emit_return(ir);
> + break;
> +
> + case IR_ASSIGN:
> + ir_emit_assign(ir);
> + break;
> +
> + case IR_FUNC_CALL:
> + ir_emit_func_call(ir);
> + break;
> +
> + case IR_LIST:
> + /*
> + * FIXME: LIST within a LIST. Optimize out earlier?
> + */
> + ir_emit_statement_list(ir);
> + break;
> +
> + default:
> + ir_error(ir, "Unknown statement with ir_type %s\n",
> + ir_type_string(ir->ir_type));
> + }
> +}
> +
> +
> +void
> +ir_emit_statement_list(struct ir *ir_list)
> +{
> + struct ir *ir;
> +
> + if (ir_list == NULL)
> + return;
> +
> + if (ir_list->ir_type != IR_LIST)
> + return;
> +
> + for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) {
> + ir_emit_statement(ir);
> + }
> +}
> +
> +
> +/*
> + * Enter a /define/ function definitin into IRS_ROOT symtab.
> + */
> +void
> +ir_emit_func_def(struct ir *ir_func_def)
> +{
> + char *func_name;
> + struct ir_symbol *irsym;
> + struct ir *ir_pos;
> +
> + ir_pos = ir_func_def->ir_expr1
> + ? ir_func_def->ir_expr1 : ir_func_def;
> +
> + func_name = ir_eval_for_name(ir_func_def->ir_name);
> +
> +
> + irsym = irs_lookup(func_name, IRS_ROOT);
> + if (irsym != NULL) {
> + ir_warn(ir_pos,
> + "Redefinintion of \"%s\" ignored\n",
> + func_name);
That seems it should be an error, not a warning.
> +void
> +ir_emit_root(struct ir *ir)
> +{
> + struct reserve_info *ri_list;
> + struct node *node_list;
> +
> + if (ir == NULL)
> + return;
> +
> + if (ir->ir_type != IR_ROOT) {
> + debug("emit: Bad root node\n");
> + return;
> + }
Again, this seems too quiet a failure -- you have to have debug messages
enabled to see that anything's wrong.
> +void
> +irs_free_scope(struct ir_scope *irs)
> +{
> + free(irs);
> +}
The IRS is never free. :-)
> +/*
> + * Try to find a symbol that is local to the innermost function.
> + *
> + * Look through scope stack finding matching scopes.
> + * Peer into FUNC_CALL, FOR_LOOP and IR_ROOT symbol tables,
> + * but bail at first FUNC_CALL to make them be "local".
> + */
No declaration scoping in if-blocks?
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
[not found] ` <097BFF8D-317F-4E85-AC2A-4C0A8D6C608B-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
2008-09-24 16:51 ` Jon Loeliger
@ 2008-09-25 3:50 ` David Gibson
1 sibling, 0 replies; 25+ messages in thread
From: David Gibson @ 2008-09-25 3:50 UTC (permalink / raw)
To: Kumar Gala; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
On Tue, Sep 23, 2008 at 09:34:38PM -0500, Kumar Gala wrote:
>
> On Sep 23, 2008, at 2:04 PM, Jon Loeliger wrote:
>
>> This series of patches enhances the DTS source language to
>> support a fullly interpreted language for generating nodes
>> and properties. It is backward compatible with V1 sources.
>>
>> The main features implemented by this patch set support
>> function definitions, 'if', 'for', 'return' and assignment
>> statements. Local variables, global constants and
>> almost complete C-like expressions are also supported.
>>
>> Enhancements to the source position and error/warning
>> reporting now support source column positions too.
>>
>> Jon Loeliger (8):
>> Remove support for the legacy DTS source file format.
>> Add conditionalized debug() print macro.
>> Enhance source position implementation.
>> Add header files for new Internal Representation form.
>> Add most of the new IR implementation files.
>> Add the main IR evaluation implementation
>> Introduce new DTS language.
>> Add documentation for the new DTS language.
>
> Any examples/tests of all the cool new features?
Um.. yeah. I'd really like to discuss the syntax, before diving into
the implementation. You've certainly taken a different approach to
this than the one I was thinking of.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
2008-09-24 16:51 ` Jon Loeliger
2008-09-24 18:48 ` Jon Loeliger
@ 2008-09-25 4:26 ` David Gibson
[not found] ` <20080925042613.GJ15169-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
1 sibling, 1 reply; 25+ messages in thread
From: David Gibson @ 2008-09-25 4:26 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss
On Wed, Sep 24, 2008 at 11:51:45AM -0500, Jon Loeliger wrote:
> On Tue, 2008-09-23 at 21:34 -0500, Kumar Gala wrote:
>
> > Any examples/tests of all the cool new features?
> >
> > - k
>
> Here is a QAD example based on the MPC8641 DTS file
> as found in the arch/powerpc/boot/dts directory today.
> It is maybe not the best example, but it shows the
> flavor of what can be done.
>
> Enjoy,
> jdl
>
>
> /*
> * MPC8641 HPCN Device Tree Source
> *
> * Copyright 2006 Freescale Semiconductor Inc.
> *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms of the GNU General Public License as published by the
> * Free Software Foundation; either version 2 of the License, or (at your
> * option) any later version.
> */
>
> /dts-v1/;
>
> /define/ make_cpu(\cpu)
Eck. The \identified parameters certainly seem to violate the
look-like-C principle.
> {
> "PowerPC,8641@" % \cpu {
You use quotes for the node name here in the macro. Is that always
required, or only needed if you're defining the node name with an
expression. If the latter, how are the two cases lexically
distinguished?
> device_type = "cpu";
> reg = < (\cpu) >;
So.. in the node name the \cpu parameter is treated as a string, here
it's treated as a number. What makes the difference? Does the %
operator implicitly convert?
> d-cache-line-size = <32>;
> i-cache-line-size = <32>;
> d-cache-size = <32768>; // L1
> i-cache-size = <32768>; // L1
> timebase-frequency = <0>; // From uboot
> bus-frequency = <0>; // From uboot
> clock-frequency = <0>; // From uboot
> };
> }
>
> /define/ make_i2c(\id, \addr)
> {
> "i2c@" % \hexstr(\addr) {
Ok, so you have built-in functions as well.
How does "typing" work on these functions? Each of the examples you
have here defines exactly one node. Does that have to be the case, or
are there other options? Can you define multiple nodes with one
function. Can you define properties only with a function?
> #address-cells = <1>;
> #size-cells = <0>;
> cell-index = <\id>;
> compatible = "fsl-i2c";
> reg = < (\addr) 0x100>;
> interrupts = <43 2>;
> interrupt-parent = <&mpic>;
> dfsrr;
> };
> }
>
> /define/ make_ethernet(\id, \addr)
> {
> "enet" % \id : "ethernet@" % \hexstr(\addr) {
Here labels too are defined with quotes. Again, what distinguishes
this from the non-quoted case? This form also means the : no longer
lexically distinguishes a label, which makes life interesting.
> cell-index = <\id>;
> device_type = "network";
> model = "TSEC";
> compatible = "gianfar";
> reg = < (\addr) 0x1000>;
> local-mac-address = [ 00 00 00 00 00 00 ];
> if (\id == 0) {
> interrupts = <29 2 30 2 34 2>;
> }
This isn't a language problem, per se, but this looks like a bad way
of doing a make_ethernet() function: having these individual cases
for the interrupts means board knowledge is built into the function
which is what we're trying to avoid. Better to pass in the interrupt
numbers to the function, I think.
> if (\id == 1) {
> interrupts = <35 2 36 2 40 2>;
> }
> if (\id == 2) {
> interrupts = <31 2 32 2 33 2>;
> }
> if (\id == 3) {
> interrupts = <37 2 38 2 39 2>;
> }
> interrupt-parent = <&mpic>;
> phy-handle = <&("phy" % \id)>;
> phy-connection-type = "rgmii-id";
> };
> }
>
> /define/ make_ethernet_phy(\id)
> {
> "phy" % \id : "ethernet-phy@" % \id {
> interrupt-parent = <&mpic>;
> interrupts = <10 1>;
> reg = < (\id) >;
> device_type = "ethernet-phy";
> };
> }
>
>
> /define/ make_dma_channel(\id)
> {
> "dma-channel@" % hexstr(\id * 0x80) {
> compatible = "fsl,mpc8641-dma-channel",
> "fsl,eloplus-dma-channel";
> reg = < (0x80 * \id) 0x80>;
> cell-index = < (\id) >;
> interrupt-parent = <&mpic>;
> interrupts = < (20 + \id) 2>;
> };
> }
>
> /define/ make_serial(\id, \addr)
> {
> "serial" % \id : "serial@" % hexstr(\addr) {
> cell-index = < (\id) >;
> device_type = "serial";
> compatible = "ns16550";
> reg = < (\addr) 0x100>;
> clock-frequency = <0>;
> if (\id == 0) {
> interrupts = <42 2>;
> } else {
> interrupts = <28 2>;
> }
> interrupt-parent = <&mpic>;
> };
> }
>
>
> / {
> model = "MPC8641HPCN";
> compatible = "fsl,mpc8641hpcn";
> #address-cells = <1>;
> #size-cells = <1>;
>
> aliases {
> ethernet0 = &enet0;
> ethernet1 = &enet1;
> ethernet2 = &enet2;
> ethernet3 = &enet3;
> serial0 = &serial0;
> serial1 = &serial1;
> pci0 = &pci0;
> pci1 = &pci1;
> rapidio0 = &rapidio0;
> };
>
> cpus {
> #address-cells = <1>;
> #size-cells = <0>;
>
> make_cpu(0);
> make_cpu(1);
> };
>
> memory {
> device_type = "memory";
> reg = <0x00000000 0x40000000>; // 1G at 0x0
> };
>
> localbus@f8005000 {
> #address-cells = <2>;
> #size-cells = <1>;
> compatible = "fsl,mpc8641-localbus", "simple-bus";
> reg = <0xf8005000 0x1000>;
> interrupts = <19 2>;
> interrupt-parent = <&mpic>;
>
> ranges = <0 0 0xff800000 0x00800000
> 1 0 0xfe000000 0x01000000
> 2 0 0xf8200000 0x00100000
> 3 0 0xf8100000 0x00100000>;
>
> flash@0,0 {
> compatible = "cfi-flash";
> reg = <0 0 0x00800000>;
> bank-width = <2>;
> device-width = <2>;
> #address-cells = <1>;
> #size-cells = <1>;
> partition@0 {
> label = "kernel";
> reg = <0x00000000 0x00300000>;
> };
> partition@300000 {
> label = "firmware b";
> reg = <0x00300000 0x00100000>;
> read-only;
> };
> partition@400000 {
> label = "fs";
> reg = <0x00400000 0x00300000>;
> };
> partition@700000 {
> label = "firmware a";
> reg = <0x00700000 0x00100000>;
> read-only;
> };
> };
> };
>
> soc8641@f8000000 {
> #address-cells = <1>;
> #size-cells = <1>;
> device_type = "soc";
> compatible = "simple-bus";
> ranges = <0x00000000 0xf8000000 0x00100000>;
> reg = <0xf8000000 0x00001000>; // CCSRBAR
> bus-frequency = <0>;
>
> make_i2c(0, 0x3000);
> make_i2c(1, 0x3100);
>
> dma@21300 {
> #address-cells = <1>;
> #size-cells = <1>;
> compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
> reg = <0x21300 0x4>;
> ranges = <0x0 0x21100 0x200>;
> cell-index = <0>;
>
> for \i in 0 .. 3 {
This would seem to be another violation of the look-like-C principle.
This for syntax is pretty much unprecedented.
> make_dma_channel(\i);
> }
> };
>
> mdio@24520 {
> #address-cells = <1>;
> #size-cells = <0>;
> compatible = "fsl,gianfar-mdio";
> reg = <0x24520 0x20>;
>
> for \i in 0 .. 3 {
> make_ethernet_phy(\i);
> }
> };
>
> for \i in 0 .. 3 {
> make_ethernet(\i, 0x24000 + \i * 0x1000);
> }
>
> make_serial(0, 0x4500);
> make_serial(1, 0x4600);
>
> mpic: pic@40000 {
> interrupt-controller;
> #address-cells = <0>;
> #interrupt-cells = <2>;
> reg = <0x40000 0x40000>;
> compatible = "chrp,open-pic";
> device_type = "open-pic";
> };
>
> global-utilities@e0000 {
> compatible = "fsl,mpc8641-guts";
> reg = <0xe0000 0x1000>;
> fsl,has-rstcr;
> };
> };
>
> pci0: pcie@f8008000 {
> cell-index = <0>;
> compatible = "fsl,mpc8641-pcie";
> device_type = "pci";
> #interrupt-cells = <1>;
> #size-cells = <2>;
> #address-cells = <3>;
> reg = <0xf8008000 0x1000>;
> bus-range = <0x0 0xff>;
> ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
> 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
> clock-frequency = <33333333>;
> interrupt-parent = <&mpic>;
> interrupts = <24 2>;
> interrupt-map-mask = <0xff00 0 0 7>;
> interrupt-map = <
> /* IDSEL 0x11 func 0 - PCI slot 1 */
> 0x8800 0 0 1 &mpic 2 1
> 0x8800 0 0 2 &mpic 3 1
> 0x8800 0 0 3 &mpic 4 1
> 0x8800 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 1 - PCI slot 1 */
> 0x8900 0 0 1 &mpic 2 1
> 0x8900 0 0 2 &mpic 3 1
> 0x8900 0 0 3 &mpic 4 1
> 0x8900 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 2 - PCI slot 1 */
> 0x8a00 0 0 1 &mpic 2 1
> 0x8a00 0 0 2 &mpic 3 1
> 0x8a00 0 0 3 &mpic 4 1
> 0x8a00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 3 - PCI slot 1 */
> 0x8b00 0 0 1 &mpic 2 1
> 0x8b00 0 0 2 &mpic 3 1
> 0x8b00 0 0 3 &mpic 4 1
> 0x8b00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 4 - PCI slot 1 */
> 0x8c00 0 0 1 &mpic 2 1
> 0x8c00 0 0 2 &mpic 3 1
> 0x8c00 0 0 3 &mpic 4 1
> 0x8c00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 5 - PCI slot 1 */
> 0x8d00 0 0 1 &mpic 2 1
> 0x8d00 0 0 2 &mpic 3 1
> 0x8d00 0 0 3 &mpic 4 1
> 0x8d00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 6 - PCI slot 1 */
> 0x8e00 0 0 1 &mpic 2 1
> 0x8e00 0 0 2 &mpic 3 1
> 0x8e00 0 0 3 &mpic 4 1
> 0x8e00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x11 func 7 - PCI slot 1 */
> 0x8f00 0 0 1 &mpic 2 1
> 0x8f00 0 0 2 &mpic 3 1
> 0x8f00 0 0 3 &mpic 4 1
> 0x8f00 0 0 4 &mpic 1 1
>
> /* IDSEL 0x12 func 0 - PCI slot 2 */
> 0x9000 0 0 1 &mpic 3 1
> 0x9000 0 0 2 &mpic 4 1
> 0x9000 0 0 3 &mpic 1 1
> 0x9000 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 1 - PCI slot 2 */
> 0x9100 0 0 1 &mpic 3 1
> 0x9100 0 0 2 &mpic 4 1
> 0x9100 0 0 3 &mpic 1 1
> 0x9100 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 2 - PCI slot 2 */
> 0x9200 0 0 1 &mpic 3 1
> 0x9200 0 0 2 &mpic 4 1
> 0x9200 0 0 3 &mpic 1 1
> 0x9200 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 3 - PCI slot 2 */
> 0x9300 0 0 1 &mpic 3 1
> 0x9300 0 0 2 &mpic 4 1
> 0x9300 0 0 3 &mpic 1 1
> 0x9300 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 4 - PCI slot 2 */
> 0x9400 0 0 1 &mpic 3 1
> 0x9400 0 0 2 &mpic 4 1
> 0x9400 0 0 3 &mpic 1 1
> 0x9400 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 5 - PCI slot 2 */
> 0x9500 0 0 1 &mpic 3 1
> 0x9500 0 0 2 &mpic 4 1
> 0x9500 0 0 3 &mpic 1 1
> 0x9500 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 6 - PCI slot 2 */
> 0x9600 0 0 1 &mpic 3 1
> 0x9600 0 0 2 &mpic 4 1
> 0x9600 0 0 3 &mpic 1 1
> 0x9600 0 0 4 &mpic 2 1
>
> /* IDSEL 0x12 func 7 - PCI slot 2 */
> 0x9700 0 0 1 &mpic 3 1
> 0x9700 0 0 2 &mpic 4 1
> 0x9700 0 0 3 &mpic 1 1
> 0x9700 0 0 4 &mpic 2 1
>
> // IDSEL 0x1c USB
> 0xe000 0 0 1 &i8259 12 2
> 0xe100 0 0 2 &i8259 9 2
> 0xe200 0 0 3 &i8259 10 2
> 0xe300 0 0 4 &i8259 11 2
>
> // IDSEL 0x1d Audio
> 0xe800 0 0 1 &i8259 6 2
>
> // IDSEL 0x1e Legacy
> 0xf000 0 0 1 &i8259 7 2
> 0xf100 0 0 1 &i8259 7 2
>
> // IDSEL 0x1f IDE/SATA
> 0xf800 0 0 1 &i8259 14 2
> 0xf900 0 0 1 &i8259 5 2
> >;
>
> pcie@0 {
> reg = <0 0 0 0 0>;
> #size-cells = <2>;
> #address-cells = <3>;
> device_type = "pci";
> ranges = <0x02000000 0x0 0x80000000
> 0x02000000 0x0 0x80000000
> 0x0 0x20000000
>
> 0x01000000 0x0 0x00000000
> 0x01000000 0x0 0x00000000
> 0x0 0x00100000>;
> uli1575@0 {
> reg = <0 0 0 0 0>;
> #size-cells = <2>;
> #address-cells = <3>;
> ranges = <0x02000000 0x0 0x80000000
> 0x02000000 0x0 0x80000000
> 0x0 0x20000000
> 0x01000000 0x0 0x00000000
> 0x01000000 0x0 0x00000000
> 0x0 0x00100000>;
> isa@1e {
> device_type = "isa";
> #interrupt-cells = <2>;
> #size-cells = <1>;
> #address-cells = <2>;
> reg = <0xf000 0 0 0 0>;
> ranges = <1 0 0x01000000 0 0
> 0x00001000>;
> interrupt-parent = <&i8259>;
>
> i8259: interrupt-controller@20 {
> reg = <1 0x20 2
> 1 0xa0 2
> 1 0x4d0 2>;
> interrupt-controller;
> device_type = "interrupt-controller";
> #address-cells = <0>;
> #interrupt-cells = <2>;
> compatible = "chrp,iic";
> interrupts = <9 2>;
> interrupt-parent = <&mpic>;
> };
>
> i8042@60 {
> #size-cells = <0>;
> #address-cells = <1>;
> reg = <1 0x60 1 1 0x64 1>;
> interrupts = <1 3 12 3>;
> interrupt-parent =
> <&i8259>;
>
> keyboard@0 {
> reg = <0>;
> compatible = "pnpPNP,303";
> };
>
> mouse@1 {
> reg = <1>;
> compatible = "pnpPNP,f03";
> };
> };
>
> rtc@70 {
> compatible =
> "pnpPNP,b00";
> reg = <1 0x70 2>;
> };
>
> gpio@400 {
> reg = <1 0x400 0x80>;
> };
> };
> };
> };
>
> };
>
> pci1: pcie@f8009000 {
> cell-index = <1>;
> compatible = "fsl,mpc8641-pcie";
> device_type = "pci";
> #interrupt-cells = <1>;
> #size-cells = <2>;
> #address-cells = <3>;
> reg = <0xf8009000 0x1000>;
> bus-range = <0 0xff>;
> ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
> 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
> clock-frequency = <33333333>;
> interrupt-parent = <&mpic>;
> interrupts = <25 2>;
> interrupt-map-mask = <0xf800 0 0 7>;
> interrupt-map = <
> /* IDSEL 0x0 */
> 0x0000 0 0 1 &mpic 4 1
> 0x0000 0 0 2 &mpic 5 1
> 0x0000 0 0 3 &mpic 6 1
> 0x0000 0 0 4 &mpic 7 1
> >;
> pcie@0 {
> reg = <0 0 0 0 0>;
> #size-cells = <2>;
> #address-cells = <3>;
> device_type = "pci";
> ranges = <0x02000000 0x0 0xa0000000
> 0x02000000 0x0 0xa0000000
> 0x0 0x20000000
>
> 0x01000000 0x0 0x00000000
> 0x01000000 0x0 0x00000000
> 0x0 0x00100000>;
> };
> };
> rapidio0: rapidio@f80c0000 {
> #address-cells = <2>;
> #size-cells = <2>;
> compatible = "fsl,rapidio-delta";
> reg = <0xf80c0000 0x20000>;
> ranges = <0 0 0xc0000000 0 0x20000000>;
> interrupt-parent = <&mpic>;
> /* err_irq bell_outb_irq bell_inb_irq
> msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
> interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>;
> };
> };
>
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org
> https://ozlabs.org/mailman/listinfo/devicetree-discuss
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
2008-09-24 18:48 ` Jon Loeliger
@ 2008-09-25 4:31 ` David Gibson
0 siblings, 0 replies; 25+ messages in thread
From: David Gibson @ 2008-09-25 4:31 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss
On Wed, Sep 24, 2008 at 01:48:55PM -0500, Jon Loeliger wrote:
> On Wed, 2008-09-24 at 11:51 -0500, Jon Loeliger wrote:
> > On Tue, 2008-09-23 at 21:34 -0500, Kumar Gala wrote:
> >
> > > Any examples/tests of all the cool new features?
> > >
> > > - k
> >
> > Here is a QAD example based on the MPC8641 DTS file
> > as found in the arch/powerpc/boot/dts directory today.
> > It is maybe not the best example, but it shows the
> > flavor of what can be done.
> >
> > Enjoy,
> > jdl
>
>
> Also, here is the same refactoring done on the
> mpc8572ds.dts file too.
>
> And, perhaps more important than doing this work
> on this one file, it shows that the first section
> of both this 8572 DTS file and the 8641 DTS file
> are almost identical throughout the /define/ section.
> Minor refactoring needed in the 8641 variant.
> The only "real" difference is 8641 says "TSEC" and
> the 8572 says "eTSEC", and one weird interrupt thing
> in the serial node. Dunno.
[snip]
> /define/ make_i2c(\id)
> {
> \addr := 0x3000 + \id * 0x100;
Hrm. Again, not very C-like. Plus it bothers me that there are 3
somewhat different definition constructs: /define/, /const/ and :=.
At least /define/ and /const/ should be mergeable, with /const/
becoming a zero-parameter /define/. Maybe local defines need
something different, but the distinction seems dangerously ad-hoc to
me at the moment.
[snip]
> /define/ make_dma_channel(\part, \id, \intr_base)
> {
> "dma-channel@" % hexstr(\id * 0x80) {
> compatible = < ("fsl,mpc" % \part % "-dma-channel")
> ("fsl,eloplus-dma-channel") >;
WTF!? What is a < > construct doing containing strings rather than
cells.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 2/8] Add conditionalized debug() print macro.
[not found] ` <1222196652-13811-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 3/8] Enhance source position implementation Jon Loeliger
@ 2008-09-25 12:42 ` Josh Boyer
1 sibling, 0 replies; 25+ messages in thread
From: Josh Boyer @ 2008-09-25 12:42 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
On Tue, 23 Sep 2008 14:04:06 -0500
Jon Loeliger <jdl-CYoMK+44s/E@public.gmane.org> wrote:
> From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>
> Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> ---
> dtc.h | 8 ++++++++
> 1 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/dtc.h b/dtc.h
> index 08d54c8..ec636f8 100644
> --- a/dtc.h
> +++ b/dtc.h
> @@ -34,7 +34,15 @@
> #include <libfdt_env.h>
> #include <fdt.h>
>
> +#ifdef DEBUG
> +#define debug(fmt,args...) printf(fmt, ##args)
> +#else
> +#define debug(fmt,args...)
> +#endif
> +
> +
So, not to be nitpicky, but this requires a rebuild of dtc with -DDEBUG
(or similar) to get the debug output.
Would it be better to have it just take a --debug option on the command
line and conditionalize on a global variable? dtc isn't exactly a
performance crazy application, so the if checks shouldn't matter too
much.
josh
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 8/8] Add documentation for the new DTS language.
[not found] ` <1222196652-13811-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-25 13:00 ` Josh Boyer
0 siblings, 0 replies; 25+ messages in thread
From: Josh Boyer @ 2008-09-25 13:00 UTC (permalink / raw)
To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A
On Tue, 23 Sep 2008 14:04:12 -0500
Jon Loeliger <jdl-CYoMK+44s/E@public.gmane.org> wrote:
> +4.1) DTS Lexical Components
> +
> +Property and node names [a-zA-Z0-9,._+*#?@-]+
> +Identifiers \\[a-zA-Z_][a-zA-Z0-9_]*
> +Labels [a-zA-Z_][a-zA-Z0-9_]*
> +Strings <C-style-double-quoted-strings>
> +Comments Both /* ... */ and // style are supported
> +Numeric literals <C-style-integer-numbers>
> +Bytes [0-9a-fA-F][0-9a-fA-F]
> +
> +Keywords:
> + else
> + for
> + if
> + in
> + return
> + void
> + /const/
> + /define/
> + /incbin/
> +
> +C-style expression operators:
> + <<
> + >>
> + <=
> + >=
> + ==
> + !=
> + &&
> + ||
> + +
> + -
> + *
> + /
> + %
> +
> +Additional tokens:
> + ..
> + :=
> + {
> + }
> + ,
> + &
> +
You have ^, &, |, <, >, ~, (, and ) listed in the "expr_oper:" part of
the DTS grammar below this, but none of those are included here.
Which list is complete/correct?
josh
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/8] Implement a new DTS Source Language
[not found] ` <20080925042613.GJ15169-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-09-25 15:25 ` Scott Wood
0 siblings, 0 replies; 25+ messages in thread
From: Scott Wood @ 2008-09-25 15:25 UTC (permalink / raw)
To: David Gibson; +Cc: devicetree-discuss
David Gibson wrote:
>> /define/ make_cpu(\cpu)
>
> Eck. The \identified parameters certainly seem to violate the
> look-like-C principle.
It's to disambiguate from existing doesn't-look-like-C constructs
(property and node definitions), though it's not really needed in this
context.
>> {
>> device_type = "cpu";
>> reg = < (\cpu) >;
>
> So.. in the node name the \cpu parameter is treated as a string, here
> it's treated as a number. What makes the difference? Does the %
> operator implicitly convert?
Yes, it implicitly converts.
> Can you define multiple nodes with one
> function. Can you define properties only with a function?
Yes to both.
>> for \i in 0 .. 3 {
>
> This would seem to be another violation of the look-like-C principle.
I don't think we particularly need to inherit C's warts.
> This for syntax is pretty much unprecedented.
It's similar to Python, albeit with less flexibility (I suggested to Jon
that we introduce a "set" construct to remedy this).
-Scott
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2008-09-25 15:25 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-23 19:04 [PATCH 0/8] Implement a new DTS Source Language Jon Loeliger
[not found] ` <1222196652-13811-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 1/8] Remove support for the legacy DTS source file format Jon Loeliger
[not found] ` <1222196652-13811-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 2/8] Add conditionalized debug() print macro Jon Loeliger
[not found] ` <1222196652-13811-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 3/8] Enhance source position implementation Jon Loeliger
[not found] ` <1222196652-13811-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 4/8] Add header files for new Internal Representation form Jon Loeliger
[not found] ` <1222196652-13811-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 5/8] Add most of the new IR implementation files Jon Loeliger
[not found] ` <1222196652-13811-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 6/8] Add the main IR evaluation implementation Jon Loeliger
[not found] ` <1222196652-13811-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 7/8] Introduce new DTS language Jon Loeliger
[not found] ` <1222196652-13811-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-23 19:04 ` [PATCH 8/8] Add documentation for the " Jon Loeliger
[not found] ` <1222196652-13811-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-25 13:00 ` Josh Boyer
2008-09-24 22:25 ` [PATCH 5/8] Add most of the new IR implementation files Scott Wood
2008-09-24 19:17 ` [PATCH 4/8] Add header files for new Internal Representation form Scott Wood
2008-09-24 17:07 ` [PATCH 3/8] Enhance source position implementation Scott Wood
[not found] ` <48DA73DA.5000603-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-09-24 17:17 ` Jon Loeliger
2008-09-24 17:21 ` Scott Wood
2008-09-24 17:23 ` Warner Losh
2008-09-24 17:23 ` Scott Wood
2008-09-25 12:42 ` [PATCH 2/8] Add conditionalized debug() print macro Josh Boyer
2008-09-24 2:34 ` [PATCH 0/8] Implement a new DTS Source Language Kumar Gala
[not found] ` <097BFF8D-317F-4E85-AC2A-4C0A8D6C608B-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
2008-09-24 16:51 ` Jon Loeliger
2008-09-24 18:48 ` Jon Loeliger
2008-09-25 4:31 ` David Gibson
2008-09-25 4:26 ` David Gibson
[not found] ` <20080925042613.GJ15169-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-09-25 15:25 ` Scott Wood
2008-09-25 3:50 ` David Gibson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.