File: GCBuiltins.hpp

package info (click to toggle)
fauhdlc 20180504-3.1
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 3,064 kB
  • sloc: cpp: 23,188; ansic: 6,077; yacc: 3,764; lex: 763; makefile: 605; python: 412; xml: 403; sh: 61
file content (468 lines) | stat: -rw-r--r-- 12,796 bytes parent folder | download | duplicates (3)
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/* $Id$ 
 *
 * Generate intermediate code, intermediate code implementation of builtins.
 *
 * Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#ifndef __GC_BUILTINS_HPP_INCLUDED
#define __GC_BUILTINS_HPP_INCLUDED

#include "frontend/visitor/GenCode.hpp"
#include "frontend/misc/BuiltinSymbolTable.hpp"
#include <list>
#include "intermediate/opcodes/OpCode.hpp"
#include "intermediate/operands/RegisterFactory.hpp"
#include "intermediate/opcodes/Sub.hpp"
#include "intermediate/opcodes/Add.hpp"
#include "intermediate/opcodes/IMul.hpp"
#include "intermediate/opcodes/Div.hpp"

namespace ast {

//! abstract base class for an arbitrary builtin operator.
/** GCBuiltins is the abstract base class for all builtin operators.
 *  To generate code, the following functions must always get called:
 *
 *    reset();
 *     generate code to evaluate first operand here ...
 *    shortCutfirstOp(cc, firstOp);
 *     generate code to evaluate the remaining operands here ...
 *    emitCode(cc, operands);
 *
 *  The operands parameter of emitCode must contain *all* operands.
 */
class GCBuiltins {
public:
	//! virtual dummy d'tor.
	virtual ~GCBuiltins() {}

	//! generic abstract interface to emit code for a builtin function
	/** @param gc Code generator instance.
	 *  @param ops list of operands.
	 *  @return RegisterSet containing the result of the operands.
	 */
	virtual RegisterSet
	emitCode(GenCode &gc, std::list<AssociationElement*> ops) const = 0;
};

//! abstract base class for non-short-circuit operators
class GCBuiltinsNoShortCircuit : public GCBuiltins {
private:
	//! generic abstract interface to emit code for a builtin function
	/** @param gc Code generator instance.
	 *  @param ops list of operands.
	 *  @return RegisterSet containing the result of the operands.
	 */
	virtual RegisterSet
	emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;

protected:
	//! emit code to calculate the result
	/** @param cc container to add generated code to.
	 *  @param ops RegisterSets containing the operands.
	 *  @return RegisterSet containing the result.
	 */
	virtual RegisterSet 
	calculate(
		intermediate::CodeContainer &cc, 
		std::list<RegisterSet> ops,
		std::list<enum BaseType> btl) const = 0;
};

//! abstract base class for all binary short-circuit operators.
class GCBuiltinsShortCircuit : public GCBuiltins {
private:
	//! generic abstract interface to emit code for a builtin function
	/** 
	 * res = <default>
	 * if (left == <shortCut>) {
         * 	goto out
	 * }
	 * if (right == <shortCut>) {
	 * 	goto out
	 * 	res = < 1 - default >
	 * }
	 *
	 *  @param gc Code generator instance.
	 *  @param ops list of operands.
	 *  @return RegisterSet containing the result of the operands.
	 */
	virtual RegisterSet
	emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;

protected:
	/** determine the default value, which gets used if the comparison
	 *  against getShortCut is equal.
	 *  @return the default value of the short circuit operator in the
	 *          range between 0 and 1.
	 */
	virtual universal_integer getDefault(void) const = 0;

	/** determine the value to check against, if the shortcut condition
	 *  matches.
	 *  @return if the operand is equal to the return value, the default
	 *          value will be used as result.
	 */
	virtual universal_integer getShortCut(void) const = 0;
private:
	//! evaluate the result of one assocation and return it in an operand
	/** @param cc CodeContainer to add code to.
	 *  @param assoc association to evaluate. (FIXME interface ?)
	 *  @return operand containing the result */
	static intermediate::Operand *
	evaluate(intermediate::CodeContainer *cc, AssociationElement &assoc);
};

//! implementation of the "AND" short-circuit operator.
class GCBuiltinsAnd : public GCBuiltinsShortCircuit {
private:
	virtual universal_integer getDefault(void) const {
		return 0;
	}

	virtual universal_integer getShortCut(void) const {
		return 0;
	}
};

//! implementation of the "OR" short-circuit operator.
class GCBuiltinsOr : public GCBuiltinsShortCircuit {
private:
	virtual universal_integer getDefault(void) const {
		return 1;
	}

	virtual universal_integer getShortCut(void) const {
		return 1;
	}
};

//! implementation of the "NAND" short-circuit operator.
class GCBuiltinsNand : public GCBuiltinsShortCircuit {
private:
	virtual universal_integer getDefault(void) const {
		return 1;
	}

	virtual universal_integer getShortCut(void) const {
		return 0;
	}
};

//! implementation of the "NOR" short-circuit operator.
class GCBuiltinsNor : public GCBuiltinsShortCircuit {
private:
	virtual universal_integer getDefault(void) const {
		return 0;
	}

	virtual universal_integer getShortCut(void) const {
		return 1;
	}
};

