1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
//
//
// The Nimrod Compiler
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
// This module implements a transformator. It transforms the syntax tree
// to ease the work of the code generators. Does the transformation to
// introduce temporaries to split up complex expressions.
// THIS MODULE IS NOT USED!
procedure transInto(c: PContext; var dest: PNode; father, src: PNode); forward;
// transforms the expression `src` into the destination `dest`. Uses `father`
// for temorary statements. If dest = nil, the expression is put into a
// temporary.
function transTmp(c: PContext; father, src: PNode): PNode;
// convienence proc
begin
result := nil;
transInto(c, result, father, src);
end;
function newLabel(c: PContext): PSym;
begin
inc(gTmpId);
result := newSym(skLabel, getIdent(genPrefix +{&} ToString(gTmpId),
c.transCon.owner));
end;
function fewCmps(s: PNode): bool;
// this function estimates whether it is better to emit code
// for constructing the set or generating a bunch of comparisons directly
begin
assert(s.kind in [nkSetConstr, nkConstSetConstr]);
if (s.typ.size <= platform.intSize) and
(s.kind = nkConstSetConstr) then
result := false // it is better to emit the set generation code
else if skipRange(s.typ.sons[0]).Kind in [tyInt..tyInt64] then
result := true // better not emit the set if int is basetype!
else
result := sonsLen(s) <= 8 // 8 seems to be a good value
end;
function transformIn(c: PContext; father, n: PNode): PNode;
var
a, b, e, setc: PNode;
destLabel, label2: PSym;
begin
if (n.sons[1].kind = nkSetConstr) and fewCmps(n.sons[1]) then begin
// a set constructor but not a constant set:
// do not emit the set, but generate a bunch of comparisons
result := newSymNode(newTemp(c, n.typ, n.info));
e := transTmp(c, father, n.sons[2]);
setc := n.sons[1];
destLabel := newLabel(c);
for i := 0 to sonsLen(setc)-1 do begin
if setc.sons[i].kind = nkRange then begin
a := transTmp(c, father, setc.sons[i].sons[0]);
b := transTmp(c, father, setc.sons[i].sons[1]);
label2 := newLabel(c);
addSon(father, newLt(result, e, a)); // e < a? --> goto end
addSon(father, newCondJmp(result, label2));
addSon(father, newLe(result, e, b)); // e <= b? --> goto set end
addSon(father, newCondJmp(result, destLabel));
addSon(father, newLabelNode(label2));
end
else begin
a := transTmp(c, father, setc.sons[i]);
addSon(father, newEq(result, e, a));
addSon(father, newCondJmp(result, destLabel));
end
end;
addSon(father, newLabelNode(destLabel));
end
else begin
result := n;
end
end;
procedure transformOp2(c: PContext; var dest: PNode; father, n: PNode);
var
a, b: PNode;
begin
if dest = nil then dest := newSymNode(newTemp(c, n.typ, n.info));
a := transTmp(c, father, n.sons[1]);
b := transTmp(c, father, n.sons[2]);
addSon(father, newAsgnStmt(dest, newOp2(n, a, b)));
end;
procedure transformOp1(c: PContext; var dest: PNode; father, n: PNode);
var
a: PNode;
begin
if dest = nil then dest := newSymNode(newTemp(c, n.typ, n.info));
a := transTmp(c, father, n.sons[1]);
addSon(father, newAsgnStmt(dest, newOp1(n, a)));
end;
procedure genTypeInfo(c: PContext; initSection: PNode);
begin
end;
procedure genNew(c: PContext; father, n: PNode);
begin
// how do we handle compilerprocs?
end;
function transformCase(c: PContext; father, n: PNode): PNode;
var
ty: PType;
e: PNode;
begin
ty := skipGeneric(n.sons[0].typ);
if ty.kind = tyString then begin
// transform a string case to a bunch of comparisons:
result := newNodeI(nkIfStmt, n);
e := transTmp(c, father, n.sons[0]);
end
else result := n
end;
procedure transInto(c: PContext; var dest: PNode; father, src: PNode);
begin
if src = nil then exit;
if (src.typ <> nil) and (src.typ.kind = tyGenericInst) then
src.typ := skipGeneric(src.typ);
case src.kind of
nkIdent..nkNilLit: begin
if dest = nil then dest := copyTree(src)
else begin
// generate assignment:
addSon(father, newAsgnStmt(dest, src));
end
end;
nkCall, nkCommand, nkCallStrLit: begin
end;
end;
end;
|