diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2008-08-17 13:53:04 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2008-08-17 13:53:04 +0000 |
commit | abb247fc036d55d06b06853cae66ab055269d605 (patch) | |
tree | 28dea7527803dc00201a17e5beee6bae7031aea3 /lib/CodeGen/AsmPrinter.cpp | |
parent | 9e422dd4f630fe4d253143371488e25bfe5b0a79 (diff) |
Move all assembler printing related stuff into new libAsmPrinter
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54885 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/AsmPrinter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter.cpp | 1509 |
1 files changed, 0 insertions, 1509 deletions
diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp deleted file mode 100644 index 4d16c7b0f1..0000000000 --- a/lib/CodeGen/AsmPrinter.cpp +++ /dev/null @@ -1,1509 +0,0 @@ -//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the AsmPrinter class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/GCs.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Support/Mangler.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Streams.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" -#include <cerrno> -using namespace llvm; - -char AsmPrinter::ID = 0; -AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm, - const TargetAsmInfo *T) - : MachineFunctionPass((intptr_t)&ID), FunctionNumber(0), O(o), - TM(tm), TAI(T), TRI(tm.getRegisterInfo()), - IsInTextSection(false) -{} - -AsmPrinter::~AsmPrinter() { - for (gcp_iterator I = GCMetadataPrinters.begin(), - E = GCMetadataPrinters.end(); I != E; ++I) - delete I->second; -} - -std::string AsmPrinter::getSectionForFunction(const Function &F) const { - return TAI->getTextSection(); -} - - -/// SwitchToTextSection - Switch to the specified text section of the executable -/// if we are not already in it! -/// -void AsmPrinter::SwitchToTextSection(const char *NewSection, - const GlobalValue *GV) { - std::string NS; - if (GV && GV->hasSection()) - NS = TAI->getSwitchToSectionDirective() + GV->getSection(); - else - NS = NewSection; - - // If we're already in this section, we're done. - if (CurrentSection == NS) return; - - // Close the current section, if applicable. - if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) - O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; - - CurrentSection = NS; - - if (!CurrentSection.empty()) - O << CurrentSection << TAI->getTextSectionStartSuffix() << '\n'; - - IsInTextSection = true; -} - -/// SwitchToDataSection - Switch to the specified data section of the executable -/// if we are not already in it! -/// -void AsmPrinter::SwitchToDataSection(const char *NewSection, - const GlobalValue *GV) { - std::string NS; - if (GV && GV->hasSection()) - NS = TAI->getSwitchToSectionDirective() + GV->getSection(); - else - NS = NewSection; - - // If we're already in this section, we're done. - if (CurrentSection == NS) return; - - // Close the current section, if applicable. - if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) - O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; - - CurrentSection = NS; - - if (!CurrentSection.empty()) - O << CurrentSection << TAI->getDataSectionStartSuffix() << '\n'; - - IsInTextSection = false; -} - - -void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { - MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired<CollectorModuleMetadata>(); -} - -bool AsmPrinter::doInitialization(Module &M) { - Mang = new Mangler(M, TAI->getGlobalPrefix()); - - CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); - assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?"); - for (CollectorModuleMetadata::iterator I = CMM->begin(), - E = CMM->end(); I != E; ++I) - if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*I)) - GCP->beginAssembly(O, *this, *TAI); -<<<<<<< HEAD:lib/CodeGen/AsmPrinter.cpp -======= - ->>>>>>> Factor out asmprinters from collector interface.:lib/CodeGen/AsmPrinter.cpp - - if (!M.getModuleInlineAsm().empty()) - O << TAI->getCommentString() << " Start of file scope inline assembly\n" - << M.getModuleInlineAsm() - << '\n' << TAI->getCommentString() - << " End of file scope inline assembly\n"; - - SwitchToDataSection(""); // Reset back to no section. - - MMI = getAnalysisToUpdate<MachineModuleInfo>(); - if (MMI) MMI->AnalyzeModule(M); - - return false; -} - -bool AsmPrinter::doFinalization(Module &M) { - if (TAI->getWeakRefDirective()) { - if (!ExtWeakSymbols.empty()) - SwitchToDataSection(""); - - for (std::set<const GlobalValue*>::iterator i = ExtWeakSymbols.begin(), - e = ExtWeakSymbols.end(); i != e; ++i) { - const GlobalValue *GV = *i; - std::string Name = Mang->getValueName(GV); - O << TAI->getWeakRefDirective() << Name << '\n'; - } - } - - if (TAI->getSetDirective()) { - if (!M.alias_empty()) - SwitchToTextSection(TAI->getTextSection()); - - O << '\n'; - for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); - I!=E; ++I) { - std::string Name = Mang->getValueName(I); - std::string Target; - - const GlobalValue *GV = cast<GlobalValue>(I->getAliasedGlobal()); - Target = Mang->getValueName(GV); - - if (I->hasExternalLinkage() || !TAI->getWeakRefDirective()) - O << "\t.globl\t" << Name << '\n'; - else if (I->hasWeakLinkage()) - O << TAI->getWeakRefDirective() << Name << '\n'; - else if (!I->hasInternalLinkage()) - assert(0 && "Invalid alias linkage"); - - if (I->hasHiddenVisibility()) { - if (const char *Directive = TAI->getHiddenDirective()) - O << Directive << Name << '\n'; - } else if (I->hasProtectedVisibility()) { - if (const char *Directive = TAI->getProtectedDirective()) - O << Directive << Name << '\n'; - } - - O << TAI->getSetDirective() << ' ' << Name << ", " << Target << '\n'; - - // If the aliasee has external weak linkage it can be referenced only by - // alias itself. In this case it can be not in ExtWeakSymbols list. Emit - // weak reference in such case. - if (GV->hasExternalWeakLinkage()) { - if (TAI->getWeakRefDirective()) - O << TAI->getWeakRefDirective() << Target << '\n'; - else - O << "\t.globl\t" << Target << '\n'; - } - } - } - - CollectorModuleMetadata *CMM = getAnalysisToUpdate<CollectorModuleMetadata>(); - assert(CMM && "AsmPrinter didn't require CollectorModuleMetadata?"); - for (CollectorModuleMetadata::iterator I = CMM->end(), - E = CMM->begin(); I != E; ) - if (GCMetadataPrinter *GCP = GetOrCreateGCPrinter(*--I)) - GCP->finishAssembly(O, *this, *TAI); - - // If we don't have any trampolines, then we don't require stack memory - // to be executable. Some targets have a directive to declare this. - Function* InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); - if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) - if (TAI->getNonexecutableStackDirective()) - O << TAI->getNonexecutableStackDirective() << '\n'; - - delete Mang; Mang = 0; - return false; -} - -std::string AsmPrinter::getCurrentFunctionEHName(const MachineFunction *MF) { - assert(MF && "No machine function?"); - std::string Name = MF->getFunction()->getName(); - if (Name.empty()) - Name = Mang->getValueName(MF->getFunction()); - return Mang->makeNameProper(Name + ".eh", TAI->getGlobalPrefix()); -} - -void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { - // What's my mangled name? - CurrentFnName = Mang->getValueName(MF.getFunction()); - IncrementFunctionNumber(); -} - -/// EmitConstantPool - Print to the current output stream assembly -/// representations of the constants in the constant pool MCP. This is -/// used to print out constants which have been "spilled to memory" by -/// the code generator. -/// -void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { - const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); - if (CP.empty()) return; - - // Some targets require 4-, 8-, and 16- byte constant literals to be placed - // in special sections. - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > FourByteCPs; - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > EightByteCPs; - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > SixteenByteCPs; - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > OtherCPs; - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > TargetCPs; - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - MachineConstantPoolEntry CPE = CP[i]; - const Type *Ty = CPE.getType(); - if (TAI->getFourByteConstantSection() && - TM.getTargetData()->getABITypeSize(Ty) == 4) - FourByteCPs.push_back(std::make_pair(CPE, i)); - else if (TAI->getEightByteConstantSection() && - TM.getTargetData()->getABITypeSize(Ty) == 8) - EightByteCPs.push_back(std::make_pair(CPE, i)); - else if (TAI->getSixteenByteConstantSection() && - TM.getTargetData()->getABITypeSize(Ty) == 16) - SixteenByteCPs.push_back(std::make_pair(CPE, i)); - else - OtherCPs.push_back(std::make_pair(CPE, i)); - } - - unsigned Alignment = MCP->getConstantPoolAlignment(); - EmitConstantPool(Alignment, TAI->getFourByteConstantSection(), FourByteCPs); - EmitConstantPool(Alignment, TAI->getEightByteConstantSection(), EightByteCPs); - EmitConstantPool(Alignment, TAI->getSixteenByteConstantSection(), - SixteenByteCPs); - EmitConstantPool(Alignment, TAI->getConstantPoolSection(), OtherCPs); -} - -void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section, - std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP) { - if (CP.empty()) return; - - SwitchToDataSection(Section); - EmitAlignment(Alignment); - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << CP[i].second << ":\t\t\t\t\t" << TAI->getCommentString() << ' '; - WriteTypeSymbolic(O, CP[i].first.getType(), 0) << '\n'; - if (CP[i].first.isMachineConstantPoolEntry()) - EmitMachineConstantPoolValue(CP[i].first.Val.MachineCPVal); - else - EmitGlobalConstant(CP[i].first.Val.ConstVal); - if (i != e-1) { - const Type *Ty = CP[i].first.getType(); - unsigned EntSize = - TM.getTargetData()->getABITypeSize(Ty); - unsigned ValEnd = CP[i].first.getOffset() + EntSize; - // Emit inter-object padding for alignment. - EmitZeros(CP[i+1].first.getOffset()-ValEnd); - } - } -} - -/// EmitJumpTableInfo - Print assembly representations of the jump tables used -/// by the current function to the current output stream. -/// -void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, - MachineFunction &MF) { - const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); - if (JT.empty()) return; - - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; - - // Pick the directive to use to print the jump table entries, and switch to - // the appropriate section. - TargetLowering *LoweringInfo = TM.getTargetLowering(); - - const char* JumpTableDataSection = TAI->getJumpTableDataSection(); - const Function *F = MF.getFunction(); - unsigned SectionFlags = TAI->SectionFlagsForGlobal(F); - if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) || - !JumpTableDataSection || - SectionFlags & SectionFlags::Linkonce) { - // In PIC mode, we need to emit the jump table to the same section as the - // function body itself, otherwise the label differences won't make sense. - // We should also do if the section name is NULL or function is declared in - // discardable section. - SwitchToTextSection(getSectionForFunction(*F).c_str(), F); - } else { - SwitchToDataSection(JumpTableDataSection); - } - - EmitAlignment(Log2_32(MJTI->getAlignment())); - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs; - - // If this jump table was deleted, ignore it. - if (JTBBs.empty()) continue; - - // For PIC codegen, if possible we want to use the SetDirective to reduce - // the number of relocations the assembler will generate for the jump table. - // Set directives are all printed before the jump table itself. - SmallPtrSet<MachineBasicBlock*, 16> EmittedSets; - if (TAI->getSetDirective() && IsPic) - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) - if (EmittedSets.insert(JTBBs[ii])) - printPICJumpTableSetLabel(i, JTBBs[ii]); - - // On some targets (e.g. darwin) we want to emit two consequtive labels - // before each jump table. The first label is never referenced, but tells - // the assembler and linker the extents of the jump table object. The - // second label is actually referenced by the code. - if (const char *JTLabelPrefix = TAI->getJumpTableSpecialLabelPrefix()) - O << JTLabelPrefix << "JTI" << getFunctionNumber() << '_' << i << ":\n"; - - O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << i << ":\n"; - - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { - printPICJumpTableEntry(MJTI, JTBBs[ii], i); - O << '\n'; - } - } -} - -void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const { - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; - - // Use JumpTableDirective otherwise honor the entry size from the jump table - // info. - const char *JTEntryDirective = TAI->getJumpTableDirective(); - bool HadJTEntryDirective = JTEntryDirective != NULL; - if (!HadJTEntryDirective) { - JTEntryDirective = MJTI->getEntrySize() == 4 ? - TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); - } - - O << JTEntryDirective << ' '; - - // If we have emitted set directives for the jump table entries, print - // them rather than the entries themselves. If we're emitting PIC, then - // emit the table entries as differences between two text section labels. - // If we're emitting non-PIC code, then emit the entries as direct - // references to the target basic blocks. - if (IsPic) { - if (TAI->getSetDirective()) { - O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << uid << "_set_" << MBB->getNumber(); - } else { - printBasicBlockLabel(MBB, false, false, false); - // If the arch uses custom Jump Table directives, don't calc relative to - // JT - if (!HadJTEntryDirective) - O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" - << getFunctionNumber() << '_' << uid; - } - } else { - printBasicBlockLabel(MBB, false, false, false); - } -} - - -/// EmitSpecialLLVMGlobal - Check to see if the specified global is a -/// special global used by LLVM. If so, emit it and return true, otherwise -/// do nothing and return false. -bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { - if (GV->getName() == "llvm.used") { - if (TAI->getUsedDirective() != 0) // No need to emit this at all. - EmitLLVMUsedList(GV->getInitializer()); - return true; - } - - // Ignore debug and non-emitted data. - if (GV->getSection() == "llvm.metadata") return true; - - if (!GV->hasAppendingLinkage()) return false; - - assert(GV->hasInitializer() && "Not a special LLVM global!"); - - const TargetData *TD = TM.getTargetData(); - unsigned Align = Log2_32(TD->getPointerPrefAlignment()); - if (GV->getName() == "llvm.global_ctors" && GV->use_empty()) { - SwitchToDataSection(TAI->getStaticCtorsSection()); - EmitAlignment(Align, 0); - EmitXXStructorList(GV->getInitializer()); - return true; - } - - if (GV->getName() == "llvm.global_dtors" && GV->use_empty()) { - SwitchToDataSection(TAI->getStaticDtorsSection()); - EmitAlignment(Align, 0); - EmitXXStructorList(GV->getInitializer()); - return true; - } - - return false; -} - -/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each -/// global in the specified llvm.used list as being used with this directive. -void AsmPrinter::EmitLLVMUsedList(Constant *List) { - const char *Directive = TAI->getUsedDirective(); - - // Should be an array of 'sbyte*'. - ConstantArray *InitList = dyn_cast<ConstantArray>(List); - if (InitList == 0) return; - - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - O << Directive; - EmitConstantValueOnly(InitList->getOperand(i)); - O << '\n'; - } -} - -/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the -/// function pointers, ignoring the init priority. -void AsmPrinter::EmitXXStructorList(Constant *List) { - // Should be an array of '{ int, void ()* }' structs. The first value is the - // init priority, which we ignore. - if (!isa<ConstantArray>(List)) return; - ConstantArray *InitList = cast<ConstantArray>(List); - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) - if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){ - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. - - if (CS->getOperand(1)->isNullValue()) - return; // Found a null terminator, exit printing. - // Emit the function pointer. - EmitGlobalConstant(CS->getOperand(1)); - } -} - -/// getGlobalLinkName - Returns the asm/link name of of the specified -/// global variable. Should be overridden by each target asm printer to -/// generate the appropriate value. -const std::string AsmPrinter::getGlobalLinkName(const GlobalVariable *GV) const{ - std::string LinkName; - - if (isa<Function>(GV)) { - LinkName += TAI->getFunctionAddrPrefix(); - LinkName += Mang->getValueName(GV); - LinkName += TAI->getFunctionAddrSuffix(); - } else { - LinkName += TAI->getGlobalVarAddrPrefix(); - LinkName += Mang->getValueName(GV); - LinkName += TAI->getGlobalVarAddrSuffix(); - } - - return LinkName; -} - -/// EmitExternalGlobal - Emit the external reference to a global variable. -/// Should be overridden if an indirect reference should be used. -void AsmPrinter::EmitExternalGlobal(const GlobalVariable *GV) { - O << getGlobalLinkName(GV); -} - - - -//===----------------------------------------------------------------------===// -/// LEB 128 number encoding. - -/// PrintULEB128 - Print a series of hexidecimal values (separated by commas) -/// representing an unsigned leb128 value. -void AsmPrinter::PrintULEB128(unsigned Value) const { - do { - unsigned Byte = Value & 0x7f; - Value >>= 7; - if (Value) Byte |= 0x80; - O << "0x" << std::hex << Byte << std::dec; - if (Value) O << ", "; - } while (Value); -} - -/// PrintSLEB128 - Print a series of hexidecimal values (separated by commas) -/// representing a signed leb128 value. -void AsmPrinter::PrintSLEB128(int Value) const { - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - unsigned Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - O << "0x" << std::hex << Byte << std::dec; - if (IsMore) O << ", "; - } while (IsMore); -} - -//===--------------------------------------------------------------------===// -// Emission and print routines -// - -/// PrintHex - Print a value as a hexidecimal value. -/// -void AsmPrinter::PrintHex(int Value) const { - O << "0x" << std::hex << Value << std::dec; -} - -/// EOL - Print a newline character to asm stream. If a comment is present -/// then it will be printed first. Comments should not contain '\n'. -void AsmPrinter::EOL() const { - O << '\n'; -} - -void AsmPrinter::EOL(const std::string &Comment) const { - if (VerboseAsm && !Comment.empty()) { - O << '\t' - << TAI->getCommentString() - << ' ' - << Comment; - } - O << '\n'; -} - -void AsmPrinter::EOL(const char* Comment) const { - if (VerboseAsm && *Comment) { - O << '\t' - << TAI->getCommentString() - << ' ' - << Comment; - } - O << '\n'; -} - -/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an -/// unsigned leb128 value. -void AsmPrinter::EmitULEB128Bytes(unsigned Value) const { - if (TAI->hasLEB128()) { - O << "\t.uleb128\t" - << Value; - } else { - O << TAI->getData8bitsDirective(); - PrintULEB128(Value); - } -} - -/// EmitSLEB128Bytes - print an assembler byte data directive to compose a -/// signed leb128 value. -void AsmPrinter::EmitSLEB128Bytes(int Value) const { - if (TAI->hasLEB128()) { - O << "\t.sleb128\t" - << Value; - } else { - O << TAI->getData8bitsDirective(); - PrintSLEB128(Value); - } -} - -/// EmitInt8 - Emit a byte directive and value. -/// -void AsmPrinter::EmitInt8(int Value) const { - O << TAI->getData8bitsDirective(); - PrintHex(Value & 0xFF); -} - -/// EmitInt16 - Emit a short directive and value. -/// -void AsmPrinter::EmitInt16(int Value) const { - O << TAI->getData16bitsDirective(); - PrintHex(Value & 0xFFFF); -} - -/// EmitInt32 - Emit a long directive and value. -/// -void AsmPrinter::EmitInt32(int Value) const { - O << TAI->getData32bitsDirective(); - PrintHex(Value); -} - -/// EmitInt64 - Emit a long long directive and value. -/// -void AsmPrinter::EmitInt64(uint64_t Value) const { - if (TAI->getData64bitsDirective()) { - O << TAI->getData64bitsDirective(); - PrintHex(Value); - } else { - if (TM.getTargetData()->isBigEndian()) { - EmitInt32(unsigned(Value >> 32)); O << '\n'; - EmitInt32(unsigned(Value)); - } else { - EmitInt32(unsigned(Value)); O << '\n'; - EmitInt32(unsigned(Value >> 32)); - } - } -} - -/// toOctal - Convert the low order bits of X into an octal digit. -/// -static inline char toOctal(int X) { - return (X&7)+'0'; -} - -/// printStringChar - Print a char, escaped if necessary. -/// -static void printStringChar(std::ostream &O, unsigned char C) { - if (C == '"') { - O << "\\\""; - } else if (C == '\\') { - O << "\\\\"; - } else if (isprint(C)) { - O << C; - } else { - switch(C) { - case '\b': O << "\\b"; break; - case '\f': O << "\\f"; break; - case '\n': O << "\\n"; break; - case '\r': O << "\\r"; break; - case '\t': O << "\\t"; break; - default: - O << '\\'; - O << toOctal(C >> 6); - O << toOctal(C >> 3); - O << toOctal(C >> 0); - break; - } - } -} - -/// EmitString - Emit a string with quotes and a null terminator. -/// Special characters are emitted properly. -/// \literal (Eg. '\t') \endliteral -void AsmPrinter::EmitString(const std::string &String) const { - const char* AscizDirective = TAI->getAscizDirective(); - if (AscizDirective) - O << AscizDirective; - else - O << TAI->getAsciiDirective(); - O << '\"'; - for (unsigned i = 0, N = String.size(); i < N; ++i) { - unsigned char C = String[i]; - printStringChar(O, C); - } - if (AscizDirective) - O << '\"'; - else - O << "\\0\""; -} - - -/// EmitFile - Emit a .file directive. -void AsmPrinter::EmitFile(unsigned Number, const std::string &Name) const { - O << "\t.file\t" << Number << " \""; - for (unsigned i = 0, N = Name.size(); i < N; ++i) { - unsigned char C = Name[i]; - printStringChar(O, C); - } - O << '\"'; -} - - -//===----------------------------------------------------------------------===// - -// EmitAlignment - Emit an alignment directive to the specified power of -// two boundary. For example, if you pass in 3 here, you will get an 8 -// byte alignment. If a global value is specified, and if that global has -// an explicit alignment requested, it will unconditionally override the -// alignment request. However, if ForcedAlignBits is specified, this value -// has final say: the ultimate alignment will be the max of ForcedAlignBits -// and the alignment computed with NumBits and the global. -// -// The algorithm is: -// Align = NumBits; -// if (GV && GV->hasalignment) Align = GV->getalignment(); -// Align = std::max(Align, ForcedAlignBits); -// -void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV, - unsigned ForcedAlignBits, - bool UseFillExpr) const { - if (GV && GV->getAlignment()) - NumBits = Log2_32(GV->getAlignment()); - NumBits = std::max(NumBits, ForcedAlignBits); - - if (NumBits == 0) return; // No need to emit alignment. - if (TAI->getAlignmentIsInBytes()) NumBits = 1 << NumBits; - O << TAI->getAlignDirective() << NumBits; - - unsigned FillValue = TAI->getTextAlignFillValue(); - UseFillExpr &= IsInTextSection && FillValue; - if (UseFillExpr) O << ",0x" << std::hex << FillValue << std::dec; - O << '\n'; -} - - -/// EmitZeros - Emit a block of zeros. -/// -void AsmPrinter::EmitZeros(uint64_t NumZeros) const { - if (NumZeros) { - if (TAI->getZeroDirective()) { - O << TAI->getZeroDirective() << NumZeros; - if (TAI->getZeroDirectiveSuffix()) - O << TAI->getZeroDirectiveSuffix(); - O << '\n'; - } else { - for (; NumZeros; --NumZeros) - O << TAI->getData8bitsDirective() << "0\n"; - } - } -} - -// Print out the specified constant, without a storage class. Only the -// constants valid in constant expressions can occur here. -void AsmPrinter::EmitConstantValueOnly(const Constant *CV) { - if (CV->isNullValue() || isa<UndefValue>(CV)) - O << '0'; - else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - O << CI->getZExtValue(); - } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) { - // This is a constant address for a global variable or function. Use the - // name of the variable or function as the address value, possibly - // decorating it with GlobalVarAddrPrefix/Suffix or - // FunctionAddrPrefix/Suffix (these all default to "" ) - if (isa<Function>(GV)) { - O << TAI->getFunctionAddrPrefix() - << Mang->getValueName(GV) - << TAI->getFunctionAddrSuffix(); - } else { - O << TAI->getGlobalVarAddrPrefix() - << Mang->getValueName(GV) - << TAI->getGlobalVarAddrSuffix(); - } - } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { - const TargetData *TD = TM.getTargetData(); - unsigned Opcode = CE->getOpcode(); - switch (Opcode) { - case Instruction::GetElementPtr: { - // generate a symbolic expression for the byte address - const Constant *ptrVal = CE->getOperand(0); - SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end()); - if (int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], - idxVec.size())) { - if (Offset) - O << '('; - EmitConstantValueOnly(ptrVal); - if (Offset > 0) - O << ") + " << Offset; - else if (Offset < 0) - O << ") - " << -Offset; - } else { - EmitConstantValueOnly(ptrVal); - } - break; - } - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - assert(0 && "FIXME: Don't yet support this kind of constant cast expr"); - break; - case Instruction::BitCast: - return EmitConstantValueOnly(CE->getOperand(0)); - - case Instruction::IntToPtr: { - // Handle casts to pointers by changing them into casts to the appropriate - // integer type. This promotes constant folding and simplifies this code. - Constant *Op = CE->getOperand(0); - Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(), false/*ZExt*/); - return EmitConstantValueOnly(Op); - } - - - case Instruction::PtrToInt: { - // Support only foldable casts to/from pointers that can be eliminated by - // changing the pointer to the appropriately sized integer type. - Constant *Op = CE->getOperand(0); - const Type *Ty = CE->getType(); - - // We can emit the pointer value into this slot if the slot is an - // integer slot greater or equal to the size of the pointer. - if (TD->getABITypeSize(Ty) >= TD->getABITypeSize(Op->getType())) - return EmitConstantValueOnly(Op); - - O << "(("; - EmitConstantValueOnly(Op); - APInt ptrMask = APInt::getAllOnesValue(TD->getABITypeSizeInBits(Ty)); - - SmallString<40> S; - ptrMask.toStringUnsigned(S); - O << ") & " << S.c_str() << ')'; - break; - } - case Instruction::Add: - case Instruction::Sub: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - O << '('; - EmitConstantValueOnly(CE->getOperand(0)); - O << ')'; - switch (Opcode) { - case Instruction::Add: - O << " + "; - break; - case Instruction::Sub: - O << " - "; - break; - case Instruction::And: - O << " & "; - break; - case Instruction::Or: - O << " | "; - break; - case Instruction::Xor: - O << " ^ "; - break; - default: - break; - } - O << '('; - EmitConstantValueOnly(CE->getOperand(1)); - O << ')'; - break; - default: - assert(0 && "Unsupported operator!"); - } - } else { - assert(0 && "Unknown constant value!"); - } -} - -/// printAsCString - Print the specified array as a C compatible string, only if -/// the predicate isString is true. -/// -static void printAsCString(std::ostream &O, const ConstantArray *CVA, - unsigned LastElt) { - assert(CVA->isString() && "Array is not string compatible!"); - - O << '\"'; - for (unsigned i = 0; i != LastElt; ++i) { - unsigned char C = - (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getZExtValue(); - printStringChar(O, C); - } - O << '\"'; -} - -/// EmitString - Emit a zero-byte-terminated string constant. -/// -void AsmPrinter::EmitString(const ConstantArray *CVA) const { - unsigned NumElts = CVA->getNumOperands(); - if (TAI->getAscizDirective() && NumElts && - cast<ConstantInt>(CVA->getOperand(NumElts-1))->getZExtValue() == 0) { - O << TAI->getAscizDirective(); - printAsCString(O, CVA, NumElts-1); - } else { - O << TAI->getAsciiDirective(); - printAsCString(O, CVA, NumElts); - } - O << '\n'; -} - -/// EmitGlobalConstant - Print a general LLVM constant to the .s file. -void AsmPrinter::EmitGlobalConstant(const Constant *CV) { - const TargetData *TD = TM.getTargetData(); - unsigned Size = TD->getABITypeSize(CV->getType()); - - if (CV->isNullValue() || isa<UndefValue>(CV)) { - EmitZeros(Size); - return; - } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { - if (CVA->isString()) { - EmitString(CVA); - } else { // Not a string. Print the values in successive locations - for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) - EmitGlobalConstant(CVA->getOperand(i)); - } - return; - } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { - // Print the fields in successive locations. Pad to align if needed! - const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); - uint64_t sizeSoFar = 0; - for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { - const Constant* field = CVS->getOperand(i); - - // Check if padding is needed and insert one or more 0s. - uint64_t fieldSize = TD->getABITypeSize(field->getType()); - uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) - - cvsLayout->getElementOffset(i)) - fieldSize; - sizeSoFar += fieldSize + padSize; - - // Now print the actual field value. - EmitGlobalConstant(field); - - // Insert padding - this may include padding to increase the size of the - // current field up to the ABI size (if the struct is not packed) as well - // as padding to ensure that the next field starts at the right offset. - EmitZeros(padSize); - } - assert(sizeSoFar == cvsLayout->getSizeInBytes() && - "Layout of constant struct may be incorrect!"); - return; - } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { - // FP Constants are printed as integer constants to avoid losing - // precision... - if (CFP->getType() == Type::DoubleTy) { - double Val = CFP->getValueAPF().convertToDouble(); // for comment only - uint64_t i = CFP->getValueAPF().convertToAPInt().getZExtValue(); - if (TAI->getData64bitsDirective()) - O << TAI->getData64bitsDirective() << i << '\t' - << TAI->getC |