//! no-short circuit unary operators for non-composite types.
class GCBuiltinsUnop : public GCBuiltinsNoShortCircuit {
private:
	//! emit code to calculate the result
	/** @param ops list of operands
	 *  @return RegisterSet containing the result.
	 */
	virtual RegisterSet 
	calculate(
		intermediate::CodeContainer &cc, 
		std::list<RegisterSet> ops,
		std::list<enum BaseType> btl) const;

protected:
	//! calculate the result of the unary operator
	/** @param cc container to add generated code to.
	 *  @param op operand
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcUnOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *op) const = 0;
};

//! no-short circuit binary opartors for non-composite types.
class GCBuiltinsBinOp : public GCBuiltinsNoShortCircuit {
private:
	//! emit code to calculate the result
	/** @param ops list of operands
	 *  @return RegisterSet containing the result.
	 */
	virtual RegisterSet 
	calculate(
		intermediate::CodeContainer &cc, 
		std::list<RegisterSet> ops,
		std::list<enum BaseType> btl) const;

protected:
	//! calculate the result of the binary operator
	/** @param cc container to add generated code to.
	 *  @param left left operand
	 *  @param right right operand.
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcBinOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *left,
		intermediate::Operand *right) const = 0;
};


//! unary not for boolean and bit.
class GCBuiltinsNot : public GCBuiltinsUnop {
private:
	//! emit code for an unary not (bit, boolean)
	virtual intermediate::Register *
	calcUnOp(
		intermediate::CodeContainer &cc, 
		intermediate::Operand *op) const;
};

//! xor for boolean and bit.
class GCBuiltinsXor : public GCBuiltinsBinOp {
protected:
	//! calculate the result of XOR
	/** @param cc container to add generated code to.
	 *  @param left left operand
	 *  @param right right operand.
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcBinOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *left,
		intermediate::Operand *right) const;

};

//! xnor for boolean and bit.
class GCBuiltinsXnor : public GCBuiltinsXor {
private:
	//! calculate the result of XOR
	/** @param cc container to add generated code to.
	 *  @param left left operand
	 *  @param right right operand.
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcBinOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *left,
		intermediate::Operand *right) const;

};

//! base class for comparison operators for non-composite types.
class GCBuiltinsCompare : public GCBuiltinsBinOp {
private:
	//! calculate the result of XOR
	/** @param cc container to add generated code to.
	 *  @param left left operand
	 *  @param right right operand.
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcBinOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *left,
		intermediate::Operand *right) const;

protected:
	//! emit the comparison operation branch opcode.
	/** If the branch is not taken, 1-default value will be the result.
	 *  If the branch is taken, default value will be the result.
	 *  @param left left operand to compare
	 *  @param right right operand to compare
	 *  @param out branch target that uses the default value.
	 *  @return generated branch opcode.
	 */
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const = 0;
	
	//! get the default value of the comparison operator.
	/** @return default value of the comparison operator.
	 */
	virtual universal_integer getDefaultValue(void) const = 0;
};

//! equality for non-composite types.
class GCBuiltinsEqual : public GCBuiltinsCompare {
private:
	//! emit a je.
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_TRUE;
	}
};

//! inequality for non-composite types.
class GCBuiltinsInEqual : public GCBuiltinsCompare {
private:
	//! emit a jne
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_TRUE;
	}
};

//! less than for non-composite types.
class GCBuiltinsLess : public GCBuiltinsCompare {
private:
	//! emit a jb
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_TRUE;
	}
};

//! less or equal for non-composite types.
class GCBuiltinsLessEqual : public GCBuiltinsCompare {
private:
	//! emit a jbe
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_TRUE;
	}
};

//! greater than for non-composite types.
class GCBuiltinsGreater : public GCBuiltinsCompare {
private:
	//! emit a jbe
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_FALSE;
	}
};

//! greater or equal for non-composite types.
class GCBuiltinsGreaterEqual : public GCBuiltinsCompare {
private:
	//! emit a jb
	virtual intermediate::OpCode *
	emitBranch(
		intermediate::Operand *left, 
		intermediate::Operand *right, 
		intermediate::Label *out) const;

	virtual universal_integer getDefaultValue(void) const {
		return VHDL_FALSE;
	}
};

//! unary - (negation) for range constraint/physical types.
class GCBuiltinsUnaryMinus : public GCBuiltinsUnop {
private:
	//! calculate the result of the unary -.
	/** @param cc container to add generated code to.
	 *  @param op operand
	 *  @return Register containing the result.
	 */
	virtual intermediate::Register *
	calcUnOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *op) const;
};

//! identity (unary plus)
class GCBuiltinsIdentity : public GCBuiltins {
private:
	virtual RegisterSet
	emitCode(GenCode &gc, std::list<AssociationElement*> ops) const;
};

//! unary abs for range constraint/physical types.
class GCBuiltinsAbs : public GCBuiltinsUnop {
private:
	//! calculate absolute value.
	virtual intermediate::Register *
	calcUnOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *op) const;
};

//! template class for binary mathematical builtins
/** template class for binary mathematical builtins that can use 
 *  a direct intermediate opcode for evaluation.
 */
template <typename T>
class GCBuiltinsBinaryMath : public GCBuiltinsBinOp {
private:
	//calculate left + right
	virtual intermediate::Register *
	calcBinOp(
		intermediate::CodeContainer &cc,
		intermediate::Operand *left,
		intermediate::Operand *right) const {
		
		assert(left->type == right->type);
		intermediate::Register *result = 
			cc.createRegister(left->type);

		T *operation = new T(left, right, result);
		cc.addCode(operation);

		return result;
	};
};

//! binary plus.
class GCBuiltinsPlus : public GCBuiltinsBinaryMath<intermediate::Add> {
};

//! binary minus.
class GCBuiltinsMinus : public GCBuiltinsBinaryMath<intermediate::Sub> {
};

//! binary multiplication.
class GCBuiltinsMult : public GCBuiltinsBinaryMath<intermediate::IMul> {
};

//! binary division.
class GCBuiltinsDiv : public GCBuiltinsBinaryMath<intermediate::Div> {
};




}; /* namespace ast */

#endif /* __GC_BUILTINS_HPP_INCLUDED */