Newer
Older
Sanjiv Gupta
committed
EmitZeros(padSize, AddrSpace);
}
assert(sizeSoFar == cvsLayout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
Sanjiv Gupta
committed
void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP,
unsigned AddrSpace) {
// FP Constants are printed as integer constants to avoid losing
// precision...
LLVMContext &Context = CFP->getContext();
const TargetData *TD = TM.getTargetData();
if (CFP->getType()->isDoubleTy()) {
double Val = CFP->getValueAPF().convertToDouble(); // for comment only
uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (MAI->getData64bitsDirective(AddrSpace)) {
O << MAI->getData64bitsDirective(AddrSpace) << i;
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " double " << Val;
O << '\n';
} else if (TD->isBigEndian()) {
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant word of double " << Val;
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant word of double " << Val;
} else {
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant word of double " << Val;
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant word of double " << Val;
}
return;
}
if (CFP->getType()->isFloatTy()) {
float Val = CFP->getValueAPF().convertToFloat(); // for comment only
O << MAI->getData32bitsDirective(AddrSpace)
<< CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " float " << Val;
return;
}
if (CFP->getType()->isX86_FP80Ty()) {
// all long double variants are printed as hex
// api needed to prevent premature destruction
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();
bool ignored;
DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
&ignored);
if (TD->isBigEndian()) {
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant halfword of x86_fp80 ~"
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant halfword";
} else {
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant halfword of x86_fp80 ~"
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next halfword";
O << MAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant halfword";
}
EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) -
TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace);
return;
}
if (CFP->getType()->isPPC_FP128Ty()) {
// all long double variants are printed as hex
// api needed to prevent premature destruction
APInt api = CFP->getValueAPF().bitcastToAPInt();
const uint64_t *p = api.getRawData();
if (TD->isBigEndian()) {
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant word of ppc_fp128";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next word";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next word";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant word";
} else {
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant word of ppc_fp128";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next word";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " next word";
O << MAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant word";
}
return;
} else llvm_unreachable("Floating point constant type not handled");
}
Sanjiv Gupta
committed
void AsmPrinter::EmitGlobalConstantLargeInt(const ConstantInt *CI,
unsigned AddrSpace) {
const TargetData *TD = TM.getTargetData();
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 (MAI->getData64bitsDirective(AddrSpace))
O << MAI->getData64bitsDirective(AddrSpace) << Val << '\n';
else if (TD->isBigEndian()) {
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant half of i64 " << Val;
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant half of i64 " << Val;
} else {
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " least significant half of i64 " << Val;
O << MAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32);
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString()
<< " most significant half of i64 " << Val;
}
}
}
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
Sanjiv Gupta
committed
void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
const TargetData *TD = TM.getTargetData();
const Type *type = CV->getType();
unsigned Size = TD->getTypeAllocSize(type);
Sanjiv Gupta
committed
EmitZeros(Size, AddrSpace);
return;
} else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
EmitGlobalConstantArray(CVA , AddrSpace);
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
Sanjiv Gupta
committed
EmitGlobalConstantStruct(CVS, AddrSpace);
return;
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
Sanjiv Gupta
committed
EmitGlobalConstantFP(CFP, AddrSpace);
return;
} else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
// Small integers are handled below; large integers are handled here.
if (Size > 4) {
Sanjiv Gupta
committed
EmitGlobalConstantLargeInt(CI, AddrSpace);
} else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
EmitGlobalConstantVector(CP);
return;
Sanjiv Gupta
committed
printDataDirective(type, AddrSpace);
EmitConstantValueOnly(CV);
if (VerboseAsm) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
SmallString<40> S;
CI->getValue().toStringUnsigned(S, 16);
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " 0x" << S.str();
}
O << '\n';
void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
// Target doesn't support this yet!
llvm_unreachable("Target does not support EmitMachineConstantPoolValue");
}
/// PrintSpecial - Print information related to the specified machine instr
/// that is independent of the operand, and may be independent of the instr
/// itself. This can be useful for portably encoding the comment character
/// or other bits of target-specific knowledge into the asmstrings. The
/// syntax used is ${:comment}. Targets can override this to add support
/// for their own strange codes.
void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const {
if (!strcmp(Code, "private")) {
O << MAI->getPrivateGlobalPrefix();
} else if (!strcmp(Code, "comment")) {
O << MAI->getCommentString();
} else if (!strcmp(Code, "uid")) {
// Comparing the address of MI isn't sufficient, because machineinstrs may
// be allocated to the same address across functions.
const Function *ThisF = MI->getParent()->getParent()->getFunction();
// If this is a new LastFn instruction, bump the counter.
if (LastMI != MI || LastFn != ThisF) {
O << Counter;
} else {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Unknown special formatter '" << Code
Bill Wendling
committed
<< "' for machine instr: " << *MI;
llvm_report_error(Msg.str());
}
}
Argyrios Kyrtzidis
committed
/// processDebugLoc - Processes the debug information of each machine
/// instruction's DebugLoc.
Devang Patel
committed
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
bool BeforePrintingInsn) {
if (!MAI || !DW || !MAI->doesSupportDebugInformation()
|| !DW->ShouldEmitDwarfDebug())
Chris Lattner
committed
return;
DebugLoc DL = MI->getDebugLoc();
if (DL.isUnknown())
return;
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
if (CurDLT.Scope == 0)
return;
if (BeforePrintingInsn) {
if (CurDLT != PrevDLT) {
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
CurDLT.Scope);
printLabel(L);
DW->BeginScope(MI, L);
Argyrios Kyrtzidis
committed
PrevDLT = CurDLT;
}
} else {
// After printing instruction
DW->EndScope(MI);
Argyrios Kyrtzidis
committed
}
}
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
unsigned NumOperands = MI->getNumOperands();
// Count the number of register definitions.
unsigned NumDefs = 0;
for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
assert(NumDefs != NumOperands-1 && "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();
O << '\t';
// 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 << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t";
O << MAI->getCommentString() << MAI->getInlineAsmEnd() << '\n';
return;
}
O << MAI->getCommentString() << MAI->getInlineAsmStart() << "\n\t";
int AsmPrinterVariant = MAI->getAssemblerDialect();
int CurVariant = -1; // The number of the {.|.|.} region we are in.
const char *LastEmitted = AsmStr; // One past the last character emitted.
while (*LastEmitted) {
switch (*LastEmitted) {
default: {
// Not a special case, emit the string section literally.
const char *LiteralEnd = LastEmitted+1;
while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
*LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
++LiteralEnd;
if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
O.write(LastEmitted, LiteralEnd-LastEmitted);
LastEmitted = LiteralEnd;
break;
}
case '\n':
++LastEmitted; // Consume newline character.
O << '\n'; // Indent code with newline.
case '$': {
++LastEmitted; // Consume '$' character.
bool Done = true;
// Handle escapes.
switch (*LastEmitted) {
default: Done = false; break;
case '$': // $$ -> $
if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
O << '$';
++LastEmitted; // Consume second '$' character.
break;
case '(': // $( -> same as GCC's { character.
++LastEmitted; // Consume '(' character.
if (CurVariant != -1) {
llvm_report_error("Nested variants found in inline asm string: '"
+ std::string(AsmStr) + "'");
}
CurVariant = 0; // We're in the first variant now.
break;
case '|':
++LastEmitted; // consume '|' character.
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)
O << '}'; // this is gcc's behavior for } outside a variant
else
CurVariant = -1;
break;
}
if (Done) break;
bool HasCurlyBraces = false;
if (*LastEmitted == '{') { // ${variable}
++LastEmitted; // Consume '{' character.
HasCurlyBraces = true;
}
// If we have ${:foo}, then this is not a real operand reference, it is a
// "magic" string reference, just like in .td files. Arrange to call
// PrintSpecial.
if (HasCurlyBraces && *LastEmitted == ':') {
++LastEmitted;
const char *StrStart = LastEmitted;
const char *StrEnd = strchr(StrStart, '}');
if (StrEnd == 0) {
llvm_report_error("Unterminated ${:foo} operand in inline asm string: '"
+ std::string(AsmStr) + "'");
}
std::string Val(StrStart, StrEnd);
PrintSpecial(MI, Val.c_str());
LastEmitted = StrEnd+1;
break;
}
const char *IDStart = LastEmitted;
char *IDEnd;
long Val = strtol(IDStart, &IDEnd, 10); // We only accept numbers for IDs.
if (!isdigit(*IDStart) || (Val == 0 && errno == EINVAL)) {
llvm_report_error("Bad $ operand number in inline asm string: '"
+ std::string(AsmStr) + "'");
}
LastEmitted = IDEnd;
char Modifier[2] = { 0, 0 };
if (HasCurlyBraces) {
// If we have curly braces, check for a modifier character. This
// supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
if (*LastEmitted == ':') {
++LastEmitted; // Consume ':' character.
if (*LastEmitted == 0) {
llvm_report_error("Bad ${:} expression in inline asm string: '"
+ std::string(AsmStr) + "'");
}
Modifier[0] = *LastEmitted;
++LastEmitted; // Consume modifier character.
}
if (*LastEmitted != '}') {
llvm_report_error("Bad ${} expression in inline asm string: '"
+ std::string(AsmStr) + "'");
}
++LastEmitted; // Consume '}' character.
}
if ((unsigned)Val >= NumOperands-1) {
llvm_report_error("Invalid $ operand number in inline asm string: '"
+ std::string(AsmStr) + "'");
}
// Okay, we finally have a value number. Ask the target to print this
// operand!
if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
unsigned OpNo = 1;
// Scan to find the machine operand number for the operand.
for (; Val; --Val) {
if (OpNo >= MI->getNumOperands()) break;
unsigned OpFlags = MI->getOperand(OpNo).getImm();
Evan Cheng
committed
OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
if (OpNo >= MI->getNumOperands()) {
Error = true;
unsigned OpFlags = MI->getOperand(OpNo).getImm();
++OpNo; // Skip over the ID number.
if (Modifier[0]=='l') // labels are target independent
GetMBBSymbol(MI->getOperand(OpNo).getMBB()
->getNumber())->print(O, MAI);
else {
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
if ((OpFlags & 7) == 4) {
Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
} else {
Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
}
}
if (Error) {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Invalid operand found in inline asm: '"
Bill Wendling
committed
<< AsmStr << "'\n";
MI->print(Msg);
llvm_report_error(Msg.str());
}
}
break;
}
}
}
O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd();
}
/// printImplicitDef - This method prints the specified machine instruction
/// that is an implicit def.
void AsmPrinter::printImplicitDef(const MachineInstr *MI) const {
if (!VerboseAsm) return;
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " implicit-def: "
<< TRI->getName(MI->getOperand(0).getReg());
}
void AsmPrinter::printKill(const MachineInstr *MI) const {
if (!VerboseAsm) return;
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " kill:";
for (unsigned n = 0, e = MI->getNumOperands(); n != e; ++n) {
const MachineOperand &op = MI->getOperand(n);
assert(op.isReg() && "KILL instruction must have only register operands");
O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>");
}
}
/// printLabel - This method prints a local label used by debug and
/// exception handling tables.
void AsmPrinter::printLabel(const MachineInstr *MI) const {
printLabel(MI->getOperand(0).getImm());
Evan Cheng
committed
void AsmPrinter::printLabel(unsigned Id) const {
O << MAI->getPrivateGlobalPrefix() << "label" << Id << ':';
Evan Cheng
committed
}
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
/// instruction, using the specified assembler variant. Targets should
/// overried this to format as appropriate.
bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode) {
// Target doesn't support this yet!
return true;
bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
// Target doesn't support this yet!
return true;
}
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA,
const char *Suffix) const {
return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix);
}
MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
const BasicBlock *BB,
const char *Suffix) const {
assert(BB->hasName() &&
"Address of anonymous basic block not supported yet!");
// This code must use the function name itself, and not the function number,
// since it must be possible to generate the label name from within other
// functions.
std::string FuncName = Mang->getMangledName(F);
SmallString<60> Name;
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BA"
<< FuncName.size() << '_' << FuncName << '_'
<< Mang->makeNameProper(BB->getName())
<< Suffix;
return OutContext.GetOrCreateSymbol(Name.str());
MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const {
SmallString<60> Name;
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB"
<< getFunctionNumber() << '_' << MBBID;
return OutContext.GetOrCreateSymbol(Name.str());
}
/// EmitBasicBlockStart - This method prints the label for the specified
/// MachineBasicBlock, an alignment (if present) and a comment describing
/// it if appropriate.
void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
// Emit an alignment directive for this block, if needed.
if (unsigned Align = MBB->getAlignment())
EmitAlignment(Log2_32(Align));
Evan Cheng
committed
// If the block has its address taken, emit a special label to satisfy
// references to the block. This is done so that we don't need to
// remember the number of this label, and so that we can make
// forward references to labels without knowing what their numbers
// will be.
if (MBB->hasAddressTaken()) {
GetBlockAddressSymbol(MBB->getBasicBlock()->getParent(),
MBB->getBasicBlock())->print(O, MAI);
O << ':';
if (VerboseAsm) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Address Taken";
}
O << '\n';
}
if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) {
if (VerboseAsm)
O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':';
} else {
GetMBBSymbol(MBB->getNumber())->print(O, MAI);
O << ':';
if (!VerboseAsm)
O << '\n';
}
if (VerboseAsm) {
if (const BasicBlock *BB = MBB->getBasicBlock())
if (BB->hasName()) {
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
WriteAsOperand(O, BB, /*PrintType=*/false);
EmitComments(*MBB);
O << '\n';
}
/// printPICJumpTableSetLabel - This method prints a set label for the
/// specified MachineBasicBlock for a jumptable entry.
void AsmPrinter::printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const {
if (!MAI->getSetDirective())
return;
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
GetMBBSymbol(MBB->getNumber())->print(O, MAI);
O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
}
void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
const MachineBasicBlock *MBB) const {
if (!MAI->getSetDirective())
O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << '_' << uid2
<< "_set_" << MBB->getNumber() << ',';
GetMBBSymbol(MBB->getNumber())->print(O, MAI);
O << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
/// printDataDirective - This method prints the asm directive for the
/// specified type.
Sanjiv Gupta
committed
void AsmPrinter::printDataDirective(const Type *type, unsigned AddrSpace) {
const TargetData *TD = TM.getTargetData();
switch (type->getTypeID()) {
case Type::FloatTyID: case Type::DoubleTyID:
case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID:
assert(0 && "Should have already output floating point constant.");
default:
assert(0 && "Can't handle printing this type of thing");
case Type::IntegerTyID: {
unsigned BitWidth = cast<IntegerType>(type)->getBitWidth();
if (BitWidth <= 8)
O << MAI->getData8bitsDirective(AddrSpace);
O << MAI->getData16bitsDirective(AddrSpace);
O << MAI->getData32bitsDirective(AddrSpace);
assert(MAI->getData64bitsDirective(AddrSpace) &&
O << MAI->getData64bitsDirective(AddrSpace);
} else {
llvm_unreachable("Target cannot handle given data directive width!");
break;
case Type::PointerTyID:
if (TD->getPointerSize() == 8) {
assert(MAI->getData64bitsDirective(AddrSpace) &&
"Target cannot handle 64-bit pointer exprs!");
O << MAI->getData64bitsDirective(AddrSpace);
} else if (TD->getPointerSize() == 2) {
O << MAI->getData16bitsDirective(AddrSpace);
} else if (TD->getPointerSize() == 1) {
O << MAI->getData8bitsDirective(AddrSpace);
O << MAI->getData32bitsDirective(AddrSpace);
}
break;
}
}
Anton Korobeynikov
committed
void AsmPrinter::printVisibility(const std::string& Name,
unsigned Visibility) const {
if (Visibility == GlobalValue::HiddenVisibility) {
if (const char *Directive = MAI->getHiddenDirective())
Anton Korobeynikov
committed
O << Directive << Name << '\n';
} else if (Visibility == GlobalValue::ProtectedVisibility) {
if (const char *Directive = MAI->getProtectedDirective())
Anton Korobeynikov
committed
O << Directive << Name << '\n';
}
}
Gordon Henriksen
committed
void AsmPrinter::printOffset(int64_t Offset) const {
if (Offset > 0)
O << '+' << Offset;
else if (Offset < 0)
O << Offset;
}
GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
if (!S->usesMetadata())
Gordon Henriksen
committed
return 0;
gcp_iterator GCPI = GCMetadataPrinters.find(S);
Gordon Henriksen
committed
if (GCPI != GCMetadataPrinters.end())
return GCPI->second;
const char *Name = S->getName().c_str();
Gordon Henriksen
committed
for (GCMetadataPrinterRegistry::iterator
I = GCMetadataPrinterRegistry::begin(),
E = GCMetadataPrinterRegistry::end(); I != E; ++I)
if (strcmp(Name, I->getName()) == 0) {
GCMetadataPrinter *GMP = I->instantiate();
GMP->S = S;
GCMetadataPrinters.insert(std::make_pair(S, GMP));
return GMP;
Gordon Henriksen
committed
}
errs() << "no GCMetadataPrinter registered for GC: " << Name << "\n";
llvm_unreachable(0);
Gordon Henriksen
committed
}
void AsmPrinter::EmitComments(const MachineInstr &MI) const {
bool Newline = false;
if (!MI.getDebugLoc().isUnknown()) {
DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
// Print source line info.
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " SrcLine ";
if (DLT.Scope) {
DICompileUnit CU(DLT.Scope);
if (!CU.isNull())
O << CU.getFilename() << " ";
}
O << DLT.Line;
if (DLT.Col != 0)
O << ":" << DLT.Col;
Newline = true;
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
// Check for spills and reloads
int FI;
const MachineFrameInfo *FrameInfo =
MI.getParent()->getParent()->getFrameInfo();
// We assume a single instruction only has a spill or reload, not
// both.
if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
if (Newline) O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Reload";
Newline = true;
}
}
else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
if (Newline) O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Folded Reload";
Newline = true;
}
}
else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
if (Newline) O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Spill";
Newline = true;
}
}
else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, FI)) {
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
if (Newline) O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Folded Spill";
Newline = true;
}
}
// Check for spill-induced copies
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
SrcSubIdx, DstSubIdx)) {
if (MI.getAsmPrinterFlag(ReloadReuse)) {
if (Newline) O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Reload Reuse";
Newline = true;
}
}
/// PrintChildLoopComment - Print comments about child loops within
/// the loop for this basic block, with nesting.
///
static void PrintChildLoopComment(formatted_raw_ostream &O,
const MachineLoop *loop,
const MCAsmInfo *MAI,
int FunctionNumber) {
// Add child loop information
for(MachineLoop::iterator cl = loop->begin(),
clend = loop->end();
cl != clend;
++cl) {
MachineBasicBlock *Header = (*cl)->getHeader();
assert(Header && "No header for loop");
O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString();
O.indent(((*cl)->getLoopDepth()-1)*2)
<< " Child Loop BB" << FunctionNumber << "_"
<< Header->getNumber() << " Depth " << (*cl)->getLoopDepth();
PrintChildLoopComment(O, *cl, MAI, FunctionNumber);
// Add loop depth information
const MachineLoop *loop = LI->getLoopFor(&MBB);
if (loop) {
// Print a newline after bb# annotation.
O << "\n";
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Loop Depth " << loop->getLoopDepth()
O.PadToColumn(MAI->getCommentColumn());
MachineBasicBlock *Header = loop->getHeader();
assert(Header && "No header for loop");
if (Header == &MBB) {
O << MAI->getCommentString() << " Loop Header";
PrintChildLoopComment(O, loop, MAI, getFunctionNumber());
O << MAI->getCommentString() << " Loop Header is BB"
<< getFunctionNumber() << "_" << loop->getHeader()->getNumber();
}
if (loop->empty()) {
O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << " Inner Loop";
}
// Add parent loop information
for (const MachineLoop *CurLoop = loop->getParentLoop();
CurLoop;
CurLoop = CurLoop->getParentLoop()) {
MachineBasicBlock *Header = CurLoop->getHeader();
assert(Header && "No header for loop");
O << '\n';
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString();
O.indent((CurLoop->getLoopDepth()-1)*2)