#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/GCMetadataPrinter.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/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include <cerrno>
using namespace llvm;
char AsmPrinter::ID = 0;
-AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm,
+AsmPrinter::AsmPrinter(raw_ostream &o, TargetMachine &tm,
const TargetAsmInfo *T)
- : MachineFunctionPass((intptr_t)&ID), FunctionNumber(0), O(o),
+ : MachineFunctionPass(&ID), FunctionNumber(0), O(o),
TM(tm), TAI(T), TRI(tm.getRegisterInfo()),
IsInTextSection(false)
{}
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!
IsInTextSection = false;
}
+/// SwitchToSection - Switch to the specified section of the executable if we
+/// are not already in it!
+void AsmPrinter::SwitchToSection(const Section* NS) {
+ const std::string& NewSection = NS->getName();
+
+ // If we're already in this section, we're done.
+ if (CurrentSection == NewSection) return;
+
+ // Close the current section, if applicable.
+ if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+ O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
+
+ // FIXME: Make CurrentSection a Section* in the future
+ CurrentSection = NewSection;
+ CurrentSection_ = NS;
+
+ if (!CurrentSection.empty()) {
+ // If section is named we need to switch into it via special '.section'
+ // directive and also append funky flags. Otherwise - section name is just
+ // some magic assembler directive.
+ if (NS->isNamed())
+ O << TAI->getSwitchToSectionDirective()
+ << CurrentSection
+ << TAI->getSectionFlags(NS->getFlags());
+ else
+ O << CurrentSection;
+ O << TAI->getDataSectionStartSuffix() << '\n';
+ }
+
+ IsInTextSection = (NS->getFlags() & SectionFlags::Code);
+}
void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
- AU.addRequired<CollectorModuleMetadata>();
+ AU.addRequired<GCModuleInfo>();
}
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
+ GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I)
+ if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
+ MP->beginAssembly(O, *this, *TAI);
if (!M.getModuleInlineAsm().empty())
O << TAI->getCommentString() << " Start of file scope inline assembly\n"
if (TAI->getSetDirective()) {
if (!M.alias_empty())
- SwitchToTextSection(TAI->getTextSection());
+ SwitchToSection(TAI->getTextSection());
O << '\n';
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
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())
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';
- }
+ printVisibility(Name, I->getVisibility());
O << TAI->getSetDirective() << ' ' << Name << ", " << 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);
+ GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; )
+ if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I))
+ MP->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.
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;
+ // Calculate sections for constant pool entries. We collect entries to go into
+ // the same section together to reduce amount of section switch statements.
+ typedef
+ std::multimap<const Section*,
+ std::pair<MachineConstantPoolEntry, unsigned> > CPMap;
+ CPMap CPs;
+ SmallPtrSet<const Section*, 5> Sections;
+
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));
+ const Section* S = TAI->SelectSectionForMachineConst(CPE.getType());
+ CPs.insert(std::make_pair(S, std::make_pair(CPE, i)));
+ Sections.insert(S);
}
- 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;
+ // Now print stuff into the calculated sections.
+ for (SmallPtrSet<const Section*, 5>::iterator IS = Sections.begin(),
+ ES = Sections.end(); IS != ES; ++IS) {
+ SwitchToSection(*IS);
+ EmitAlignment(MCP->getConstantPoolAlignment());
+
+ std::pair<CPMap::iterator, CPMap::iterator> II = CPs.equal_range(*IS);
+ for (CPMap::iterator I = II.first, E = II.second; I != E; ++I) {
+ CPMap::iterator J = next(I);
+ MachineConstantPoolEntry Entry = I->second.first;
+ unsigned index = I->second.second;
+
+ O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+ << index << ":\t\t\t\t\t";
+ // O << TAI->getCommentString() << ' ' <<
+ // WriteTypeSymbolic(O, CP[i].first.getType(), 0);
+ O << '\n';
+ if (Entry.isMachineConstantPoolEntry())
+ EmitMachineConstantPoolValue(Entry.Val.MachineCPVal);
+ else
+ EmitGlobalConstant(Entry.Val.ConstVal);
- 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);
+ if (J != E) {
+ const Type *Ty = Entry.getType();
+ unsigned EntSize = TM.getTargetData()->getABITypeSize(Ty);
+ unsigned ValEnd = Entry.getOffset() + EntSize;
+ EmitZeros(J->second.first.getOffset()-ValEnd);
+ }
}
}
}
// 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);
+ SwitchToSection(TAI->SectionForGlobal(F));
} else {
SwitchToDataSection(JumpTableDataSection);
}
return false;
}
+/// findGlobalValue - if CV is an expression equivalent to a single
+/// global value, return that value.
+const GlobalValue * AsmPrinter::findGlobalValue(const Constant *CV) {
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
+ return GV;
+ else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+ const TargetData *TD = TM.getTargetData();
+ unsigned Opcode = CE->getOpcode();
+ switch (Opcode) {
+ case Instruction::GetElementPtr: {
+ const Constant *ptrVal = CE->getOperand(0);
+ SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
+ if (TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], idxVec.size()))
+ return 0;
+ return findGlobalValue(ptrVal);
+ }
+ case Instruction::BitCast:
+ return findGlobalValue(CE->getOperand(0));
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each
-/// global in the specified llvm.used list as being used with this directive.
+/// global in the specified llvm.used list for which emitUsedDirectiveFor
+/// is true, as being used with this directive.
+
void AsmPrinter::EmitLLVMUsedList(Constant *List) {
const char *Directive = TAI->getUsedDirective();
if (InitList == 0) return;
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
- O << Directive;
- EmitConstantValueOnly(InitList->getOperand(i));
- O << '\n';
+ const GlobalValue *GV = findGlobalValue(InitList->getOperand(i));
+ if (TAI->emitUsedDirectiveFor(GV, Mang)) {
+ O << Directive;
+ EmitConstantValueOnly(InitList->getOperand(i));
+ O << '\n';
+ }
}
}
unsigned Byte = Value & 0x7f;
Value >>= 7;
if (Value) Byte |= 0x80;
- O << "0x" << std::hex << Byte << std::dec;
+ O << "0x" << utohexstr(Byte);
if (Value) O << ", ";
} while (Value);
}
Value >>= 7;
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
if (IsMore) Byte |= 0x80;
- O << "0x" << std::hex << Byte << std::dec;
+ O << "0x" << utohexstr(Byte);
if (IsMore) O << ", ";
} while (IsMore);
}
/// PrintHex - Print a value as a hexidecimal value.
///
void AsmPrinter::PrintHex(int Value) const {
- O << "0x" << std::hex << Value << std::dec;
+ O << "0x" << utohexstr(static_cast<unsigned>(Value));
}
/// EOL - Print a newline character to asm stream. If a comment is present
/// printStringChar - Print a char, escaped if necessary.
///
-static void printStringChar(std::ostream &O, unsigned char C) {
+static void printStringChar(raw_ostream &O, char C) {
if (C == '"') {
O << "\\\"";
} else if (C == '\\') {
unsigned FillValue = TAI->getTextAlignFillValue();
UseFillExpr &= IsInTextSection && FillValue;
- if (UseFillExpr) O << ",0x" << std::hex << FillValue << std::dec;
+ if (UseFillExpr) O << ",0x" << utohexstr(FillValue);
O << '\n';
}
/// 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,
+static void printAsCString(raw_ostream &O, const ConstantArray *CVA,
unsigned LastElt) {
assert(CVA->isString() && "Array is not string compatible!");
// precision...
if (CFP->getType() == Type::DoubleTy) {
double Val = CFP->getValueAPF().convertToDouble(); // for comment only
- uint64_t i = CFP->getValueAPF().convertToAPInt().getZExtValue();
+ uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (TAI->getData64bitsDirective())
O << TAI->getData64bitsDirective() << i << '\t'
<< TAI->getCommentString() << " double value: " << Val << '\n';
} else if (CFP->getType() == Type::FloatTy) {
float Val = CFP->getValueAPF().convertToFloat(); // for comment only
O << TAI->getData32bitsDirective()
- << CFP->getValueAPF().convertToAPInt().getZExtValue()
+ << CFP->getValueAPF().bitcastToAPInt().getZExtValue()
<< '\t' << TAI->getCommentString() << " float " << Val << '\n';
return;
} else if (CFP->getType() == Type::X86_FP80Ty) {
// all long double variants are printed as hex
// api needed to prevent premature destruction
- APInt api = CFP->getValueAPF().convertToAPInt();
+ APInt api = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = api.getRawData();
+ // Convert to double so we can print the approximate val as a comment.
APFloat DoubleVal = CFP->getValueAPF();
- DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
+ bool ignored;
+ DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
+ &ignored);
if (TD->isBigEndian()) {
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
<< '\t' << TAI->getCommentString()
} else if (CFP->getType() == Type::PPC_FP128Ty) {
// all long double variants are printed as hex
// api needed to prevent premature destruction
- APInt api = CFP->getValueAPF().convertToAPInt();
+ APInt api = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = api.getRawData();
if (TD->isBigEndian()) {
O << TAI->getData32bitsDirective() << uint32_t(p[0] >> 32)
}
return;
} else assert(0 && "Floating point constant type not handled");
- } else if (CV->getType() == Type::Int64Ty) {
+ } else if (CV->getType()->isInteger() &&
+ cast<IntegerType>(CV->getType())->getBitWidth() >= 64) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- uint64_t Val = CI->getZExtValue();
-
- if (TAI->getData64bitsDirective())
- O << TAI->getData64bitsDirective() << Val << '\n';
- else if (TD->isBigEndian()) {
- O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
- << '\t' << TAI->getCommentString()
- << " Double-word most significant word " << Val << '\n';
- O << TAI->getData32bitsDirective() << unsigned(Val)
- << '\t' << TAI->getCommentString()
- << " Double-word least significant word " << Val << '\n';
- } else {
- O << TAI->getData32bitsDirective() << unsigned(Val)
- << '\t' << TAI->getCommentString()
- << " Double-word least significant word " << Val << '\n';
- O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
- << '\t' << TAI->getCommentString()
- << " Double-word most significant word " << Val << '\n';
+ unsigned BitWidth = CI->getBitWidth();
+ assert(isPowerOf2_32(BitWidth) &&
+ "Non-power-of-2-sized integers not handled!");
+
+ // We don't expect assemblers to support integer data directives
+ // for more than 64 bits, so we emit the data in at most 64-bit
+ // quantities at a time.
+ const uint64_t *RawData = CI->getValue().getRawData();
+ for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
+ uint64_t Val;
+ if (TD->isBigEndian())
+ Val = RawData[e - i - 1];
+ else
+ Val = RawData[i];
+
+ if (TAI->getData64bitsDirective())
+ O << TAI->getData64bitsDirective() << Val << '\n';
+ else if (TD->isBigEndian()) {
+ O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
+ << '\t' << TAI->getCommentString()
+ << " Double-word most significant word " << Val << '\n';
+ O << TAI->getData32bitsDirective() << unsigned(Val)
+ << '\t' << TAI->getCommentString()
+ << " Double-word least significant word " << Val << '\n';
+ } else {
+ O << TAI->getData32bitsDirective() << unsigned(Val)
+ << '\t' << TAI->getCommentString()
+ << " Double-word least significant word " << Val << '\n';
+ O << TAI->getData32bitsDirective() << unsigned(Val >> 32)
+ << '\t' << TAI->getCommentString()
+ << " Double-word most significant word " << Val << '\n';
+ }
}
return;
}
// Count the number of register definitions.
unsigned NumDefs = 0;
- for (; MI->getOperand(NumDefs).isRegister() && MI->getOperand(NumDefs).isDef();
+ for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
++NumDefs)
assert(NumDefs != NumOperands-1 && "No asm string?");
- assert(MI->getOperand(NumDefs).isExternalSymbol() && "No asm string?");
+ assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
// Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
break;
case '|':
++LastEmitted; // consume '|' character.
- if (CurVariant == -1) {
- cerr << "Found '|' character outside of variant in inline asm "
- << "string: '" << AsmStr << "'\n";
- exit(1);
- }
- ++CurVariant; // We're in the next variant.
+ if (CurVariant == -1)
+ O << '|'; // this is gcc's behavior for | outside a variant
+ else
+ ++CurVariant; // We're in the next variant.
break;
case ')': // $) -> same as GCC's } char.
++LastEmitted; // consume ')' character.
- if (CurVariant == -1) {
- cerr << "Found '}' character outside of variant in inline asm "
- << "string: '" << AsmStr << "'\n";
- exit(1);
- }
- CurVariant = -1;
+ if (CurVariant == -1)
+ O << '}'; // this is gcc's behavior for } outside a variant
+ else
+ CurVariant = -1;
break;
}
if (Done) break;
false, false, false);
else {
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
- if ((OpFlags & 7) == 4 /*ADDR MODE*/) {
+ if ((OpFlags & 7) == 4) {
Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
} else {
assert(TAI->getData64bitsDirective() &&
"Target cannot handle 64-bit constant exprs!");
O << TAI->getData64bitsDirective();
+ } else {
+ assert(0 && "Target cannot handle given data directive width!");
}
break;
}
}
}
-GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(Collector *C) {
- if (!C->usesMetadata())
+GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
+ if (!S->usesMetadata())
return 0;
-<<<<<<< HEAD:lib/CodeGen/AsmPrinter.cpp
- gcp_iterator GCPI = GCMetadataPrinters.find(C);
+ gcp_iterator GCPI = GCMetadataPrinters.find(S);
if (GCPI != GCMetadataPrinters.end())
return GCPI->second;
- const char *Name = C->getName().c_str();
+ const char *Name = S->getName().c_str();
-=======
-
- gcp_iterator GCPI = GCMetadataPrinters.find(C);
- if (GCPI != GCMetadataPrinters.end())
- return GCPI->second;
-
- const char *Name = C->getName().c_str();
-
->>>>>>> Factor out asmprinters from collector interface.:lib/CodeGen/AsmPrinter.cpp
for (GCMetadataPrinterRegistry::iterator
I = GCMetadataPrinterRegistry::begin(),
E = GCMetadataPrinterRegistry::end(); I != E; ++I)
if (strcmp(Name, I->getName()) == 0) {
- GCMetadataPrinter *GCP = I->instantiate();
- GCP->Coll = C;
- GCMetadataPrinters.insert(std::make_pair(C, GCP));
- return GCP;
+ GCMetadataPrinter *GMP = I->instantiate();
+ GMP->S = S;
+ GCMetadataPrinters.insert(std::make_pair(S, GMP));
+ return GMP;
}
-<<<<<<< HEAD:lib/CodeGen/AsmPrinter.cpp
-=======
-
->>>>>>> Factor out asmprinters from collector interface.:lib/CodeGen/AsmPrinter.cpp
- cerr << "no GCMetadataPrinter registered for collector: " << Name << "\n";
+ cerr << "no GCMetadataPrinter registered for GC: " << Name << "\n";
abort();
}