#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Streams.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 <cerrno>
using namespace llvm;
-static cl::opt<bool>
-AsmVerbose("asm-verbose", cl::Hidden, cl::desc("Add comments to directives."));
-
char AsmPrinter::ID = 0;
AsmPrinter::AsmPrinter(std::ostream &o, TargetMachine &tm,
const TargetAsmInfo *T)
// Close the current section, if applicable.
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
- O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << "\n";
+ O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
CurrentSection = NS;
// Close the current section, if applicable.
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
- O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << "\n";
+ O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
CurrentSection = NS;
if (!M.getModuleInlineAsm().empty())
O << TAI->getCommentString() << " Start of file scope inline assembly\n"
<< M.getModuleInlineAsm()
- << "\n" << TAI->getCommentString()
+ << '\n' << TAI->getCommentString()
<< " End of file scope inline assembly\n";
SwitchToDataSection(""); // Reset back to no section.
e = ExtWeakSymbols.end(); i != e; ++i) {
const GlobalValue *GV = *i;
std::string Name = Mang->getValueName(GV);
- O << TAI->getWeakRefDirective() << Name << "\n";
+ O << TAI->getWeakRefDirective() << Name << '\n';
}
}
if (!M.alias_empty())
SwitchToTextSection(TAI->getTextSection());
- O << "\n";
+ O << '\n';
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I!=E; ++I) {
std::string Name = Mang->getValueName(I);
Target = Mang->getValueName(GV);
if (I->hasExternalLinkage() || !TAI->getWeakRefDirective())
- O << "\t.globl\t" << Name << "\n";
+ O << "\t.globl\t" << Name << '\n';
else if (I->hasWeakLinkage())
- O << TAI->getWeakRefDirective() << Name << "\n";
+ 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";
+ O << Directive << Name << '\n';
} else if (I->hasProtectedVisibility()) {
if (const char *Directive = TAI->getProtectedDirective())
- O << Directive << Name << "\n";
+ O << Directive << Name << '\n';
}
- O << TAI->getSetDirective() << ' ' << Name << ", " << Target << "\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";
+ O << TAI->getWeakRefDirective() << Target << '\n';
else
- O << "\t.globl\t" << Target << "\n";
+ O << "\t.globl\t" << Target << '\n';
}
}
}
Function* InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
if (TAI->getNonexecutableStackDirective())
- O << TAI->getNonexecutableStackDirective() << "\n";
+ O << TAI->getNonexecutableStackDirective() << '\n';
delete Mang; Mang = 0;
return false;
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() << " ";
+ << 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);
// the appropriate section.
TargetLowering *LoweringInfo = TM.getTargetLowering();
- const char* JumpTableDataSection = TAI->getJumpTableDataSection();
+ const char* JumpTableDataSection = TAI->getJumpTableDataSection();
+ const Function *F = MF.getFunction();
+ unsigned SectionFlags = TAI->SectionFlagsForGlobal(F);
if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) ||
- !JumpTableDataSection) {
+ !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.
- const Function *F = MF.getFunction();
+ // 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);
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
O << Directive;
EmitConstantValueOnly(InitList->getOperand(i));
- O << "\n";
+ O << '\n';
}
}
/// 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";
+ O << '\n';
}
+
void AsmPrinter::EOL(const std::string &Comment) const {
- if (AsmVerbose && !Comment.empty()) {
- O << "\t"
+ 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";
+ O << '\n';
}
/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
PrintHex(Value);
} else {
if (TM.getTargetData()->isBigEndian()) {
- EmitInt32(unsigned(Value >> 32)); O << "\n";
+ EmitInt32(unsigned(Value >> 32)); O << '\n';
EmitInt32(unsigned(Value));
} else {
- EmitInt32(unsigned(Value)); O << "\n";
+ EmitInt32(unsigned(Value)); O << '\n';
EmitInt32(unsigned(Value >> 32));
}
}
O << AscizDirective;
else
O << TAI->getAsciiDirective();
- O << "\"";
+ O << '\"';
for (unsigned i = 0, N = String.size(); i < N; ++i) {
unsigned char C = String[i];
printStringChar(O, C);
}
if (AscizDirective)
- O << "\"";
+ O << '\"';
else
O << "\\0\"";
}
unsigned char C = Name[i];
printStringChar(O, C);
}
- O << "\"";
+ O << '\"';
}
unsigned FillValue = TAI->getTextAlignFillValue();
UseFillExpr &= IsInTextSection && FillValue;
if (UseFillExpr) O << ",0x" << std::hex << FillValue << std::dec;
- O << "\n";
+ O << '\n';
}
O << TAI->getZeroDirective() << NumZeros;
if (TAI->getZeroDirectiveSuffix())
O << TAI->getZeroDirectiveSuffix();
- O << "\n";
+ O << '\n';
} else {
for (; NumZeros; --NumZeros)
O << TAI->getData8bitsDirective() << "0\n";
// constants valid in constant expressions can occur here.
void AsmPrinter::EmitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue() || isa<UndefValue>(CV))
- O << "0";
+ O << '0';
else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
O << CI->getZExtValue();
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
if (int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
idxVec.size())) {
if (Offset)
- O << "(";
+ O << '(';
EmitConstantValueOnly(ptrVal);
if (Offset > 0)
O << ") + " << Offset;
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
- O << "(";
+ O << '(';
EmitConstantValueOnly(CE->getOperand(0));
- O << ")";
+ O << ')';
switch (Opcode) {
case Instruction::Add:
O << " + ";
default:
break;
}
- O << "(";
+ O << '(';
EmitConstantValueOnly(CE->getOperand(1));
- O << ")";
+ O << ')';
break;
default:
assert(0 && "Unsupported operator!");
unsigned LastElt) {
assert(CVA->isString() && "Array is not string compatible!");
- O << "\"";
+ O << '\"';
for (unsigned i = 0; i != LastElt; ++i) {
unsigned char C =
(unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getZExtValue();
printStringChar(O, C);
}
- O << "\"";
+ O << '\"';
}
/// EmitString - Emit a zero-byte-terminated string constant.
O << TAI->getAsciiDirective();
printAsCString(O, CVA, NumElts);
}
- O << "\n";
+ O << '\n';
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
-/// If Packed is false, pad to the ABI size.
-void AsmPrinter::EmitGlobalConstant(const Constant *CV, bool Packed) {
+void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
const TargetData *TD = TM.getTargetData();
- unsigned Size = Packed ?
- TD->getTypeStoreSize(CV->getType()) : TD->getABITypeSize(CV->getType());
+ unsigned Size = TD->getABITypeSize(CV->getType());
if (CV->isNullValue() || isa<UndefValue>(CV)) {
EmitZeros(Size);
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), false);
+ EmitGlobalConstant(CVA->getOperand(i));
}
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
const Constant* field = CVS->getOperand(i);
// Check if padding is needed and insert one or more 0s.
- uint64_t fieldSize = TD->getTypeStoreSize(field->getType());
+ 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 without ABI size padding.
- EmitGlobalConstant(field, true);
+ // 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
double Val = CFP->getValueAPF().convertToDouble(); // for comment only
uint64_t i = CFP->getValueAPF().convertToAPInt().getZExtValue();
if (TAI->getData64bitsDirective())
- O << TAI->getData64bitsDirective() << i << "\t"
- << TAI->getCommentString() << " double value: " << Val << "\n";
+ O << TAI->getData64bitsDirective() << i << '\t'
+ << TAI->getCommentString() << " double value: " << Val << '\n';
else if (TD->isBigEndian()) {
O << TAI->getData32bitsDirective() << unsigned(i >> 32)
- << "\t" << TAI->getCommentString()
- << " double most significant word " << Val << "\n";
+ << '\t' << TAI->getCommentString()
+ << " double most significant word " << Val << '\n';
O << TAI->getData32bitsDirective() << unsigned(i)
- << "\t" << TAI->getCommentString()
- << " double least significant word " << Val << "\n";
+ << '\t' << TAI->getCommentString()
+ << " double least significant word " << Val << '\n';
} else {
O << TAI->getData32bitsDirective() << unsigned(i)
- << "\t" << TAI->getCommentString()
- << " double least significant word " << Val << "\n";
+ << '\t' << TAI->getCommentString()
+ << " double least significant word " << Val << '\n';
O << TAI->getData32bitsDirective() << unsigned(i >> 32)
- << "\t" << TAI->getCommentString()
- << " double most significant word " << Val << "\n";
+ << '\t' << TAI->getCommentString()
+ << " double most significant word " << Val << '\n';
}
return;
} else if (CFP->getType() == Type::FloatTy) {
float Val = CFP->getValueAPF().convertToFloat(); // for comment only
O << TAI->getData32bitsDirective()
<< CFP->getValueAPF().convertToAPInt().getZExtValue()
- << "\t" << TAI->getCommentString() << " float " << Val << "\n";
+ << '\t' << TAI->getCommentString() << " float " << Val << '\n';
return;
} else if (CFP->getType() == Type::X86_FP80Ty) {
// all long double variants are printed as hex
DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven);
if (TD->isBigEndian()) {
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double most significant halfword of ~"
- << DoubleVal.convertToDouble() << "\n";
+ << DoubleVal.convertToDouble() << '\n';
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 16)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[0])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[1])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double least significant halfword\n";
} else {
O << TAI->getData16bitsDirective() << uint16_t(p[1])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double least significant halfword of ~"
- << DoubleVal.convertToDouble() << "\n";
+ << DoubleVal.convertToDouble() << '\n';
O << TAI->getData16bitsDirective() << uint16_t(p[0])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 16)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next halfword\n";
O << TAI->getData16bitsDirective() << uint16_t(p[0] >> 48)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double most significant halfword\n";
}
EmitZeros(Size - TD->getTypeStoreSize(Type::X86_FP80Ty));
const uint64_t *p = api.getRawData();
if (TD->isBigEndian()) {
O << TAI->getData32bitsDirective() << uint32_t(p[0] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double most significant word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[0])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[1] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[1])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double least significant word\n";
} else {
O << TAI->getData32bitsDirective() << uint32_t(p[1])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double least significant word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[1] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[0])
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double next word\n";
O << TAI->getData32bitsDirective() << uint32_t(p[0] >> 32)
- << "\t" << TAI->getCommentString()
+ << '\t' << TAI->getCommentString()
<< " long double most significant word\n";
}
return;
uint64_t Val = CI->getZExtValue();
if (TAI->getData64bitsDirective())
- O << TAI->getData64bitsDirective() << Val << "\n";
+ 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";
+ << '\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";
+ << '\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";
+ << '\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";
+ << '\t' << TAI->getCommentString()
+ << " Double-word most significant word " << Val << '\n';
}
return;
}
const VectorType *PTy = CP->getType();
for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
- EmitGlobalConstant(CP->getOperand(I), false);
+ EmitGlobalConstant(CP->getOperand(I));
return;
}
const Type *type = CV->getType();
printDataDirective(type);
EmitConstantValueOnly(CV);
- O << "\n";
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
+ O << "\t\t\t"
+ << TAI->getCommentString()
+ << " 0x" << CI->getValue().toStringUnsigned(16);
+ }
+ O << '\n';
}
void
// If this asmstr is empty, just print the #APP/#NOAPP markers.
// These are useful to see where empty asm's wound up.
if (AsmStr[0] == 0) {
- O << TAI->getInlineAsmStart() << "\n\t" << TAI->getInlineAsmEnd() << "\n";
+ O << TAI->getInlineAsmStart() << "\n\t" << TAI->getInlineAsmEnd() << '\n';
return;
}
}
case '\n':
++LastEmitted; // Consume newline character.
- O << "\n"; // Indent code with newline.
+ O << '\n'; // Indent code with newline.
break;
case '$': {
++LastEmitted; // Consume '$' character.
}
}
}
- O << "\n\t" << TAI->getInlineAsmEnd() << "\n";
+ O << "\n\t" << TAI->getInlineAsmEnd() << '\n';
}
/// printImplicitDef - This method prints the specified machine instruction
/// that is an implicit def.
void AsmPrinter::printImplicitDef(const MachineInstr *MI) const {
- O << "\t" << TAI->getCommentString() << " implicit-def: "
- << TRI->getAsmName(MI->getOperand(0).getReg()) << "\n";
+ O << '\t' << TAI->getCommentString() << " implicit-def: "
+ << TRI->getAsmName(MI->getOperand(0).getReg()) << '\n';
}
/// printLabel - This method prints a local label used by debug and
/// exception handling tables.
void AsmPrinter::printLabel(const MachineInstr *MI) const {
- O << TAI->getPrivateGlobalPrefix()
- << "label" << MI->getOperand(0).getImm() << ":\n";
+ printLabel(MI->getOperand(0).getImm());
}
void AsmPrinter::printLabel(unsigned Id) const {
EmitAlignment(Log2_32(Align));
}
- O << TAI->getPrivateGlobalPrefix() << "BB" << getFunctionNumber() << "_"
+ O << TAI->getPrivateGlobalPrefix() << "BB" << getFunctionNumber() << '_'
<< MBB->getNumber();
if (printColon)
O << ':';
if (printComment && MBB->getBasicBlock())
O << '\t' << TAI->getCommentString() << ' '
- << MBB->getBasicBlock()->getName();
+ << MBB->getBasicBlock()->getNameStart();
}
/// printPICJumpTableSetLabel - This method prints a set label for the
}
}
-void AsmPrinter::printSuffixedName(std::string &Name, const char* Suffix) {
+void AsmPrinter::printSuffixedName(const char *Name, const char *Suffix,
+ const char *Prefix) {
+ if (Name[0]=='\"')
+ O << '\"';
+ O << TAI->getPrivateGlobalPrefix();
+ if (Prefix) O << Prefix;
+ if (Name[0]=='\"')
+ O << '\"';
if (Name[0]=='\"')
- O << "\"" << TAI->getPrivateGlobalPrefix() <<
- Name.substr(1, Name.length()-2) << Suffix << "\"";
+ O << Name[1];
else
- O << TAI->getPrivateGlobalPrefix() << Name << Suffix;
+ O << Name;
+ O << Suffix;
+ if (Name[0]=='\"')
+ O << '\"';
+}
+
+void AsmPrinter::printSuffixedName(const std::string &Name, const char* Suffix) {
+ printSuffixedName(Name.c_str(), Suffix);
}