OpenASIP  2.0
Scope.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file Scope.cc
26  *
27  * Implementation of Scope class.
28  *
29  * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30  * @note rating: red
31  */
32 
33 #include "Scope.hh"
34 #include "CodeLabel.hh"
35 #include "DataLabel.hh"
36 #include "ContainerTools.hh"
37 #include "Application.hh"
38 
39 namespace TTAProgram {
40 
41 /////////////////////////////////////////////////////////////////////////////
42 // Scope
43 /////////////////////////////////////////////////////////////////////////////
44 
45 /**
46  * Constructor.
47  */
48 Scope::Scope(): parent_(NULL) {
49 }
50 
51 /**
52  * Destructor.
53  */
55  for (unsigned int i = 0; i < dataLabels_.size(); i++) {
56  delete dataLabels_.at(i);
57  }
58  dataLabels_.clear();
59 
60  for (unsigned int i = 0; i < codeLabels_.size(); i++) {
61  delete codeLabels_.at(i);
62  }
63  codeLabels_.clear();
64 }
65 
66 /**
67  * Tells whether this is a global scope.
68  *
69  * @return True if this is a global scope.
70  */
71 bool
72 Scope::isGlobal() const {
73  return false;
74 }
75 
76 /**
77  * Tells whether this is a unit scope.
78  *
79  * @return True if this is a unit scope.
80  */
81 bool
82 Scope::isUnit() const {
83  return false;
84 }
85 
86 /**
87  * Tells whether this is a procedure scope.
88  *
89  * @return True if this is a procedure scope.
90  */
91 bool
93  return false;
94 }
95 
96 /**
97  * Tells whether this is a local scope.
98  *
99  * @return True if this is a local scope.
100  */
101 bool
102 Scope::isLocal() const {
103  return false;
104 }
105 
106 /**
107  * Adds a child scope to this scope.
108  *
109  * @param scope The child scope to be added.
110  * @exception ObjectAlreadyExists if the given scope has already been added.
111  * or a scope with the same name already exists.
112  */
113 void
114 Scope::addChild(const Scope& scope) {
116  children_.push_back(&scope);
117  } else {
118  throw ObjectAlreadyExists(__FILE__, __LINE__);
119  }
120 }
121 
122 /**
123  * Return the parent scope., that is, the scope that contains this scope.
124  *
125  * @return The parent scope, that is, the scope that contains this scope.
126  * @exception WrongSubclass if this scope has no parent scope (it is the
127  * global scope).
128  * @exception IllegalRegistration if no parent has been set (and the scope
129  * is not the global scope.
130  */
131 Scope&
132 Scope::parent() const {
133  if (isGlobal()) {
134  throw WrongSubclass(
135  __FILE__, __LINE__, "Scope::parent()",
136  "Global scope cannot have parent scope.");
137  } else if (parent_ == NULL) {
138  throw IllegalRegistration(
139  __FILE__, __LINE__, "Scope::parent()", "No parent set.");
140  } else {
141  return *parent_;
142  }
143 }
144 
145 /**
146  * Sets the parent scope.
147  *
148  * @param scope The new parent scope.
149  * @exception WrongSubclass if the scope is the global scope.
150  */
151 void
153  if (!isGlobal()) {
154  parent_ = &scope;
155  } else {
156  throw WrongSubclass(
157  __FILE__, __LINE__, "Scope::parent()",
158  "Global scope cannot have parent scope.");
159  }
160 }
161 
162 /**
163  * Returns the number of contained scopes.
164  *
165  * Only scopes directly contained in this scope are counted, not inner
166  * scopes inside one of the child scopes.
167  *
168  * @return The number of contained scopes.
169  */
170 int
172  return children_.size();
173 }
174 
175 /**
176  * Returns the child scope at given index.
177  *
178  * @param index The index of the child scope.
179  * @return The child scope at given index.
180  * @exception OutOfRange if the exceeds the number of scopes contained in
181  * this scope.
182  */
183 const Scope&
184 Scope::child(int index) const {
185  if (index >= 0 && static_cast<unsigned int>(index) < children_.size()) {
186  return *children_.at(index);
187  } else {
188  throw OutOfRange(__FILE__, __LINE__);
189  }
190 }
191 
192 /**
193  * Tells whether this scope contains a code label with the given name.
194  *
195  * @param The name of the label.
196  * @return True if this scope contains a code label with the given name.
197  */
198 bool
199 Scope::containsCodeLabel(const std::string& name) const {
200  for (unsigned int i = 0; i < codeLabels_.size(); i++) {
201  if (name == codeLabels_.at(i)->name()) {
202  return true;
203  }
204  }
205  return false;
206 }
207 
208 /**
209  * Tells whether this scope contains a data label with the given name.
210  *
211  * @param The name of the label.
212  * @return True if this scope contains a data label with the given name.
213  */
214 bool
215 Scope::containsDataLabel(const std::string& name) const {
216  for (unsigned int i = 0; i < dataLabels_.size(); i++) {
217  if (name == dataLabels_.at(i)->name()) {
218  return true;
219  }
220  }
221  return false;
222 }
223 
224 /**
225  * Returns the code label with the given name.
226  *
227  * @param name The name of the label.
228  * @exception KeyNotFound if no code label with the given name exists in this
229  * scope.
230  * @return The code label with the given name.
231  */
232 const CodeLabel&
233 Scope::codeLabel(const std::string& name) const {
234  for (unsigned int i = 0; i < codeLabels_.size(); i++) {
235  if (name == codeLabels_.at(i)->name()) {
236  return *codeLabels_.at(i);
237  }
238  }
239  throw KeyNotFound(__FILE__, __LINE__);
240 }
241 
242 /**
243  * Returns the data label with the given name.
244  *
245  * @param name The name of the label.
246  * @exception KeyNotFound if no data label with the given name exists in this
247  * scope.
248  * @return The data label with the given name.
249  */
250 const DataLabel&
251 Scope::dataLabel(const std::string& name) const {
252  for (unsigned int i = 0; i < dataLabels_.size(); i++) {
253  if (name == dataLabels_.at(i)->name()) {
254  return *dataLabels_.at(i);
255  }
256  }
257  throw KeyNotFound(__FILE__, __LINE__);
258 }
259 
260 /**
261  * Returns the number of code labels in the given address visible in this
262  * scope.
263  *
264  * @param address The address of the label.
265  * @return The number of code labels in the given address visible in this
266  * scope.
267  */
268 int
270  int count = 0;
271  for (unsigned int i = 0; i < codeLabels_.size(); i++) {
272  if (&codeLabels_.at(i)->address().space() == &address.space() &&
273  codeLabels_.at(i)->address().location() == address.location()) {
274  count++;
275  }
276  }
277  return count;
278 }
279 
280 /**
281  * Returns a code label visible in this scope in the given address and index.
282  *
283  * @param address The address of the code label.
284  * @param index The index of the label if there area many labels at this
285  * address.
286  * @return A code label visible in this scope in the given address and index.
287  */
288 const CodeLabel&
289 Scope::codeLabel(Address address, int index) const {
290  if (index < codeLabelCount(address)) {
291 
292  int found = -1;
293  for (unsigned int i = 0; i < codeLabels_.size(); i++) {
294 
295  if (&codeLabels_.at(i)->address().space() ==
296  &address.space() &&
297  codeLabels_.at(i)->address().location() ==
298  address.location()) {
299 
300  found++;
301  if (found == index) {
302  return *codeLabels_.at(i);
303  }
304  }
305  }
306 
307  throw KeyNotFound(__FILE__, __LINE__);
308 
309  } else {
310  throw OutOfRange(__FILE__, __LINE__);
311  }
312 }
313 
314 /**
315  * Returns the number of data labels in the given address visible in this
316  * scope.
317  *
318  * @param address The address of the label.
319  * @return The number of data labels in the given address visible in this
320  * scope.
321  */
322 int
324  int count = 0;
325  for (unsigned int i = 0; i < dataLabels_.size(); i++) {
326  if (&dataLabels_.at(i)->address().space() == &address.space() &&
327  dataLabels_.at(i)->address().location() == address.location()) {
328  count++;
329  }
330  }
331  return count;
332 }
333 
334 /**
335  * Returns a data label visible in this scope in the given address and index.
336  *
337  * @param address The address of the data label.
338  * @param index The index of the label if there area many labels at this
339  * address.
340  * @return A data label visible in this scope in the given address and index.
341  */
342 const DataLabel&
343 Scope::dataLabel(Address address, int index) const {
344  if (index < dataLabelCount(address)) {
345 
346  int found = -1;
347  for (unsigned int i = 0; i < dataLabels_.size(); i++) {
348 
349  if (&dataLabels_.at(i)->address().space() ==
350  &address.space() &&
351  dataLabels_.at(i)->address().location() ==
352  address.location()) {
353 
354  found++;
355  if (found == index) {
356  return *dataLabels_.at(i);
357  }
358  }
359  }
360 
361  throw KeyNotFound(__FILE__, __LINE__);
362 
363  } else {
364  throw OutOfRange(__FILE__, __LINE__);
365  }
366 }
367 
368 /**
369  * Adds a code label to this scope.
370  *
371  * @param codeLabel The code label to be added.
372  * @exception KeyAlreadyExists of a code label of the same name already
373  * exists.
374  */
375 void
376 Scope::addCodeLabel(const CodeLabel* codeLabel) {
377  if (containsCodeLabel(codeLabel->name())) {
378  throw KeyAlreadyExists(
379  __FILE__, __LINE__, "Scope::addCodeLabel()",
380  "A code label already exists by this name.");
381 
382  } else {
383  codeLabels_.push_back(codeLabel);
384 
385  // add label to the global bookkeeping
386  Scope* scope = NULL;
387 
388  if (!isGlobal()) {
389  scope = &parent();
390  while (!scope->isGlobal()) {
391  try {
392  scope = &scope->parent();
393  } catch (WrongSubclass) {
394  assert(false);
395  } catch (IllegalRegistration) {
396  assert(false);
397  }
398  }
399  } else {
400  scope = this;
401  }
402 
403  scope->addGlobalCodeLabel(*codeLabel, *this);
404  }
405 }
406 
407 /**
408  * Adds a data label to this scope.
409  *
410  * @param dataLabel The data label to be added.
411  * @exception KeyAlreadyExists of a data label of the same name already
412  * exists.
413  */
414 void
415 Scope::addDataLabel(const DataLabel* dataLabel) {
416  if (containsDataLabel(dataLabel->name())) {
417  throw KeyAlreadyExists(
418  __FILE__, __LINE__, "Scope::addDataLabel()",
419  "A data label already exists by this name.");
420  } else {
421  dataLabels_.push_back(dataLabel);
422 
423  // add label to the global bookkeeping
424  Scope* scope = NULL;
425 
426  if (!isGlobal()) {
427  scope = &parent();
428  while (!scope->isGlobal()) {
429  try {
430  scope = &scope->parent();
431  } catch (WrongSubclass) {
432  assert(false);
433  } catch (IllegalRegistration) {
434  assert(false);
435  }
436  }
437  } else {
438  scope = this;
439  }
440 
441  scope->addGlobalDataLabel(*dataLabel, *this);
442  }
443 }
444 
445 /**
446  * Removes all code labels attached to the given instruction address.
447  *
448  * @param address The instruction address.
449  */
450 void
452 
453  for (CodeLabelList::iterator i = codeLabels_.begin();
454  i != codeLabels_.end(); ) {
455  CodeLabelList::iterator next = i;
456  next++;
457  if ((*i)->address().location() == address) {
458  delete (*i);
459  codeLabels_.erase(i);
460  }
461  i = next;
462  }
463 }
464 
465 }
KeyAlreadyExists
Definition: Exception.hh:268
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Scope::codeLabel
const CodeLabel & codeLabel(const std::string &name) const
Definition: Scope.cc:233
InstructionAddress
UInt32 InstructionAddress
Definition: BaseType.hh:175
TTAProgram::Address
Definition: Address.hh:51
TTAProgram::Scope::parent
Scope & parent() const
Definition: Scope.cc:132
TTAProgram::Scope::dataLabelCount
int dataLabelCount(Address address) const
Definition: Scope.cc:323
TTAProgram::Scope::addDataLabel
virtual void addDataLabel(const DataLabel *dataLabel)
Definition: Scope.cc:415
TTAProgram::Scope::codeLabels_
CodeLabelList codeLabels_
Code labels contained by this scope.
Definition: Scope.hh:95
TTAProgram::Scope::parent_
Scope * parent_
The smallest outer scope that contains this scope.
Definition: Scope.hh:125
OutOfRange
Definition: Exception.hh:320
TTAProgram::Address::space
const TTAMachine::AddressSpace & space() const
TTAProgram::Scope::isProcedure
virtual bool isProcedure() const
Definition: Scope.cc:92
TTAProgram::Scope::dataLabels_
DataLabelList dataLabels_
Data labels contained by this scope.
Definition: Scope.hh:93
TTAProgram::Scope::isLocal
virtual bool isLocal() const
Definition: Scope.cc:102
TTAProgram::Scope
Definition: Scope.hh:53
TTAProgram::Scope::addChild
void addChild(const Scope &scope)
Definition: Scope.cc:114
TTAProgram::Scope::Scope
Scope()
Definition: Scope.cc:48
DataLabel.hh
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::Label::name
std::string name() const
Definition: Label.cc:74
TTAProgram::Scope::addCodeLabel
virtual void addCodeLabel(const CodeLabel *codeLabel)
Definition: Scope.cc:376
TTAProgram::Scope::addGlobalDataLabel
virtual void addGlobalDataLabel(const DataLabel &dataLabel, const Scope &owner)=0
Adds a data label and its owner to the global label bookkeeping.
TTAProgram::Scope::isUnit
virtual bool isUnit() const
Definition: Scope.cc:82
WrongSubclass
Definition: Exception.hh:336
Scope.hh
TTAProgram::DataLabel
Definition: DataLabel.hh:45
TTAProgram::Scope::isGlobal
virtual bool isGlobal() const
Definition: Scope.cc:72
Application.hh
TTAProgram::CodeLabel
Definition: CodeLabel.hh:49
TTAProgram::Address::location
InstructionAddress location() const
TTAProgram::Scope::setParent
void setParent(Scope &scope)
Definition: Scope.cc:152
TTAProgram::Scope::removeCodeLabels
virtual void removeCodeLabels(InstructionAddress address)
Definition: Scope.cc:451
IllegalRegistration
Definition: Exception.hh:532
TTAProgram::Scope::~Scope
virtual ~Scope()
Definition: Scope.cc:54
ObjectAlreadyExists
Definition: Exception.hh:1002
TTAProgram::Scope::child
const Scope & child(int index) const
Definition: Scope.cc:184
TTAProgram::Scope::addGlobalCodeLabel
virtual void addGlobalCodeLabel(const CodeLabel &codeLabel, const Scope &owner)=0
Adds a code label and its owner to the global label bookkeeping.
TTAProgram::Scope::dataLabel
const DataLabel & dataLabel(const std::string &name) const
Definition: Scope.cc:251
TTAProgram::Scope::containsCodeLabel
bool containsCodeLabel(const std::string &name) const
Definition: Scope.cc:199
ContainerTools::containsValue
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
KeyNotFound
Definition: Exception.hh:285
TTAProgram::Scope::codeLabelCount
int codeLabelCount(Address address) const
Definition: Scope.cc:269
CodeLabel.hh
TTAProgram::Scope::containsDataLabel
bool containsDataLabel(const std::string &name) const
Definition: Scope.cc:215
TTAProgram::Scope::children_
ScopeList children_
Child scopes.
Definition: Scope.hh:85
TTAProgram::Scope::childCount
int childCount() const
Definition: Scope.cc:171
ContainerTools.hh