File: GenCode.hpp

package info (click to toggle)
fauhdlc 20180504-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 2,956 kB
  • sloc: cpp: 23,188; ansic: 6,077; yacc: 3,764; lex: 763; makefile: 605; sh: 494; xml: 403
file content (820 lines) | stat: -rw-r--r-- 24,542 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
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
/* $Id$
 *
 * Code generator, which transforms the abstract syntax tree into intermediate
 * code.
 *
 * 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 __GEN_CODE_HPP_INCLUDED
#define __GEN_CODE_HPP_INCLUDED

#include "frontend/visitor/TopDownVisitor.hpp"
#include "intermediate/container/CodeContainer.hpp"
#include "intermediate/operands/Register.hpp"
#include "intermediate/container/Data.hpp"
#include "intermediate/opcodes/OpCode.hpp"
#include "frontend/visitor/NullVisitor.hpp"
#include "frontend/visitor/GCArrays.hpp"
#include "frontend/visitor/GCLoops.hpp"
#include "frontend/visitor/GCRegisterSet.hpp"
#include "frontend/ast/Types.hpp"
#include "frontend/misc/Driver.hpp"

namespace ast {

//! generate intermediate code from the AST
/** This visitor will generate intermediate code from the abstract syntax
 *  tree. 
 *  Steps, that must have been done prior to running this visitor are:
 *  - all symbols must have been resolved (ParserDriver, Parser in 
 *    conjunction with ResolveSymbols)
 *  - types must have been resolved (ResolveTypes)
 *  - intermediate code names must have been set (SetPathNames)
 *  - process drivers and formal parts must have been collected
 *    (GatherImplicits).
 *  - concurrent statements must have been transformed into processes
 *    (not implemented yet)
 *  - CheckLoops
 *  - port map's must have been normalized
 *  - what else?
 *
 */
class GenCode : public TopDownVisitor {
public:
	//! c'tor
	GenCode();

	//! alternate c'tor for expression handling
	/** This c'tor can be used to handle (sub-)expressions.
	 *  @param cc CodeContainer instance to reuse.
	 */
	GenCode(intermediate::CodeContainer *cc);

private:
	/** Visit a Package node.
	 *  @param node Package node that gets visited.
	 */
	virtual void visit(Package &node);

	/** Visit an Entity declaration.
	 *  @param node Entity Declaration node that gets visited.
	 */
	virtual void visit(Entity &node);

	/** Visit an Architecture node.
	 *  @param node Architecture node that gets visited.
	 */
	virtual void visit(Architecture &node);

	/** Visit a CompInstStat node.
	 *  @param node CompInstStat node that gets visited.
	 */
	virtual void visit(CompInstStat &node);

	/** Visit a VarAssignStat
	 *  @param node VarAssignStat node that gets visited.
	 */
	virtual void visit(VarAssignStat &node);

	/** Visit a SigAssignStat
	 *  @param node SigAssignStat node that gets visited.
	 */
	virtual void visit(SigAssignStat &node);

	/** visit a ConstInteger
         *  @param node node that gets visited.
         */
	virtual void visit(ConstInteger &node);

	/** visit a ConstReal
         *  @param node node that gets visited.
         */
	virtual void visit(ConstReal &node);

	/** visit a SimpleName
         *  @param node node that gets visited.
         */
	virtual void visit(SimpleName &node);

	/** visit an AttributeName
         *  @param node node that gets visited.
         */
	virtual void visit(AttributeName &node);

	/** visit an IfStat
         *  @param node node that gets visited.
         */
	virtual void visit(IfStat &node);

	/** visit a Subscript
         *  @param node node that gets visited.
         */
	virtual void visit(Subscript &node);

	/** visit a Slice
         *  @param node node that gets visited.
         */
	virtual void visit(Slice &node);

	/** visit a DiscreteRange
         *  @param node node that gets visited.
         */
	virtual void visit(DiscreteRange &node);

	/** visit a SelectedName
         *  @param node node that gets visited.
         */
	virtual void visit(SelectedName &node);

	/** visit a FunctionCall
         *  @param node node that gets visited.
         */
	virtual void visit(FunctionCall &node);

