Newer
Older
LLVMContext &Context = CFP->getContext();
const TargetData *TD = TM.getTargetData();
if (CFP->getType() == Type::getDoubleTy(Context)) {
double Val = CFP->getValueAPF().convertToDouble(); // for comment only
uint64_t i = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (TAI->getData64bitsDirective(AddrSpace)) {
O << TAI->getData64bitsDirective(AddrSpace) << i;
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " double " << Val;
O << '\n';
} else if (TD->isBigEndian()) {
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant word of double " << Val;
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant word of double " << Val;
} else {
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant word of double " << Val;
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(i >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant word of double " << Val;
}
return;
} else if (CFP->getType() == Type::getFloatTy(Context)) {
float Val = CFP->getValueAPF().convertToFloat(); // for comment only
Sanjiv Gupta
committed
O << TAI->getData32bitsDirective(AddrSpace)
<< CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " float " << Val;
}
return;
} else if (CFP->getType() == Type::getX86_FP80Ty(Context)) {
// 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 << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant halfword of x86_fp80 ~"
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant halfword";
} else {
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant halfword of x86_fp80 ~"
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next halfword";
O << '\n';
O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant halfword";
}
EmitZeros(TD->getTypeAllocSize(Type::getX86_FP80Ty(Context)) -
TD->getTypeStoreSize(Type::getX86_FP80Ty(Context)), AddrSpace);
return;
} else if (CFP->getType() == Type::getPPC_FP128Ty(Context)) {
// 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 << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant word of ppc_fp128";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next word";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next word";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant word";
} else {
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant word of ppc_fp128";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[1] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next word";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0]);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " next word";
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << uint32_t(p[0] >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->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];
Sanjiv Gupta
committed
if (TAI->getData64bitsDirective(AddrSpace))
O << TAI->getData64bitsDirective(AddrSpace) << Val << '\n';
else if (TD->isBigEndian()) {
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " most significant half of i64 " << Val;
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant half of i64 " << Val;
} else {
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString()
<< " least significant half of i64 " << Val;
O << '\n';
O << TAI->getData32bitsDirective(AddrSpace) << unsigned(Val >> 32);
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->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(TAI->getCommentColumn());
O << TAI->getCommentString() << " 0x" << S.c_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 << TAI->getPrivateGlobalPrefix();
} else if (!strcmp(Code, "comment")) {
if (VerboseAsm)
O << TAI->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.
void AsmPrinter::processDebugLoc(DebugLoc DL) {
Chris Lattner
committed
if (!TAI || !DW)
return;
Argyrios Kyrtzidis
committed
if (TAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) {
if (!DL.isUnknown()) {
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
if (CurDLT.CompileUnit != 0 && PrevDLT != CurDLT)
printLabel(DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
DICompileUnit(CurDLT.CompileUnit)));
PrevDLT = CurDLT;
}
}
}
/// 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();
// 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->getCommentString() << TAI->getInlineAsmStart() << "\n\t";
O << TAI->getCommentString() << TAI->getInlineAsmEnd() << '\n';
return;
}
O << TAI->getCommentString() << TAI->getInlineAsmStart() << "\n\t";
// The variant of the current asmprinter.
int AsmPrinterVariant = TAI->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
printBasicBlockLabel(MI->getOperand(OpNo).getMBB(),
Evan Cheng
committed
false, false, false);
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" << TAI->getCommentString() << TAI->getInlineAsmEnd() << '\n';
}
/// printImplicitDef - This method prints the specified machine instruction
/// that is an implicit def.
void AsmPrinter::printImplicitDef(const MachineInstr *MI) const {
if (VerboseAsm) {
O.PadToColumn(TAI->getCommentColumn());
O << 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 {
printLabel(MI->getOperand(0).getImm());
Evan Cheng
committed
void AsmPrinter::printLabel(unsigned Id) const {
O << TAI->getPrivateGlobalPrefix() << "label" << Id << ":\n";
Evan Cheng
committed
}
Evan Cheng
committed
/// printDeclare - This method prints a local variable declaration used by
/// debug tables.
Evan Cheng
committed
/// FIXME: It doesn't really print anything rather it inserts a DebugVariable
/// entry into dwarf table.
Evan Cheng
committed
void AsmPrinter::printDeclare(const MachineInstr *MI) const {
unsigned FI = MI->getOperand(0).getIndex();
Evan Cheng
committed
GlobalValue *GV = MI->getOperand(1).getGlobal();
DW->RecordVariable(cast<GlobalVariable>(GV), FI, MI);
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;
}
/// printBasicBlockLabel - This method prints the label for the specified
/// MachineBasicBlock
void AsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB,
Evan Cheng
committed
bool printAlign,
bool printColon,
bool printComment) const {
Evan Cheng
committed
if (printAlign) {
unsigned Align = MBB->getAlignment();
if (Align)
EmitAlignment(Log2_32(Align));
}
O << TAI->getPrivateGlobalPrefix() << "BB" << getFunctionNumber() << '_'
if (printColon)
O << ':';
if (const BasicBlock *BB = MBB->getBasicBlock())
if (BB->hasName()) {
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << ' ';
WriteAsOperand(O, BB, /*PrintType=*/false);
}
/// 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 (!TAI->getSetDirective())
return;
O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
Evan Cheng
committed
printBasicBlockLabel(MBB, false, false, false);
O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << uid << '\n';
}
void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
const MachineBasicBlock *MBB) const {
if (!TAI->getSetDirective())
return;
O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << '_' << uid2
<< "_set_" << MBB->getNumber() << ',';
Evan Cheng
committed
printBasicBlockLabel(MBB, false, false, false);
O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << uid << '_' << uid2 << '\n';
/// 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)
Sanjiv Gupta
committed
O << TAI->getData8bitsDirective(AddrSpace);
Sanjiv Gupta
committed
O << TAI->getData16bitsDirective(AddrSpace);
Sanjiv Gupta
committed
O << TAI->getData32bitsDirective(AddrSpace);
Sanjiv Gupta
committed
assert(TAI->getData64bitsDirective(AddrSpace) &&
Sanjiv Gupta
committed
O << TAI->getData64bitsDirective(AddrSpace);
} else {
llvm_unreachable("Target cannot handle given data directive width!");
break;
case Type::PointerTyID:
if (TD->getPointerSize() == 8) {
Sanjiv Gupta
committed
assert(TAI->getData64bitsDirective(AddrSpace) &&
"Target cannot handle 64-bit pointer exprs!");
Sanjiv Gupta
committed
O << TAI->getData64bitsDirective(AddrSpace);
} else if (TD->getPointerSize() == 2) {
Sanjiv Gupta
committed
O << TAI->getData16bitsDirective(AddrSpace);
} else if (TD->getPointerSize() == 1) {
Sanjiv Gupta
committed
O << TAI->getData8bitsDirective(AddrSpace);
Sanjiv Gupta
committed
O << TAI->getData32bitsDirective(AddrSpace);
}
break;
}
}
Anton Korobeynikov
committed
void AsmPrinter::printVisibility(const std::string& Name,
unsigned Visibility) const {
if (Visibility == GlobalValue::HiddenVisibility) {
if (const char *Directive = TAI->getHiddenDirective())
O << Directive << Name << '\n';
} else if (Visibility == GlobalValue::ProtectedVisibility) {
if (const char *Directive = TAI->getProtectedDirective())
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;
}
Daniel Dunbar
committed
void AsmPrinter::printMCInst(const MCInst *MI) {
llvm_unreachable("MCInst printing unavailable on this target!");
}
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
}
cerr << "no GCMetadataPrinter registered for GC: " << Name << "\n";
llvm_unreachable(0);
Gordon Henriksen
committed
}
void AsmPrinter::EmitComments(const MachineInstr &MI) const {
if (!VerboseAsm ||
MI.getDebugLoc().isUnknown())
return;
DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
// Print source line info.
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " SrcLine ";
if (DLT.CompileUnit->hasInitializer()) {
Constant *Name = DLT.CompileUnit->getInitializer();
if (ConstantArray *NameString = dyn_cast<ConstantArray>(Name))
if (NameString->isString())
O << NameString->getAsString() << " ";
O << DLT.Line;
if (DLT.Col != 0)
O << ":" << DLT.Col;
}
/// EmitComments - Pretty-print comments for instructions
void AsmPrinter::EmitComments(const MCInst &MI) const
{
if (VerboseAsm) {
if (!MI.getDebugLoc().isUnknown()) {
DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
// Print source line info
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " SrcLine ";
if (DLT.CompileUnit->hasInitializer()) {
Constant *Name = DLT.CompileUnit->getInitializer();
if (ConstantArray *NameString = dyn_cast<ConstantArray>(Name))
if (NameString->isString()) {
O << NameString->getAsString() << " ";
}
}
O << DLT.Line;
if (DLT.Col != 0)
O << ":" << DLT.Col;
}
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
/// Indent - Insert spaces into the character output stream. The
/// "level" is multiplied by the "scale" to calculate the number of
/// spaces to insert. "level" can represent something like loop
/// nesting level, for example.
///
static formatted_raw_ostream &
Indent(formatted_raw_ostream &out, int level, int scale = 2) {
for(int i = 0; i < level*scale; ++i) {
out << " ";
}
return out;
}
/// 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 TargetAsmInfo *TAI,
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(TAI->getCommentColumn());
O << TAI->getCommentString();
Indent(O, (*cl)->getLoopDepth()-1)
<< " Child Loop BB" << FunctionNumber << "_"
<< Header->getNumber() << " Depth " << (*cl)->getLoopDepth();
PrintChildLoopComment(O, *cl, TAI, FunctionNumber);
}
}
/// EmitComments - Pretty-print comments for basic blocks
void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const
{
// Add loop depth information
const MachineLoop *loop = LI->getLoopFor(&MBB);
if (loop) {
// Print a newline after bb# annotation.
O << "\n";
O.PadToColumn(TAI->getCommentColumn());
O << TAI->getCommentString() << " Loop Depth " << loop->getLoopDepth()
<< '\n';
O.PadToColumn(TAI->getCommentColumn());
MachineBasicBlock *Header = loop->getHeader();
assert(Header && "No header for loop");
if (Header == &MBB) {
O << TAI->getCommentString() << " Loop Header";
}
else {
O << TAI->getCommentString() << " Loop Header is BB"
<< getFunctionNumber() << "_" << loop->getHeader()->getNumber();
}
if (loop->empty()) {
O << '\n';
O.PadToColumn(TAI->getCommentColumn());
O << TAI->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(TAI->getCommentColumn());
O << TAI->getCommentString();
Indent(O, CurLoop->getLoopDepth()-1)
<< " Inside Loop BB" << getFunctionNumber() << "_"