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);
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';
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);
-}
+ // 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());
-void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section,
- std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP) {
- if (CP.empty()) return;
+ 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;
- 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";
+ O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+ << index << ":\t\t\t\t\t";
// O << TAI->getCommentString() << ' ' <<
// WriteTypeSymbolic(O, CP[i].first.getType(), 0);
- O << '\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;
+ O << '\n';
+ if (Entry.isMachineConstantPoolEntry())
+ EmitMachineConstantPoolValue(Entry.Val.MachineCPVal);
+ else
+ EmitGlobalConstant(Entry.Val.ConstVal);
+
// 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);
}
}
/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each
-/// global in the specified llvm.used list as being used with this directive.
-/// Non-globals (i.e. internal linkage) should not be emitted.
+/// 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();
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
const GlobalValue *GV = findGlobalValue(InitList->getOperand(i));
- if (GV && !GV->hasInternalLinkage()) {
+ if (TAI->emitUsedDirectiveFor(GV, Mang)) {
O << Directive;
EmitConstantValueOnly(InitList->getOperand(i));
O << '\n';
// 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;
}