	/** visit an Aggregate
         *  @param node node that gets visited.
         */
	virtual void visit(Aggregate &node);

	/** visit a ReturnStat
         *  @param node node that gets visited.
         */
	virtual void visit(ReturnStat &node);

	/** Visit an Signal declaration.
	 *  @param node SignalDeclaration node that gets visited.
	 */
	virtual void visit(SignalDeclaration &node);

	/** Visit a VarDeclaration
	 *  @param node VarDeclaration node that gets visited.
	 */
	virtual void visit(VarDeclaration &node);

	/** Visit an Constant declaration.
	 *  @param node ConstantDeclaration node that gets visited.
	 */
	virtual void visit(ConstantDeclaration &node);

	/** Visit a Process node.
	 *  @param node Process node that gets visited.
	 */
	virtual void visit(Process &node);

	/** Visit a ForLoopStat
	 *  @param node ForLoopStat node that gets visited.
	 */
	virtual void visit(ForLoopStat &node);

	/** Visit a WhileLoopStat
	 *  @param node WhileLoopStat node that gets visited.
	 */
	virtual void visit(WhileLoopStat &node);

	/** Visit a NextStat
	 *  @param node NextStat node that gets visited.
	 */
	virtual void visit(NextStat &node);

	/** Visit an ExitStat
	 *  @param node ExitStat node that gets visited.
	 */
	virtual void visit(ExitStat &node);

	/** Visit a WaitStat
	 *  @param node WaitStat node that gets visited.
	 */
	virtual void visit(WaitStat &node);

	/** Visit an AssertStat
	 *  @param node AssertStat node that get's visited.
	 */
	virtual void visit(AssertStat &node);

	/** Visit a ProcCallStat
	 *  @param node ReturnStat node that get's visited.
	 */
	virtual void visit(ProcCallStat &node);

	/** visit a ConstArray
         *  @param node node that get's visited.
         */
	virtual void visit(ConstArray &node);

	/** visit a SubtypeIndication
         *  @param node node that get's visited.
         */
	virtual void visit(SubtypeIndication &node);

	/** Visit an AttributeSpecification node.
	 *  @param node AttributeSpecification node that gets visited.
	 */
	virtual void visit(AttributeSpecification &node);

	/** Visit a CaseStat
	 *  @param node CaseStat node that get's visited.
	 */
	virtual void visit(CaseStat &node);

	/** Visit a FunctionDeclaration
	 *  @param node FunctionDeclaration node that get's visited.
	 */
	virtual void visit(FunctionDeclaration &node);

	/** Visit a ProcedureDeclaration
	 *  @param node ProcedureDeclaration node that get's visited.
	 */
	virtual void visit(ProcedureDeclaration &node);

	/** process (w. direct dispatch) to CaseAlternative 
	 *  @param node CaseAlternative node.
	 *  @param cmpVal compare value of CaseStat node.
	 *  @param caseNext label to jump to for the next alternative.
	 *         This might be the same as caseOut.
	 *  @param caseOut label to jump to after the case statement.
	 */
	void 
	processAlternative(
		CaseAlternative &node,
		intermediate::Operand *cmpVal,
		intermediate::Label *caseNext,
		intermediate::Label *caseOut
	);

public:
	//! the code container containing the generated code
	/** This container will get allocated by the c'tor, but it
	 *  won't get free'd again, since the caller will need it.
	 */
	intermediate::CodeContainer *container;

private:
	/** process a RangeConstraintType.
	 *  @param node RangeConstraintType to generate icode for */
	template <typename T> 
	void processRCT(RangeConstraintType &node);

	//! Process a generic Callable.
        /** This function will get called for each Callable (or class
         *  derived from Callable) that gets visited.
         *
         *  @param node Callable instance.
	 *  @return CodeContainer of the create subprogram.
         */
	intermediate::CodeContainer *processCallable(Callable &node);

	//! Process a generic TypeDeclaration.
        /** This function will get called for each TypeDeclaration (or class
         *  derived from TypeDeclaration) that gets visited.
         *
         *  @param node TypeDeclaration instance.
         */
	virtual void process(TypeDeclaration &node);

