#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "llvm/SlotCalculator.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Support/Mangler.h"
#include "Support/StringExtras.h"
#include "Support/Statistic.h"
#include "SparcInternals.h"
#include <string>
-
using namespace llvm;
-namespace llvm {
-
namespace {
-
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
- class GlobalIdTable: public Annotation {
- static AnnotationID AnnotId;
- friend class AsmPrinter; // give access to AnnotId
-
- typedef hash_map<const Value*, int> ValIdMap;
- typedef ValIdMap::const_iterator ValIdMapConstIterator;
- typedef ValIdMap:: iterator ValIdMapIterator;
- public:
- SlotCalculator Table; // map anonymous values to unique integer IDs
- ValIdMap valToIdMap; // used for values not handled by SlotCalculator
-
- GlobalIdTable(Module* M) : Annotation(AnnotId), Table(M, true) {}
- };
-
- AnnotationID GlobalIdTable::AnnotId =
- AnnotationManager::getID("ASM PRINTER GLOBAL TABLE ANNOT");
-
//===--------------------------------------------------------------------===//
// Utility functions
- /// Can we treat the specified array as a string? Only if it is an array of
- /// ubytes or non-negative sbytes.
- ///
- bool isStringCompatible(const ConstantArray *CVA) {
- const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
- if (ETy == Type::UByteTy) return true;
- if (ETy != Type::SByteTy) return false;
-
- for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
- if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
- return false;
-
- return true;
- }
-
/// getAsCString - Return the specified array as a C compatible string, only
- /// if the predicate isStringCompatible is true.
+ /// if the predicate isString() is true.
///
std::string getAsCString(const ConstantArray *CVA) {
- assert(isStringCompatible(CVA) && "Array is not string compatible!");
+ assert(CVA->isString() && "Array is not string compatible!");
- std::string Result;
- const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
- Result = "\"";
- for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
+ std::string Result = "\"";
+ for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
if (C == '"') {
} // End anonymous namespace
-} // End namespace llvm
-
//===---------------------------------------------------------------------===//
// Code abstracted away from the AsmPrinter
//===---------------------------------------------------------------------===//
-namespace llvm {
-
namespace {
-
class AsmPrinter {
- GlobalIdTable* idTable;
+ // Mangle symbol names appropriately
+ Mangler *Mang;
+
public:
std::ostream &toAsm;
const TargetMachine &Target;
} CurSection;
AsmPrinter(std::ostream &os, const TargetMachine &T)
- : idTable(0), toAsm(os), Target(T), CurSection(Unknown) {}
+ : /* idTable(0), */ toAsm(os), Target(T), CurSection(Unknown) {}
+ ~AsmPrinter() {
+ delete Mang;
+ }
+
// (start|end)(Module|Function) - Callback methods invoked by subclasses
void startModule(Module &M) {
- // Create the global id table if it does not already exist
- idTable = (GlobalIdTable*)M.getAnnotation(GlobalIdTable::AnnotId);
- if (idTable == NULL) {
- idTable = new GlobalIdTable(&M);
- M.addAnnotation(idTable);
- }
+ Mang = new Mangler(M);
}
void PrintZeroBytesToPad(int numBytes) {
- for (/* no init */; numBytes >= 8; numBytes -= 8)
- printSingleConstantValue(Constant::getNullValue(Type::ULongTy));
-
- if (numBytes >= 4) {
- printSingleConstantValue(Constant::getNullValue(Type::UIntTy));
- numBytes -= 4;
- }
-
+ //
+ // Always use single unsigned bytes for padding. We don't know upon
+ // what data size the beginning address is aligned, so using anything
+ // other than a byte may cause alignment errors in the assembler.
+ //
while (numBytes--)
printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
}
toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
// Print .size and .type only if it is not a string.
- const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
- if (CVA && isStringCompatible(CVA)) {
- // print it as a string and return
- toAsm << valID << ":\n";
- toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
- return;
- }
+ if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
+ if (CVA->isString()) {
+ // print it as a string and return
+ toAsm << valID << ":\n";
+ toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
+ return;
+ }
toAsm << "\t.type" << "\t" << valID << ",#object\n";
printConstantValueOnly(CV);
}
- void startFunction(Function &F) {
- // Make sure the slot table has information about this function...
- idTable->Table.incorporateFunction(&F);
- }
- void endFunction(Function &) {
- idTable->Table.purgeFunction(); // Forget all about F
- }
-
- // Check if a value is external or accessible from external code.
- bool isExternal(const Value* V) {
- const GlobalValue *GV = dyn_cast<GlobalValue>(V);
- return GV && GV->hasExternalLinkage();
- }
-
// enterSection - Use this method to enter a different section of the output
// executable. This is used to only output necessary section transitions.
//
toAsm << "\n";
}
- static std::string getValidSymbolName(const std::string &S) {
- std::string Result;
-
- // Symbol names in Sparc assembly language have these rules:
- // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
- // (b) A name beginning in "." is treated as a local name.
- //
- if (isdigit(S[0]))
- Result = "ll";
-
- for (unsigned i = 0; i < S.size(); ++i) {
- char C = S[i];
- if (C == '_' || C == '.' || C == '$' || isalpha(C) || isdigit(C))
- Result += C;
- else {
- Result += '_';
- Result += char('0' + ((unsigned char)C >> 4));
- Result += char('0' + (C & 0xF));
- }
- }
- return Result;
- }
-
- // getID - Return a valid identifier for the specified value. Base it on
- // the name of the identifier if possible (qualified by the type), and
- // use a numbered value based on prefix otherwise.
- // FPrefix is always prepended to the output identifier.
- //
- std::string getID(const Value *V, const char *Prefix,
- const char *FPrefix = 0)
- {
- std::string Result = FPrefix ? FPrefix : ""; // "Forced prefix"
-
- Result += V->hasName() ? V->getName() : std::string(Prefix);
-
- // Qualify all internal names with a unique id.
- if (!isExternal(V)) {
- int valId = idTable->Table.getSlot(V);
- if (valId == -1) {
- GlobalIdTable::ValIdMapConstIterator I = idTable->valToIdMap.find(V);
- if (I == idTable->valToIdMap.end())
- valId = idTable->valToIdMap[V] = idTable->valToIdMap.size();
- else
- valId = I->second;
- }
- Result = Result + "_" + itostr(valId);
-
- // Replace or prefix problem characters in the name
- Result = getValidSymbolName(Result);
- }
-
- return Result;
- }
-
- // getID Wrappers - Ensure consistent usage...
+ // getID Wrappers - Ensure consistent usage
+ // Symbol names in Sparc assembly language have these rules:
+ // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
+ // (b) A name beginning in "." is treated as a local name.
std::string getID(const Function *F) {
- return getID(F, "LLVMFunction_");
+ return Mang->getValueName(F);
}
std::string getID(const BasicBlock *BB) {
- return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
+ return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB);
}
std::string getID(const GlobalVariable *GV) {
- return getID(GV, "LLVMGlobal_");
+ return Mang->getValueName(GV);
}
std::string getID(const Constant *CV) {
- return getID(CV, "LLVMConst_", ".C_");
+ return ".C_" + Mang->getValueName(CV);
}
std::string getID(const GlobalValue *GV) {
if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
///
std::string valToExprString(const Value* V, const TargetMachine& target);
};
-
} // End anonymous namespace
-} // End namespace llvm
/// Print a single constant value.
///
toAsm << "\t! " << CV->getType()->getDescription()
<< " value: " << Val << "\n";
+ } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
+ toAsm << (int)CB->getValue() << "\n";
} else {
WriteAsOperand(toAsm, CV, false, false) << "\n";
}
/// Uses printSingleConstantValue() to print each individual value.
///
void AsmPrinter::printConstantValueOnly(const Constant* CV,
- int numPadBytesAfter)
-{
- const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
-
- if (CVA && isStringCompatible(CVA)) {
- // print the string alone and return
- toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
- } else if (CVA) {
- // Not a string. Print the values in successive locations
- const std::vector<Use> &constValues = CVA->getValues();
- for (unsigned i=0; i < constValues.size(); i++)
- printConstantValueOnly(cast<Constant>(constValues[i].get()));
+ int numPadBytesAfter) {
+ if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
+ if (CVA->isString()) {
+ // print the string alone and return
+ toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
+ } else {
+ // Not a string. Print the values in successive locations
+ const std::vector<Use> &constValues = CVA->getValues();
+ for (unsigned i=0; i < constValues.size(); i++)
+ printConstantValueOnly(cast<Constant>(constValues[i].get()));
+ }
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
// Print the fields in successive locations. Pad to align if needed!
const StructLayout *cvsLayout =
// SparcAsmPrinter Code
//===----------------------------------------------------------------------===//
-namespace llvm {
-
namespace {
struct SparcAsmPrinter : public FunctionPass, public AsmPrinter {
virtual bool runOnFunction(Function &F) {
currFunction = &F;
- startFunction(F);
emitFunction(F);
- endFunction(F);
return false;
}
inline bool
SparcAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
unsigned int opNum) {
- switch (MI->getOpCode()) {
+ switch (MI->getOpcode()) {
case V9::JMPLCALLr:
case V9::JMPLCALLi:
case V9::JMPLRETr:
inline bool
SparcAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
unsigned int opNum) {
- if (Target.getInstrInfo().isLoad(MI->getOpCode()))
+ if (Target.getInstrInfo().isLoad(MI->getOpcode()))
return (opNum == 0);
- else if (Target.getInstrInfo().isStore(MI->getOpCode()))
+ else if (Target.getInstrInfo().isStore(MI->getOpcode()))
return (opNum == 1);
else
return false;
const MachineOperand& mop = MI->getOperand(opNum);
if (OpIsBranchTargetLabel(MI, opNum)) {
- PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
+ PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
return 2;
} else if (OpIsMemoryAddressBase(MI, opNum)) {
toAsm << "[";
- PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
+ PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
toAsm << "]";
return 2;
} else {
- printOneOperand(mop, MI->getOpCode());
+ printOneOperand(mop, MI->getOpcode());
return 1;
}
}
}
void SparcAsmPrinter::emitMachineInst(const MachineInstr *MI) {
- unsigned Opcode = MI->getOpCode();
+ unsigned Opcode = MI->getOpcode();
if (Target.getInstrInfo().isDummyPhiInstr(Opcode))
return; // IGNORE PHI NODES
toAsm << "\n";
}
-FunctionPass *createAsmPrinterPass(std::ostream &Out, const TargetMachine &TM) {
+FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out,
+ const TargetMachine &TM) {
return new SparcAsmPrinter(Out, TM);
}
-
-} // End llvm namespace