OpenASIP 2.2
Loading...
Searching...
No Matches
DataSectionCreator.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 DataSectionCreator.hh
26 *
27 * Definition of DataSectionCreator class.
28 *
29 * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30 * @note rating: yellow
31 */
32
33#include <map>
34#include <vector>
35
36#include "DataSectionCreator.hh"
37#include "LabelManager.hh"
39
40#include "MapTools.hh"
41
42#include "Binary.hh"
43#include "Section.hh"
44#include "DataSection.hh"
46#include "MathTools.hh"
47
48using namespace TPEF;
49
50/**
51 * Constructor.
52 *
53 * @param resourceManager Resource manager for TPEF to create.
54 */
57 resources_(resourceManager), currentStartAddress_(0),
58 isStartAddressDefined_(false) {
59}
60
61/**
62 * Destructor.
63 */
67
68/**
69 * Sets fixed address for the next data area definition.
70 *
71 * @param address Start address of next data area definition.
72 */
77
78/**
79 * Adds data line.
80 *
81 * @param origLine Parsed data line to copy to creator.
82 */
83void
85
86 // make copy of original
87 DataLine* line = new DataLine;
88
89 line->dataSpace = origLine.dataSpace;
90 line->width = origLine.width;
91 line->initData = origLine.initData;
92 line->labels = origLine.labels;
93 line->asmLineNumber = origLine.asmLineNumber;
94
95 // find out section where to we add line by
96 // address and address space
97 assert(line != NULL);
98
99 InternalSection* foundSection = NULL;
100 for (int foundIndex = sections_.size() - 1;
101 foundIndex >= 0; foundIndex--) {
102
103 InternalSection& section = sections_[foundIndex];
104
105 // try to find last suitable section for the data line
106 if (section.addressSpace == line->dataSpace) {
107
108 // we always create new section for datalines with fixed address,
109 // otherwise we just check, if last created section is fine for
110 // currently added line
111
112 if (section.isInitialized != line->initData.empty() &&
114
115 // section with same type of data lines was found
116 foundSection = &section;
117 break;
118
119 } else {
120 // section with same type of data lines
121 // was not found -> create new section
122 break;
123 }
124 }
125 }
126
127 // create new section if suitable is not found
128 if (foundSection == NULL) {
129 InternalSection newSection;
130
131 newSection.isInitialized = !line->initData.empty();
134 newSection.addressSpace = line->dataSpace;
135 newSection.length = 0;
136
137 sections_.push_back(newSection);
138
139 // set found section
140 foundSection = &sections_.back();
141
144 }
145
146 assert(foundSection != NULL);
147
148 // add line to section
149 foundSection->lines.push_back(line);
150}
151
152/**
153 * Frees all internally allocated data.
154 */
155void
157
158 for (unsigned int i = 0; i < sections_.size(); i++) {
159 InternalSection &section = sections_[i];
160
161 for (unsigned int j = 0; j < section.lines.size(); j++) {
162 section.lines[j]->initData.clear();
163 section.lines[j]->labels.clear();
164 delete section.lines[j];
165 }
166
167 section.lines.clear();
168 }
169
170 sections_.clear();
171
174}
175
176/**
177 * Writes created sections to given binary.
178 *
179 * All data stored inside creator are freed after this call, unless
180 * exception is thrown.
181 *
182 * In case of exception the creator restores its state to what it was before
183 * calling this method, and this method can be run again.
184 *
185 * @param tpef Binary to which created sections should be added.
186 * @param labels LabelManager where to add data labels and relocations.
187 * @exception CompileError If there is any errors during compiling.
188 */
189void
191 Binary& tpef, LabelManager& labels, bool littleEndian) {
192 // completed tpef data sections.
193 std::vector<TPEF::Section*> completed;
194
195 // find out start addresses of each section and resolve label values
196 std::map<std::string, UValue> addressSpaceUsedMAUs;
197 std::vector<std::string> addedLabels;
198
199 try {
200
202 addressSpaceUsedMAUs, addedLabels, labels);
203
204 // create TPEF sections and add initialization data + relocation
205 // elements
206 for (unsigned int i = 0; i < sections_.size(); i++) {
207 InternalSection &section = sections_[i];
208
209 Section* newSection = NULL;
210
211 // if initialized, generate initialization data
212 if (section.isInitialized) {
213 if (littleEndian) {
215 } else {
217 }
218 } else {
220 }
221
222 // add section to completed sections
223 completed.push_back(newSection);
224
225 newSection->setName(resources_.stringToChunk(""));
226
227 assert(section.fixedStartAddress);
228 newSection->setStartingAddress(section.startAddress);
229
230 ASpaceElement* aSpace = NULL;
231
232 // wrap IllegalMachine to
233 // CompileError exception with linenumber
234 try {
235 aSpace =
237
238 } catch (IllegalMachine& e) {
239 CompileError error(
240 __FILE__, __LINE__, __func__, e.errorMessage());
241
242 error.setCodeFileLineNumber(section.lines[0]->asmLineNumber);
243 error.setCause(e);
244
245 throw error;
246
247 } catch (InvalidData& e) {
248 CompileError error(
249 __FILE__, __LINE__, __func__,
250 "Can't write data to instruction memory.");
251
252 error.setCodeFileLineNumber(section.lines[0]->asmLineNumber);
253 error.setCause(e);
254
255 throw error;
256 }
257
258 assert(aSpace != NULL);
259 newSection->setASpace(aSpace);
260
261 // sets data section length in MAUs
262 RawSection *rawSection = dynamic_cast<RawSection*>(newSection);
263 assert(rawSection != NULL);
264 rawSection->setLengthInMAUs(section.length);
265
266 // aSpace had to be set before writing initialization data of
267 // section
268 if (section.isInitialized) {
269 DataSection *dataSection =
270 dynamic_cast<DataSection*>(newSection);
271
272 UValue currentMAUIndex = 0;
273
274 for (unsigned int j = 0; j < section.lines.size(); j++) {
275 DataLine *line = section.lines[j];
276 currentMAUIndex += writeDataLineToTPEF(
277 line, dataSection, labels, currentMAUIndex);
278 }
279 }
280 }
281
282 } catch (CompileError& e) {
283
284 labels.clearLastRelocations();
285
286 // clean added labels
287 for (unsigned int i = 0; i < addedLabels.size(); i++) {
288 labels.removeLabel(addedLabels[i]);
289 }
290
291 // clean already created stuff and throw error forward
292 for (UValue j = 0; j < completed.size(); j++) {
293 delete completed[j];
294 }
295
296 completed.clear();
297
298 throw e;
299
300 }
301
302 // really add relocations to manager
303 labels.commitLastRelocations();
304
305 // add completed sections to binary
306 for (UValue i = 0; i < completed.size(); i++) {
307 tpef.addSection(completed[i]);
308 }
309
310 cleanup();
311}
312
313/**
314 * Resolves data area definition sizes, addresses and
315 * writes resolved data labels to label manager.
316 *
317 * @param addressSpaceUsedMAUs Table for updating number of MAUs that are
318 * used for each section.
319 * @param addedLabels List of all labels added to label manager for
320 * error cleanup.
321 * @param labels Label bookkeeper.
322 */
323void
325 std::map<std::string, UValue>& addressSpaceUsedMAUs,
326 std::vector<std::string>& addedLabels, LabelManager& labels) {
327 // calculate sizes and addresses for each data section and
328 // add values for labels
329
330 for (unsigned int i = 0; i < sections_.size(); i++) {
331 InternalSection &section = sections_[i];
332 UValue spaceLastAddress;
333
335 addressSpaceUsedMAUs, section.addressSpace)) {
336
337 addressSpaceUsedMAUs[section.addressSpace] = 0;
338 }
339
340 // last used address of address space of current section
341 spaceLastAddress = addressSpaceUsedMAUs[section.addressSpace];
342
343 // check if we have to look, if current address is ok or
344 // we set the address
345 if (section.fixedStartAddress) {
346 if (spaceLastAddress > section.startAddress) {
347
348 CompileError error(
349 __FILE__, __LINE__, __func__,
350 "Can't start data section from address: " +
352 " first unused address in address space: " +
353 section.addressSpace +
354 " is: " + Conversion::toString(spaceLastAddress));
355
356 error.setCodeFileLineNumber(section.lines[0]->asmLineNumber);
357
358 throw error;
359 }
360 } else {
361 section.startAddress = spaceLastAddress;
362 }
363
364 section.fixedStartAddress = true;
365
366 // add also labels to label map
367 UValue dataLineAddress = section.startAddress;
368
369 for (unsigned int j = 0; j < section.lines.size(); j++) {
370 DataLine *currentLine = section.lines[j];
371
372 // wrap IllegalMachine and ObjectAlreadyExists exceptions
373 // to CompileError exception with linenumber
374 try {
375
376 for (unsigned int k = 0;
377 k < currentLine->labels.size(); k++) {
378
379 labels.addLabel(
381 section.addressSpace),
382 currentLine->labels[k], dataLineAddress);
383
384 // for cleanup
385 addedLabels.push_back(currentLine->labels[k]);
386 }
387
388 dataLineAddress += currentLine->width;
389
390 } catch (InvalidData& e) {
391 CompileError error(
392 __FILE__, __LINE__, __func__,
393 "Can't write data to instruction memory.");
394
395 error.setCodeFileLineNumber(currentLine->asmLineNumber);
396 error.setCause(e);
397
398 throw error;
399
400 } catch (Exception& e) {
401
402 CompileError error(
403 __FILE__, __LINE__, __func__, e.errorMessage());
404
405 error.setCodeFileLineNumber(currentLine->asmLineNumber);
406 error.setCause(e);
407
408 throw error;
409 }
410 }
411
412 section.length = dataLineAddress - section.startAddress;
413 addressSpaceUsedMAUs[section.addressSpace] = dataLineAddress;
414#if 0
415 // some useful dedug info about created data sections and mapping
416 std::cerr << "Section length: " << section.length
417 << "\tSection start: " << section.startAddress
418 << std::endl;
419#endif
420 // NOTE: here we can check if we can merge two sections together.
421 // If both are initialized or uninitialized and second
422 // section's start address is same that first section
423 // start address + first section size then merging can
424 // be done.
425 }
426}
427
428/**
429 * Write one data line definition to TPEF data section.
430 *
431 * @param line Data line to write.
432 * @param dataSection Section where to write data.
433 * @param label Label manager to resolve label values.
434 * @param currentMAUIndex MAU index to start of data line in TPEF.
435 * @return MAU count that were written to TPEF.
436 * @exception CompileError the data line contains errors.
437 */
438UValue
440 DataLine* line, DataSection* dataSection, LabelManager& labels,
441 UValue currentMAUIndex) {
442 UValue writtenMAUs = 0;
443
444 // read maus from init data until inited data of line ends
445 for (unsigned int k = 0; k < line->initData.size(); k++) {
446 InitDataField &data = line->initData[k];
447
448 UValue value = 0;
449 bool isSigned = false;
450
451 // if expression resolve value
452 if(data.litOrExpr.isExpression) {
453 value = labels.resolveExpressionValue(
454 line->asmLineNumber, data.litOrExpr);
455 } else {
456 value = data.litOrExpr.value;
457 isSigned = data.litOrExpr.isSigned;
458 }
459
460 UValue usedMAUs =
461 sizeInWords(value, dataSection->aSpace()->MAU(), isSigned);
462
463 // if data width is explicitely set use that width
464 if (data.width != 0) {
465 if (usedMAUs > data.width) {
466
467 CompileError error(
468 __FILE__, __LINE__, __func__,
469 "Init field contains too long value. Reserved MAUs: " +
471 " Needed MAUs: " +
472 Conversion::toString(usedMAUs));
473
475
476 throw error;
477 }
478
479 usedMAUs = data.width;
480 }
481
482 // check if data line width is enough for writing next value
483 if (writtenMAUs + usedMAUs > line->width) {
484
485 CompileError error(
486 __FILE__, __LINE__, __func__,
487 "Data line contains too much init data. Reserved MAUs: " +
489 " Already inited MAUs: " +
490 Conversion::toString(writtenMAUs));
491
493
494 throw error;
495 }
496
497 // select extending for writing data to data section
498 if (isSigned) {
499 dataSection->writeValue(
500 currentMAUIndex + writtenMAUs,
501 usedMAUs, static_cast<SValue>(value));
502
503 } else {
504 dataSection->writeValue(
505 currentMAUIndex + writtenMAUs, usedMAUs, value);
506 }
507
508 // if expression then add relocation.
509 if(data.litOrExpr.isExpression) {
510 Chunk *srcChunk =
511 dataSection->chunk(
512 dataSection->MAUsToBytes(
513 currentMAUIndex + writtenMAUs));
514
515 labels.addRelocation(
516 *dataSection, *srcChunk,
518 value, usedMAUs * dataSection->aSpace()->MAU());
519 }
520
521 writtenMAUs += usedMAUs;
522 }
523
524 if (writtenMAUs < line->width) {
525 dataSection->writeValue(currentMAUIndex+writtenMAUs, 1,
526 static_cast<unsigned long>(0));
527 writtenMAUs++;
528 }
529
530 // increase index to data section
531 return line->width;
532}
533
534/**
535 * Compute the minimum number of words of given bit width that are necessary
536 * to encode an integer value.
537 *
538 * @param value Integer value to encode.
539 * @param width Bit width of the words.
540 * @param isSigned Tells whether the value had a sign ('+'/'-') in front of
541 * it.
542 */
543int
544DataSectionCreator::sizeInWords(UValue value, int width, bool isSigned)
545 const {
546
547 // maximum word width allowed: 32 bits
548 assert(static_cast<unsigned int>(width) <= sizeof(value) * BYTE_BITWIDTH);
549
550 int neededBits = 0;
551
552 if (isSigned) {
553 neededBits = MathTools::requiredBitsSigned(SLongWord(value));
554 } else {
555 neededBits = MathTools::requiredBits(value);
556 }
557
558 int wordCount = static_cast<int>(
559 ceil(static_cast<double>(neededBits) /
560 static_cast<double>(width)));
561
562 return wordCount;
563}
564
#define __func__
#define assert(condition)
long SLongWord
Definition BaseType.hh:52
const Byte BYTE_BITWIDTH
Definition BaseType.hh:136
find Finds info of the inner loops in the false
unsigned long UValue
long SValue
void setCodeFileLineNumber(int lineNum)
static std::string toString(const T &source)
UValue width
Number of MAUs initialized by this data line.
std::vector< InitDataField > initData
Init data fields of data line. Uninitilized data line, if empty.
std::vector< std::string > labels
Labels of this data line.
std::string dataSpace
Address space whose MAUs are initialized.
UValue asmLineNumber
Line number where in source code this DA line is found.
void resolveDataAreaSizesAndLabelAddresses(std::map< std::string, UValue > &addressSpaceUsedMAUs, std::vector< std::string > &addedLabels, LabelManager &labels)
void addDataLine(const DataLine &origLine)
UValue writeDataLineToTPEF(DataLine *line, TPEF::DataSection *dataSection, LabelManager &labels, UValue currentMAUIndex)
void finalize(TPEF::Binary &tpef, LabelManager &labels, bool littleEndian)
DataSectionCreator(MachineResourceManager &resourceManager, AssemblyParserDiagnostic *parent)
void setAreaStartAddress(UValue address)
UValue currentStartAddress_
Start address of next line (if fixed address).
MachineResourceManager & resources_
TPEF Resources and strings.
bool isStartAddressDefined_
Is next data line address fixed.
std::vector< InternalSection > sections_
Internal data sections.
int sizeInWords(UValue value, int MAUWidth, bool isSigned) const
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
std::string label
Name of the label.
LiteralOrExpression litOrExpr
Initialisation value.
UValue width
Number of MAUs that are initialized by the init field.
void removeLabel(std::string &name)
void clearLastRelocations()
UValue resolveExpressionValue(UValue asmLineNumber, LiteralOrExpression &litOrExpr)
void commitLastRelocations()
TPEF::ASpaceElement & aSpaceElement(std::string &labelName)
void addRelocation(TPEF::Section &locationSect, TPEF::SectionElement &location, TPEF::ASpaceElement &dstASpace, UValue destination, UValue bitWidth)
void addLabel(TPEF::ASpaceElement &aSpace, std::string &name, UValue value)
bool isExpression
Does object contain expression or literal.
UValue value
If literal, the literal. Otherwise not used.
bool isSigned
Sign of the value.
Expression expression
If expression the expression, Otherwise not used.
TPEF::ASpaceElement * findDataAddressSpace(std::string name)
TPEF::Chunk * stringToChunk(const std::string aStr)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static int requiredBits(unsigned long int number)
static int requiredBitsSigned(SLongWord number)
Byte MAU() const
void addSection(Section *section)
virtual void writeValue(Word index, Word numOfMAUs, unsigned long value)
virtual void setLengthInMAUs(Word length)
Definition Section.cc:265
virtual Chunk * chunk(SectionOffset offset) const
Definition Section.cc:212
virtual Word MAUsToBytes(Word mauCount) const
Definition Section.cc:320
static Section * createSection(SectionType type)
Definition Section.cc:91
@ ST_DATA
Initialized data section.
Definition Section.hh:80
@ ST_UDATA
Uninitialized data section.
Definition Section.hh:81
@ ST_LEDATA
Initialized little endian data section.
Definition Section.hh:82
void setStartingAddress(AddressImage address)
void setASpace(const ReferenceManager::SafePointer *addrSpace)
void setName(const ReferenceManager::SafePointer *sectionName)
ASpaceElement * aSpace() const
UValue length
Number of MAUs stored in section.
UValue startAddress
The start address of the section.
std::vector< DataLine * > lines
Initialization data of the section. (or uninitialization data;)
bool isInitialized
If section contains initialization data.
bool fixedStartAddress
Is start address of the section fixed.
std::string addressSpace
Address space of the section.