	/** process an attribute name "range".
	 *  @param node attribute name that is a range attribute.
	 */
	void processRangeAttr(AttributeName &node);

	/** eventually perform an assignment, if the current mode is load.
	 *  This is useful, if the storage area must have been determined
	 *  before arrays can get assigned. The assignment will hence get 
	 *  done on the right hand side, in the top expression.
	 *
	 *  @param node expression of the assignment.
	 */
	void processExpression(Expression &node);

	/** process a discrete range by from and to members.
	 *  @param node DiscreteRange that has from and to set.
	 */
	void processDRByBounds(DiscreteRange &node);

	/** perform an assignment from sourceRegs to destRegs based
	 *  on a specified type.
	 *  @param type type that the source/destination RegisterSet
	 *         refers to.
	 */
	void doAssignment(TypeDeclaration &type);

	/** process an array aggregate association.
	 *  @param node ElementAssociation to process.
	 *  @param aType type of the aggregate.
	 */
	void 
	processArrayAssoc(
		ElementAssociation &node, 
		TypeDeclaration *aType
	);

	/** process an array aggregate.
	 *  @param node Aggregate to process.
	 */
	void processArrayAggregate(Aggregate &node);

	/** process an aggregate, which is of base type record.
	 *  @param node Aggregate to process.
	 */
	void processRecordAggregate(Aggregate &node);

	/** process a signal/constant/vardeclaration
	 *  @param node declaration to process
	 *  @param st desired storage type for intermediate code.
	 *  @return resulting Data declaration that is already added
	 *          to the current code container.
	 */
	intermediate::Data *
	processValDecl(
		ValDeclaration &node, 
		enum intermediate::StorageType st
	);

	/** Call a subprogram node.
	 *  This function will push the arguments, and call the subprogram.
	 *  @param node subprogram to call.
	 *  @param foreign foreign annotation to pass on, NULL for non-foreign
	 *  @return return register (pointer to value) or NULL for procedures
	 */
	template <typename T>
	intermediate::Register *callSubprog(T &node, const char *foreign);

	/** add code to move the return value into a register.
	 *  Must only be called at a place where a corresponding transfer
	 *  frame is accessible (here only from callSubprog)
	 *
	 *  @param node Subprogram in question.
	 *  @param callee Reference of the Subprogram.
	 *  @return Register with the return value.
	 */
	template <typename T>
	intermediate::Register *
	getReturnValue(T &node, intermediate::Reference *callee);

	typedef 
	std::pair<const ValDeclaration*, intermediate::Operand *> copyBackT;

	typedef std::list<copyBackT> copyBackListT;

	//! push the argument list of FunctionCall/ProcedureCall node.
	/** @param node subprogram call, which's argument list should get
	 *  		transferred.
	 *  @param foreign foreign annotation to pass to arguments
	 *         NULL for non-foreign.
	 *  @return list of intermediate code commands to copy back 
	 *          actuals to formals after the call.
	 */
	template <typename T>
	std::list<intermediate::OpCode *>
	setArgList(T &node, const char *foreign);

	//! push an argument of a function call on the stack.
	/** @param c Callable in question.
	 *  @param vd corresponding declaration of the formal.
	 *  @param arg argument
	 *  @param foreign desired foreign annotation or NULL if not foreign
	 *  @return intermediate opcode to copy back the actual to the
	 *          formal (or NULL if not applicable).
	 */
	intermediate::OpCode *
	setArg(
		Callable &c, 
		const ValDeclaration &vd, 
		AssociationElement &element,
		const char *foreign);

	/** set an argument by value.
	 *  used for 
	 *  - constant (non-composite)
	 *  - variable (non-composite) 
	 *
	 *  @param callee Reference name of the Callee
	 *  @param vd formal declaration (may be NULL, if the element 
	 *         contains a formal)
	 *  @param element AssociationElement with the actual.
	 *  @param foreign char value to annotate as foreign value, NULL
	 *         if not foreign.
	 *  @param copyBack prepare target operand for copy back values?
	 *  @return copy back command to copy back the actual to the formal
	 *          if copyBack is true, NULL otherwise.
	 */
	intermediate::OpCode *
	setArgByValue(
		intermediate::Reference *callee,
		const ValDeclaration *vd,
		AssociationElement &element,
		const char *foreign,
		bool copyBack);

