//===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
//
// 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 implements all of the stuff necessary to output a .s file from
// LLVM. The code in this file assumes that the specified module has already
// been compiled into the internal data structures of the Module.
//
// This code largely consists of two LLVM Pass's: a FunctionPass and a Pass.
// The FunctionPass is pipelined together with all of the rest of the code
// generation stages, and the Pass runs at the end to emit code for global
// variables and such.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/SlotCalculator.h"
#include "llvm/Pass.h"
#include "llvm/Assembly/Writer.h"
#include "Support/StringExtras.h"
#include "Support/Statistic.h"
#include "SparcInternals.h"
#include <string>
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");
//===---------------------------------------------------------------------===//
// Code Shared By the two printer passes, as a mixin
//===---------------------------------------------------------------------===//
class AsmPrinter {
GlobalIdTable* idTable;
public:
std::ostream &toAsm;
const TargetMachine &Target;
enum Sections {
Unknown,
Text,
ReadOnlyData,
InitRWData,
ZeroInitRWData,
} CurSection;
AsmPrinter(std::ostream &os, const TargetMachine &T)
: idTable(0), toAsm(os), Target(T), CurSection(Unknown) {}
// (start|end)(Module|Function) - Callback methods to be 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);
}
}
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
}
void endModule() {
}
// 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.
//
void enterSection(enum Sections S) {
if (S == CurSection) return; // Only switch section if necessary
CurSection = S;
toAsm << "\n\t.section ";
switch (S)
{
default: assert(0 && "Bad section name!");
case Text: toAsm << "\".text\""; break;
case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break;
}
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