X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcAsmPrinter.cpp;h=c9c1815b4a767c1f239abba31212a7eea6fb7772;hb=8ddde0a151c5297ae5694a4b9201b2d3fe56b196;hp=0a5035eb75b0461895c6ef58b30c5a7ff6eb7bf9;hpb=09c130981456e54305c0d05f7842aa15164d0950;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index 0a5035eb75b..c9c1815b4a7 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -1,52 +1,45 @@ -//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===// -// +//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// +// // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to GAS-format Sparc V8 assembly language. +// of machine-dependent LLVM code to GAS-format SPARC assembly language. // //===----------------------------------------------------------------------===// -#include "SparcV8.h" -#include "SparcV8InstrInfo.h" +#define DEBUG_TYPE "asm-printer" +#include "Sparc.h" +#include "SparcInstrInfo.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" -#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" -#include "Support/Statistic.h" -#include "Support/StringExtras.h" -#include "Support/CommandLine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MathExtras.h" #include using namespace llvm; -namespace { - Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); - - struct V8Printer : public MachineFunctionPass { - /// Output stream on which we're printing assembly code. - /// - std::ostream &O; - - /// Target machine description which we query for reg. names, data - /// layout, etc. - /// - TargetMachine &TM; - - /// Name-mangler for global names. - /// - Mangler *Mang; +STATISTIC(EmittedInsts, "Number of machine instrs printed"); - V8Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { } +namespace { + struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter { + SparcAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) + : AsmPrinter(O, TM, T) { + } /// We name each basic block in a Function with a unique number, so /// that we can consistently refer to them later. This is cleared @@ -55,274 +48,43 @@ namespace { typedef std::map ValueMapTy; ValueMapTy NumberForBB; - /// Cache of mangled name for current function. This is - /// recalculated at the beginning of each call to - /// runOnMachineFunction(). - /// - std::string CurrentFnName; - virtual const char *getPassName() const { - return "SparcV8 Assembly Printer"; + return "Sparc Assembly Printer"; } - void emitConstantValueOnly(const Constant *CV); - void emitGlobalConstant(const Constant *CV); - void printConstantPool(MachineConstantPool *MCP); void printOperand(const MachineInstr *MI, int opNum); - void printBaseOffsetPair (const MachineInstr *MI, int i); - void printMachineInstruction(const MachineInstr *MI); - bool runOnMachineFunction(MachineFunction &F); + void printMemOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + void printCCOperand(const MachineInstr *MI, int opNum); + + bool printInstruction(const MachineInstr *MI); // autogenerated. + bool runOnMachineFunction(MachineFunction &F); bool doInitialization(Module &M); bool doFinalization(Module &M); }; } // end of anonymous namespace -/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8 +#include "SparcGenAsmWriter.inc" + +/// createSparcCodePrinterPass - Returns a pass that prints the SPARC /// assembly code for a MachineFunction to the given output stream, /// using the given target machine description. This should work /// regardless of whether the function is in SSA form. /// -FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o, - TargetMachine &tm) { - return new V8Printer(o, tm); -} - -/// toOctal - Convert the low order bits of X into an octal digit. -/// -static inline char toOctal(int X) { - return (X&7)+'0'; -} - -/// getAsCString - Return the specified array as a C compatible -/// string, only if the predicate isStringCompatible is true. -/// -static void printAsCString(std::ostream &O, const ConstantArray *CVA) { - assert(CVA->isString() && "Array is not string compatible!"); - - O << "\""; - for (unsigned i = 0; i != CVA->getNumOperands(); ++i) { - unsigned char C = cast(CVA->getOperand(i))->getRawValue(); - - if (C == '"') { - O << "\\\""; - } else if (C == '\\') { - O << "\\\\"; - } else if (isprint(C)) { - O << C; - } else { - switch(C) { - case '\b': O << "\\b"; break; - case '\f': O << "\\f"; break; - case '\n': O << "\\n"; break; - case '\r': O << "\\r"; break; - case '\t': O << "\\t"; break; - default: - O << '\\'; - O << toOctal(C >> 6); - O << toOctal(C >> 3); - O << toOctal(C >> 0); - break; - } - } - } - O << "\""; -} - -// Print out the specified constant, without a storage class. Only the -// constants valid in constant expressions can occur here. -void V8Printer::emitConstantValueOnly(const Constant *CV) { - if (CV->isNullValue()) - O << "0"; - else if (const ConstantBool *CB = dyn_cast(CV)) { - assert(CB == ConstantBool::True); - O << "1"; - } else if (const ConstantSInt *CI = dyn_cast(CV)) - if (((CI->getValue() << 32) >> 32) == CI->getValue()) - O << CI->getValue(); - else - O << (unsigned long long)CI->getValue(); - else if (const ConstantUInt *CI = dyn_cast(CV)) - O << CI->getValue(); - else if (const ConstantPointerRef *CPR = dyn_cast(CV)) - // This is a constant address for a global variable or function. Use the - // name of the variable or function as the address value. - O << Mang->getValueName(CPR->getValue()); - else if (const ConstantExpr *CE = dyn_cast(CV)) { - const TargetData &TD = TM.getTargetData(); - switch(CE->getOpcode()) { - case Instruction::GetElementPtr: { - // generate a symbolic expression for the byte address - const Constant *ptrVal = CE->getOperand(0); - std::vector idxVec(CE->op_begin()+1, CE->op_end()); - if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) { - O << "("; - emitConstantValueOnly(ptrVal); - O << ") + " << Offset; - } else { - emitConstantValueOnly(ptrVal); - } - 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. - Constant *Op = CE->getOperand(0); - const Type *OpTy = Op->getType(), *Ty = CE->getType(); - - // Pointers on ILP32 machines can be losslessly converted back and - // forth into 32-bit or wider integers, regardless of signedness. - assert(((isa(OpTy) - && (Ty == Type::LongTy || Ty == Type::ULongTy - || Ty == Type::IntTy || Ty == Type::UIntTy)) - || (isa(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"); - O << "("; - emitConstantValueOnly(Op); - O << ")"; - break; - } - case Instruction::Add: - O << "("; - emitConstantValueOnly(CE->getOperand(0)); - O << ") + ("; - emitConstantValueOnly(CE->getOperand(1)); - O << ")"; - break; - default: - assert(0 && "Unsupported operator!"); - } - } else { - assert(0 && "Unknown constant value!"); - } -} - -// Print a constant value or values, with the appropriate storage class as a -// prefix. -void V8Printer::emitGlobalConstant(const Constant *CV) { - const TargetData &TD = TM.getTargetData(); - - if (CV->isNullValue()) { - O << "\t.zero\t " << TD.getTypeSize(CV->getType()) << "\n"; - return; - } else if (const ConstantArray *CVA = dyn_cast(CV)) { - if (CVA->isString()) { - O << "\t.ascii\t"; - printAsCString(O, CVA); - O << "\n"; - } else { // Not a string. Print the values in successive locations - const std::vector &constValues = CVA->getValues(); - for (unsigned i=0; i < constValues.size(); i++) - emitGlobalConstant(cast(constValues[i].get())); - } - return; - } else if (const ConstantStruct *CVS = dyn_cast(CV)) { - // Print the fields in successive locations. Pad to align if needed! - const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType()); - const std::vector& constValues = CVS->getValues(); - unsigned sizeSoFar = 0; - for (unsigned i=0, N = constValues.size(); i < N; i++) { - const Constant* field = cast(constValues[i].get()); - - // Check if padding is needed and insert one or more 0s. - unsigned fieldSize = TD.getTypeSize(field->getType()); - unsigned padSize = ((i == N-1? cvsLayout->StructSize - : cvsLayout->MemberOffsets[i+1]) - - cvsLayout->MemberOffsets[i]) - fieldSize; - sizeSoFar += fieldSize + padSize; - - // Now print the actual field value - emitGlobalConstant(field); - - // Insert the field padding unless it's zero bytes... - if (padSize) - O << "\t.zero\t " << padSize << "\n"; - } - assert(sizeSoFar == cvsLayout->StructSize && - "Layout of constant struct may be incorrect!"); - return; - } else if (const ConstantFP *CFP = dyn_cast(CV)) { - // FP Constants are printed as integer constants to avoid losing - // precision... - double Val = CFP->getValue(); - switch (CFP->getType()->getTypeID()) { - default: assert(0 && "Unknown floating point type!"); - case Type::FloatTyID: { - union FU { // Abide by C TBAA rules - float FVal; - unsigned UVal; - } U; - U.FVal = Val; - O << ".long\t" << U.UVal << "\t! float " << Val << "\n"; - return; - } - case Type::DoubleTyID: { - union DU { // Abide by C TBAA rules - double FVal; - uint64_t UVal; - } U; - U.FVal = Val; - O << ".quad\t" << U.UVal << "\t! double " << Val << "\n"; - return; - } - } - } - - const Type *type = CV->getType(); - O << "\t"; - switch (type->getTypeID()) { - case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: - O << ".byte"; - break; - case Type::UShortTyID: case Type::ShortTyID: - O << ".word"; - break; - case Type::FloatTyID: case Type::PointerTyID: - case Type::UIntTyID: case Type::IntTyID: - O << ".long"; - break; - case Type::DoubleTyID: - case Type::ULongTyID: case Type::LongTyID: - O << ".quad"; - break; - default: - assert (0 && "Can't handle printing this type of thing"); - break; - } - O << "\t"; - emitConstantValueOnly(CV); - O << "\n"; -} - -/// printConstantPool - Print to the current output stream assembly -/// representations of the constants in the constant pool MCP. This is -/// used to print out constants which have been "spilled to memory" by -/// the code generator. -/// -void V8Printer::printConstantPool(MachineConstantPool *MCP) { - const std::vector &CP = MCP->getConstants(); - const TargetData &TD = TM.getTargetData(); - - if (CP.empty()) return; - - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - O << "\t.section .rodata\n"; - O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType()) - << "\n"; - O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!" - << *CP[i] << "\n"; - emitGlobalConstant(CP[i]); - } +FunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o, + TargetMachine &tm) { + return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo()); } /// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. /// -bool V8Printer::runOnMachineFunction(MachineFunction &MF) { +bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + // BBNumber is used here so that a given Printer will never give two // BBs the same name. (If you have a better way, please let me know!) static unsigned BBNumber = 0; @@ -331,18 +93,17 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) { // What's my mangled name? CurrentFnName = Mang->getValueName(MF.getFunction()); - // Print out constants referenced by the function - printConstantPool(MF.getConstantPool()); - - // Print out labels for the function. - O << "\t.text\n"; - O << "\t.align 16\n"; + // Print out the label for the function. + const Function *F = MF.getFunction(); + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + EmitAlignment(4, F); O << "\t.globl\t" << CurrentFnName << "\n"; O << "\t.type\t" << CurrentFnName << ", #function\n"; O << CurrentFnName << ":\n"; // Number each basic block so that we can consistently refer to them // in PC-relative references. + // FIXME: Why not use the MBB numbers? NumberForBB.clear(); for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { @@ -353,14 +114,16 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) { for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block. - O << ".LBB" << Mang->getValueName(MF.getFunction ()) - << "_" << I->getNumber () << ":\t! " - << I->getBasicBlock ()->getName () << "\n"; + if (I != MF.begin()) { + printBasicBlockLabel(I, true); + O << '\n'; + } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { + II != E; ++II) { // Print the assembly for the instruction. O << "\t"; - printMachineInstruction(II); + printInstruction(II); + ++EmittedInsts; } } @@ -368,54 +131,31 @@ bool V8Printer::runOnMachineFunction(MachineFunction &MF) { return false; } - -std::string LowercaseString (const std::string &S) { - std::string result (S); - for (unsigned i = 0; i < S.length(); ++i) - if (isupper (result[i])) - result[i] = tolower(result[i]); - return result; -} - -void V8Printer::printOperand(const MachineInstr *MI, int opNum) { +void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { const MachineOperand &MO = MI->getOperand (opNum); const MRegisterInfo &RI = *TM.getRegisterInfo(); bool CloseParen = false; - if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) { + if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) { O << "%hi("; CloseParen = true; - } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) { + } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) + && !MO.isRegister() && !MO.isImmediate()) { O << "%lo("; CloseParen = true; } switch (MO.getType()) { - case MachineOperand::MO_VirtualRegister: - if (Value *V = MO.getVRegValueOrNull()) { - O << "<" << V->getName() << ">"; - break; - } - // FALLTHROUGH - case MachineOperand::MO_MachineRegister: + case MachineOperand::MO_Register: if (MRegisterInfo::isPhysicalRegister(MO.getReg())) O << "%" << LowercaseString (RI.get(MO.getReg()).Name); else O << "%reg" << MO.getReg(); break; - case MachineOperand::MO_SignExtendedImmed: - case MachineOperand::MO_UnextendedImmed: + case MachineOperand::MO_Immediate: O << (int)MO.getImmedValue(); break; - case MachineOperand::MO_MachineBasicBlock: { - MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); - O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) - << "_" << MBBOp->getNumber () << "\t! " - << MBBOp->getBasicBlock ()->getName (); - return; - } - case MachineOperand::MO_PCRelativeDisp: - std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs"; - abort (); + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMachineBasicBlock()); return; case MachineOperand::MO_GlobalAddress: O << Mang->getValueName(MO.getGlobal()); @@ -423,141 +163,83 @@ void V8Printer::printOperand(const MachineInstr *MI, int opNum) { case MachineOperand::MO_ExternalSymbol: O << MO.getSymbolName(); break; + case MachineOperand::MO_ConstantPoolIndex: + O << TAI->getPrivateGlobalPrefix() << "CPI" << MO.getConstantPoolIndex() + << '_' << CurrentFnName; + break; default: - O << ""; break; + O << ""; abort (); break; } if (CloseParen) O << ")"; } -static bool isLoadInstruction (const MachineInstr *MI) { - switch (MI->getOpcode ()) { - case V8::LDSBmr: - case V8::LDSHmr: - case V8::LDUBmr: - case V8::LDUHmr: - case V8::LDmr: - case V8::LDDmr: - return true; - default: - return false; +void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + const char *Modifier) { + printOperand(MI, opNum); + + // If this is an ADD operand, emit it like normal operands. + if (Modifier && !strcmp(Modifier, "arith")) { + O << ", "; + printOperand(MI, opNum+1); + return; } -} - -static bool isStoreInstruction (const MachineInstr *MI) { - switch (MI->getOpcode ()) { - case V8::STBrm: - case V8::STHrm: - case V8::STrm: - case V8::STDrm: - return true; - default: - return false; + + if (MI->getOperand(opNum+1).isRegister() && + MI->getOperand(opNum+1).getReg() == SP::G0) + return; // don't print "+%g0" + if (MI->getOperand(opNum+1).isImmediate() && + MI->getOperand(opNum+1).getImmedValue() == 0) + return; // don't print "+0" + + O << "+"; + if (MI->getOperand(opNum+1).isGlobalAddress() || + MI->getOperand(opNum+1).isConstantPoolIndex()) { + O << "%lo("; + printOperand(MI, opNum+1); + O << ")"; + } else { + printOperand(MI, opNum+1); } } -void V8Printer::printBaseOffsetPair (const MachineInstr *MI, int i) { - O << "["; - printOperand (MI, i); - assert (MI->getOperand (i + 1).isImmediate() - && "2nd half of base-offset pair must be immediate-value machine operand"); - int Val = (int) MI->getOperand (i + 1).getImmedValue (); - if (Val != 0) { - O << ((Val >= 0) ? " + " : " - "); - O << ((Val >= 0) ? Val : -Val); - } - O << "]"; +void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { + int CC = (int)MI->getOperand(opNum).getImmedValue(); + O << SPARCCondCodeToString((SPCC::CondCodes)CC); } -/// printMachineInstruction -- Print out a single SparcV8 LLVM instruction -/// MI in GAS syntax to the current output stream. -/// -void V8Printer::printMachineInstruction(const MachineInstr *MI) { - unsigned Opcode = MI->getOpcode(); - const TargetInstrInfo &TII = *TM.getInstrInfo(); - const TargetInstrDescriptor &Desc = TII.get(Opcode); - O << Desc.Name << " "; - - // Printing memory instructions is a special case. - // for loads: %dest = op %base, offset --> op [%base + offset], %dest - // for stores: op %src, %base, offset --> op %src, [%base + offset] - if (isLoadInstruction (MI)) { - printBaseOffsetPair (MI, 1); - O << ", "; - printOperand (MI, 0); - O << "\n"; - return; - } else if (isStoreInstruction (MI)) { - printOperand (MI, 0); - O << ", "; - printBaseOffsetPair (MI, 1); - O << "\n"; - return; - } - // print non-immediate, non-register-def operands - // then print immediate operands - // then print register-def operands. - std::vector print_order; - for (unsigned i = 0; i < MI->getNumOperands (); ++i) - if (!(MI->getOperand (i).isImmediate () - || (MI->getOperand (i).isRegister () - && MI->getOperand (i).isDef ()))) - print_order.push_back (i); - for (unsigned i = 0; i < MI->getNumOperands (); ++i) - if (MI->getOperand (i).isImmediate ()) - print_order.push_back (i); - for (unsigned i = 0; i < MI->getNumOperands (); ++i) - if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ()) - print_order.push_back (i); - for (unsigned i = 0, e = print_order.size (); i != e; ++i) { - printOperand (MI, print_order[i]); - if (i != (print_order.size () - 1)) - O << ", "; - } - O << "\n"; -} -bool V8Printer::doInitialization(Module &M) { +bool SparcAsmPrinter::doInitialization(Module &M) { Mang = new Mangler(M); return false; // success } -// SwitchSection - Switch to the specified section of the executable if we are -// not already in it! -// -static void SwitchSection(std::ostream &OS, std::string &CurSection, - const char *NewSection) { - if (CurSection != NewSection) { - CurSection = NewSection; - if (!CurSection.empty()) - OS << "\t" << NewSection << "\n"; - } -} - -bool V8Printer::doFinalization(Module &M) { - const TargetData &TD = TM.getTargetData(); - std::string CurSection; +bool SparcAsmPrinter::doFinalization(Module &M) { + const TargetData *TD = TM.getTargetData(); // Print out module-level global variables here. - for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) if (I->hasInitializer()) { // External global require no code + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(I)) + continue; + O << "\n\n"; std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); - unsigned Size = TD.getTypeSize(C->getType()); - unsigned Align = TD.getTypeAlignment(C->getType()); + unsigned Size = TD->getTypeSize(C->getType()); + unsigned Align = TD->getPrefTypeAlignment(C->getType()); - if (C->isNullValue() && + if (C->isNullValue() && (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || I->hasWeakLinkage() /* FIXME: Verify correct */)) { - SwitchSection(O, CurSection, ".data"); + SwitchToDataSection(".data", I); if (I->hasInternalLinkage()) O << "\t.local " << name << "\n"; - - O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()) - << "," << (unsigned)TD.getTypeAlignment(C->getType()); - O << "\t\t! "; - WriteAsOperand(O, I, true, true, &M); + + O << "\t.comm " << name << "," << TD->getTypeSize(C->getType()) + << "," << Align; O << "\n"; } else { switch (I->getLinkage()) { @@ -565,10 +247,11 @@ bool V8Printer::doFinalization(Module &M) { case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. // Nonnull linkonce -> weak O << "\t.weak " << name << "\n"; - SwitchSection(O, CurSection, ""); - O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; + SwitchToDataSection("", I); + O << "\t.section\t\".llvm.linkonce.d." << name + << "\",\"aw\",@progbits\n"; break; - + case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. @@ -578,24 +261,30 @@ bool V8Printer::doFinalization(Module &M) { // FALL THROUGH case GlobalValue::InternalLinkage: if (C->isNullValue()) - SwitchSection(O, CurSection, ".bss"); + SwitchToDataSection(".bss", I); else - SwitchSection(O, CurSection, ".data"); + SwitchToDataSection(".data", I); break; + case GlobalValue::GhostLinkage: + cerr << "Should not have any unmaterialized functions!\n"; + abort(); + case GlobalValue::DLLImportLinkage: + cerr << "DLLImport linkage is not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + cerr << "DLLExport linkage is not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); } O << "\t.align " << Align << "\n"; O << "\t.type " << name << ",#object\n"; O << "\t.size " << name << "," << Size << "\n"; - O << name << ":\t\t\t\t! "; - WriteAsOperand(O, I, true, true, &M); - O << " = "; - WriteAsOperand(O, C, false, false, &M); - O << "\n"; - emitGlobalConstant(C); + O << name << ":\n"; + EmitGlobalConstant(C); } } - delete Mang; - return false; // success + return AsmPrinter::doFinalization(M); }