	/* set an argument by passing a pointer
	 * used for
	 * - signal (in, inout) (composite) (here it's a pointer to the signal
	 *   pointer)
	 * - variable (composite)
	 *
	 *  @param callee Reference name of the Callee
	 *  @param vd formal declaration (may be NULL, if the element 
	 *         contains a formal)
	 *  @param element AssociationElement with the actual.
	 *  @param foreign char value to annotate as foreign value, NULL
	 *         if not foreign.
	 */
	void 
	setArgByBasePointer(
		intermediate::Reference *callee,
		const ValDeclaration *vd,
		AssociationElement &element,
		const char *foreign);

	/** set an argumenty by passing a pointer to the signal
	 *  used fo
	 *  - signal (non-composite)
	 *  @param callee Reference name of the Callee
	 *  @param vd formal declaration (may be NULL, if the element 
	 *         contains a formal)
	 *  @param element AssociationElement with the actual.
	 *  @param foreign char value to annotate as foreign value, NULL
	 *         if not foreign.
	 */
	void 
	setArgByPointer(
		intermediate::Reference *callee,
		const ValDeclaration *vd,
		AssociationElement &element,
		const char *foreign);

	/* set an argument by passing a pointer to a temporary.
	 * used for
	 * - composite constant 
	 */
	void 
	setArgByBasePointerToTemporary(
		intermediate::Reference *callee,
		const ValDeclaration &vd,
		AssociationElement &element,
		const char *foreign);

	/** set an argument by passing the base pointer to the driver.
	 *  (pointer to driver pointer)
	 *  used for 
	 *  - signal (inout, out) (composite [usePointer=true])
	 *  - signal (inout, out) (non-composite [usePointer=false])
	 *
	 *  For a signal parameter of mode inout, the actual part will
	 *  be visited twice!
	 */
	void 
	setArgByDriver(
		intermediate::Reference *callee,
		const std::list<Driver*> &drivers,
		const ValDeclaration &vd,
		AssociationElement &element,
		const char *foreign,
		bool usePointer);

	/** set the constraint arguments for an unconstraint array by 
	 *  the constraints from the given declaration.
	 *  @param cRef Reference to the function call
	 *  @param icPrefix intermediate code name prefix.
	 *  @param t type containing the constraint.
	 *  @param foreign optional foreign annotation.
	 */
	void 
	setConstraintsByType(
		intermediate::Reference *cRef,
		const std::string &icPrefix, 
		const TypeDeclaration *t,
		const char *foreign);

	/** set the constraint arguments for an unconstraint array by 
	 *  the constraints from the source register set.
	 *  @param cRef Reference to the function call
	 *  @param icPrefix intermediate code name prefix
	 *  @param foreign optional foreign annotation
	 */
	void
	setConstraintsByRS(
		intermediate::Reference *cRef, 
		const std::string &icPrefix,
		const char *foreign);

	/** add data elements for unconstraint array bounds to
	 *  the container.
	 *  @param node unconstraint ValDeclaration 
	 */
	void addUnconstraintParams(const ValDeclaration &node);

	/** pickup the constraints for an unconstraint SimpleName
	 */
	void getConstraints(const ValDeclaration &vd);

	/** copy the array node to the destination register set.
	 *  @param node array to copy.
	 */
	void processArrayCopy(ConstArray &node);

	/** udpate (sig-assign) the const array to the destination register
	 *  set.
	 *  @param node source array.
	 */
	void processArrayUpdate(ConstArray &node);

	//! process a ConstReal or ConstInteger node.
	/** @param node node to process.
	 */
	template <typename T>
	void
	processConst(T &node);

	//! process a Subscript node with one index.
	/** @param node subscript to process.
	 *  @param indices list with index expressions.
	 */
	void
	processSubscription(Subscript &node, std::list<Expression*> &indices);

