#include "llvm/Module.h"
#include "llvm/Support/HashExtras.h"
#include "llvm/Support/StringExtras.h"
+#include <locale.h>
namespace {
typedef ValIdMap:: iterator ValIdMapIterator;
typedef ValIdMap::const_iterator ValIdMapConstIterator;
- ostream &Out;
+ ostream &toAsm;
SlotCalculator Table; // map anonymous values to unique integer IDs
ValIdMap valToIdMap; // used for values not handled by SlotCalculator
const UltraSparc &Target;
public:
inline SparcAsmPrinter(ostream &o, const Module *M, const UltraSparc &t)
- : Out(o), Table(SlotCalculator(M, true)), Target(t), CurSection(Unknown) {
+ : toAsm(o), Table(SlotCalculator(M, true)), Target(t), CurSection(Unknown) {
emitModule(M);
}
if (S == CurSection) return; // Only switch section if neccesary
CurSection = S;
- Out << "\n\t.section ";
+ toAsm << "\n\t.section ";
switch (S)
{
default: assert(0 && "Bad section name!");
- case Text: Out << "\".text\""; break;
- case ReadOnlyData: Out << "\".rodata\",#alloc"; break;
- case InitRWData: Out << "\".data\",#alloc,#write"; break;
- case UninitRWData: Out << "\".bss\",#alloc,#write\nBbss.bss:"; break;
+ case Text: toAsm << "\".text\""; break;
+ case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
+ case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
+ case UninitRWData: toAsm << "\".bss\",#alloc,#write\nBbss.bss:"; break;
}
- Out << "\n";
+ toAsm << "\n";
}
- string getEscapedString(const string &S) {
+ string getValidSymbolName(const string &S) {
string Result;
-
- for (unsigned i = 0; i < S.size(); ++i) {
- char C = S[i];
- if ((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
- (C >= '0' && C <= '9')) {
- Result += C;
- } else {
- Result += '_';
- Result += char('0' + ((unsigned char)C >> 4));
- Result += char('0' + (C & 0xF));
+
+ // 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.
+ // (c) Names beginning with "_" are reserved by ANSI C and shd not be used.
+ //
+ if (S[0] == '_' || 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;
}
// prefix otherwise. FPrefix is always prepended to the output identifier.
//
string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
+ string Result;
string FP(FPrefix ? FPrefix : ""); // "Forced prefix"
if (V->hasName()) {
- return FP + getEscapedString(V->getName());
+ Result = FP + V->getName();
} else {
int valId = Table.getValSlot(V);
if (valId == -1) {
valId = (I == valToIdMap.end())? (valToIdMap[V] = valToIdMap.size())
: (*I).second;
}
- return FP + string(Prefix) + itostr(valId);
+ Result = FP + string(Prefix) + itostr(valId);
}
+ return getValidSymbolName(Result);
}
// getID Wrappers - Ensure consistent usage...
#define PrintOp1PlusOp2(Op1, Op2) \
- printOneOperand(Op1); Out << "+"; printOneOperand(Op2);
+ printOneOperand(Op1); toAsm << "+"; printOneOperand(Op2);
unsigned int
}
else if (OpIsMemoryAddressBase(MI, opNum))
{
- Out << "[";
+ toAsm << "[";
PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
- Out << "]";
+ toAsm << "]";
return 2;
}
else
void
-SparcAsmPrinter::printOneOperand(const MachineOperand &Op)
+SparcAsmPrinter::printOneOperand(const MachineOperand &op)
{
- switch (Op.getOperandType())
+ switch (op.getOperandType())
{
case MachineOperand::MO_VirtualRegister:
case MachineOperand::MO_CCRegister:
case MachineOperand::MO_MachineRegister:
{
- int RegNum = (int)Op.getAllocatedRegNum();
+ int RegNum = (int)op.getAllocatedRegNum();
// ****this code is temporary till NULL Values are fixed
if (RegNum == 10000) {
- Out << "<NULL VALUE>";
+ toAsm << "<NULL VALUE>";
} else {
- Out << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
+ toAsm << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
}
break;
}
case MachineOperand::MO_PCRelativeDisp:
{
- const Value *Val = Op.getVRegValue();
+ const Value *Val = op.getVRegValue();
if (!Val)
- Out << "\t<*NULL Value*>";
+ toAsm << "\t<*NULL Value*>";
else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
- Out << getID(BB);
+ toAsm << getID(BB);
else if (const Method *M = dyn_cast<const Method>(Val))
- Out << getID(M);
+ toAsm << getID(M);
else if (const GlobalVariable *GV=dyn_cast<const GlobalVariable>(Val))
- Out << getID(GV);
+ toAsm << getID(GV);
else if (const ConstPoolVal *CV = dyn_cast<const ConstPoolVal>(Val))
- Out << getID(CV);
+ toAsm << getID(CV);
else
- Out << "<unknown value=" << Val << ">";
+ toAsm << "<unknown value=" << Val << ">";
break;
}
case MachineOperand::MO_SignExtendedImmed:
case MachineOperand::MO_UnextendedImmed:
- Out << Op.getImmedValue();
+ toAsm << op.getImmedValue();
break;
default:
- Out << Op; // use dump field
+ toAsm << op; // use dump field
break;
}
}
if (TargetInstrDescriptors[Opcode].iclass & M_DUMMY_PHI_FLAG)
return; // IGNORE PHI NODES
- Out << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
+ toAsm << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
unsigned Mask = getOperandMask(Opcode);
unsigned N = 1;
for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
- if (NeedComma) Out << ", "; // Handle comma outputing
+ if (NeedComma) toAsm << ", "; // Handle comma outputing
NeedComma = true;
N = printOperands(MI, OpNum);
}
else
N = 1;
- Out << endl;
+ toAsm << endl;
}
void
SparcAsmPrinter::emitBasicBlock(const BasicBlock *BB)
{
// Emit a label for the basic block
- Out << getID(BB) << ":\n";
+ toAsm << getID(BB) << ":\n";
// Get the vector of machine instructions corresponding to this bb.
const MachineCodeForBasicBlock &MIs = BB->getMachineInstrVec();
// Loop over all of the instructions in the basic block...
for (; MII != MIE; ++MII)
emitMachineInst(*MII);
- Out << "\n"; // Seperate BB's with newlines
+ toAsm << "\n"; // Seperate BB's with newlines
}
void
// Make sure the slot table has information about this method...
Table.incorporateMethod(M);
- string MethName = getID(M);
- Out << "!****** Outputing Method: " << MethName << " ******\n";
+ string methName = getID(M);
+ toAsm << "!****** Outputing Method: " << methName << " ******\n";
enterSection(Text);
- Out << "\t.align\t4\n\t.global\t" << MethName << "\n";
- //Out << "\t.type\t" << MethName << ",#function\n";
- Out << "\t.type\t" << MethName << ", 2\n";
- Out << MethName << ":\n";
+ toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
+ //toAsm << "\t.type\t" << methName << ",#function\n";
+ toAsm << "\t.type\t" << methName << ", 2\n";
+ toAsm << methName << ":\n";
// Output code for all of the basic blocks in the method...
for (Method::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
emitBasicBlock(*I);
// Output a .size directive so the debugger knows the extents of the function
- Out << ".EndOf_" << MethName << ":\n\t.size "
- << MethName << ", .EndOf_"
- << MethName << "-" << MethName << endl;
+ toAsm << ".EndOf_" << methName << ":\n\t.size "
+ << methName << ", .EndOf_"
+ << methName << "-" << methName << endl;
// Put some spaces between the methods
- Out << "\n\n";
+ toAsm << "\n\n";
// Forget all about M.
Table.purgeMethod();
arrayType->getElementType() == Type::SByteTy);
}
-inline const string TypeToDataDirective(const Type* type) {
- switch(type->getPrimitiveID()) {
- case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
- return ".byte";
- case Type::UShortTyID: case Type::ShortTyID:
- return ".half";
- case Type::UIntTyID: case Type::IntTyID:
- return ".word";
- case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
- return ".xword";
- case Type::FloatTyID:
- return ".float";
- case Type::DoubleTyID:
- return ".double";
- case Type::ArrayTyID:
- if (ArrayTypeIsString((ArrayType*) type))
- return ".ascii";
- else
+inline const string TypeToDataDirective(const Type* type)
+{
+ switch(type->getPrimitiveID())
+ {
+ case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
+ return ".byte";
+ case Type::UShortTyID: case Type::ShortTyID:
+ return ".half";
+ case Type::UIntTyID: case Type::IntTyID:
+ return ".word";
+ case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
+ return ".xword";
+ case Type::FloatTyID:
+ return ".single";
+ case Type::DoubleTyID:
+ return ".double";
+ case Type::ArrayTyID:
+ if (ArrayTypeIsString((ArrayType*) type))
+ return ".ascii";
+ else
+ return "<InvaliDataTypeForPrinting>";
+ default:
return "<InvaliDataTypeForPrinting>";
- default:
- return "<InvaliDataTypeForPrinting>";
- }
+ }
}
inline unsigned int ConstantToSize(const ConstPoolVal* CV,
if (valID.length() == 0)
valID = getID(CV);
- Out << "\t.align\t" << TypeToAlignment(CV->getType(), Target)
- << endl;
+ assert(CV->getType() != Type::VoidTy &&
+ CV->getType() != Type::TypeTy &&
+ CV->getType() != Type::LabelTy &&
+ "Unexpected type for ConstPoolVal");
+
+ toAsm << "\t.align\t" << TypeToAlignment(CV->getType(), Target)
+ << endl;
- Out << valID << ":" << endl;
+ toAsm << valID << ":" << endl;
- Out << "\t"
- << TypeToDataDirective(CV->getType()) << "\t";
-
- if (ConstPoolArray *CPA = dyn_cast<ConstPoolArray>(CV)) {
+ toAsm << "\t"
+ << TypeToDataDirective(CV->getType()) << "\t";
+
+ if (ConstPoolArray *CPA = dyn_cast<ConstPoolArray>(CV))
if (isStringCompatible(CPA))
- Out << getAsCString(CPA) << endl;
- else
- Out << CV->getStrValue() << endl; // TODO: This is broken
- } else {
- Out << CV->getStrValue() << endl; // TODO: this is broken
- }
+ {
+ toAsm << getAsCString(CPA) << endl;
+ return;
+ }
- Out << "\t.type" << "\t" << valID << ",#object" << endl;
- Out << "\t.size" << "\t" << valID << ","
- << ConstantToSize(CV, Target) << endl;
+ if (CV->getType()->isPrimitiveType())
+ {
+ if (CV->getType() == Type::FloatTy || CV->getType() == Type::DoubleTy)
+ toAsm << "0r"; // FP constants must have this prefix
+ toAsm << CV->getStrValue() << endl;
+ }
+ else if (ConstPoolPointer* CPP = dyn_cast<ConstPoolPointer>(CV))
+ {
+ if (! CPP->isNullValue())
+ assert(0 && "Cannot yet print non-null pointer constants to assembly");
+ else
+ toAsm << (void*) NULL;
+ }
+ else if (ConstPoolPointerRef* CPRef = dyn_cast<ConstPoolPointerRef>(CV))
+ {
+ assert(0 && "Cannot yet initialize pointer refs in assembly");
+ }
+ else
+ {
+ assert(0 && "Cannot yet print non-primitive constants to assembly");
+ // toAsm << CV->getStrValue() << endl;
+ }
+
+ toAsm << "\t.type" << "\t" << valID << ",#object" << endl;
+ toAsm << "\t.size" << "\t" << valID << ","
+ << ConstantToSize(CV, Target) << endl;
}
void
SparcAsmPrinter::printGlobalVariable(const GlobalVariable* GV)
{
- Out << "\t.global\t" << getID(GV) << endl;
+ toAsm << "\t.global\t" << getID(GV) << endl;
if (GV->hasInitializer())
printConstant(GV->getInitializer(), getID(GV));
else {
- Out << "\t.align" << TypeToAlignment(GV->getType()->getValueType(), Target)
- << getID(GV) << ":" << endl;
+ toAsm << "\t.align" << TypeToAlignment(GV->getType()->getValueType(), Target)
+ << getID(GV) << ":" << endl;
- Out << "\t.type" << "\t" << getID(GV) << ",#object" << endl;
- Out << "\t.size" << "\t" << getID(GV) << ","
- << TypeToSize(GV->getType()->getValueType(), Target)
- << endl;
+ toAsm << "\t.type" << "\t" << getID(GV) << ",#object" << endl;
+ toAsm << "\t.size" << "\t" << getID(GV) << ","
+ << TypeToSize(GV->getType()->getValueType(), Target)
+ << endl;
}
}
static void
FoldConstPools(const Module *M,
- hash_set<const ConstPoolVal*>& moduleConstPool) {
- for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
- const hash_set<const ConstPoolVal*>& pool =
- (*I)->getMachineCode().getConstantPoolValues();
- moduleConstPool.insert(pool.begin(), pool.end());
- }
+ hash_set<const ConstPoolVal*>& moduleConstPool)
+{
+ for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (! (*I)->isExternal())
+ {
+ const hash_set<const ConstPoolVal*>& pool =
+ MachineCodeForMethod::get(*I).getConstantPoolValues();
+ moduleConstPool.insert(pool.begin(), pool.end());
+ }
}
}
}
- Out << endl;
+ toAsm << endl;
}
// used.
//
void
-UltraSparc::emitAssembly(const Module *M, ostream &Out) const
+UltraSparc::emitAssembly(const Module *M, ostream &toAsm) const
{
- SparcAsmPrinter Print(Out, M, *this);
+ SparcAsmPrinter Print(toAsm, M, *this);
}