DataSectionStartSuffix(""),
SectionEndDirectiveSuffix(0),
ConstantPoolSection("\t.section .rodata\n"),
- JumpTableSection("\t.section .rodata\n"),
+ JumpTableDataSection("\t.section .rodata\n"),
+ JumpTableTextSection("\t.text\n"),
StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"),
StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"),
FourByteConstantSection(0),
EightByteConstantSection(0),
SixteenByteConstantSection(0),
+ SetDirective(0),
LCOMMDirective(0),
COMMDirective("\t.comm\t"),
COMMDirectiveTakesAlignment(true),
O << CurrentSection << TextSectionStartSuffix << '\n';
}
-/// SwitchToTextSection - Switch to the specified text section of the executable
+/// SwitchToDataSection - Switch to the specified data section of the executable
/// if we are not already in it!
///
void AsmPrinter::SwitchToDataSection(const char *NewSection,
if (JT.empty()) return;
const TargetData *TD = TM.getTargetData();
- // FIXME: someday we need to handle PIC jump tables
- assert((TM.getRelocationModel() == Reloc::Static ||
- TM.getRelocationModel() == Reloc::DynamicNoPIC) &&
- "Unhandled relocation model emitting jump table information!");
+ // JTEntryDirective is a string to print sizeof(ptr) for non-PIC jump tables,
+ // and 32 bits for PIC since PIC jump table entries are differences, not
+ // pointers to blocks.
+ const char *JTEntryDirective = Data32bitsDirective;
- SwitchToDataSection(JumpTableSection, 0);
+ // Pick the directive to use to print the jump table entries, and switch to
+ // the appropriate section.
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ SwitchToTextSection(JumpTableTextSection, 0);
+ } else {
+ SwitchToDataSection(JumpTableDataSection, 0);
+ if (TD->getPointerSize() == 8)
+ JTEntryDirective = Data64bitsDirective;
+ }
EmitAlignment(Log2_32(TD->getPointerAlignment()));
- // Pick the directive to use based on the pointer size. FIXME: when we support
- // PIC jumptables, this should always use the 32-bit directive for label
- // differences.
- const char *PtrDataDirective = Data32bitsDirective;
- if (TD->getPointerSize() == 8)
- PtrDataDirective = Data64bitsDirective;
-
for (unsigned i = 0, e = JT.size(); i != e; ++i) {
+ const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs;
+
+ // For PIC codegen, if possible we want to use the SetDirective to reduce
+ // the number of relocations the assembler will generate for the jump table.
+ // Set directives are all printed before the jump table itself.
+ std::set<MachineBasicBlock*> EmittedSets;
+ if (SetDirective && TM.getRelocationModel() == Reloc::PIC_)
+ for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii)
+ if (EmittedSets.insert(JTBBs[ii]).second)
+ printSetLabel(i, JTBBs[ii]);
+
O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << '_' << i
<< ":\n";
- const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs;
+
for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
- O << PtrDataDirective << ' ';
- printBasicBlockLabel(JTBBs[ii]);
+ O << JTEntryDirective << ' ';
+ // If we have emitted set directives for the jump table entries, print
+ // them rather than the entries themselves. If we're emitting PIC, then
+ // emit the table entries as differences between two text section labels.
+ // If we're emitting non-PIC code, then emit the entries as direct
+ // references to the target basic blocks.
+ if (!EmittedSets.empty()) {
+ O << PrivateGlobalPrefix << getFunctionNumber() << '_' << i << "_set_"
+ << JTBBs[ii]->getNumber();
+ } else if (TM.getRelocationModel() == Reloc::PIC_) {
+ printBasicBlockLabel(JTBBs[ii], false, false);
+ O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber()
+ << '_' << i;
+ } else {
+ printBasicBlockLabel(JTBBs[ii], false, false);
+ }
O << '\n';
}
}
break;
}
case Instruction::Cast: {
- // Support only non-converting or widening casts for now, that is, ones
- // that do not involve a change in value. This assertion is really gross,
- // and may not even be a complete check.
+ // Support only foldable casts to/from pointers that can be eliminated by
+ // changing the pointer to the appropriately sized integer type.
Constant *Op = CE->getOperand(0);
const Type *OpTy = Op->getType(), *Ty = CE->getType();
- // Remember, kids, pointers can be losslessly converted back and forth
- // into 32-bit or wider integers, regardless of signedness. :-P
- assert(((isa<PointerType>(OpTy)
- && (Ty == Type::LongTy || Ty == Type::ULongTy
- || Ty == Type::IntTy || Ty == Type::UIntTy))
- || (isa<PointerType>(Ty)
- && (OpTy == Type::LongTy || OpTy == Type::ULongTy
- || OpTy == Type::IntTy || OpTy == Type::UIntTy))
- || (((TD->getTypeSize(Ty) >= TD->getTypeSize(OpTy))
- && OpTy->isLosslesslyConvertibleTo(Ty))))
- && "FIXME: Don't yet support this kind of constant cast expr");
+ // Handle casts to pointers by changing them into casts to the appropriate
+ // integer type. This promotes constant folding and simplifies this code.
+ if (isa<PointerType>(Ty)) {
+ const Type *IntPtrTy = TD->getIntPtrType();
+ Op = ConstantExpr::getCast(Op, IntPtrTy);
+ return EmitConstantValueOnly(Op);
+ }
+
+ // We know the dest type is not a pointer. Is the src value a pointer or
+ // integral?
+ if (isa<PointerType>(OpTy) || OpTy->isIntegral()) {
+ // We can emit the pointer value into this slot if the slot is an
+ // integer slot greater or equal to the size of the pointer.
+ if (Ty->isIntegral() && TD->getTypeSize(Ty) >= TD->getTypeSize(OpTy))
+ return EmitConstantValueOnly(Op);
+ }
+
+ assert(0 && "FIXME: Don't yet support this kind of constant cast expr");
EmitConstantValueOnly(Op);
break;
}
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
- O << InlineAsmStart << "\n\t";
unsigned NumOperands = MI->getNumOperands();
// Count the number of register definitions.
// Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
+ // If this asmstr is empty, don't bother printing the #APP/#NOAPP markers.
+ if (AsmStr[0] == 0) {
+ O << "\n"; // Tab already printed, avoid double indenting next instr.
+ return;
+ }
+
+ O << InlineAsmStart << "\n\t";
+
// The variant of the current asmprinter: FIXME: change.
int AsmPrinterVariant = 0;
if (printComment)
O << '\t' << CommentString << MBB->getBasicBlock()->getName();
}
+
+/// printSetLabel - This method prints a set label for the specified
+/// MachineBasicBlock
+void AsmPrinter::printSetLabel(unsigned uid,
+ const MachineBasicBlock *MBB) const {
+ if (!SetDirective)
+ return;
+
+ O << SetDirective << ' ' << PrivateGlobalPrefix << getFunctionNumber()
+ << '_' << uid << "_set_" << MBB->getNumber() << ',';
+ printBasicBlockLabel(MBB, false, false);
+ O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber()
+ << '_' << uid << '\n';
+}