	//! process a next/exit statement.
	/** @param optCond optional condition when the next/exit statement
	 *         should be evaluated.
	 *  @param target branch target, if the condition is met.
	 */
	void
	processCFLoopStat(
		Expression *optCond, 
		intermediate::Label *target);

	//! assign the expression to the destination register set if true.
	bool assignExpression;

	//! is the currently evaluated expression a target?
	/** For a target, instead of the signal pointer, the driver pointer
	 *  must get used. Also direct values in valueReg are not allowed.
	 */
	bool isTarget;

public:
	//! source register set
	RegisterSet sourceRegs;
private:

	//! destination register set
	RegisterSet destRegs;

	//! data operand passed to AssignVisitor. 
	/** Contains various additional data depending on the assignMode.
	 *  (e.g. delay for signal assignments, severity level for log 
	 *  opcodes etc. See assignMode for details).
	 */
	intermediate::Operand *dataOp;

	/** Correctly copy/assign composite return values of a function 
	 *  call to the appropriate place and mangle the source
	 *  RegisterSet accordingly.
	 */
	void handleCompositeReturn(FunctionCall &node);

	/** create an init function for the architecture and add it to
	 *  the current code container.
	 *  @param node Architecture for which to create an init function.
	 */
	void createInitFunction(const Architecture &node);

	/** generate code to initialize an Architecture declared as 
	 *  foreign.
	 *
	 *  @param node foreign Architecture 
	 *  @param foreign corresponding foreign attribute.
	 */
	void foreignInit(
		const Architecture &node, 
		const AttributeSpecification &foreign
	);

	/** instantiate subcomponents in the architectures init function.
	 *  @param node Architecture which holds the subcomponents.
	 */
	void instantiateComponents(const Architecture &node);

	/** instantiate one subcomponent given by the CompInstStat
	 *  @param node CompInstStat of the sub component instantiation.
	 */
	void instantiateComponent(CompInstStat &node);

	/** generate an AssociationList where formal 
	 *  and actual both refer to the declaration.
	 *  @param dest append generated Associations in dest
	 *  @param src list of ValDeclarations (or derived from VDs).
	 *  @param lookupRegion declarative Region where the declarations
	 *         of src reside.
	 *
	 *  mainly useful for foreignInit(Architecture)
	 */
	template <typename T>
	void
	makeSelfAssociations(
		std::list<AssociationElement *> &dest,
		const T &src,
		const DeclarativeRegion *lookupRegion
	);


	/** Set all ports as parameters to reference ref.
	 *  @param cont Reference of component container
	 *  @param portList port list that should get set as parameters.
	 *  @param isForeign is this for a foreign entity?
	 */
	void 
	setPortList(
		intermediate::Reference *cont, 
		const std::list<AssociationElement *> &portList,
		bool isForeign
	);

	/** Set all generics as parameters to reference ref.
	 *  @param cont Reference of component container
	 *  @param genericMap generic map that should get set as parameters.
	 *  @param isForeign is this for a foreign entity?
	 */
	void
	setGenericMap(
		intermediate::Reference *cont,
		std::list<AssociationElement *> &genericMap,
		bool isForeign);

	/** create an init function for the process and add it to
	 *  the current code container.
	 *  @param node Process for which an init function should get created
	 */
	void createInitFunction(const Process &node);

	/** register the drivers in the stack segment for the process.
	 *  @param node process with drivers.
	 */
	void registerDrivers(const Process &node);

	/** register one driver in the stack segment for the process.
	 *  @param drv driver to register.
	 */
	void registerDriver(Driver &drv);


	/** annotate the type size for a type (in case it is known).
	 *  @param data data node that should get annotated.
	 *  @param type type of the declaration.
	 */
	static void annotateDataSize(
		intermediate::Data &data, 
		const SubtypeIndication *type
	);

	/** generate code for an index expression of a subscription.
	 *  @param index Expression to traverse to.
	 *  @return operand with the value of the index.
	 */
	intermediate::Operand *
	getSubscriptIndex(Expression *index);

