OpenASIP 2.2
Loading...
Searching...
No Matches
LLVMTCEBuilder.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2020 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 LLVMTCEBuilder.cc
26 *
27 * Implementation of LLVMTCEBuilder class.
28 *
29 * @author Veli-Pekka Jääskeläinen 2007-2009 (vjaaskel-no.spam-cs.tut.fi)
30 * @author Mikael Lepistö 2009 (mikael.lepisto-no.spam-tut.fi)
31 * @author Esa Määttä 2009 (esa.maatta-no.spam-tut.fi)
32 * @author Pekka Jääskeläinen 2007-2020
33 * @author Henry Linjamäki 2016-2017 (henry.linjamaki-no.spam-tut.fi)
34 * @note reting: red
35 */
36#ifdef NDEBUG
37#undef NDEBUG
38#endif
39
40#include <list>
41#include <fstream>
42#include <sstream>
43
44#include <boost/format.hpp>
45
46#include "CompilerWarnings.hh"
47
48IGNORE_COMPILER_WARNING("-Wunused-parameter")
49
50#include "LLVMTCEBuilder.hh"
51#include "Program.hh"
52#include "BasicBlock.hh"
53#include "Machine.hh"
54#include "Procedure.hh"
55#include "Instruction.hh"
56#include "NullInstruction.hh"
57#include "DataDefinition.hh"
58#include "DataAddressDef.hh"
61#include "Move.hh"
62#include "MoveGuard.hh"
63#include "Guard.hh"
64#include "Terminal.hh"
67#include "TerminalAddress.hh"
68#include "TerminalRegister.hh"
69#include "TerminalImmediate.hh"
70#include "TerminalFUPort.hh"
72#include "ControlUnit.hh"
74#include "UniversalMachine.hh"
76#include "ExecutionPipeline.hh"
77#include "POMDisassembler.hh"
78#include "DataMemory.hh"
79#include "CodeLabel.hh"
80#include "DataLabel.hh"
81#include "LLVMTCEBuilder.hh"
82#include "Operand.hh"
83#include "CodeGenerator.hh"
84#include "ProgramAnnotation.hh"
85#include "TCEString.hh"
86#include "ProgramOperation.hh"
88#include "GlobalScope.hh"
90#include "HWOperation.hh"
91#include "AssocTools.hh"
93#include "Conversion.hh"
95#include "InstructionElement.hh"
96#include "MachineInfo.hh"
97#include "LiveRangeData.hh"
98#include "LLVMUtilities.hh"
99
100#include <llvm/IR/Constants.h>
101#include <llvm/IR/DerivedTypes.h>
102#include <llvm/IR/Module.h>
103#include "llvm/IR/InlineAsm.h"
104#include <llvm/CodeGen/MachineInstr.h>
105#include <llvm/CodeGen/MachineMemOperand.h>
106#include <llvm/CodeGen/MachineConstantPool.h>
107#include <llvm/CodeGen/TargetInstrInfo.h>
108#include <llvm/CodeGen/TargetLowering.h>
109#include <llvm/Target/TargetMachine.h>
110#include <llvm/Support/Debug.h>
111#include <llvm/Support/raw_ostream.h>
112
113#include <llvm/IR/DebugInfo.h>
114
115#include <llvm/MC/MCContext.h>
116#include <llvm/MC/MCSymbol.h>
117
118#include "MapTools.hh"
119#include "StringTools.hh"
120#include "Operation.hh"
121#include "OperationPool.hh"
122#include "MoveNode.hh"
123
124#include "TCETargetMachine.hh"
125
126#include "tce_config.h"
127
128#include "llvm/IR/DataLayout.h"
129
130#define TYPE_CONST
131#include <llvm/MC/MCInstrDesc.h>
132
133#include <llvm/ADT/SmallString.h>
134
135#define END_SYMBOL_NAME "_end"
136
137//#define DISASSEMBLE_LLVM_OUTPUT
139
140using namespace TTAMachine;
141using namespace llvm;
143
144unsigned LLVMTCEBuilder::MAU_BITS = 8;
145//pointer size in bytes
146unsigned LLVMTCEBuilder::POINTER_SIZE_32 = 4; // Pointer size in maus.
147unsigned LLVMTCEBuilder::POINTER_SIZE_64 = 8; // Pointer size in maus.
148
149char LLVMTCEBuilder::ID = 0;
150
151//#define DEBUG_LLVMTCEBUILDER
152//#define WARN_AS_FU_NOT_FOUND
153
155 const TargetMachine& tm,
157 char& ID,
158 bool functionAtATime) :
159 MachineFunctionPass(ID) {
160 initMembers();
161 tm_ = &tm;
162 mach_ = mach;
163 functionAtATime_ = functionAtATime;
164 dl_ = new DataLayout(tm_->createDataLayout());
165}
166
167LLVMTCEBuilder::LLVMTCEBuilder(char& ID) : MachineFunctionPass(ID) {
168 initMembers();
169}
170
171void
173 mod_ = NULL;
174 tm_ = NULL;
175 prog_ = NULL;
176 mach_ = NULL;
177 mang_ = NULL;
178 noAliasFound_ = false;
179 multiAddrSpacesFound_ = false;
180 multiDataMemMachine_ = false;
181 spillMoveCount_ = 0;
182 dataInitialized_ = false;
184
185 if (Application::cmdLineOptions() != NULL) {
186 options_ =
187 dynamic_cast<LLVMTCECmdLineOptions*>(
189 }
190}
191
192
193/**
194 * The Destructor.
195 */
197 if (mang_ != NULL) {
198 delete mang_;
199 mang_ = NULL;
200 }
201}
202
203/**
204 * Initializes the data sections of the POM.
205 *
206 * Can be called multiple times. Doesn't do anything after the first
207 * successful call.
208 */
209void
211
212 if (dataInitialized_)
213 return;
214
215 dataInitialized_ = true;
216
217 assert(mach_ != NULL);
218 assert(tm_ != NULL);
219 assert(mod_ != NULL);
220
221 if (prog_ != NULL) {
222 delete prog_;
223 prog_ = NULL;
224 }
225
226 // List of supported operations.
227 opset_.insert("jump");
228 opset_.insert("call");
231
232 for (int i = 0;i < fuNav.count(); i++) {
233 const FunctionUnit& fu = *fuNav.item(i);
234 for (int o = 0; o < fu.operationCount(); o++) {
236 }
237 }
238
239 const auto& cu = *mach_->controlUnit();
240 for (int o = 0; o < cu.operationCount(); o++) {
241 opset_.insert(StringTools::stringToLower(cu.operation(o)->name()));
242 }
243
244 // Set GCU address space as the instruction address space.
245 if (mach_->controlUnit() == NULL) {
246 std::cerr << "ERROR: No control unit in the target machine!"
247 << std::endl;
248
249 assert(false);
250 }
251
253 if (instrAddressSpace_ == NULL) {
254 std::cerr << "ERROR: Address space set for the control unit in the "
255 << "target machine."
256 << std::endl;
257
258 assert(false);
259 }
260
261 // FIXME: data address space
264
265 multiDataMemMachine_ = nav.count() > 2;
267
268 for (int i = 0; i < nav.count(); i++) {
269 if (nav.item(i) != instrAddressSpace_) {
270 if (!multiDataMemMachine_ || nav.item(i)->hasNumericalId(0)) {
272 break;
273 }
274 }
275 }
276
277 if (defaultDataAddressSpace_ == NULL) {
278 std::cerr << "ERROR: Unable to determine the default data address space."
279 << std::endl;
280 abort();
281 } else {
284 << "using '" << defaultDataAddressSpace_->name()
285 << "' as the default data address space"
286 << std::endl;
287 }
288 }
289
291 mang_ = new Mangler();
292
293 const TCETargetMachine* tm = dynamic_cast<const TCETargetMachine*>(tm_);
294 assert(tm != NULL);
295
297
298 // Global variables.
299 for (Module::const_global_iterator i = mod_->global_begin();
300 i != mod_->global_end(); i++) {
301
302 SmallString<256> Buffer;
303 mang_->getNameWithPrefix(Buffer, &(*i), false);
304 TCEString name(Buffer.c_str());
305
306 const llvm::GlobalObject& gv = *i;
307 MaybeAlign gvAlign = gv.getAlign();
308
309 if (gv.hasSection() &&
310 gv.getSection() == std::string("llvm.metadata")) {
311 // do not write debug constants to the data section
312 continue;
313 }
314
315 if (name == END_SYMBOL_NAME) {
316 // Skip original _end symbol.
317 continue;
318 }
319
320 if (name == "__dso_handle") {
321 // Should not be needed without dynamic library support.
322 continue;
323 }
324
325 if (!i->hasInitializer()) {
326 std::cerr << "Initializer missing for: " << name << std::endl;
327 assert(false && "No initializer. External linkage?");
328 }
329
330 const Constant* initializer = i->getInitializer();
331 TYPE_CONST Type* type = initializer->getType();
332
333 DataDef def;
334 def.name = name;
335 def.address = 0;
336 def.addressSpaceId =
337 cast<PointerType>(gv.getType())->getAddressSpace();
338 #ifdef LLVM_OLDER_THAN_16
339 def.alignment = std::max(gvAlign.hasValue()? gvAlign->value():0, (long unsigned int)(dl_->getPrefTypeAlignment(type)));
340 #else
341 def.alignment = std::max(gvAlign.has_value()? gvAlign->value():0, (long unsigned int)(dl_->getPrefTypeAlignment(type)));
342 #endif
343 def.size = dl_->getTypeStoreSize(type);
344 // memcpy seems to assume global values are aligned by 4
345 if (def.size > def.alignment) {
346 def.alignment = std::max(def.alignment, tm->stackAlignment());
347 }
348
349 assert(def.alignment != 0);
350
351 if (isInitialized(initializer)) {
352 def.initialize = true;
353 data_.push_back(def);
354 } else {
355 def.initialize = false;
356 udata_.push_back(def);
357 }
358 }
359
360 // Map initialized data to memory.
361 for (unsigned i = 0; i < data_.size(); i++) {
362
363 TTAMachine::AddressSpace& aSpace =
365
366 unsigned& dataEndPos = dataEnd(aSpace);
368
369 // padding
370 unsigned pad = 0;
371 while ((dataEndPos + pad) % data_[i].alignment != 0) pad++;
372 if (pad > 0) {
373 TTAProgram::Address address(dataEndPos, aSpace);
376 address, pad, mach_->isLittleEndian(), NULL, true));
377 dataEndPos += pad;
378 }
379
380 dataLabels_[data_[i].name] = dataEndPos;
381 data_[i].address = dataEndPos;
382
383 // Add data label.
384 TTAProgram::Address addr(dataEndPos, aSpace);
385 TTAProgram::DataLabel* label =
386 new TTAProgram::DataLabel(data_[i].name, addr, gscope);
387
388 gscope.addDataLabel(label);
389
390 dataEndPos += data_[i].size;
391 }
392
393 // Map uninitialized data to memory.
394 for (unsigned i = 0; i < udata_.size(); i++) {
395
396 TTAMachine::AddressSpace& aSpace =
398
399 unsigned& dataEndPos = dataEnd(aSpace);
401
402 // padding
403 unsigned pad = 0;
404 while ((dataEndPos + pad) % udata_[i].alignment != 0) pad++;
405 if (pad > 0) {
406 TTAProgram::Address address(dataEndPos, aSpace);
409 address, pad, mach_->isLittleEndian()));
410
411 dataEndPos += pad;
412 }
413
414 udata_[i].address = dataEndPos;
415 dataLabels_[udata_[i].name] = dataEndPos;
416
417 // Add data label.
418 TTAProgram::Address addr(dataEndPos, aSpace);
419 TTAProgram::DataLabel* label =
420 new TTAProgram::DataLabel(udata_[i].name, addr, gscope);
421
422 gscope.addDataLabel(label);
423 dataEndPos += udata_[i].size;
424 }
425}
426
427/**
428 * Initializer creates a new POM and adds all global data initializations.
429 *
430 * @param m Module to initialize the writer for.
431 */
432bool
434 mod_ = &m;
435 dataInitialized_ = false;
436 return false;
437}
438
439/**
440 * Creates data definition from a Constant initializer and adds it to the
441 * machine data memory.
442 *
443 * @param addr Address where the data is to be defined in the data memory.
444 * @param cv Constant initializer for the data.
445 */
446void
448
449 TTAMachine::AddressSpace& aSpace =
452
453 if (!def.initialize) {
454
455 if (def.address % def.alignment != 0) {
456 std::cerr << def.name << " misaligned!" << std::endl;
457 std::cerr << " address: " << def.address
458 << " alignment: " << def.alignment << std::endl;
459
460 assert(false);
461 }
462
463 TTAProgram::Address addr(def.address, aSpace);
466 addr, def.size, mach_->isLittleEndian()));
467
468 return;
469 } else {
470
471 const GlobalVariable* var = NULL;
472 for (Module::const_global_iterator i = mod_->global_begin();
473 i != mod_->global_end(); i++) {
474
475 SmallString<256> Buffer;
476 mang_->getNameWithPrefix(Buffer, &(*i), false);
477 if (def.name == Buffer.c_str()) {
478 var = &(*i);
479 break;
480 }
481 }
482
483 unsigned addr = def.address;
484
485 assert(var != NULL && "Variable not found!");
486
487#ifndef NDEBUG
488 unsigned paddedAddr =
489#endif
490 createDataDefinition(def.addressSpaceId, addr, var->getInitializer());
491 assert(paddedAddr == def.address);
492 }
493}
494
495/**
496 * Creates data definition from a Constant pool entry definition.
497 *
498 * @param addr Address where the data is to be defined in the data memory.
499 * @param cv Constant initializer for the data.
500 */
501void
503
504#ifndef NDEBUG
505 unsigned address = def.address;
506#endif
507 createDataDefinition(0, address, def.value);
508 assert(address == def.address + def.size);
509}
510
511/**
512 * Creates POM data definition from a llvm data initializer.
513 *
514 * @param addr Address for the POM data.
515 * @param cv Initializer for the data in llvm.
516 * @param forceInitialize In case wanting to use initialization data even
517 * for null values.
518 * @param forceAlignment Use the given alignment for the constant instead of
519 * the alignment defined in DataLayout.
520 * @return POM data address after padding data to correct alignment.
521 */
522unsigned
524 int addressSpaceId, unsigned& addr, const Constant* cv,
525 bool forceInitialize, unsigned forceAlignment) {
526
527 unsigned sz = dl_->getTypeStoreSize(cv->getType());
528 llvm::Align align = (forceAlignment == 0)?
529 dl_->getABITypeAlign(cv->getType()):llvm::Align(forceAlignment);
530
531 // KLUDGE FIX: Currently, for little-endian machines, OSAL base simd
532 // module has only vector load and store operations that require full
533 // vector width alignment.
534 // Remove this when accesses can be done at ABI alignment.
535 if (mach_->isLittleEndian() && cv->getType()->isVectorTy()) {
536 align = (forceAlignment == 0)?llvm::Align(sz):llvm::Align(forceAlignment);
537 }
538
539 TTAMachine::AddressSpace& aSpace =
542
543 padToAlignment(addressSpaceId, addr, align.value());
544
545 // paddedAddr is the actual address data was put to
546 // after alignment.
547 unsigned paddedAddr = addr;
548
549 // Initialize with zeros if this is an uninitialized part of a partially
550 // initialized data structure.
551 if (!forceInitialize &&
552 (cv->isNullValue() || dyn_cast<UndefValue>(cv) != NULL)) {
553 TTAProgram::Address address(addr, aSpace);
556 address, sz, mach_->isLittleEndian(), NULL, true));
557 addr += sz;
558 return paddedAddr;
559 }
560
561 if (isa<ConstantArray>(cv) ||
562 isa<ConstantStruct>(cv) ||
563 isa<ConstantVector>(cv)) {
564
565 for (unsigned i = 0, e = cv->getNumOperands(); i != e; ++i) {
567 addressSpaceId, addr, cast<Constant>(cv->getOperand(i)));
568 }
569 } else if (const ConstantInt* ci = dyn_cast<ConstantInt>(cv)) {
571 } else if (const ConstantFP* cfp = dyn_cast<ConstantFP>(cv)) {
573 } else if (const GlobalValue* gv = dyn_cast<GlobalValue>(cv)) {
575 } else if (const ConstantExpr* ce = dyn_cast<ConstantExpr>(cv)) {
577 } else if (const ConstantDataArray* cda = dyn_cast<ConstantDataArray>(cv)){
578 if (cda->isNullValue()) {
579 TTAProgram::Address address(addr, aSpace);
580 dmem.addDataDefinition(
582 address, sz, mach_->isLittleEndian(), NULL, false) );
583 } else {
584 /* If the array has non-zero values, do not split the
585 definitions to initialized and uninitialized data sections, but
586 initialize them all. Otherwise we might end up having zillions
587 of UData and Data sections after each other in the TPEF for the
588 initialization data, because the sections have only one start
589 address. It soon exceeds the maximum number of
590 sections in case of large initialized arrays with some of the
591 values being zeros. */
592 bool allZeros = true;
593 for (unsigned i = 0, e = cda->getNumElements(); i != e; ++i) {
594 llvm::Constant *ace =
595 cast<Constant>(cda->getElementAsConstant(i));
596 if (ace->isNullValue() || isa<UndefValue>(ace))
597 continue;
598 allZeros = false;
599 break;
600 }
601
602 for (unsigned int i = 0; i < cda->getNumElements(); i++) {
604 addressSpaceId, addr, cda->getElementAsConstant(i),
605 !allZeros);
606 }
607 }
608 } else if (const ConstantDataSequential* cds =
609 dyn_cast<ConstantDataSequential>(cv)) {
610 // Force other alignment for vector types. If the element type is less
611 // than i32, it gets promoted based on DataLayout's ABI or Preferred
612 // alignment of integer type.
613 unsigned alignmentOverride = 0;
614 if (cv->getType()->isVectorTy()) {
615 alignmentOverride = sz/cds->getNumElements();
616 }
617 for (unsigned int i = 0; i < cds->getNumElements(); i++) {
619 addressSpaceId, addr, cds->getElementAsConstant(i),
620 forceInitialize, alignmentOverride);
621 }
622 } else {
623 // LLVM does not include dump() when built in non-debug mode.
624 // cv->dump();
625 abortWithError("Unknown cv type.");
626 }
627 return paddedAddr;
628}
629
630
631/**
632 * Creates data definition of a constant integer value.
633 *
634 * @param addr Address where the integer is to be defined.
635 * @param ci Constant initializer for the integer value.
636 */
637void
639 int addressSpaceId, unsigned& addr, const ConstantInt* ci,
640 bool isPointer) {
641
642 assert(addr % (dl_->getABITypeAlign(ci->getType()).value()) == 0 &&
643 "Invalid alignment for constant int!");
644
645 std::vector<MinimumAddressableUnit> maus;
646
647 unsigned sz = ((ci->getBitWidth() + MAU_BITS-1) / MAU_BITS);
648
649 if (isPointer) {
651 }
652
653 if (!(sz == 1 || sz == 2 || sz == 4 || sz == 8)) {
654
655// std::cerr << "## int with size " << sz << "!" << std::endl;
656 }
657
658 TTAMachine::AddressSpace& aSpace =
661
662 TTAProgram::Address start(addr, aSpace);
663
664 // FIXME: Assuming 8bit MAU.
665 union {
666 int64_t d;
667 char bytes[8];
668 } u;
669
670 u.d = ci->getZExtValue();
671
673
674 if (!mach_->isLittleEndian()) {
675 for (unsigned i = 0; i < sz; i++) {
676 maus.push_back(u.bytes[sz - i - 1]);
677 }
678 } else {
679 for (unsigned i = 0; i < sz; i++) {
680 maus.push_back(u.bytes[i]);
681 }
682 }
683
684 def = new TTAProgram::DataDefinition(start, maus, mach_->isLittleEndian());
685 addr += def->size();
686 dmem.addDataDefinition(def);
687}
688
689
690/**
691 * Creates data definition of a floating point constant.
692 */
693void
695 int addressSpaceId, unsigned& addr, const ConstantFP* cfp) {
696
697 assert(addr % (dl_->getABITypeAlign(cfp->getType()).value()) == 0
698 && "Invalid alignment for constant fp!");
699
700 TTAMachine::AddressSpace& aSpace =
703
704 TTAProgram::Address start(addr, aSpace);
705 std::vector<MinimumAddressableUnit> maus;
706
707 TYPE_CONST Type* type = cfp->getType();
708 unsigned sz = dl_->getTypeStoreSize(type);
709
710 TTAProgram::DataDefinition* def = NULL;
711
712 if (type->getTypeID() == Type::DoubleTyID) {
713
714 double val = cfp->getValueAPF().convertToDouble();
715 assert(sz == 8);
716 union {
717 double d;
718 char bytes[8];
719 } u;
720
721 u.d = val;
722 if (!mach_->isLittleEndian()) {
723 for (unsigned i = 0; i < sz; i++) {
724 maus.push_back(u.bytes[sz - i - 1]);
725 }
726 } else {
727 for (unsigned i = 0; i < sz; i++) {
728 maus.push_back(u.bytes[i]);
729 }
730 }
732 start, maus, mach_->isLittleEndian());
733 } else if (type->getTypeID() == Type::FloatTyID) {
734
735 float val = cfp->getValueAPF().convertToFloat();
736 assert(sz == 4);
737 union {
738 float f;
739 char bytes[4];
740 } u;
741
742 u.f = val;
743 if (!mach_->isLittleEndian()) {
744 for (unsigned i = 0; i < sz; i++) {
745 maus.push_back(u.bytes[sz - i - 1]);
746 }
747 } else {
748 for (unsigned i = 0; i < sz; i++) {
749 maus.push_back(u.bytes[i]);
750 }
751 }
753 start, maus, mach_->isLittleEndian());
754 } else if (type->getTypeID() == Type::HalfTyID) {
755 APInt bits = cfp->getValueAPF().bitcastToAPInt();
756 uint64_t bigval = bits.getLimitedValue(0xFFFF);
757 assert(sz == 2);
758 union {
759 short h;
760 char bytes[2];
761 } u;
762 u.h = bigval;
763 if (!mach_->isLittleEndian()) {
764 for (unsigned i = 0; i < sz; i++) {
765 maus.push_back(u.bytes[sz - i - 1]);
766 }
767 } else {
768 for (unsigned i = 0; i < sz; i++) {
769 maus.push_back(u.bytes[i]);
770 }
771 }
773 start, maus, mach_->isLittleEndian());
774 } else {
775 assert(false && "Unknown floating point typeID!");
776 }
777 addr += def->size();
778 dmem.addDataDefinition(def);
779}
780
781
782/**
783 * Creates data definition for a global value reference.
784 *
785 * @param addr Address where the reference is to be defined.
786 * @param gv Global value reference.
787 */
788void
790 int addressSpaceId, unsigned& addr, const GlobalValue* gv, int offset) {
791
792 TYPE_CONST PointerType* type = gv->getType();
793
794 unsigned sz = dl_->getTypeStoreSize(type);
795
796 SmallString<256> Buffer;
797 mang_->getNameWithPrefix(Buffer, gv, false);
798 TCEString label(Buffer.c_str());
799
800 TTAMachine::AddressSpace& aSpace =
803
804 TTAProgram::Address start(addr, aSpace);
805
806 TTAProgram::DataDefinition* def = NULL;
807 if (codeLabels_.find(label) != codeLabels_.end()) {
808 assert(
809 offset == 0 &&
810 "Instruction reference with an offset not supported yet.");
811
812 TTAProgram::Instruction* instr = codeLabels_[label];
815
817 start, sz, ref, mach_->isLittleEndian());
818 } else if (dataLabels_.find(label) != dataLabels_.end()) {
819 unsigned gvAS = type->getAddressSpace();
821 TTAProgram::Address ref((dataLabels_[label] + offset), aSpace);
822
824 start, sz, ref, mach_->isLittleEndian());
825 } else {
826 assert(false && "Global value label not found!");
827 }
828 addr += def->size();
829 dmem.addDataDefinition(def);
830}
831
832/**
833 * Creates POM data definition from a llvm constant expression initializer.
834 *
835 * @param addr Address of the POM data definition.
836 * @param ce Expression to create the data definition for.
837 * @param offset Offset for an address defined by the expression.
838 */
839void
841 int addressSpaceId, unsigned& addr, const ConstantExpr* ce, int offset) {
842
843 assert(addr % (dl_->getABITypeAlign(ce->getType()).value()) == 0 &&
844 "Invalid alignment for constant expr!");
845
846 unsigned opcode = ce->getOpcode();
847 if (opcode == Instruction::GetElementPtr) {
848 const Constant* ptr = ce->getOperand(0);
849 SmallVector<Value*, 8> idxVec(ce->op_begin() + 1, ce->op_end());
850
851 APInt offsetAI(dl_->getPointerTypeSizeInBits(ce->getType()), 0);
852 bool success = cast<GEPOperator>(ce)->accumulateConstantOffset(
853 *dl_, offsetAI);
854 assert(success); // Fails if GEP is not all-constant.
855 int64_t ptrOffset = offset + offsetAI.getSExtValue();
856
857 if (const GlobalValue* gv = dyn_cast<GlobalValue>(ptr)) {
859 addressSpaceId, addr, gv, ptrOffset);
860 } else if (const ConstantExpr* ce =
861 dyn_cast<ConstantExpr>(ptr)) {
863 addressSpaceId, addr, ce, ptrOffset);
864 } else {
865 assert(false && "Unsuported getElementPtr target!");
866 }
867 } else if (opcode == Instruction::BitCast) {
868 const Constant* ptr = ce->getOperand(0);
869 if (const ConstantExpr* ce = dyn_cast<ConstantExpr>(ptr)) {
871 addressSpaceId, addr, ce, offset);
872 } else if (const GlobalValue* gv = dyn_cast<GlobalValue>(ptr)) {
874 addressSpaceId, addr, gv, offset);
875 } else {
876 assert(offset == 0);
877#ifndef NDEBUG
878 unsigned dataAddr =
880 addressSpaceId, addr, ptr);
881 // Data should have been padded already:
882 assert(dataAddr == addr);
883#else
885#endif
886 }
887 } else if (opcode == Instruction::IntToPtr) {
888 assert(offset == 0);
889 const ConstantInt* ci = dyn_cast<ConstantInt>(ce->getOperand(0));
890 assert(ci != NULL);
892 } else if (opcode == Instruction::PtrToInt) {
893 assert(offset == 0);
894 // Data should have been padded already:
895#ifndef NDEBUG
896 unsigned dataAddr =
897#endif
898 createDataDefinition(addressSpaceId, addr, ce->getOperand(0));
899 assert(dataAddr == addr);
900 } else if (opcode == Instruction::Add) {
901 assert(false && "NOT IMPLEMENTED");
902 } else if (opcode == Instruction::Sub) {
903 assert(false && "NOT IMPLEMENTED");
904 } else {
905 assert(false && "NOT IMPLEMENTED");
906 }
907}
908
909/**
910 * Pads data memory with zeroes until desired alignment is reached.
911 *
912 * Zero padding is only added when necessary. That is the address is already
913 * aligned.
914 *
915 * @param addressSpaceId The address space id.
916 * @param addr The current address, which is updated to the desired alignment
917 * after the call.
918 * @param align The desired alignment.
919 */
920void
922 int addressSpaceId, unsigned& addr, unsigned align) {
923
926
927 unsigned pad = 0;
928 while ((addr + pad) % align != 0) pad++;
929
930 // Pad with zeros to correct alignment.
931 if (pad > 0) {
932 std::vector<MinimumAddressableUnit> zeros(pad, 0);
933 TTAProgram::Address address(addr, aSpace);
936 address, zeros, mach_->isLittleEndian()));
937
938 addr += pad;
939 }
940}
941
942
943/**
944 * Creates POM procedure of a MachineFunction object and adds it to the
945 * current program.
946 *
947 * @param mf MachineFunction to process.
948 * @return Always false.
949 */
950bool
952 return writeMachineFunction(mf);
953}
954
955/**
956 * Writes machine function to POM.
957 *
958 * Actually does things to MachineFunction which was supposed to be done
959 * in runOnMachineFunction, but which cannot be done during that, because
960 * MachineDCE is not ready yet at that time...
961 */
962bool
964
965 // the new TTA backend does not initialize TCETargetMachine
966 // in construction (at least not yet)
967 if (tm_ == NULL)
968 tm_ = dynamic_cast<const TCETargetMachine*>(&mf.getTarget());
969
970 assert(tm_ != NULL);
971
972 curFrameInfo_ = &mf.getFrameInfo();
973 assert(curFrameInfo_ != NULL);
974
975 // ensure data sections have been initialized
977
978 // omit empty functions..
979 if (mf.begin() == mf.end()) return true;
980
981 // TODO: make list of mf's which for the pass will be ran afterwards..
982
983 SmallString<256> Buffer;
984 mang_->getNameWithPrefix(Buffer, &mf.getFunction(), false);
985 TCEString fnName(Buffer.c_str());
986
987 emitConstantPool(*mf.getConstantPool());
988
991
992 prog_->addProcedure(proc);
993
994 std::set<std::string> emptyMBBs;
995
996 bool firstInsOfProc = true;
997 spillMoveCount_ = 0;
998 // iterate basic blocks from MachineFunction
999 for (MachineFunction::const_iterator i = mf.begin();
1000 i != mf.end(); i++) {
1001
1002 bool newMBB = true;
1003
1004 // iterate MachineInstr from basic blocks
1005 for (MachineBasicBlock::const_iterator j = i->begin();
1006 j != i->end(); j++) {
1007
1008 TTAProgram::Instruction* instr = NULL;
1009#ifdef DEBUG_LLVMTCEBUILDER
1010 std::cerr << "### converting: ";
1011 std::cerr << std::endl;
1012#endif
1013 instr = emitInstruction(&*j, proc);
1014
1015 // Pseudo instructions:
1016 if (instr == NULL) continue;
1017
1020 << "ERROR: The machine contains multiple data address spaces "
1021 << "and ambigious memory accessing moves '"
1022 << instr->toString() << "' were found." << std::endl;
1023 abort();
1024 }
1025
1026 // If there was any empty basic blocks before this instruction,
1027 // set the basic blocks to point the next available (this)
1028 // instruction.
1029 while (!emptyMBBs.empty()) {
1030 mbbs_[*emptyMBBs.begin()] = instr;
1031 emptyMBBs.erase(emptyMBBs.begin());
1032 }
1033
1034 std::string mbb = mbbName(*i);
1035
1036 // Keep book of first instructions in basic blocks.
1037 if (newMBB) {
1038 newMBB = false;
1040 mbbs_[mbb] = instr;
1041 bbIndex_[(*i).getBasicBlock()] = instr;
1042 }
1043
1044 // Keep book of first instructions in functions.
1045 if (firstInsOfProc) {
1047 instructionReferenceManager().createReference(*instr);
1049 new TTAProgram::CodeLabel(ref, fnName));
1050
1051 codeLabels_[fnName] = instr;
1052 firstInsOfProc = false;
1053 }
1054 }
1055
1056 // If the basic block didn't hold any instructions
1057 // (i.e. it probably contained only pseudo instructions),
1058 // add it to the set of empty BBs that will be set to point
1059 // the next instruction in the program.
1060 if (newMBB) {
1061 emptyMBBs.insert(mbbName(*i));
1062 }
1063 }
1064
1065 // if the procedure would otherwise be empty, add a dummy instruction there,
1066 // and make the procedure cdelabel to point it.
1067 if (firstInsOfProc) {
1069 proc->add(dummyIns);
1070
1072 instructionReferenceManager().createReference(*dummyIns);
1074 new TTAProgram::CodeLabel(ref, fnName));
1075
1076 codeLabels_[fnName] = dummyIns;
1077 }
1078 if (Application::verboseLevel() > 0) {
1080 << "spill moves in " <<
1081 (std::string)(mf.getFunction().getName()) << ": "
1082 << spillMoveCount_ << std::endl;
1083 }
1084 return false;
1085}
1086
1087/**
1088 * Finalizes the POM building.
1089 *
1090 * Creates data initializers.
1091 * Fixes dummy code references to point the actual instructions.
1092 */
1093bool
1095
1096 // errs() << "Finalize LLVMPOM builder\n";
1097
1099 unsigned& dataEndPos = dataEnd(aSpace);
1100
1101 // Create new _end symbol at the end of the data memory definitions of
1102 // the default address space. This is used by malloc() to determine the
1103 // beginning of the heap.
1104 DataDef def;
1105 def.name = END_SYMBOL_NAME;
1106 def.address = dataEndPos;
1107 def.addressSpaceId = 0;
1108 def.alignment = 1;
1109 def.size = 1;
1110 def.initialize = false;
1111 emitDataDef(def);
1112 dataLabels_[def.name] = def.address;
1113
1114 // Create data initializers.
1115 for (unsigned i = 0; i < data_.size(); i++) {
1116 emitDataDef(data_[i]);
1117 }
1118 for (unsigned i = 0; i < udata_.size(); i++) {
1119 emitDataDef(udata_[i]);
1120 }
1121 for (auto cpDataDef : cpData_) {
1122 emitDataDef(cpDataDef);
1123 }
1124
1125
1126 TTAProgram::Address endAddr(dataEndPos, aSpace);
1128 END_SYMBOL_NAME, endAddr, prog_->globalScope());
1129
1130 prog_->globalScope().addDataLabel(label);
1131
1132 // Fix references to _end symbol.
1133 unsigned i = 0;
1134 for (; i < endReferences_.size(); i++) {
1135 SimValue endLoc(mach_->is64bit() ? 64 : 32);
1136 endLoc = dataEndPos;
1138 new TTAProgram::TerminalAddress(endLoc, aSpace);
1139
1140 endReferences_[i]->setSource(ea);
1141 }
1142
1143 for (DataMemIndex::const_iterator i = dmemIndex_.begin();
1144 i != dmemIndex_.end(); ++i) {
1145 prog_->addDataMemory((*i).second);
1146 }
1147
1148 // Fix references to basic blocks.
1150 std::string>::iterator mbbRefIter =
1151 mbbReferences_.begin();
1152
1153 for (; mbbRefIter != mbbReferences_.end(); mbbRefIter++) {
1154 TTAProgram::TerminalInstructionAddress* term = mbbRefIter->first;
1155
1156 std::string mbb = mbbRefIter->second;
1157 if (mbbs_.find(mbb) == mbbs_.end()) {
1158 assert(false && "MBB not found from book keeping.");
1159 }
1160 TTAProgram::Instruction& instr = *mbbs_[mbb];
1163 term->setInstructionReference(newRef);
1164 }
1165
1166 // Fix references to code labels.
1168 std::string>::iterator codeRefIter =
1169 codeLabelReferences_.begin();
1170
1171 for (; codeRefIter != codeLabelReferences_.end(); codeRefIter++) {
1172 TTAProgram::TerminalInstructionAddress* term = codeRefIter->first;
1173 std::string label = codeRefIter->second;
1174 if (codeLabels_.find(label) == codeLabels_.end()) {
1175 std::cerr << (boost::format(
1176 "Function '%s' not defined.\n") %
1177 label).str();
1178 exit(EXIT_FAILURE);
1179 }
1180
1181 TTAProgram::Instruction& instr = *codeLabels_[label];
1184
1185 term->setInstructionReference(newRef);
1186 }
1187
1188 // Add stackpointer initialization.
1190
1191#ifdef DISASSEMBLE_LLVM_OUTPUT
1192 std::ofstream outfile("llvm_output.S");
1193 outfile << POMDisassembler::disassemble(*prog_, true);
1194 outfile.close();
1195#endif
1196
1197 return false;
1198}
1199
1200void
1202 // get machine dce analysis
1203 MachineDCE& MDCE = getAnalysis<MachineDCE>();
1204
1205 for (MachineDCE::UnusedFunctionsList::iterator i =
1206 MDCE.removeableFunctions.begin();
1207 i != MDCE.removeableFunctions.end(); i++) {
1208 std::string name = *i;
1209 if (Application::verboseLevel() > 0) {
1211 << "Deleting unused function: " << name << std::endl;
1212 }
1213 TTAProgram::Procedure& notUsedProc = prog_->procedure(name);
1214 // Delete data definitions poining to the deleted procedure.
1215 for (int dmemIdx = 0; dmemIdx < prog_->dataMemoryCount(); dmemIdx++) {
1216 auto& dmem = prog_->dataMemory(dmemIdx);
1217 for (int dataDefIdx = 0; dataDefIdx < dmem.dataDefinitionCount();
1218 dataDefIdx++) {
1219 auto& dataDef = dmem.dataDefinition(dataDefIdx);
1220 if (dataDef.isInstructionAddress()) {
1221 auto instrAddr = dataDef.destinationAddress();
1222 if (instrAddr != notUsedProc.startAddress()) {
1223 continue;
1224 }
1225 if (Application::verboseLevel() > 0) {
1227 << "Deleting data definition pointing to "
1228 << "dead function: " << name << std::endl;
1229 }
1230 dmem.deleteDataDefinition(dataDefIdx);
1231 }
1232 }
1233 }
1234 prog_->removeProcedure(notUsedProc);
1235
1236 delete &notUsedProc;
1237 }
1238}
1239
1240/**
1241 * Sets the value the stack pointer should be initialized to.
1242 */
1243void
1247
1248
1249// std::min(addressSpaceById(0).end() & 0xfffffff8, value);
1250
1251/**
1252 * Checks that the potential memory operations triggered in the
1253 * given unscheduled instruction (with exactly one move) have
1254 * unambiguous address space.
1255 *
1256 * This should be called as a sanity check for instructions in
1257 * a program (and a machine) with multiple address spaces. Returns
1258 * true in case the instruction has at least one move that refers
1259 * to memory without the address space information being unambiguous
1260 * in the currently targeted machine.
1261 */
1262bool
1264 const TTAProgram::Instruction& instr) const {
1265
1266 const TTAProgram::Move& m = instr.move(0);
1267 const TTAProgram::Terminal& t = m.destination();
1268 if (t.isFUPort() && !t.isRA() &&
1270 !m.hasAnnotations(
1272
1273 TCEString opName =
1274 dynamic_cast<const TTAProgram::TerminalFUPort&>(t).
1275 hwOperation()->name();
1276 int numberOfPotentialFUs = 0;
1279 for (int i = 0; i < fuNav.count(); i++) {
1280 const TTAMachine::FunctionUnit& fu = *fuNav.item(i);
1281 if (fu.hasOperation(opName)) numberOfPotentialFUs++;
1282 }
1283
1284 if (numberOfPotentialFUs > 1) {
1285 return true;
1286 }
1287 }
1288 return false;
1289}
1290
1293 const TTAMachine::FunctionUnit* fu = NULL;
1294
1295 if (UniversalMachine::instance().controlUnit()->hasOperation(opName)) {
1297 } else if (UniversalMachine::instance().universalFunctionUnit().
1298 hasOperation(opName)) {
1300 } else {
1302 TCEString("ERROR: Operation '") + opName +
1303 "' not found in the machine.");
1304 }
1305
1306 // Check that the target machine supports this instruction.
1307 if (opset_.find(StringTools::stringToLower(opName)) == opset_.end()) {
1308 std::cerr << "ERROR: Operation '" << opName
1309 << "' is required by the program but not found "
1310 << "in the machine." << std::endl;
1311 abortWithError("Cannot proceed.");
1312 }
1313 return *fu->operation(opName);
1314}
1315
1316/**
1317 * Creates POM instructions from a LLVM MachineInstruction.
1318 *
1319 * One POM instruction per Move are created.
1320 *
1321 * @param mi Machine instruction to emit to the POM.
1322 * @param proc POM procedure to append the instruction to.
1323 * @return First of the POM instructions emitted.
1324 */
1327 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
1328
1329 bool isSpill = false;
1330 bool isRaSlot = false;
1331 bool isFpSlot = false;
1332 const llvm::MCInstrDesc* opDesc = &mi->getDesc();
1333 unsigned opc = mi->getDesc().getOpcode();
1334
1335 // when the -g option turn on, this will come up opc with this, therefore
1336 // add this to ignore however, it is uncertain whether the debug "-g" will
1337 // generate more opc, need to verify
1338 // NOTE there is similar code in ConstantTransformer::runOnMachineFunction
1339 if (opc == TargetOpcode::DBG_VALUE
1340 || opc == TargetOpcode::DBG_LABEL
1341 || opc == TargetOpcode::DBG_INSTR_REF
1342 || opc == TargetOpcode::DBG_VALUE_LIST
1343 || opc == TargetOpcode::DBG_PHI
1344 || opc == TargetOpcode::KILL) {
1345 return NULL;
1346 }
1347
1348 std::string opName = "";
1349
1350 bool hasGuard = false;
1351 bool trueGuard = true;
1352 if (dynamic_cast<const TCETargetMachine*>(&targetMachine()) != NULL) {
1353
1354 if (opDesc->isReturn()) {
1355 // in case of TTA targets, the return node needs to be
1356 // converted to ra -> jump here as it does not map 1:1
1357 // with the DAG names and we map LLVM DAG names to OSAL
1358 // operations
1359 // FIXME: this is the wrong way to do this:
1360 // should LowerReturn to RA -> JUMP.1 instead and process just
1361 // like any other operation here.
1362 return emitReturn(mi, proc);
1363 }
1364 opName = operationName(*mi);
1365
1366 // Pseudo instructions don't require any actual instructions.
1367 if (opName == "PSEUDO" || opName == "DEBUG_LABEL") {
1368 return NULL;
1369 }
1370
1371 // Debug labels don't require any actual instructions.
1372 // TODO: should store the data and apply to next? (or prev?) instr,
1373 // but just ignore it to not cause a crash.
1374 if (opName =="DEBUG_LABEL") {
1375 return nullptr;
1376 }
1377
1378 if (opName[0] == '?') {
1379 hasGuard = true;
1380 opName = opName.substr(1);
1381 }
1382
1383 if (opName[0] == '!') {
1384 hasGuard = true;
1385 trueGuard = false;
1386 opName = opName.substr(1);
1387 }
1388
1389 if (opName == "MOVE") {
1390 return emitMove(mi, proc, hasGuard, trueGuard);
1391 }
1392
1393 // TODO: guarded also for these
1394 if (opName == "INLINEASM") {
1395 return emitOperationMacro(mi, proc);
1396 }
1397
1398 if (opName == "CMOV_SELECT") {
1399 return emitSelect(mi, proc);
1400 }
1401 } else {
1402 opName = operationName(*mi);
1403 }
1404
1405 // split compare + jump combo op.
1406 size_t split = opName.find("+");
1407 if (split != std::string::npos) {
1408 TCEString firstOp = opName.substr(0, split);
1409 TCEString remainingName = opName.substr(split+1);
1410 TTAProgram::Instruction* ins = emitComparisonForBranch(firstOp, mi, proc);
1411 emitRemaingingBrach(remainingName, mi, proc);
1412 return ins;
1413 }
1414
1415 const HWOperation& op = getHWOperation(opName);
1416
1418
1419 OperationPool pool;
1420 const Operation& operation = pool.operation(opName.c_str());
1421
1422 std::vector<TTAProgram::Instruction*> operandMoves;
1423 std::vector<TTAProgram::Instruction*> resultMoves;
1424
1425 int inputOperand = 0;
1426 int outputOperand = operation.numberOfInputs();
1427#ifdef DEBUG_LLVMTCEBUILDER
1428 PRINT_VAR(operation.numberOfInputs());
1429 PRINT_VAR(operation.numberOfOutputs());
1430 Application::logStream() << " mi->getNumOperands() = "
1431 << mi->getNumOperands() << std::endl;
1432#endif
1433 TTAProgram::MoveGuard* guard = NULL;
1434 int guardOperandIndex = -1;
1435
1436 if (hasGuard) {
1437 for (unsigned o = 0; o < mi->getNumOperands(); o++) {
1438 const MachineOperand& mo = mi->getOperand(o);
1439
1440 // Guarded operations have the guarded element as the first
1441 // operand.
1442
1443 if (mo.isReg() && mo.isUse()) {
1444 guardOperandIndex = o;
1445 // Create move from the condition operand register to bool
1446 // register which is used by the guard.
1448 // inv guards not yet supported
1449 guard = createGuard(t, trueGuard);
1450 delete t;
1451 assert(guard != NULL);
1452 break;
1453 }
1454 }
1455 }
1456
1457
1458 for (unsigned o = 0; o < mi->getNumOperands(); o++) {
1459 if ((int)o == guardOperandIndex) {
1460 continue;
1461 }
1462
1463 const MachineOperand& mo = mi->getOperand(o);
1464 TTAProgram::Terminal* src = NULL;
1465 TTAProgram::Terminal* dst = NULL;
1466
1467 if (!mo.isReg() || mo.isUse() || operation.numberOfOutputs() == 0) {
1468 ++inputOperand;
1469 if (inputOperand > operation.numberOfInputs()) {
1470
1471 if (mo.isMetadata()) {
1472 const MDNode* mdNode = mo.getMetadata();
1473 for (unsigned int i = 0; i < mdNode->getNumOperands(); i++) {
1474 const MDOperand & oper = mdNode->getOperand(i);
1475 if (llvm::MDString* mds = dyn_cast<llvm::MDString>(oper)) {
1476 TCEString s = mds->getString().str();
1477 if (s == "AA_CATEGORY_STACK_SLOT") {
1478 isSpill = true;
1479 } else if (s == "AA_CATEGORY_RA_SAVE_SLOT") {
1480 isRaSlot = true;
1481 } else if (s == "AA_CATEGORY_FP_SAVE_SLOT") {
1482 isFpSlot = true;
1483 }
1484 }
1485 }
1486 }
1487 continue;
1488 }
1489
1490 assert(operation.operand(inputOperand).isInput() &&
1491 "Operand mismatch.");
1492
1493 // currently the input operand of the base+offset mem operations
1494 // are not marked as addresses as alias analysis does not work
1495 // in that case correctly, thus we have to treat those operations
1496 // as special cases for the time being
1497 if (operation.operand(inputOperand).isAddress() ||
1498 (operation.isBaseOffsetMemOperation() && inputOperand == 1)) {
1499 // MachineInstructions have two operands for each Operation
1500 // address operand: base and offset immediate, split it to
1501 // two in case of an add+ld/st.
1502 const MachineOperand& base = mo;
1503 src = createTerminal(base);
1504 dst = new TTAProgram::TerminalFUPort(op, inputOperand);
1505 TTAProgram::MoveGuard* guardCopy =
1506 guard == NULL ? NULL : guard->copy();
1507
1508 auto move = createMove(src, dst, bus, guardCopy);
1510 instr->addMove(move);
1511
1512 operandMoves.push_back(instr);
1513
1514 debugDataToAnnotations(mi, *move);
1515 addPointerAnnotations(mi, *move);
1516 o += 1;
1517 const MachineOperand& offset = mi->getOperand(o);
1518 if (operation.isBaseOffsetMemOperation()) {
1519 ++inputOperand;
1520 // the offset is always the 2nd operand for the standard
1521 // base+offset ops
1522 assert(inputOperand == 2);
1523
1524 // create the offset operand move
1525 src = createTerminal(offset);
1526 dst = new TTAProgram::TerminalFUPort(op, inputOperand);
1527 TTAProgram::MoveGuard* guardCopy =
1528 guard == NULL ? NULL : guard->copy();
1529
1530 auto move = createMove(src, dst, bus, guardCopy);
1531 instr = new TTAProgram::Instruction();
1532 instr->addMove(move);
1533 operandMoves.push_back(instr);
1534 debugDataToAnnotations(mi, *move);
1535 } else {
1536 assert(offset.getImm() == 0);
1537 }
1538 } else {
1539 src = createTerminal(mo);
1540 dst = new TTAProgram::TerminalFUPort(op, inputOperand);
1541 TTAProgram::MoveGuard* guardCopy =
1542 guard == NULL ? NULL : guard->copy();
1543
1544 auto move = createMove(src, dst, bus, guardCopy);
1546 instr->addMove(move);
1547#ifdef DEBUG_LLVMTCEBUILDER
1549 << "adding " << move->toString() << std::endl;
1550#endif
1551 operandMoves.push_back(instr);
1552 debugDataToAnnotations(mi, *move);
1553 }
1554 } else {
1555 ++outputOperand;
1556 if (operation.operand(outputOperand).isNull())
1557 continue;
1558
1559 assert(operation.operand(outputOperand).isOutput() &&
1560 !operation.operand(outputOperand).isAddress() &&
1561 "Operand mismatch.");
1562
1563 src = new TTAProgram::TerminalFUPort(op, outputOperand);
1564 dst = createTerminal(mo);
1565
1566 TTAProgram::MoveGuard* guardCopy =
1567 guard == NULL ? NULL : guard->copy();
1568
1569 auto move = createMove(src, dst, bus, guardCopy);
1571 instr->addMove(move);
1572#ifdef DEBUG_LLVMTCEBUILDER
1574 << "adding " << move->toString() << std::endl;
1575#endif
1576 resultMoves.push_back(instr);
1577 debugDataToAnnotations(mi, *move);
1578 }
1579 } // End of for each MI Operand
1580
1581 for (unsigned int i = 0; i < resultMoves.size();i++) {
1582 TTAProgram::Instruction& resultIns = *resultMoves[i];
1583 for (int j = 0; j < resultIns.moveCount(); j++) {
1584 TTAProgram::Move& resultMove = resultIns.move(j);
1585 // if some operand was mem operand, copy the addr space annotations from that operand
1586 copyFUAnnotations(operandMoves, resultMove);
1587 }
1588 }
1589 // Return the first instruction of the whole operation.
1590 TTAProgram::Instruction* first = NULL;
1591 if (!operandMoves.empty()) {
1592 first = operandMoves[0];
1593 } else if (!resultMoves.empty()) {
1594 first = resultMoves[0];
1595 } else if (opDesc->isReturn() && mi->getNumOperands() == 0) {
1596 // LLVM allows RET without any paramters and with defined return value.
1597 // RET with return value is converted above but not the other one.
1598 // To convert it to move, we just write 0 as source terminal.
1599 // LLVM already generated code to put return address on a top of the stack,
1600 // so no point explicitely writing ra -> ret.1.
1601 const TTAMachine::HWOperation* jump = &getHWOperation(opName);
1603 new TTAProgram::TerminalFUPort(*jump, 1);
1604 int width = mach_->is64bit() ? 64 : 32;
1605 SimValue val(0, width);
1606
1607 auto move = createMove(
1608 new TTAProgram::TerminalImmediate(val), dst, bus);
1610 instr->addMove(move);
1611 operandMoves.push_back(instr);
1612 first = instr;
1613 debugDataToAnnotations(mi, *move);
1614 } else {
1615 assert(false && "No moves?");
1616 }
1617 ProgramOperationPtr po(new ProgramOperation(operation, mi));
1618
1619 // Read candidate FUs from MachineInstr metadata.
1620 std::vector<std::string> candidateFUs;
1621 for (unsigned i = 0; i < mi->getNumOperands(); ++i) {
1622
1623 const MachineOperand& op = mi->getOperand(i);
1624 if (!op.isMetadata()) continue;
1625 const MDNode* mdNode = op.getMetadata();
1626 if (mdNode->getNumOperands() > 0) {
1627
1628 llvm::Metadata* op = mdNode->getOperand(0);
1629 MDString* str = dyn_cast<llvm::MDString>(op);
1630
1631 if (str->getString().str() == "fu_candidates") {
1632 for (unsigned j = 1; j < mdNode->getNumOperands(); ++j) {
1633 op = mdNode->getOperand(j);
1634 str = dyn_cast<MDString>(op);
1635 TCEString fuName = str->getString().str();
1636 /* The metadata from MachineInstr might contain "illegal"
1637 FU candidates, pointing to FUs that do not contain the
1638 operation. Filter them out. */
1639 if (mach_->functionUnitNavigator().hasItem(fuName) &&
1640 mach_->functionUnitNavigator().item(fuName)->
1641 hasOperation(operation.name())) {
1642#ifdef DEBUG_LLVMTCEBUILDER
1644 << "FU candidate " << str->getString().str() << " set for ";
1645 mi->dump();
1646#endif
1647 candidateFUs.push_back(str->getString().str());
1648 }
1649 }
1650 }
1651 }
1652 }
1653
1654 for (unsigned i = 0; i < operandMoves.size(); i++) {
1655 TTAProgram::Instruction* instr = operandMoves[i];
1656 auto m = instr->movePtr(0);
1657
1658 // Add candidate FUs as DST candidates
1659 for (unsigned j = 0; j < candidateFUs.size(); ++j) {
1660 if (m->hasAnnotations(
1662 !m->hasAnnotation(
1664 candidateFUs[j]))
1665 continue; // do not add candidates that are not allowed
1666
1667 m->addAnnotation(
1670 }
1671
1672 // create the memory category annotations
1673 if (isSpill) {
1674 m->addAnnotation(
1677 } else if (isRaSlot) {
1678 m->addAnnotation(
1681 } else if (isFpSlot) {
1682 m->addAnnotation(
1685 }
1686
1687 proc->add(instr);
1688 createMoveNode(po, m, true);
1689 }
1690 for (unsigned i = 0; i < resultMoves.size(); i++) {
1691 TTAProgram::Instruction* instr = resultMoves[i];
1692 auto m = instr->movePtr(0);
1693
1694 // Add candidate FUs as SRC candidates
1695 for (unsigned j = 0; j < candidateFUs.size(); ++j) {
1696 if (m->hasAnnotations(
1698 !m->hasAnnotation(
1700 candidateFUs[j]))
1701 continue; // do not add candidates that are not allowed
1702
1703 m->addAnnotation(TTAProgram::ProgramAnnotation(
1705 }
1706
1707 // create the memory category annotations
1708 if (isSpill) {
1709 m->addAnnotation(
1712 } else if (isRaSlot) {
1713 m->addAnnotation(
1716 } else if (isFpSlot) {
1717 m->addAnnotation(
1720 }
1721
1722 proc->add(instr);
1723 createMoveNode(po, m, false);
1724 }
1725
1726 delete guard; guard = NULL;
1727 return first;
1728}
1729
1730
1732 TCEString opName, const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
1733
1734 const HWOperation& op = getHWOperation(opName);
1735
1736 OperationPool pool;
1737 const Operation& operation = pool.operation(opName.c_str());
1739
1740 ProgramOperationPtr po(new ProgramOperation(operation, mi));
1741
1742 TTAProgram::Instruction* first = nullptr;
1743 for (int i = 0; i < 2; i++) {
1744 const MachineOperand& mo = mi->getOperand(i);
1747 auto move = createMove(src, dst, bus);
1749 if (i == 0) {
1750 first = instr;
1751 }
1752 instr->addMove(move);
1753 proc->add(instr);
1754 createMoveNode(po, move, true);
1755 }
1756
1757 // dummy result value, to universal machine register
1760 *UniversalMachine::instance().booleanRegisterFile().port(0), 0);
1761 auto move = createMove(src, dst, bus);
1763 instr->addMove(move);
1764 proc->add(instr);
1765 createMoveNode(po, move, false);
1766 return first;
1767}
1768
1770 TCEString opName, const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
1771
1772 bool inverted = (opName[0] == '!');
1773 opName = opName.substr(1); // drop the inversion char
1774 const HWOperation& op = getHWOperation(opName);
1775
1776 OperationPool pool;
1777 const Operation& operation = pool.operation(opName.c_str());
1779
1780 ProgramOperationPtr po(new ProgramOperation(operation, mi));
1781 const MachineOperand& mo = mi->getOperand(2);
1784
1785 RegisterGuard* bypassRegGuard =
1786 new RegisterGuard(inverted,
1787 UniversalMachine::instance().booleanRegisterFile(),
1788 0, nullptr);
1789
1790 auto move = createMove(src, dst, bus, (new TTAProgram::MoveGuard(*bypassRegGuard)));
1792 instr->addMove(move);
1793 proc->add(instr);
1794 createMoveNode(po, move, true);
1795 return instr;
1796}
1797
1798
1799
1800void
1802 const std::vector<TTAProgram::Instruction*>& operandMoves,
1803 TTAProgram::Move& move) const {
1804 for (unsigned int i = 0; i < operandMoves.size(); i++) {
1805 TTAProgram::Move& operandMove = operandMoves[i]->move(0);
1806 for (int j = 0; j < operandMove.annotationCount(); j++) {
1807 TTAProgram::ProgramAnnotation anno = operandMove.annotation(j);
1808 if (anno.id() ==
1810 move.addAnnotation(
1813 anno.payload()));
1814 }
1815 }
1816 }
1817}
1818
1819/**
1820 * Adds annotations to a pointer-register move to assist the
1821 * TCE-side alias analysis.
1822 *
1823 * Note: this function now assumes that mi has only one address
1824 * operand.
1825 */
1826void
1828 const llvm::MachineInstr* mi, TTAProgram::Move& move) {
1829
1830 // copy some pointer data to Move annotations
1831#if 0
1832 if (mi->memoperands_begin() == mi->memoperands_end()) {
1833 Application::logStream() << "move " << move->toString()
1834 << " does not have mem operands!"
1835 << std::endl;
1836 }
1837#endif
1838
1839 if (pregions_->markersFound()) {
1840 unsigned nodeId = pregions_->pregion(*mi);
1841 if (nodeId != UINT_MAX) {
1842 TTAProgram::ProgramAnnotation progAnnotation(
1844 nodeId);
1845 move.addAnnotation(progAnnotation);
1846 }
1847 }
1848
1849 int addrSpaceId = 0;
1850 // TODO: why this is a loop actually?? It only handles a single
1851 // Move anyways --Pekka
1852 for (MachineInstr::mmo_iterator i = mi->memoperands_begin();
1853 i != mi->memoperands_end(); i++) {
1854
1855 const PseudoSourceValue* psv = (*i)->getPseudoValue();
1856 if (psv != NULL) {
1857 if (psv->isConstant(curFrameInfo_)) {
1858 TTAProgram::ProgramAnnotation progAnnotation(
1860 move.addAnnotation(progAnnotation);
1861 } else {
1862// it seems this breaks something, so disabled.
1863#if 0
1864 if (!psv->isAliased(curFrameInfo_)) {
1865 TTAProgram::ProgramAnnotation progAnnotation(
1867 move.addAnnotation(progAnnotation);
1868 }
1869#endif
1870 }
1871 }
1872 const llvm::Value* memOpValue = (*i)->getValue();
1873
1874 if (memOpValue != NULL) {
1875 std::string pointerName = "";
1876 // can we get the name right away or have to through
1877 // GetElemntPtrInst
1878
1879 if (memOpValue->hasName()) {
1880 pointerName = memOpValue->getName().str();
1881 } else if (isa<GetElementPtrInst>(memOpValue)) {
1882 memOpValue =
1883 cast<GetElementPtrInst>(
1884 memOpValue)->getPointerOperand();
1885 if (memOpValue->hasName()) {
1886 pointerName = memOpValue->getName().str();
1887 }
1888 }
1889
1890 /// TODO: this is not very optimal, it gets the offset
1891 /// info only for the memory accesses to function argument
1892 /// pointers?
1893 if (pointerName.length() > 0 &&
1894 isa<Argument>(memOpValue)) {
1895 unsigned offset;
1896 offset = (*i)->getOffset();
1897 TTAProgram::ProgramAnnotation progAnnotation(
1899 offset);
1900 move.addAnnotation(progAnnotation);
1901 }
1902
1903 // try to find the origin for the pointer which can be
1904 // a function argument with 'noalias' attribute set
1905 const llvm::Value* originMemOpValue = memOpValue;
1906 while (originMemOpValue != NULL) {
1907 TCEString currentPointerName =
1908 (std::string)originMemOpValue->getName();
1909
1910 // Query metadata of the memory operands to find work item
1911 // identifiers for OpenCL memory operands.
1912 if (dyn_cast<Instruction>(originMemOpValue) &&
1913 dyn_cast<Instruction>(originMemOpValue)->getMetadata("wi")) {
1914 const MDNode* md =
1915 cast<Instruction>(originMemOpValue)->getMetadata("wi");
1916 const MDNode* XYZ = dyn_cast<MDNode>(md->getOperand(2));
1917 assert(XYZ->getNumOperands() == 4);
1918 ConstantInt *CX = dyn_cast<ConstantInt>(
1919 dyn_cast<llvm::ConstantAsMetadata>(XYZ->getOperand(1))->getValue());
1920 ConstantInt *CY = dyn_cast<ConstantInt>(
1921 dyn_cast<llvm::ConstantAsMetadata>(XYZ->getOperand(2))->getValue());
1922 ConstantInt *CZ = dyn_cast<ConstantInt>(
1923 dyn_cast<llvm::ConstantAsMetadata>(XYZ->getOperand(3))->getValue());
1924
1925 int id = (CZ->getZExtValue() & 0x0FF)
1926 | ((CY->getZExtValue() & 0x0FF) << 8)
1927 | ((CX->getZExtValue() & 0x0FF) << 16);
1928 TTAProgram::ProgramAnnotation progAnnotation(
1930 ANN_OPENCL_WORK_ITEM_ID, id);
1931 move.addAnnotation(progAnnotation);
1932 // In case the memory operand is BitCastInst, we may be
1933 // looking at the vector memory access.
1934 // Find the type of the accessed element and if it is
1935 // vector add second annotation marking the last work
1936 // it id the vector is accessing.
1937 // Without this information there DDGBuilder can not
1938 // correctly create edges.
1939 if (isa<BitCastInst>(originMemOpValue)) {
1940 llvm::Type* type =
1941 dyn_cast<BitCastInst>(originMemOpValue)->getDestTy();
1942 if (type->isPointerTy()) {
1943 #ifdef LLVM_OLDER_THAN_15
1944 llvm::Type* typeElem =
1945 cast<PointerType>(type)->getElementType();
1946 #else
1947 //TODO: Replace this with getLoadStoreType but
1948 // it takes a non const argument?
1949 assert((isa<LoadInst>(originMemOpValue)
1950 || isa<StoreInst>(originMemOpValue)) &&
1951 "Expected Load or Store instruction");
1952 llvm::Type* typeElem = NULL;
1953 if (auto *LI = dyn_cast<LoadInst>(originMemOpValue))
1954 typeElem = LI->getType();
1955 else
1956 typeElem = cast<StoreInst>(originMemOpValue)
1957 ->getValueOperand()->getType();
1958 #endif
1959 if (typeElem->isVectorTy()) {
1960 int numElems = cast<VectorType>(typeElem)
1961 ->getElementCount()
1962 .getKnownMinValue();
1963 int idLast = (CZ->getZExtValue() & 0x0FF)
1964 | ((CY->getZExtValue() & 0x0FF) << 8)
1965 | (((CX->getZExtValue()
1966 + numElems) & 0x0FF) << 16);
1967 TTAProgram::ProgramAnnotation progAnnotation(
1969 ANN_OPENCL_WORK_ITEM_ID_LAST, idLast);
1970 move.addAnnotation(progAnnotation);
1971 }
1972 }
1973 }
1974 }
1975
1976 if (isa<Argument>(originMemOpValue) &&
1977 cast<Argument>(originMemOpValue)->hasNoAliasAttr()) {
1978 TTAProgram::ProgramAnnotation progAnnotation(
1980 ANN_POINTER_NOALIAS, 1);
1981 move.addAnnotation(progAnnotation);
1982 noAliasFound_ = true;
1983
1984
1985 /// FIXME: this is not correct, especially
1986 /// when the above offset info is set!
1987
1988 /*
1989 As the restrict keyword is assigned only to the pointer
1990 we found, we now pretend we are accessing through
1991 that pointer even though we might not be as the
1992 new pointer might be created through pointer
1993 arithmetic. In case
1994 we are not, the offset in the pointer arithmetic
1995 should be associated with the real pointer, not
1996 the origin pointer with the restrict keyword!
1997
1998 Correct way is to add another annotation from
1999 which restrict pointer the current pointer is
2000 derived from and separate annotation for the
2001 real pointer name + offset.
2002 */
2003 pointerName = originMemOpValue->getName().str();
2004 break;
2005 } else if (isa<GetElementPtrInst>(originMemOpValue)) {
2006 originMemOpValue =
2007 cast<GetElementPtrInst>(originMemOpValue)->
2008 getPointerOperand();
2009 } else if (isa<BitCastInst>(originMemOpValue)) {
2010 originMemOpValue =
2011 cast<BitCastInst>(originMemOpValue)->
2012 getOperand(0);
2013 } else if (isa<PtrToIntInst>(originMemOpValue)) {
2014 originMemOpValue =
2015 cast<PtrToIntInst>(originMemOpValue)->
2016 getOperand(0);
2017 } else {
2018 break;
2019 }
2020 }
2021
2022 if (pointerName != "") {
2025 pointerName);
2026 move.addAnnotation(pointerAnn);
2027 }
2028
2029 addrSpaceId =
2030 cast<PointerType>(memOpValue->getType())->
2031 getAddressSpace();
2032
2033 if (addrSpaceId != 0) {
2034 // this annotation is used only for alias analysis as
2035 // the address spaces are assumed to be always disjoint
2036 std::string addressSpace =
2037 (boost::format("%d") % addrSpaceId).str();
2038 TTAProgram::ProgramAnnotation progAnnotation(
2040 addressSpace);
2041 move.addAnnotation(progAnnotation);
2042 multiAddrSpacesFound_ = true;
2043 }
2044 }
2045 }
2047 // annotate all memory moves with FU candidate sets
2048 // so the memory operations are assigned to the correct
2049 // load-store units in the multimemory machine
2050
2051 // for stack accesses, there is no LLVM pointer info in which
2052 // case we add the default addr space id 0
2053 addCandidateLSUAnnotations(addrSpaceId, move);
2054 }
2055}
2056
2057/**
2058 * Helper method that converts LLVM debug data markers to Move annotations.
2059 */
2060void
2062 const llvm::MachineInstr* mi, TTAProgram::Move& move) {
2063
2064 // annotate the moves generated from known ra saves.
2065 if (mi->getFlag(MachineInstr::FrameSetup)) {
2066 TTAProgram::ProgramAnnotation progAnnotation(
2068 move.setAnnotation(progAnnotation);
2069 }
2070
2071 DebugLoc dl = mi->getDebugLoc();
2072 if (!dl)
2073 return;
2074
2075 // TODO: nobody currently generates these
2076 // spill line number kludges, this is deprecated.
2077 // annotate the moves generated from known spill instructions
2078 if (dl.getLine() == 0xFFFFFFF0) {
2079 TTAProgram::ProgramAnnotation progAnnotation(
2081 move.setAnnotation(progAnnotation);
2083 } else {
2084 // handle file+line number debug info
2085
2086 bool hasDebugInfo = false;
2087 hasDebugInfo = dl.getScope() != NULL;
2088 if (hasDebugInfo) {
2089
2090 int sourceLineNumber = -1;
2091 TCEString sourceFileName = "";
2092
2093 // inspired from lib/codegen/MachineInstr.cpp
2094 sourceLineNumber = dl.getLine();
2095 sourceFileName =
2096 static_cast<TCEString>(
2097 cast<DIScope>(dl.getScope())->getFilename().str());
2098
2099 if (sourceFileName.size() >
2101 sourceFileName =
2102 sourceFileName.substr(
2103 sourceFileName.size() -
2106 }
2107 TTAProgram::ProgramAnnotation progAnnotation(
2109 sourceLineNumber);
2110 move.addAnnotation(progAnnotation);
2111
2112 if (sourceFileName != "") {
2113 TTAProgram::ProgramAnnotation progAnnotation(
2115 ANN_DEBUG_SOURCE_CODE_PATH,
2116 sourceFileName);
2117 move.addAnnotation(progAnnotation);
2118 }
2119 }
2120 }
2121}
2122
2125 const std::string& rfName, int idx) {
2126
2127 const RegisterFile* rf;
2128 if (!mach_->registerFileNavigator().hasItem(rfName)) {
2130 } else {
2131 rf = mach_->registerFileNavigator().item(rfName);
2132 assert(idx >= 0 && idx < rf->size());
2133 }
2134
2135 const RFPort* port = NULL;
2136 for (int i = 0; i < rf->portCount(); i++) {
2137 if (rf->port(i)->isOutput()) {
2138 port = rf->port(i);
2139 break;
2140 }
2141 }
2142 assert(port != NULL);
2143 return new TTAProgram::TerminalRegister(*port, idx);
2144}
2145
2146/**
2147 * Creates a POM source terminal from an LLVM machine operand.
2148 *
2149 * @param mo LLVM machine operand.
2150 * @return POM terminal.
2151 */
2153LLVMTCEBuilder::createTerminal(const MachineOperand& mo, int bitLimit) {
2154 if (bitLimit == 0) {
2155 bitLimit = mach_->is64bit() ? 64 : 32;
2156 }
2157
2158 if (mo.isReg()) {
2159 unsigned dRegNum = mo.getReg();
2160
2161 // is it the RA register?
2162 if (isTTATarget() && dRegNum == raPortDRegNum()) {
2163 return new TTAProgram::TerminalFUPort(
2164 *UniversalMachine::instance().controlUnit()->
2165 returnAddressPort());
2166 }
2167
2168 // an FU port register?
2170 if (term != NULL)
2171 return term;
2172
2173 // a general purpose register?
2174 std::string rfName = registerFileName(dRegNum);
2175 int idx = registerIndex(dRegNum);
2176 return createTerminalRegister(rfName, idx);
2177 } else if (mo.isFPImm()) {
2178 const APFloat& apf = mo.getFPImm()->getValueAPF();
2179 if (&apf.getSemantics() == &APFloat::IEEEhalf()) { //Half float
2180 APInt api = apf.bitcastToAPInt();
2181 uint16_t binary = (uint16_t)api.getRawData()[0];
2182 SimValue val(bitLimit);
2183 val = HalfFloatWord( binary );
2184 return new TTAProgram::TerminalImmediate(val);
2185 } else {
2186 float fval = apf.convertToFloat();
2187 SimValue val(bitLimit);
2188 val = fval;
2189 return new TTAProgram::TerminalImmediate(val);
2190 }
2191 } else if (mo.isImm()) {
2192 int width = bitLimit;
2193 SimValue val(mo.getImm(), width);
2194 return new TTAProgram::TerminalImmediate(val);
2195 } else if (mo.isMBB() || mo.isBlockAddress()) {
2196 return createMBBReference(mo);
2197 } else if (mo.isFI()) {
2198 std::cerr << " Frame index source operand NOT IMPLEMENTED!"
2199 << std::endl;
2200 assert(false);
2201 } else if (mo.isCPI()) {
2202 if (!functionAtATime_) {
2203 int width = bitLimit;
2204 unsigned idx = mo.getIndex();
2205 assert(currentFnCP_.find(idx) != currentFnCP_.end() &&
2206 "CPE not found!");
2207 unsigned addr = currentFnCP_[idx];
2208 SimValue cpeAddr(addr, width);
2209 return new TTAProgram::TerminalImmediate(cpeAddr);
2210 } else {
2211 // Constant Pool Index is converted to dummy
2212 // symbol reference. Will be converted back
2213 // when doing POM->LLVM transfer.
2214 // Format of reference is ".CP_INDEX_OFFSET".
2215 TCEString ref(".CP_");
2216 ref << mo.getIndex() << "_" << mo.getOffset();
2217 return createSymbolReference(ref);
2218 }
2219 } else if (mo.isJTI()) {
2220 TCEString ref(".JTI_");
2221 ref << mo.getIndex();
2222 return createSymbolReference(ref);
2223 } else if (mo.isGlobal()) {
2224 unsigned aSpaceId =
2225 cast<PointerType>(mo.getGlobal()->getType())->getAddressSpace();
2226
2227 TTAMachine::AddressSpace& aSpace =
2228 addressSpaceById(aSpaceId);
2229
2230 SmallString<256> Buffer;
2231 mang_->getNameWithPrefix(Buffer, mo.getGlobal(), false);
2232 TCEString name(Buffer.c_str());
2233
2234 if (name == END_SYMBOL_NAME) {
2235 return createSymbolReference(name);
2236 } else if (dataLabels_.find(name) != dataLabels_.end()) {
2237 SimValue address(dataLabels_[name] + mo.getOffset(), bitLimit);
2238 return new TTAProgram::TerminalAddress(address, aSpace);
2239
2240 } else {
2241 // TODO: this lacks offset??
2242 return createSymbolReference(name);
2243 }
2244 } else if (mo.isJTI()) {
2245 std::cerr << " Jump table index operand NOT IMPLEMENTED!\n";
2246 assert(false);
2247 } else if (mo.isSymbol()) {
2248 return createSymbolReference(mo);
2249 } else if (mo.isMCSymbol()) {
2251 } else if (mo.isMetadata()) {
2252 assert("Metadata MachineOperands should not get here" && false);
2253 } else {
2254 std::cerr << "Unknown src operand type!" << std::endl;
2255 // LLVM does not include dump() when built in non-debug mode.
2256 // mo.getParent()->dump();
2257 assert(false);
2258 }
2259 abortWithError("Should not get here!");
2260 return NULL;
2261}
2262
2265 const MachineOperand& mo) {
2266 llvm::MCSymbol* symbol = mo.getMCSymbol();
2268 new TTAProgram::TerminalProgramOperation(symbol->getName().str());
2269 symbolicPORefs_.insert(term);
2270 return term;
2271}
2272
2273/**
2274 * Fixes the symbolic ProgramOperation references to point to the
2275 * now created real ProgramOperations.
2276 *
2277 * Assumes the POs are found in the label index.
2278 */
2279void
2281 for (std::set<TTAProgram::TerminalProgramOperation*>::const_iterator i =
2282 symbolicPORefs_.begin(); i != symbolicPORefs_.end(); ++i) {
2284 if (term->isProgramOperationKnown()) continue;
2286 assert(po.get() != NULL);
2287 term->setProgramOperation(po);
2288 }
2289}
2290
2292LLVMTCEBuilder::createMBBReference(const MachineOperand& mo) {
2294
2297 mbbReferences_[ref] = mbbName(*mo.getMBB());
2298 return ref;
2299}
2300
2302LLVMTCEBuilder::createSymbolReference(const MachineOperand& mo) {
2303 //} else if (mo.isExternalSymbol()) {
2304
2305 /**
2306 * NOTE: Hack to get code compiling even if llvm falsely makes libcalls to
2307 * external functions even if they are found from currently lowered program.
2308 *
2309 * http://llvm.org/bugs/show_bug.cgi?id=2673
2310 *
2311 * Should be removed after fix is applied to llvm.. (maybe never...)
2312 */
2313 return createSymbolReference(mo.getSymbolName());
2314}
2315
2318 if (name == END_SYMBOL_NAME) {
2319 return NULL;
2320 }
2321
2324
2325
2328 *dummy);
2329
2330 codeLabelReferences_[ref] = name;
2331 return ref;
2332 /**
2333 * END OF HACK
2334 */
2335
2336}
2337
2338/**
2339 * Reserves space and addresses for constant pool entries.
2340 *
2341 * Data defitions are not emitted until in doFinalization() because CP values
2342 * may refer to symbols not yet encountered such as functions and _end symbol.
2343 *
2344 * The constant pool is appended to the end of the default data memory.
2345 * FIXME: should be emitted before global data.
2346 *
2347 * @param mcp Constant pool to emit.
2348 */
2349void
2350LLVMTCEBuilder::emitConstantPool(const MachineConstantPool& mcp) {
2351
2352 currentFnCP_.clear();
2353
2354 const std::vector<MachineConstantPoolEntry>& cp = mcp.getConstants();
2355
2356 const unsigned cpAddrSpaceId = 0;
2357 unsigned& dataEndPos = dataEnd(addressSpaceById(cpAddrSpaceId));
2358
2359 for (unsigned i = 0, e = cp.size(); i != e; ++i) {
2360 auto& cpe = cp[i];
2361 assert(!(cpe.isMachineConstantPoolEntry()) && "NOT SUPPORTED");
2362 if (!globalCP_.count(cpe.Val.ConstVal)) {
2363 // New unique constant.
2364 assert(cpe.getAlign().value() > 0);
2365 unsigned alignment = cpe.getAlign().value();
2366 padToAlignment(cpAddrSpaceId, dataEndPos, alignment);
2367 unsigned address = dataEndPos;
2368
2369 unsigned size = cpe.getSizeInBytes(*dl_);
2370 cpData_.emplace_back(ConstantDataDef(
2371 address, alignment, size, cpe.Val.ConstVal));
2372 globalCP_.insert(std::make_pair(cpe.Val.ConstVal, address));
2373 dataEndPos += size;
2374 // std::cerr << "Constant* = " << cpe.Val.ConstVal << ", "
2375 // << "value = ";
2376 // cpe.Val.ConstVal->dump();
2377 }
2378 // Map current machine function constant pool indexes to the
2379 // addresses of the global CP constants.
2380 currentFnCP_[i] = globalCP_.at(cpe.Val.ConstVal);
2381 }
2382}
2383
2384
2385/**
2386 * Creates POM instruction for a move.
2387 *
2388 * @param src The source operand.
2389 * @param dst The dst operand.
2390 * @return POM Move.
2391 */
2392std::shared_ptr<TTAProgram::Move>
2394 const MachineOperand& src, const MachineOperand& dst,
2395 TTAProgram::MoveGuard* guard) {
2396 assert(!src.isReg() || src.isUse());
2397 assert(dst.isDef());
2398
2399 // eliminate register-to-itself moves
2400 if (dst.isReg() && src.isReg() && dst.getReg() == src.getReg()) {
2401 return NULL;
2402 }
2403
2405 TTAProgram::Terminal* dstTerm = createTerminal(dst);
2406 TTAProgram::Terminal* srcTerm =
2407 createTerminal(src, dstTerm->port().width());
2408
2409 auto move = createMove(srcTerm, dstTerm, bus, guard);
2410
2411 return move;
2412}
2413
2414/**
2415 * Creates POM instruction for a move.
2416 *
2417 * @param mi Move machine instruction.
2418 * @param proc POM procedure to add the move to.
2419 * @return Emitted POM instruction.
2420 */
2423 const MachineInstr* mi, TTAProgram::CodeSnippet* proc,
2424 bool conditional, bool trueGuard) {
2425
2426 unsigned int operandCount = conditional ? 3 : 2;
2427 if (mi->getNumOperands() > operandCount) {
2428 for (unsigned int i = operandCount; i < mi->getNumOperands(); i++) {
2429#if 0
2430 if (!(mi->getOperand(i).isMetadata()) &&
2431 (!mi->getOperand(i).isImplicit())) {
2432 mi->dump();
2433 }
2434#endif
2435 assert(mi->getOperand(i).isMetadata() ||
2436 mi->getOperand(i).isImplicit());
2437 }
2438 }
2439
2440 assert(mi->getNumOperands() >= operandCount); // src, dst
2441
2442 const MachineOperand& dst = mi->getOperand(0);
2443 const MachineOperand& src = mi->getOperand(operandCount - 1);
2444 TTAProgram::MoveGuard* guard = NULL;
2445 if (conditional) {
2446 const MachineOperand& gmo = mi->getOperand(1);
2447 assert (gmo.isReg() && gmo.isUse());
2448 // Create move from the condition operand register to bool register
2449 // which is used by the guard.
2451 // inv guards not yet supported
2452 guard = createGuard(t, trueGuard);
2453 }
2454
2455 TTAProgram::Terminal* dstTerm = createTerminal(dst);
2456 TTAProgram::Terminal* srcTerm =
2457 createTerminal(src, dstTerm->port().width());
2458
2459 if (srcTerm->isGPR() && dstTerm->isGPR() &&
2460 &srcTerm->registerFile() == &dstTerm->registerFile()) {
2461
2462 // Omit no-op copies.
2463 if (srcTerm->index() == dstTerm->index())
2464 return NULL;
2465
2466 if (srcTerm->registerFile().portCount() == 1) {
2467 // Cannot perform a reg2reg move with single ported register
2468 // files, need to find another way to perform the copy.
2469 const TTAMachine::HWOperation* copyOp = NULL;
2470
2471 // Use only operations which get imm 0 as the other operand
2472 // for the lowest immediate requirements.
2473 if (mach_->hasOperation("XOR")) {
2474 copyOp = &getHWOperation("XOR");
2475 } else if (mach_->hasOperation("OR")) {
2476 copyOp = &getHWOperation("OR");
2477 } else if (mach_->hasOperation("ADD")) {
2478 copyOp = &getHWOperation("ADD");
2479 }
2480
2481 if (copyOp == NULL || guard != NULL) {
2484 TCEString("Unable to create a reg to reg copy due to "
2485 "having only one port in '") +
2486 srcTerm->registerFile().name() + "'.");
2487 }
2488
2489 SimValue val(0, mach_->is64bit() ? 64 : 32);
2490
2494 new TTAProgram::TerminalFUPort(*copyOp, 1);
2495 TTAProgram::TerminalFUPort* trigTerm =
2496 new TTAProgram::TerminalFUPort(*copyOp, 2);
2498 new TTAProgram::TerminalFUPort(*copyOp, 3);
2499
2500 Application::logStream() << "Created a reg to reg copy due to RF "
2501 << srcTerm->registerFile().name()
2502 << " having only 1 port" << std::endl;
2503 CodeGenerator codeGenerator(*mach_);
2504 // 0 -> OP.1
2505 codeGenerator.addMoveToProcedure(*proc, immTerm, oprTerm);
2506 // RF.X -> OP.2
2507 codeGenerator.addMoveToProcedure(*proc, srcTerm, trigTerm);
2508 // OP.3 -> RF.Y
2509 return codeGenerator.addMoveToProcedure(*proc, resTerm, dstTerm);
2510 }
2511 }
2513 auto move = createMove(srcTerm, dstTerm, bus, guard);
2514
2515 if (move == NULL) {
2516 return NULL;
2517 }
2519
2520 instr->addMove(move);
2521 proc->add(instr);
2522 return instr;
2523}
2524
2525
2526/**
2527 * Creates POM instructions for a return.
2528 *
2529 * @param mi Return machine instruction.
2530 * @param proc POM procedure to add the return to.
2531 * @return First of the emitted POM instructions.
2532 */
2535 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
2536
2539 *UniversalMachine::instance().controlUnit()->returnAddressPort());
2540
2543
2544 OperationPool pool;
2545 const Operation& operation = pool.operation("jump");
2546
2548 auto move = createMove(src, dst, bus);
2550 instr->addMove(move);
2551 proc->add(instr);
2552 ProgramOperationPtr po(new ProgramOperation(operation, mi));
2553 createMoveNode(po, move, true);
2554 return instr;
2555}
2556
2557/**
2558 * Creates POM instructions for a select.
2559 *
2560 * @param mi select machine instruction.
2561 * @param proc POM procedure to add the select to.
2562 * @return First of the emitted POM instructions.
2563 */
2566 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
2567
2568// 0 = dest?
2569
2570 const MachineOperand& guardMo = mi->getOperand(1);
2571
2572 // Create move from the condition operand register to bool register
2573 // which is used by the guard.
2574 TTAProgram::Terminal *guardTerminal = createTerminal(guardMo);
2575
2576 assert(guardTerminal != NULL);
2577
2578 TTAProgram::Terminal* dstT = createTerminal(mi->getOperand(0));
2579 TTAProgram::Terminal* dstF = createTerminal(mi->getOperand(0));
2580 TTAProgram::Terminal* srcT = createTerminal(mi->getOperand(2));
2581 TTAProgram::Terminal* srcF = createTerminal(mi->getOperand(3));
2582
2584 TTAProgram::Instruction *firstIns = NULL;
2585
2586 // do no create X -> X moves.
2587 if (dstT->equals(*srcT)) {
2588 if (dstT->equals(*srcF)) {
2589 std::cerr << "Empty select!" << std::endl;
2590 return NULL;
2591 }
2592 delete srcT;
2593 delete dstT;
2594 } else {
2595 TTAProgram::MoveGuard* trueGuard = createGuard(guardTerminal, true);
2596 assert(trueGuard != NULL);
2597 auto trueMove = createMove(srcT, dstT, bus, trueGuard);
2599 trueIns->addMove(trueMove);
2600 proc->add(trueIns);
2601 firstIns = trueIns;
2602 }
2603
2604 // do no create X -> X moves.
2605 if (dstF->equals(*srcF)) {
2606 delete srcF;
2607 delete dstF;
2608 } else {
2609 TTAProgram::MoveGuard* falseGuard = createGuard(guardTerminal, false);
2610 assert(falseGuard != NULL);
2611 auto falseMove = createMove(srcF, dstF, bus, falseGuard);
2613 falseIns->addMove(falseMove);
2614 proc->add(falseIns);
2615 if (firstIns == NULL) {
2616 firstIns = falseIns;
2617 }
2618 }
2619
2620 // guardTerminal was just temporary used as helper when creating guards.
2621 delete guardTerminal;
2622
2623 assert(firstIns != NULL);
2624 return firstIns;
2625}
2626
2627/**
2628 * Returns string identifier for a basic block.
2629 *
2630 * These identifiers are used for the BB -> POM instruction book keeping.
2631 *
2632 * @param mbb Basic block object.
2633 * @return String identifier for the basic block.
2634 */
2635std::string
2636LLVMTCEBuilder::mbbName(const MachineBasicBlock& mbb) {
2637 SmallString<256> Buffer;
2638 mang_->getNameWithPrefix(Buffer, &mbb.getParent()->getFunction(), false);
2639 TCEString name(Buffer.c_str());
2640 name += " ";
2641 name += Conversion::toString(mbb.getNumber());
2642 return name;
2643}
2644
2645/**
2646 * Returns true if the Constant value structure has initialized data.
2647 *
2648 * @param cv Initializer to check.
2649 * @return True, if the initializer has any non-Null data.
2650 */
2651bool
2653
2654 if ((dyn_cast<ConstantArray>(cv) != NULL) ||
2655 (dyn_cast<ConstantStruct>(cv) != NULL) ||
2656 (dyn_cast<ConstantVector>(cv) != NULL)) {
2657
2658 for (unsigned i = 0, e = cv->getNumOperands(); i != e; ++i) {
2659 if (isInitialized(cast<Constant>(cv->getOperand(i)))) {
2660 return true;
2661 }
2662 }
2663 return false;
2664 }
2665
2666 return true;
2667}
2668
2669/**
2670 * Emit stack pointer initialization move to the begining of the program.
2671 */
2672void
2681
2682void
2684
2685 unsigned spDRN = spDRegNum();
2686 std::string spRfName = registerFileName(spDRN);
2687 int idx = registerIndex(spDRN);
2689 const RegisterFile* rf = mach_->registerFileNavigator().item(spRfName);
2690 assert(idx >= 0 && idx < rf->size());
2691 const RFPort* port = NULL;
2692 for (int i = 0; i < rf->portCount(); i++) {
2693 if (rf->port(i)->isOutput()) {
2694 port = rf->port(i);
2695 break;
2696 }
2697 }
2698 assert(port != NULL);
2700 TTAProgram::TerminalRegister(*port, idx);
2701
2702 unsigned ival = initialStackPointerValue_;
2703
2704 const TCETargetMachine* tm = dynamic_cast<const TCETargetMachine*>(tm_);
2705 assert(tm != NULL);
2706 unsigned stackAlignment = tm->stackAlignment();
2707 unsigned mask = 0xffffffff;
2708
2709 while (stackAlignment > 1) {
2710 mask = mask << 1;
2711 stackAlignment = stackAlignment >> 1;
2712 }
2713
2714 if (initialStackPointerValue_ == 0 ||
2715 initialStackPointerValue_ > (addressSpaceById(0).end() & mask)) {
2716 ival = addressSpaceById(0).end() & mask;
2717 }
2718
2719 SimValue val(ival, mach_->is64bit() ? 64 : 32);
2725 auto move = createMove(src, dst, bus);
2726 TTAProgram::Instruction* spInitInst =
2728 spInitInst->addMove(move);
2729 spInit->add(spInitInst);
2730 } else {
2731 // Immediate is not enough for the initial stack pointer value, //
2732 // must load it from memory. //
2733
2734 // Data definition for initial stack pointer value stored at zero //
2735 // address //
2736
2737 // FIXME: Assuming 8bit MAU.
2738 // TODO: FIXME: Also assumes 32-bit architecture!
2739 union {
2740 unsigned i;
2741 char bytes[4];
2742 } u;
2743
2744 u.i = ival;
2745
2746 std::vector<MinimumAddressableUnit> spmaus;
2747 unsigned nMaus = sizeof(unsigned);
2748 if (!mach_->isLittleEndian()) {
2749 for (unsigned i = 0; i < nMaus; i++) {
2750 spmaus.push_back(u.bytes[nMaus-i-1]);
2751 }
2752 } else {
2753 for (unsigned i = 0; i < nMaus; i++) {
2754 spmaus.push_back(u.bytes[i]);
2755 }
2756 }
2759 TTAProgram::Address zeroAddr(0, aSpace);
2761 zeroAddr, spmaus, mach_->isLittleEndian()));
2762
2763 // Emit load for stack pointer //
2764 CodeGenerator codegen(*mach_);
2766 new TTAProgram::TerminalAddress(SimValue(0, 32), aSpace);
2767
2768 createSPInitLoad(*spInit, *zeroImm, *dst);
2769 }
2770
2771 if (target.instructionCount() > 0) {
2772 TTAProgram::Instruction& first = target.firstInstruction();
2773 target.insertBefore(first, spInit);
2776 first, spInit->firstInstruction());
2777 }
2778 } else {
2779 target.append(spInit);
2780 }
2781}
2782
2783/**
2784 * Handles INLINEASM nodes that hold real inline assembly code.
2785 *
2786 * This method should not be called for pseudo inline assembly - like TCE
2787 * operation macros (see emitOperationMacro()).
2788 */
2791 const MachineFunction& mf,
2792 const MachineInstr* mi,
2795
2796 assert(isInlineAsm(*mi));
2797 assert(bb->instructionCount() == 0 && "Expected empty BB.");
2798
2799 const TCETargetMachine* tm = dynamic_cast<const TCETargetMachine*>(tm_);
2800 assert(tm && "Inline asm parser requires TCETargetMachine.");
2801
2802 // Avoid unintended overwrite of reserved registers.
2803 auto asmOpds = getInlineAsmOperands(*mi);
2804 for (auto& opds : asmOpds) {
2805 auto& asmOpdNodes = std::get<1>(opds.second);
2806 for (auto mo : asmOpdNodes) {
2807 if (!mo->isReg() ||
2808 !mf.getRegInfo().isReserved(mo->getReg())) {
2809 continue;
2810 }
2811 auto srcLoc = getSourceLocationString(*mi);
2812 std::cerr << srcLoc
2813 << "Error: An use of reserved register '"
2814 << tm->registerName(mo->getReg())
2815 << "' in inline assembly." << std::endl;
2818 "Encountered errors in inline assembly.");
2819 }
2820 }
2821
2822 // Static since the parser has state for "%=" template strings.
2823 static InlineAsmParser inlineAsmParser(*tm, *mang_);
2824
2825 if (!inlineAsmParser.parse(*mi, dataLabels_, *bb, irm)) {
2826 auto& diag = inlineAsmParser.diagnostics();
2827 auto srcLoc = getSourceLocationInfo(*mi);
2828 if (!std::get<0>(srcLoc).empty()) {
2829 std::cerr << std::get<0>(srcLoc) << ":" << std::get<1>(srcLoc)
2830 << ":" << std::endl;
2831 }
2832 for (auto syntaxError : diag.errors()) {
2833 std::cerr << "Error in line " << syntaxError.lineNumber << ": "
2834 << syntaxError.message << std::endl;
2835 }
2836 for (auto internalError : diag.otherErrors()) {
2837 std::cerr << "Error: " << internalError.message << std::endl;
2838 }
2840 CompileError, "Encountered errors in inline assembly parsing.");
2841 }
2842
2844 for (auto warning : inlineAsmParser.diagnostics().warnings()) {
2845 // TODO point to line in C code.
2846 std::cerr << warning.toString() << std::endl;
2847 }
2848 }
2849
2850 return bb->instructionCount() ? &bb->instructionAtIndex(0)
2851 : nullptr;
2852}
2853
2854/**
2855 * Handles operation macros which too uses INLINEASM nodes.
2856 *
2857 * Here the inline assembly string is expected to be just a name
2858 * of a (custom) operation. Operation operands are expected to be listed
2859 * as the inline assembly use and def registers. Architecture specific
2860 * pseudo assembly constructs are also supported (they start with dot) and
2861 * are delegated to emitSpecialInlineAsm().
2862 */
2865 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
2866
2867// mi->print(llvm::dbgs()); //DEBUG
2868
2869#ifndef NDEBUG
2870 unsigned numOperands =
2871#endif
2872 mi->getNumOperands();
2873 // Count the number of register definitions.
2874 unsigned numDefs = 0;
2875 for (; mi->getOperand(numDefs).isReg() &&
2876 mi->getOperand(numDefs).isDef();
2877 ++numDefs) {
2878
2879 }
2880 std::string opName = mi->getOperand(numDefs).getSymbolName();
2881
2882 // ignore the dummy placeholder asm string
2883 if (opName == "") {
2884 return NULL;
2885 }
2886
2887 if (opName[0] == '.') {
2888 // Special handling for dotted architecture-dependent asm contructs,
2889 // a.k.a. "pseudo assembly strings"
2890 return emitSpecialInlineAsm(opName, mi, proc);
2891 }
2892
2893 std::vector<std::string> addressedFUs;
2894 // test this is an addressable instruction
2895 bool addressedOp = StringTools::containsChar(opName, '.');
2896
2897 if (addressedOp) {
2898 if (opName.substr(0,3) == "_AS") {
2899 int addressSpaceId = -1;
2900 std::string foo;
2901 std::string addressedAS;
2902 std::istringstream iss(opName);
2903 std::getline(iss, foo, '.');
2904 std::getline(iss, addressedAS, '.');
2905 std::getline(iss, opName, '.');
2906 char *end;
2907
2908 AddressSpace* targetAS = NULL;
2909
2910 if (addressedAS.size() && addressedAS[0] == '#') {
2911 addressSpaceId = strtol(addressedAS.c_str()+1, &end, 10);
2912 if (end == addressedAS.c_str()+1) {
2913 std::cerr << "ERROR: Address space id following # not a number '" << addressedAS
2914 << std::endl;
2915 } else {
2916 // find addresspace with given id
2918 for (int i = 0; i < nav.count(); i++) {
2919 AddressSpace* as = nav.item(i);
2920 if (as->hasNumericalId(addressSpaceId)) {
2921 targetAS = as;
2922 break;
2923 }
2924 }
2925 }
2926 } else {
2928 for (int i = 0; i < nav.count(); i++) {
2929 AddressSpace* as = nav.item(i);
2930 if (as->name() == addressedAS) {
2931 targetAS = as;
2932 break;
2933 }
2934 }
2935 }
2936
2937 if (targetAS == NULL) {
2938 std::cerr << "ERROR: Address space '" << addressedAS
2939 << "' not found."
2940 << std::endl;
2941 assert(false);
2942 }
2943
2944 // find function units with given as.
2946 for (int j = 0; j < fuNav.count(); j++) {
2947 const FunctionUnit* fu = fuNav.item(j);
2948 if (fu->addressSpace() == targetAS) {
2949 addressedFUs.push_back(fu->name());
2950 }
2951 }
2952 } else {
2953 // Split the string to get the FU and the operation
2954 std::string addressedFU;
2955
2956 std::istringstream iss(opName);
2957 std::getline(iss, addressedFU, '.');
2958 std::getline(iss, opName, '.');
2959 if (!mach_->functionUnitNavigator().hasItem(addressedFU)) {
2960 std::cerr << "ERROR: Function Unit '" << addressedFU
2961 << "' not found."
2962 << std::endl;
2963 assert(false);
2964 }
2965 addressedFUs.push_back(addressedFU);
2966 }
2967 }
2968
2969 assert(numDefs != numOperands-1 && "No asm string?");
2970 assert(mi->getOperand(numDefs).isSymbol() && "No asm string?");
2971
2972 if (StringTools::containsChar(opName, ' ') ||
2973 StringTools::containsChar(opName, ';') ||
2974 StringTools::containsChar(opName, '>') ||
2975 StringTools::containsChar(opName, '<')) {
2976
2977 std::cerr << "ERROR: Inline assembly not supported!" << std::endl;
2978 assert(false);
2979 }
2980
2982 if (!fu.hasOperation(opName)) {
2983 std::cerr
2984 << "ERROR: Explicitly executed operation '"
2985 << opName << "' does not match any operation definition in OSAL."
2986 << std::endl;
2987 assert(false);
2988 }
2989
2990 HWOperation* op = fu.operation(opName);
2991
2993 std::vector<TTAProgram::Instruction*> operandMoves;
2994 std::vector<TTAProgram::Instruction*> resultMoves;
2997
2998
2999 OperationPool pool;
3000 const Operation& operation = pool.operation(opName.c_str());
3001 int inputOperand = 0;
3002
3003 const MachineFunction& mf = *mi->getParent()->getParent();
3004
3005 // Go through the operands.
3006 unsigned startOp = InlineAsm::MIOp_FirstOperand;
3007 unsigned asmDescOp = InlineAsm::MIOp_FirstOperand;
3008 unsigned clobberOp = InlineAsm::MIOp_FirstOperand-1;
3009 for (unsigned o = startOp; o < mi->getNumOperands(); o++) {
3010 const MachineOperand& mo = mi->getOperand(o);
3011 if (mo.isMetadata()) {
3012 continue;
3013 } else if (o == asmDescOp && mo.isImm()) {
3014 // Skip inline assembly flags.
3015 unsigned flag = mo.getImm();
3016 if (InlineAsm::getKind(flag) == InlineAsm::Kind_Clobber) {
3017 clobberOp = o + 1;
3018 }
3019
3020 asmDescOp += 1 + InlineAsm::getNumOperandRegisters(flag);
3021 continue;
3022 } else if (o == clobberOp) {
3023 if (mf.getRegInfo().isReserved(mo.getReg())) {
3024 std::cerr << "Warning: inline assembly clobbers"
3025 << " reserved register (regNum = " << mo.getReg()
3026 << "), which has undefined behavior."
3027 << std::endl;
3028 }
3029 } else if (!(mo.isReg() || mo.isImm() || mo.isGlobal())) {
3030 // All operands should be immediates or in registers.
3031 // Everything else is ignored.
3032 std::cerr << "Ignoring an operand of " << opName << std::endl;
3033 continue;
3034 }
3035
3036 TTAProgram::Terminal* src = NULL;
3037 TTAProgram::Terminal* dst = NULL;
3038 if (mo.isImm() || mo.isGlobal() || mo.isUse()) {
3039 // implicit usage of whole vector when one element used.
3040 if (useOps.empty()) {
3041 // ignore implicit defs that are too many.
3042 if (mo.isImplicit()) {
3043 continue;
3044 }
3045 std::cerr << std::endl;
3046 std::cerr <<"ERROR: Too many input operands for custom "
3047 << "operation '" << opName << "'." << std::endl;
3048 assert(false);
3049 }
3050 src = createTerminal(mo);
3051 dst = new TTAProgram::TerminalFUPort(*op, (*useOps.begin()));
3052 useOps.erase(useOps.begin());
3053 ++inputOperand;
3054 } else {
3055 if (defOps.empty()) {
3056 // ignore implicit defs that are too many.
3057 if (mo.isImplicit()) {
3058 continue;
3059 }
3060 std::cerr << std::endl;
3061 std::cerr << "ERROR: Too many output operands for custom "
3062 << "operation '" << opName << "'." << std::endl;
3063 assert(false);
3064 }
3065 assert(mo.isReg());
3066 if (mf.getRegInfo().isReserved(mo.getReg())) {
3067 std::cerr << "Warning: inline assembly overwriting"
3068 << " reserved register (regNum = " << mo.getReg()
3069 << ") has undefined behavior."
3070 << std::endl;
3071 }
3072
3073 src = new TTAProgram::TerminalFUPort(*op, (*defOps.begin()));
3074 dst = createTerminal(mo);
3075 defOps.erase(defOps.begin());
3076
3077 }
3078
3079 auto move = createMove(src, dst, bus);
3081 instr->addMove(move);
3082
3083 if (mo.isImm() || mo.isGlobal() || mo.isUse()) {
3084 operandMoves.push_back(instr);
3085
3086 // Custom memory accessing operation? Assume absolute addr for now.
3087 if (operation.operand(inputOperand).isAddress()) {
3088 debugDataToAnnotations(mi, *move);
3089 addPointerAnnotations(mi, *move);
3090 }
3091 } else {
3092 resultMoves.push_back(instr);
3093 }
3094 }
3095
3096 if (!defOps.empty() || !useOps.empty()) {
3097 std::cerr << "ERROR: All operands not defined for custom operation '"
3098 << opName << "'." << std::endl;
3099
3100 std::cerr << "Undefined: " << defOps.size() << " output operands, "
3101 << useOps.size() << " input operands." << std::endl;
3102
3103 abortWithError("Cannot continue");
3104 }
3105
3106 // Return the first instruction of the whole operation.
3107 TTAProgram::Instruction* first = NULL;
3108 if (!operandMoves.empty()) {
3109 first = operandMoves[0];
3110 } else if (!resultMoves.empty()) {
3111 first = resultMoves[0];
3112 } else {
3113 assert(false && "No moves?");
3114 }
3115
3116 for (unsigned i = 0; i < operandMoves.size(); i++) {
3117 proc->add(operandMoves[i]);
3118 if (addressedOp) {
3119 // remove other allowed fu annotations, they are not allowed
3120 operandMoves[i]->move(0).removeAnnotations(
3122
3123 for (unsigned int j = 0; j < addressedFUs.size(); j++) {
3124 TTAProgram::ProgramAnnotation dstCandidate(
3126 addressedFUs[j]);
3127 operandMoves[i]->move(0).addAnnotation(dstCandidate);
3128 }
3129 }
3130 }
3131
3132 for (unsigned i = 0; i < resultMoves.size(); i++) {
3133 proc->add(resultMoves[i]);
3134 if (addressedOp) {
3135 // remove other allowed fu annotations, they are not allowed
3136 resultMoves[i]->move(0).removeAnnotations(
3138
3139 for (unsigned int j = 0; j < addressedFUs.size(); j++) {
3140 TTAProgram::ProgramAnnotation srcCandidate(
3142 addressedFUs[j]);
3143 resultMoves[i]->move(0).addAnnotation(srcCandidate);
3144 }
3145 }
3146 }
3147 return first;
3148}
3149
3150/**
3151 * Constructs moves for architecture-dependant special asm.
3152 *
3153 * @param op Assembly instruction string.
3154 * @param mi Machine instruction including the inline asm.
3155 * @param proc TTA procedure to emit moves into.
3156 *
3157 * @return First instruction in emitted block.
3158 */
3161 const std::string op, const MachineInstr* mi,
3163
3164 assert(op[0] == '.');
3165
3166 TCEString subOp(std::string(op, 1, op.length() - 1));
3167
3168 if (subOp == "setjmp")
3169 return emitSetjmp(mi, proc);
3170
3171 if (subOp == "longjmp")
3172 return emitLongjmp(mi, proc);
3173
3174 if (subOp == "call_global_ctors")
3175 return emitGlobalXXtructorCalls(mi, proc, true);
3176
3177 if (subOp == "call_global_dtors")
3178 return emitGlobalXXtructorCalls(mi, proc, false);
3179
3180 if (subOp.startsWith("read_sp "))
3181 return emitReadSP(mi, proc);
3182
3183 if (subOp.startsWith("write_sp "))
3184 return emitWriteSP(mi, proc);
3185
3186 if (subOp.startsWith("return_to "))
3187 return emitReturnTo(mi, proc);
3188
3189 // Just strip the pregion markers for now, later on, use it in the
3190 // alias analysis.
3191 if (subOp.startsWith("pregion_start.") || subOp.startsWith("pregion_end"))
3192 return NULL;
3193
3194 // memory_category pseudo asms can be used to define
3195 // categories for different pointers. They mark those
3196 // pointers to alias only with others pointers in the
3197 // same category.
3198 if (subOp.startsWith("pointer_category"))
3199 return handleMemoryCategoryInfo(mi, proc);
3200
3201 debugLog(subOp);
3202 abortWithError("Undetected special inline asm.");
3203
3204 return NULL;
3205}
3206
3207/**
3208 * Emits moves to read the stack pointer value.
3209 */
3212 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3213
3214 if (mi->getNumOperands() != 5) {
3216 "ERROR: wrong number of operands in \".read_sp\"");
3217 }
3218
3219 // Get the stack pointer. It will be used as index into
3220 // the buffer.
3221 unsigned spDRN = spDRegNum();
3222 TCEString sp = (boost::format("%s.%d") %
3223 registerFileName(spDRN) %
3224 registerIndex(spDRN)).str();
3225
3226 // We need to know where current procedure ends to
3227 // be able to return first generated instruction.
3228 TTAProgram::Instruction& lastInstruction =
3229 proc->lastInstruction();
3230
3231 CodeGenerator codeGenerator(*mach_);
3232
3233 TTAProgram::Terminal* srcTerminal =
3234 codeGenerator.createTerminalRegister(sp, false);
3235
3236 const MachineOperand& dest = mi->getOperand(3);
3237 // Save SP at the first position in the buffer.
3238 TTAProgram::Terminal* destTerminal = createTerminal(dest);
3239
3240 codeGenerator.addMoveToProcedure(*proc, srcTerminal, destTerminal);
3241 return &(proc->nextInstruction(lastInstruction));
3242}
3243
3244/**
3245 * Emits moves that overwrite the RA and return to that address.
3246 */
3249 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3250
3251 if (mi->getNumOperands() != 5) {
3253 "ERROR: wrong number of operands in \".return_to\"");
3254 }
3255
3256 // We need to know where current procedure ends to
3257 // be able to return first generated instruction.
3258 TTAProgram::Instruction& lastInstruction = proc->lastInstruction();
3259
3260 CodeGenerator codeGenerator(*mach_);
3261 // the source from which to overwrite RA
3262 const MachineOperand& src = mi->getOperand(3);
3263
3264 /* src -> RA */
3265 codeGenerator.addMoveToProcedure(
3266 *proc, createTerminal(src),
3267 codeGenerator.createTerminalRegister("RA", false));
3268 /* RA -> JUMP.1 */
3269 codeGenerator.registerJump(*proc, "RA");
3270
3271 return &(proc->nextInstruction(lastInstruction));
3272}
3273
3274
3275/**
3276 * Emits moves to write the stack pointer value.
3277 */
3280 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3281
3282 if (mi->getNumOperands() != 5) {
3284 << "got " << mi->getNumOperands() << " operands" << std::endl;
3286 "ERROR: wrong number of operands in \".write_sp\"");
3287 }
3288
3289 const TCETargetMachine* tm = dynamic_cast<const TCETargetMachine*>(tm_);
3290 assert(tm_ != NULL);
3291 // Get the stack pointer. It will be used as index into
3292 // the buffer.
3293 unsigned spDRN = tm->spDRegNum();
3294 TCEString sp = (boost::format("%s.%d") %
3295 tm->rfName(spDRN) %
3296 tm->registerIndex(spDRN)).str();
3297
3298 // We need to know where current procedure ends to
3299 // be able to return first generated instruction.
3300 TTAProgram::Instruction& lastInstruction =
3301 proc->lastInstruction();
3302
3303 CodeGenerator codeGenerator(*mach_);
3304
3305 TTAProgram::Terminal* destTerminal =
3306 codeGenerator.createTerminalRegister(sp, false);
3307
3308 const MachineOperand& src = mi->getOperand(3);
3309 TTAProgram::Terminal* srcTerminal = createTerminal(src);
3310
3311 codeGenerator.addMoveToProcedure(*proc, srcTerminal, destTerminal);
3312 return &(proc->nextInstruction(lastInstruction));
3313}
3314
3315/**
3316 * Handles the .pointer_category pseudo assembler instruction.
3317 *
3318 * First argument is a string defining the category, second refers to
3319 * the pointer.
3320 */
3323 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3324
3325 if (mi->getNumOperands() != 6) {
3327 << "got " << mi->getNumOperands() << " operands" << std::endl;
3329 "ERROR: wrong number of operands in \".pointer_category\"");
3330 }
3331
3332 TTAProgram::Instruction& lastInstruction =
3333 proc->lastInstruction();
3334
3335 CodeGenerator codeGenerator(*mach_);
3336
3337 TTAProgram::Terminal* srcTerminal =
3338 createTerminal(mi->getOperand(5));
3339
3340 TTAProgram::Terminal* dstTerminal =
3341 createTerminal(mi->getOperand(3));
3342 codeGenerator.addMoveToProcedure(*proc, srcTerminal, dstTerminal);
3343 return &(proc->nextInstruction(lastInstruction));
3344}
3345
3346
3347/*
3348 * setjmp/longjmp buffer structure description:
3349 *
3350 * buffer -> |-----------------|
3351 * | SP |
3352 * |-----------------|
3353 * | RA |
3354 * |-----------------|
3355 * | Return value |
3356 * |-----------------|
3357 * | ... |
3358 * | All RF regs |
3359 * | except SP |
3360 * | ... |
3361 * |-----------------|
3362 * | Return address |
3363 * | (to setjmp tail |
3364 * | code) |
3365 * |-----------------| <- buffer +
3366 * <number regs in all RFs> + 3
3367 */
3368
3369/**
3370 * Constructs moves for ".setjmp"
3371 *
3372 * @param mi Machine instruction including the inline asm.
3373 * @param proc TTA procedure to emit moves into.
3374 *
3375 * @return First instruction in emmited block.
3376 */
3377
3380 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3381
3382 if (mi->getNumOperands() != 7) {
3383 std::cerr << "ERROR: wrong number of operands in "".setjmp"""
3384 << std::endl;
3385 assert(false);
3386 }
3387 const MachineOperand& val = mi->getOperand(3);
3388 const MachineOperand& env = mi->getOperand(5);
3389 // Get the stack pointer. It will be used as index into
3390 // the buffer.
3391 unsigned spDRN = spDRegNum();
3392 TCEString sp = (boost::format("%s.%d") %
3393 registerFileName(spDRN) %
3394 registerIndex(spDRN)).str();
3395
3396 // We need to know where current procedure ends to
3397 // be able to return first generated instruction.
3398 int oldSize = proc->instructionCount();
3399
3400 CodeGenerator codeGenerator(*mach_);
3401
3402 // Save SP at the first position in the buffer.
3403 TTAProgram::Terminal* buffer = createTerminal(env);
3404 codeGenerator.storeToAddress(*proc, buffer, sp);
3405
3406 // Now we can scratch the stack pointer.
3407
3408 // First thing we need is to store buffer address in SP.
3409 buffer = createTerminal(env);
3410 TTAProgram::Terminal* spTerminal =
3411 codeGenerator.createTerminalRegister(sp, false);
3412
3413 codeGenerator.addMoveToProcedure(*proc, buffer, spTerminal);
3414
3415 // Increment index to jump over the place where SP was
3416 // stored.
3417 codeGenerator.incrementStackPointer(*proc, sp);
3418
3419 // Save RA first (special register).
3420 codeGenerator.pushRegisterToStack(*proc, sp, "RA");
3421
3422 // Now save the desired return value.
3423 SimValue immVal(mach_->is64bit() ? 64 : 32);
3424 immVal = 0;
3425 TTAProgram::TerminalImmediate *immTerminal =
3427 codeGenerator.pushToStack(*proc, sp, immTerminal);
3428
3429 // Now we can save every register there.
3432
3433 int buffer_words = 0;
3434
3435 for (int i = 0; i < nav.count(); i++) {
3436 const TTAMachine::RegisterFile& rf = *nav.item(i);
3437 for (int j = 0; j < rf.numberOfRegisters(); j++) {
3438 TCEString reg =
3439 (boost::format("%s.%d") % rf.name() % j).str();
3440 if (reg != sp) { // sp already saved, ignore it.
3441 codeGenerator.pushRegisterToStack(*proc, sp, reg);
3442 buffer_words++;
3443 }
3444 }
3445 }
3446
3447 // Save the setjmp return point.
3448 TTAProgram::Instruction* returnInstruction =
3451
3452 TTAProgram::InstructionReference returnReference =
3454 *returnInstruction);
3455
3456 codeGenerator.pushInstructionReferenceToStack(*proc, sp, returnReference);
3457
3458 codeGenerator.decrementStackPointer(*proc, sp);
3459
3460 proc->add(returnInstruction);
3461
3462 // Move back the stored registers.
3463 for (int i = 0; i < buffer_words; i++)
3464 codeGenerator.decrementStackPointer(*proc, sp);
3465
3466 // Get return value.
3468 codeGenerator.popFromStack(*proc, sp, rv);
3469
3470 // Restore original RA.
3471 codeGenerator.popRegisterFromStack(*proc, sp, "RA");
3472
3473 // Restore SP from first position in the buffer.
3474 codeGenerator.popRegisterFromStack(*proc, sp, sp);
3475
3476 return &(proc->instructionAtIndex(oldSize));
3477}
3478
3479
3480/**
3481 * Constructs moves for calling all global constructors or
3482 * destructors, if any.
3483 *
3484 * @param mi Machine instruction including the inline asm.
3485 * @param proc TTA procedure to append moves into.
3486 * @param constructors True, if emitting constructors, otherwise
3487 * destructors.
3488 */
3491 const MachineInstr* /*mi*/, TTAProgram::CodeSnippet* proc,
3492 bool constructors) {
3493
3494 std::string globalName =
3495 constructors ?
3496 ("llvm.global_ctors") : ("llvm.global_dtors");
3497
3498 TTAProgram::Instruction* firstInstruction = NULL;
3499
3500 // find the _llvm.global_Xtors global with the
3501 // function pointers and priorities
3502 for (Module::const_global_iterator i = mod_->global_begin();
3503 i != mod_->global_end(); i++) {
3504
3505 const GlobalVariable* gv = &(*i);
3506 if (gv->getName() == globalName && gv->use_empty()) {
3507 // The initializer should be an array of '{ int, void ()* }'
3508 // structs for LLVM 3.4 and lower, and an array of
3509 // '{ int, void ()*, i8* }' structs for LLVM 3.5.
3510 // The first value is the init priority, which we ignore.
3511 auto init = gv->getInitializer();
3512 if (!isa<ConstantArray>(init)) {
3513 abortWithError("Global array initializer not ConstantArray.");
3514 }
3515 const ConstantArray* initList = cast<const ConstantArray>(init);
3516 for (unsigned i = 0, e = initList->getNumOperands(); i != e; ++i) {
3517 if (ConstantStruct* cs =
3518 dyn_cast<ConstantStruct>(initList->getOperand(i))) {
3519
3520 // LLVM 3.5 introduced an additional field, so test for
3521 // an array of 3-element structs.
3522 if (cs->getNumOperands() != 3) {
3523 return firstInstruction;
3524 }
3525
3526 // Found a null terminator, exit printing.
3527 if (cs->getOperand(1)->isNullValue()) {
3528 return firstInstruction;
3529 }
3530
3531 // Emit the call.
3532 GlobalValue* gv = dyn_cast<GlobalValue>(
3533 cs->getOperand(1));
3534 assert(gv != NULL&&"global constructor name not constv");
3535
3536 SmallString<256> Buffer;
3537 mang_->getNameWithPrefix(Buffer, gv, false);
3538 TCEString name(Buffer.c_str());
3539
3540 TTAProgram::Terminal* xtorRef = NULL;
3541
3542 // cannot use instr. refs in the new builder as the
3543 // instructions won't belong in a procedure before
3544 // they have been fully scheduled.
3545 xtorRef = new TTAProgram::TerminalSymbolReference(name);
3546
3547 CodeGenerator codeGenerator(*mach_);
3548
3549 auto ctrCall =
3550 std::make_shared<TTAProgram::Move>(
3551 xtorRef, codeGenerator.createTerminalFUPort("call", 1),
3553
3554 OperationPool opPool;
3555
3556 // Create ProgramOperation also for return so DDGBuilder does not have
3557 // to do that.
3559 new ProgramOperation(opPool.operation("call")));
3560 createMoveNode(po, ctrCall, true);
3561
3562 TTAProgram::Instruction* newInstr =
3565
3566 newInstr->addMove(ctrCall);
3567 proc->add(newInstr);
3568
3569 if (firstInstruction == NULL)
3570 firstInstruction = &proc->lastInstruction();
3571 }
3572 }
3573 return firstInstruction;
3574 }
3575 }
3576 return NULL;
3577}
3578
3579/**
3580 * Constructs moves for ".longjmp"
3581 *
3582 * @param mi Machine instruction including the inline asm.
3583 * @param proc TTA procedure to emit moves into.
3584 *
3585 * @return First instruction in emitted block.
3586 */
3589 const MachineInstr* mi, TTAProgram::CodeSnippet* proc) {
3590
3591 if (mi->getNumOperands() != 7) {
3592 std::cerr << "ERROR: wrong number of operands in "".longjmp"""
3593 << std::endl;
3594 assert(false);
3595 }
3596 const MachineOperand& env = mi->getOperand(3);
3597 const MachineOperand& val = mi->getOperand(5);
3598
3599 // Get the stack pointer. It will be used as index into
3600 // the buffer.
3601 unsigned spDRN = spDRegNum();
3602 TCEString sp = (boost::format("%s.%d") %
3603 registerFileName(spDRN) %
3604 registerIndex(spDRN)).str();
3605
3606 // We need to know where current procedure ends to
3607 // be able to return first generated instruction.
3608 int oldSize = proc->instructionCount();
3609
3610 CodeGenerator codeGenerator(*mach_);
3611
3612 // First thing we need is to load buffer address in SP.
3613 TTAProgram::Terminal* buffer = createTerminal(env);
3614 TTAProgram::Terminal* spTerminal =
3615 codeGenerator.createTerminalRegister(sp, false);
3616
3617 codeGenerator.addMoveToProcedure(*proc, buffer, spTerminal);
3618
3619 // Increment index to jump over the place where SP was
3620 // stored.
3621 codeGenerator.incrementStackPointer(*proc, sp);
3622
3623 // Jump over RA (will be restored in setjmp tail).
3624 codeGenerator.incrementStackPointer(*proc, sp);
3625
3626 // Now save the desired return value.
3628 codeGenerator.pushToStack(*proc, sp, rv);
3629
3630 // Reload all registers but SP.
3633
3634 for (int i = 0; i < nav.count(); i++) {
3635 const TTAMachine::RegisterFile& rf = *nav.item(i);
3636 for (int j = 0; j < rf.numberOfRegisters(); j++) {
3637 TCEString reg =
3638 (boost::format("%s.%d") % rf.name() % j).str();
3639 if (reg != sp) {
3640 // Using fromStack as I am restoring towards
3641 // higher memory addresses.
3642 codeGenerator.popRegisterFromStack(*proc, sp, reg);
3643 }
3644 }
3645 }
3646
3647 // Done, jump to setjmp ending code.
3648 codeGenerator.loadFromRegisterAddress(*proc, sp, "RA");
3649 codeGenerator.registerJump(*proc, "RA");
3650
3651 return &(proc->instructionAtIndex(oldSize));
3652}
3653
3654/**
3655 * Creates instruction(s) to load initial stack pointer value.
3656 */
3657void
3661 TTAProgram::Terminal& dst) {
3662
3663 CodeGenerator codegen(*mach_);
3664 codegen.loadTerminal(target, &src, &dst);
3665}
3666
3667/**
3668 * Creates program object model move.
3669 *
3670 * @param src Source terminal of the move.
3671 * @param dst Destination terminal of the move.
3672 * @param bus Bus utilized to do the move.
3673 * @param guard Guard object for the move or NULL if the move is not
3674 * guarded.
3675 * @return Created move.
3676 */
3677std::shared_ptr<TTAProgram::Move>
3681 const TTAMachine::Bus& bus,
3682 TTAProgram::MoveGuard* guard) {
3683
3684 std::shared_ptr<TTAProgram::Move> move = nullptr;
3685
3686 bool endRef = false;
3687
3688 if (src == NULL) {
3689 // Create a dummy source Terminal so the move can be added to an
3690 // instruction.
3691 SimValue val(0, mach_->is64bit() ? 64 : 32);
3692 src = new TTAProgram::TerminalImmediate(val);
3693 endRef = true;
3694 }
3695
3696 if (guard == NULL) {
3697 move = std::make_shared<TTAProgram::Move>(src, dst, bus);
3698 } else {
3699 move = std::make_shared<TTAProgram::Move>(src, dst, bus, guard);
3700 }
3701
3702 if (endRef) {
3703 endReferences_.push_back(move);
3704 }
3705
3706 return move;
3707}
3708
3709
3710/**
3711 * Returns the program built during the pass.
3712 *
3713 * @return Result program object built.
3714 * @throw NotAvailable If program is not ready.
3715 */
3718 return prog_;
3719}
3720
3721/**
3722 * Creates a register guard to given guard register.
3723 */
3725 const TTAProgram::Terminal* terminal, bool trueOrFalse) {
3726 const TTAProgram::TerminalRegister* guardReg =
3727 dynamic_cast<const TTAProgram::TerminalRegister*>(terminal);
3728 if (guardReg == NULL) {
3729 return NULL;
3730 }
3731
3732 bool hasPortGuard = false;
3734 for (int i = 0; i < busNav.count(); i++) {
3735 Bus* bus = busNav.item(i);
3736 for (int i = 0; i < bus->guardCount(); i++) {
3737 RegisterGuard* regGuard = dynamic_cast<RegisterGuard*>(
3738 bus->guard(i));
3739 if (regGuard != NULL &&
3740 regGuard->registerFile() == &guardReg->registerFile() &&
3741 regGuard->registerIndex() == (int)guardReg->index() &&
3742 regGuard->isInverted() != trueOrFalse) {
3743 return new TTAProgram::MoveGuard(*regGuard);
3744 }
3745 PortGuard* portGuard = dynamic_cast<PortGuard*>(
3746 bus->guard(i));
3747 if (portGuard != nullptr &&
3748 portGuard->isInverted() != trueOrFalse)
3749 hasPortGuard = true;
3750 }
3751 }
3752
3753 if (hasPortGuard) {
3754 RegisterGuard* bypassRegGuard =
3755 new RegisterGuard(!trueOrFalse, guardReg->registerFile(),
3756 guardReg->index(), nullptr);
3757
3758 return new TTAProgram::MoveGuard(*bypassRegGuard);
3759 } else {
3760 std::cerr << "Warning: Could not find suitable guard from any bus in the "
3761 << "processor. Did you forget to add guards to the processor?"
3762 << std::endl;
3763 return NULL;
3764 }
3765}
3766
3767
3770
3773
3776 for (int i = 0; i < asNav.count(); i++) {
3777 TTAMachine::AddressSpace& aSpace = *asNav.item(i);
3778 if (aSpace.hasNumericalId(id))
3779 return aSpace;
3780 }
3782 << "Address space with numerical id " << id << " not found."
3783 << std::endl;
3784 abort();
3785}
3786
3787
3788/**
3789 * Returns the position after the highest written data symbol for the
3790 * given address space.
3791 */
3792unsigned&
3794 if (!MapTools::containsKey(dataEnds_, &aSpace)) {
3795 unsigned end =
3796 (options_ != nullptr && options_->isDataStartAddressSet(aSpace))
3797 ? options_->dataStartAddress(aSpace)
3798 : aSpace.start();
3799 /* Avoid placing data to address 0 as it may break some null pointer
3800 tests. Waste a valuable word of memory and add a dummy word to
3801 prevent writing bytes to 1,2,3 addresses and thus then avoid reading
3802 valid data from address 0. */
3803 if (end == 0) {
3804 const TCETargetMachine* tm =
3805 dynamic_cast<const TCETargetMachine*>(tm_);
3806 assert(tm != NULL);
3808 }
3809 dataEnds_[&aSpace] = end;
3810
3811 }
3812 return dataEnds_[&aSpace];
3813}
3814
3815/**
3816 * Returns the "layout array" for the data memory of the given address
3817 * space.
3818 */
3821 if (!MapTools::containsKey(dmemIndex_, &aSpace)) {
3822 dmemIndex_[&aSpace] = new TTAProgram::DataMemory(aSpace);
3823 }
3824 return *dmemIndex_[&aSpace];
3825}
3826
3827//#define DEBUG_LLVMTCEBUILDER
3828//#define WARN_AS_FU_NOT_FOUND
3829/**
3830 * Adds annotations to the given move that limit the choice of the
3831 * load-store unit to only those that support the given address space.
3832 */
3833void
3835 unsigned asNum, TTAProgram::Move& move) {
3836
3837 TCEString opName;
3838 if (move.destination().isFUPort()) {
3839 opName = dynamic_cast<TTAProgram::TerminalFUPort&>(
3840 move.destination()).hwOperation()->name();
3841 } else {
3842 opName = dynamic_cast<TTAProgram::TerminalFUPort&>(
3843 move.source()).hwOperation()->name();
3844 }
3845 bool foundLSU = false;
3848 for (int i = 0; i < fuNav.count(); i++) {
3849 const TTAMachine::FunctionUnit& fu = *fuNav.item(i);
3850 if (fu.hasAddressSpace()) {
3851 if (fu.addressSpace()->hasNumericalId(asNum) &&
3852 fu.hasOperation(opName)) {
3853 TTAProgram::ProgramAnnotation progAnnotation(
3855 ANN_ALLOWED_UNIT_DST, fu.name());
3856 move.addAnnotation(progAnnotation);
3857 foundLSU = true;
3858 }
3859 }
3860 }
3861
3862 /* Fail silently for now.
3863
3864 The problem here is that stack instructions should be mapped
3865 to AS0 but they do not have memoperands, thus
3866 addPointerAnnotations() does not manage to figure out any
3867 real address space info for it. Thus, we just could
3868 assume all such instructions belong to the default AS.
3869
3870 The problem appears with custom operations which take in
3871 memory operands. For example, TRY_LOCK_ADDR etc. of the DILU.
3872 The INLINEASM blocks, even if the operand is marked as 'm', do not
3873 produce MachineInstrs with memoperands, thus the pointer info cannot
3874 be obtained. However, in that case the address space could be
3875 something else than the default.
3876
3877 For now, we leave the AS info out in case FU with the operation and
3878 the address space is found, thus assume there is only one such FU
3879 which is then selected correctly during the scheduling.
3880 We only abort if the asNum != 0, otherwise fail silently.
3881 */
3882 if (!foundLSU) {
3883 if (asNum == 0){
3884#ifdef WARN_AS_FU_NOT_FOUND
3885 if (true || Application::verboseLevel() > 0) {
3887 << "WARNING: no candidate FU found for "
3888 << move.toString() << " with address space id "
3889 << asNum << " not adding any AS info."
3890 << std::endl;
3891 }
3892#endif
3893 } else {
3894 // If the asNum isn't already 0, we can't quietly make the
3895 // assumption that it should be 0. Instead abort.
3896 abortWithError((boost::format("ERROR: No candidate FU found for %s"
3897 " address space id %u") % move.toString() % asNum).str());
3898 }
3899 }
3900}
3901
3902/**
3903 * Returns true if the instruction is real inline asm aka. holds moves.
3904 *
3905 * Returns false if instruction is not inline asm.
3906 * This also return false for operation macros (_TCE_OP(...)) that also use
3907 * inline asm statements in C code.
3908 *
3909 * @param instr The instruction.
3910 */
3911bool
3912LLVMTCEBuilder::isInlineAsm(const MachineInstr& instr) {
3913 return InlineAsmParser::isInlineAsm(instr);
3914}
3915
3916
3917
3918
#define debugLog(text)
#define abortWithError(message)
#define PRINT_VAR(VARIABLE__)
#define assert(condition)
#define IGNORE_COMPILER_WARNING(X)
#define POP_COMPILER_DIAGS
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
#define END_SYMBOL_NAME
#define TYPE_CONST
std::string getSourceLocationString(const llvm::MachineInstr &mi)
AsmOperandMap getInlineAsmOperands(const llvm::MachineInstr &mi)
POP_COMPILER_DIAGS std::tuple< std::string, size_t > getSourceLocationInfo(const llvm::MachineInstr &mi)
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition MoveNode.hh:53
SimValue dummy(32)
a dummy simvalue which is given for operands that are not bound
static CmdLineOptions * cmdLineOptions()
static int verboseLevel()
static std::ostream & logStream()
const std::set< CompilerMessage > & warnings() const
static std::string toString(const T &source)
static bool isInlineAsm(const llvm::MachineInstr &mi)
const AssemblyParserDiagnostic & diagnostics() const
bool parse(const llvm::MachineInstr &inlineAsmMI, const std::map< std::string, unsigned > &symbolTable, TTAProgram::BasicBlock &bb, TTAProgram::InstructionReferenceManager &irm)
uint64_t dataStartAddress(TTAMachine::AddressSpace &aSpace) const
bool isDataStartAddressSet(TTAMachine::AddressSpace &aSpace) const
static int maxMemoryAlignment(const TTAMachine::Machine &mach)
static bool canEncodeImmediateInteger(const TTAMachine::Machine &mach, int64_t imm, unsigned destWidth=UINT_MAX)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
virtual bool isAddress() const
Definition Operand.cc:328
virtual bool isInput() const
Definition Operand.cc:145
virtual bool isOutput() const
Definition Operand.cc:155
virtual bool isNull() const
Definition Operand.hh:130
Operation & operation(const char *name)
virtual TCEString name() const
Definition Operation.cc:93
virtual bool isBaseOffsetMemOperation() const
Definition Operation.cc:323
virtual int numberOfInputs() const
Definition Operation.cc:192
virtual int numberOfOutputs() const
Definition Operation.cc:202
virtual Operand & operand(int id) const
Definition Operation.cc:541
static std::string disassemble(const TTAProgram::Move &move)
unsigned pregion(const llvm::MachineInstr &I) const
static bool containsChar(const std::string &source, char ch, bool caseSensitive=true)
static std::string stringToLower(const std::string &source)
bool startsWith(const std::string &str) const
static const size_t MAX_ANNOTATION_BYTES
Maximum number of bytes that annotation may contain.
virtual bool hasNumericalId(unsigned id) const
virtual ULongWord end() const
virtual ULongWord start() const
virtual int numberOfRegisters() const
virtual RFPort * port(const std::string &name) const
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual TCEString name() const
OperandSet writtenOperands(int cycle) const
OperandSet readOperands(int cycle) const
std::set< int > OperandSet
Set for operand indexes.
virtual AddressSpace * addressSpace() const
virtual HWOperation * operation(const std::string &name) const
virtual int operationCount() const
virtual bool hasOperation(const std::string &name) const
virtual bool hasAddressSpace() const
virtual bool isInverted() const
ExecutionPipeline * pipeline() const
const std::string & name() const
ComponentType * item(int index) const
bool hasItem(const std::string &name) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition Machine.cc:380
bool isLittleEndian() const
Definition Machine.hh:258
bool hasOperation(const TCEString &opName) const
Definition Machine.cc:1042
virtual BusNavigator busNavigator() const
Definition Machine.cc:356
virtual AddressSpaceNavigator addressSpaceNavigator() const
Definition Machine.cc:392
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
bool is64bit() const
Definition Machine.hh:260
static NullInstructionTemplate & instance()
virtual bool isOutput() const
Definition Port.cc:308
virtual int width() const =0
const RegisterFile * registerFile() const
virtual int portCount() const
Definition Unit.cc:135
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
void setAnnotation(const ProgramAnnotation &annotation)
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
void addAnnotation(const ProgramAnnotation &annotation)
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
TTAProgram::TerminalFUPort * createTerminalFUPort(const TCEString &opName, int operand)
TTAProgram::Terminal * createTerminalRegister(const TTAMachine::RegisterFile &rf, int regNum, bool readPort) const
void pushToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::Terminal *srcTerminal)
TTAProgram::Instruction * addMoveToProcedure(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, TTAProgram::Terminal *dstTerminal)
void decrementStackPointer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &spReg)
void pushRegisterToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, const TCEString &srcReg)
void registerJump(TTAProgram::CodeSnippet &dstProcedure, const TCEString &jumpAddrReg)
void loadFromRegisterAddress(TTAProgram::CodeSnippet &dstProcedure, const TCEString &srcReg, const TCEString &dstReg)
void incrementStackPointer(TTAProgram::CodeSnippet &dstProcedure, const TCEString &spReg)
void storeToAddress(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *dstTerminal, const TCEString &srcReg)
void popFromStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::Terminal *dstTerminal)
void loadTerminal(TTAProgram::CodeSnippet &dstProcedure, TTAProgram::Terminal *srcTerminal, TTAProgram::Terminal *dstTerminal)
void pushInstructionReferenceToStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, TTAProgram::InstructionReference &srcAddr)
void popRegisterFromStack(TTAProgram::CodeSnippet &dstProcedure, const TCEString &stackRegister, const TCEString &dstReg)
virtual Instruction & nextInstruction(const Instruction &ins) const
virtual Instruction & firstInstruction() const
virtual void append(const CodeSnippet &cs)
virtual void add(Instruction *ins)
virtual int instructionCount() const
virtual Address startAddress() const
virtual void insertBefore(const Instruction &pos, Instruction *ins)
virtual Instruction & lastInstruction() const
virtual Instruction & instructionAtIndex(int index) const
virtual Address destinationAddress() const
void addDataDefinition(DataDefinition *dataDef)
Definition DataMemory.cc:66
DataDefinition & dataDefinition(Address address) const
Definition DataMemory.cc:79
void replace(Instruction &insA, Instruction &insB)
InstructionReference createReference(Instruction &ins)
std::string toString() const
std::shared_ptr< Move > movePtr(int i) const
Move & move(int i) const
void addMove(std::shared_ptr< Move > move)
CodeSnippet & parent() const
MoveGuard * copy() const
Definition MoveGuard.cc:96
std::string toString() const
Definition Move.cc:436
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
void add(Instruction *ins)
Definition Procedure.cc:160
const std::vector< Byte > & payload() const
ProgramAnnotation::Id id() const
@ ANN_POINTER_NAME
information retrieved (from LLVM) about a pointer access
@ ANN_ALLOWED_UNIT_DST
Dst. unit candidate.
@ ANN_CONN_CANDIDATE_UNIT_DST
Dst. unit candidate.
@ ANN_CONN_CANDIDATE_UNIT_SRC
Src. unit candidate.
@ ANN_PARALLEL_REGION_ID
The ID from the _TCEPREGION_START(N) markers.
@ ANN_ALLOWED_UNIT_SRC
Candidate units can be passed for resource manager for choosing the source/destination unit of the mo...
@ ANN_DEBUG_SOURCE_CODE_LINE
The line number in the source code file the annotated move originates from.
@ ANN_STACKUSE_FP_SAVE
frame ptr save/load
@ ANN_CONSTANT_MEM
Constant memory access.
GlobalScope & globalScope()
Definition Program.cc:180
Procedure & procedure(int index) const
Definition Program.cc:622
Instruction & firstInstruction() const
Definition Program.cc:353
DataMemory & dataMemory(int index) const
Definition Program.cc:967
void removeProcedure(Procedure &proc)
Definition Program.cc:901
void addDataMemory(DataMemory *dataMem)
Definition Program.cc:954
void addProcedure(Procedure *proc)
Definition Program.cc:524
InstructionReferenceManager & instructionReferenceManager() const
Definition Program.cc:688
int dataMemoryCount() const
Definition Program.cc:942
virtual void addDataLabel(const DataLabel *dataLabel)
Definition Scope.cc:415
virtual void addCodeLabel(const CodeLabel *codeLabel)
Definition Scope.cc:376
void setProgramOperation(ProgramOperationPtr po)
virtual int index() const
virtual const TTAMachine::RegisterFile & registerFile() const
virtual bool isRA() const
Definition Terminal.cc:129
virtual Operation & hintOperation() const
Definition Terminal.cc:341
virtual int index() const
Definition Terminal.cc:274
virtual bool equals(const Terminal &other) const =0
virtual void setInstructionReference(InstructionReference ref)
Definition Terminal.cc:404
virtual bool isGPR() const
Definition Terminal.cc:107
virtual int operationIndex() const
Definition Terminal.cc:364
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
virtual bool isFUPort() const
Definition Terminal.cc:118
virtual TTAMachine::HWOperation * operation(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
static UniversalMachine & instance()
UniversalFunctionUnit & universalFunctionUnit() const
UnboundedRegisterFile & integerRegisterFile() const
TTAMachine::Bus & universalBus() const
MachineFrameInfo * curFrameInfo_
static unsigned POINTER_SIZE_64
std::map< TTAMachine::AddressSpace *, unsigned > dataEnds_
The first position after the last data in the given address space.
bool hasAmbiguousASpaceRefs(const TTAProgram::Instruction &instr) const
unsigned createDataDefinition(int addressSpaceId, unsigned &addr, const Constant *cv, bool forceInitialize=false, unsigned forceAlignment=0)
std::set< std::string > opset_
The operations supported by the current target machine.
virtual TTAProgram::Terminal * createMBBReference(const MachineOperand &mo)
void copyFUAnnotations(const std::vector< TTAProgram::Instruction * > &operandMoves, TTAProgram::Move &move) const
TTAProgram::Program * result()
TTAProgram::Instruction * emitSelect(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
std::vector< DataDef > data_
Data definitions.
TTAMachine::Machine * mach_
Machine for building the program.
TTAProgram::Instruction * emitSpecialInlineAsm(const std::string op, const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
static unsigned MAU_BITS
Target architechture MAU size in bits.
TTAProgram::DataMemory & dataMemoryForAddressSpace(TTAMachine::AddressSpace &aSpace)
TTAMachine::AddressSpace & addressSpaceById(unsigned id)
TTAProgram::TerminalRegister * createTerminalRegister(const std::string &rfName, int index)
virtual unsigned raPortDRegNum() const =0
std::map< TCEString, ProgramOperationPtr > labeledPOs_
std::vector< DataDef > udata_
std::set< TTAProgram::TerminalProgramOperation * > symbolicPORefs_
TTAProgram::Instruction * emitComparisonForBranch(TCEString firstOp, const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
void createExprDataDefinition(int addressSpaceId, unsigned &addr, const ConstantExpr *gv, int offset=0)
TTAMachine::AddressSpace * defaultDataAddressSpace_
The default data memory address space (address space 0).
unsigned & dataEnd(TTAMachine::AddressSpace &aSpace)
unsigned addressSpaceId(TTAMachine::AddressSpace &aSpace) const
TTAProgram::Instruction * emitOperationMacro(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
std::shared_ptr< TTAProgram::Move > createMove(const MachineOperand &src, const MachineOperand &dst, TTAProgram::MoveGuard *guard)
TTAProgram::Instruction * handleMemoryCategoryInfo(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
static unsigned POINTER_SIZE_32
Target architecture pointer size in maus.
TTAProgram::Instruction * emitReturnTo(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
const llvm::TargetMachine * tm_
Target machine description.
TTAProgram::Instruction * emitRemaingingBrach(TCEString opName, const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
TTAProgram::Terminal * createTerminal(const MachineOperand &mo, int bitLimit=0)
LLVMTCECmdLineOptions * options_
The compiler options.
void createFPDataDefinition(int addressSpaceId, unsigned &addr, const llvm::ConstantFP *cfp)
void createSPInitLoad(TTAProgram::CodeSnippet &target, TTAProgram::Terminal &src, TTAProgram::Terminal &dst)
TTAProgram::Instruction * emitSetjmp(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
virtual unsigned spDRegNum() const =0
std::string mbbName(const MachineBasicBlock &mbb)
TTAProgram::Instruction * emitGlobalXXtructorCalls(const MachineInstr *mi, TTAProgram::CodeSnippet *proc, bool constructors)
void addCandidateLSUAnnotations(unsigned asNum, TTAProgram::Move &move)
std::map< const llvm::BasicBlock *, TTAProgram::Instruction * > bbIndex_
Basic Block -> first instruction in the BB map.
static bool isInlineAsm(const MachineInstr &instr)
llvm::Mangler * mang_
Mangler for mangling label strings.
std::map< std::string, unsigned > dataLabels_
Data labels.
std::map< const llvm::Constant *, unsigned > globalCP_
Global constant pool for all constants gathered from machine functions. Map key is unique constant an...
TTAProgram::Instruction * emitWriteSP(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
std::vector< std::shared_ptr< TTAProgram::Move > > endReferences_
Dummy references to the _end symbol.
TTAProgram::Instruction * emitLongjmp(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
std::map< std::string, TTAProgram::Instruction * > mbbs_
Machine basic block -> first instruction in the BB map.
void createGlobalValueDataDefinition(int addressSpaceId, unsigned &addr, const GlobalValue *gv, int offset=0)
std::map< TTAProgram::TerminalInstructionAddress *, std::string > codeLabelReferences_
Dummy code label references that have to be fixed after all instrutions have been built.
virtual void emitSPInitialization()
void debugDataToAnnotations(const llvm::MachineInstr *mi, TTAProgram::Move &move)
TTAProgram::Program * prog_
Current program being built.
void emitDataDef(const DataDef &def)
TTAProgram::MoveGuard * createGuard(const TTAProgram::Terminal *guardReg, bool trueOrFalse)
std::vector< ConstantDataDef > cpData_
void emitConstantPool(const llvm::MachineConstantPool &cp)
const TTAMachine::HWOperation & getHWOperation(std::string opName)
bool multiDataMemMachine_
Set to true in case this machine has more than one data address spaces.
TTAProgram::Instruction * emitInstruction(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
bool isInitialized(const Constant *cv)
bool noAliasFound_
set to true in case at least one 'noalias' attribute (from the use of 'restricted' pointers) has been...
PRegionMarkerAnalyzer * pregions_
std::map< unsigned, unsigned > currentFnCP_
Constant pool for the current machine function. Map key is constant pool index and the value is addre...
const TargetMachine & targetMachine() const
std::map< TTAProgram::TerminalInstructionAddress *, std::string > mbbReferences_
Dummy basic block references that have to be fixed after all basic blocks have been built.
virtual TTAProgram::Terminal * createFUTerminal(const MachineOperand &) const
virtual TCEString operationName(const MachineInstr &mi) const =0
void setInitialStackPointerValue(unsigned value)
void createIntDataDefinition(int addressSpaceId, unsigned &addr, const llvm::ConstantInt *ci, bool isPointer=false)
void addPointerAnnotations(const llvm::MachineInstr *mi, TTAProgram::Move &move)
std::map< std::string, TTAProgram::Instruction * > codeLabels_
Code labels.
bool doFinalization(Module &M)
const llvm::DataLayout * dl_
The data layout for the machine.
TTAProgram::Instruction * emitInlineAsm(const MachineFunction &mf, const MachineInstr *mi, TTAProgram::BasicBlock *bb, TTAProgram::InstructionReferenceManager &irm)
virtual int registerIndex(unsigned llvmRegNum) const =0
virtual TTAProgram::Terminal * createSymbolReference(const MachineOperand &mo)
bool multiAddrSpacesFound_
set to true in case at least one non-default address space memory access has been found in the genera...
virtual TCEString registerFileName(unsigned llvmRegNum) const =0
TTAProgram::Instruction * emitReadSP(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
virtual TTAProgram::Terminal * createProgramOperationReference(const MachineOperand &mo)
bool runOnMachineFunction(MachineFunction &MF)
virtual TTAProgram::Instruction * emitMove(const MachineInstr *mi, TTAProgram::CodeSnippet *proc, bool conditional=false, bool trueGuard=true)
virtual bool isTTATarget() const
virtual bool writeMachineFunction(MachineFunction &MF)
TTAProgram::Instruction * emitReturn(const MachineInstr *mi, TTAProgram::CodeSnippet *proc)
TTAMachine::AddressSpace * instrAddressSpace_
virtual void createMoveNode(ProgramOperationPtr &, std::shared_ptr< TTAProgram::Move > m, bool)
bool doInitialization(Module &M)
void padToAlignment(int addressSpaceId, unsigned &addr, unsigned align)
std::string registerName(unsigned dwarfRegNum) const
std::string rfName(unsigned dwarfRegNum) const
unsigned registerIndex(unsigned dwarfRegNum) const
unsigned stackAlignment() const
Data definition structure for constant pool values.
Data definition structure for global values.
UnusedFunctionsList removeableFunctions
Definition MachineDCE.hh:97