	/** add annotations about type for foreign calls/generic/port map
	 *  aspects.
	 *  @param sp SetParam to be annotated.
	 *  @param vd ValDeclaration of the formal.
	 */
	static void
	annotateSetParamType(
		intermediate::SetParam &sp, 
		const ValDeclaration &vd);

	/** current enclosing process (or NULL). */
	Process *currentProcess;
	/** current enclosing subprogram declaration (or NULL) */
	Callable *currentSubprog;
	/** mapping for loop statements. */
	LoopRegistry loopRegistry;
	/** list of all instantiaded components by an architecture. */
	std::list<CompInstStat*> archComponents;

	/** operation to be performed for assignments */
	enum assignOperationE {
		/** standard operation: copy the parameter */
		ASSIGN_OPERATION_COPY,
		/** log each element in order with LOG. */
		ASSIGN_OPERATION_LOG,
		/** connect the driver in src to the signal in dst */
		ASSIGN_OPERATION_CONNECT,
		/** issue a WakeOn for each signal in src */
		ASSIGN_OPERATION_WAKEON

	};

	/** current operation to be used for assignements.
	 *  The default mode copy will perform a copy from source to
	 *  dest, either via MOV opcodes for non-signals and UPDATE
	 *  opcodes for signals, thereby using dataOp as delay operand.
	 *
	 *  Log will add a log opcode for each source, using dataOp
	 *  as severity level.
	 */
	enum assignOperationE assignOperation;

	//! generate code to assign src to dst
	class AssignVisitor : public NullVisitor {
	public:
		/** @param source operand referring to the source.
		 *  @param dest operand referring to the destination.
		 *  @param c CodeContainer to which code snippets should
		 *         get added.
		 *  @param dataOperand additional data passed to the visitor.
		 *         See assignMode for details.
		 */
		AssignVisitor(
			RegisterSet *source,
			RegisterSet *dest,
			intermediate::CodeContainer &c,
			intermediate::Operand *dataOperand,
			enum assignOperationE mode
			) :	src(source),
				dst(dest),
				container(c),
				dataOp(dataOperand),
				operation(mode) {}

	private:
		virtual void visit(SubtypeIndication &node);
		virtual void visit(UnconstrainedArrayType &node);
		virtual void visit(RecordType &node);
		virtual void visit(RecordTypeElement &node);
		virtual void visit(RangeConstraintType &node);
		virtual void visit(PhysicalType &node);
		virtual void visit(EnumerationType &node);

		//! generate code to perform the selected operation.
		/** @param t baseType of sourceRegs.
		 */
		void performOperation(enum BaseType t);

		//! generate code for an assign statement.
		/** This method will call the fitting operand methods.
		 *   @param t base type of the assigned value.
		 */
		void makeAssignment(enum BaseType t);

		//! log a value present in src
		void logValue(void);

		//! issue a wakeon on a signal element
		void wakeon(enum BaseType t);

		//! connect the driver in src to the signal in dst
		void connect(void);

		//! process a SubtypeIndication with an array base type.
		/** @param node SubtypeIndication of type array.
		 */
		void processArraySubtype(SubtypeIndication &node);

		/** source operand */
		RegisterSet *src;
		/** target operand */
		RegisterSet *dst;
		/** instance of the CodeContainer */
		intermediate::CodeContainer &container;
		//! delay operand
		intermediate::Operand *dataOp;
		//! desired operation
		enum assignOperationE operation;
	};

	//! process a generic expression, and perform assignments.
	/** For each subclass of an expression, this class should get 
	 *  instanciated on the stack when processing the AST node.
	 *  The c'tor will take care to stack the necessary variables
	 *  and the d'tor will perform the assignment.
	 */
	class ProcessStackedExpression {
	public:
		//! c'tor
		/** @param gc GenCode instance.
                 *  @param node currently processed Expression.
		 */
		ProcessStackedExpression(GenCode &gc, Expression &n);

		//! d'tor
		~ProcessStackedExpression();
	private:
		//! GenCode instance
		GenCode &genCode;
		
		//! currently processed expression node
		Expression &node;

		//! backup of assignExpression
		bool stackedAssignExpression;
	};
};

}; /* namespace ast */

#endif /* __GEN_CODE_HPP_INCLUDED */