#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCLabel.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ELF.h"
using namespace llvm;
typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
typedef StringMap<const MCSectionELF*> ELFUniqueMapTy;
typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri,
const MCObjectFileInfo *mofi) :
MAI(mai), MRI(mri), MOFI(mofi),
Allocator(), Symbols(Allocator), UsedNames(Allocator),
NextUniqueID(0),
CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0),
AllowTemporaryLabels(true) {
MachOUniquingMap = 0;
ELFUniquingMap = 0;
COFFUniquingMap = 0;
SecureLogFile = getenv("AS_SECURE_LOG_FILE");
SecureLog = 0;
SecureLogUsed = false;
DwarfLocSeen = false;
GenDwarfForAssembly = false;
GenDwarfFileNumber = 0;
}
MCContext::~MCContext() {
delete (MachOUniqueMapTy*)MachOUniquingMap;
delete (ELFUniqueMapTy*)ELFUniquingMap;
delete (COFFUniqueMapTy*)COFFUniquingMap;
delete (raw_ostream*)SecureLog;
}
MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) {
assert(!Name.empty() && "Normal symbols cannot be unnamed!");
StringMapEntry<MCSymbol*> &Entry = Symbols.GetOrCreateValue(Name);
MCSymbol *Sym = Entry.getValue();
if (Sym)
return Sym;
Sym = CreateSymbol(Name);
Entry.setValue(Sym);
return Sym;
}
MCSymbol *MCContext::CreateSymbol(StringRef Name) {
bool isTemporary = false;
if (AllowTemporaryLabels)
isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix());
StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name);
if (NameEntry->getValue()) {
assert(isTemporary && "Cannot rename non temporary symbols");
SmallString<128> NewName = Name;
do {
NewName.resize(Name.size());
raw_svector_ostream(NewName) << NextUniqueID++;
NameEntry = &UsedNames.GetOrCreateValue(NewName);
} while (NameEntry->getValue());
}
NameEntry->setValue(true);
MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary);
return Result;
}
MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
SmallString<128> NameSV;
Name.toVector(NameSV);
return GetOrCreateSymbol(NameSV.str());
}
MCSymbol *MCContext::CreateTempSymbol() {
SmallString<128> NameSV;
raw_svector_ostream(NameSV)
<< MAI.getPrivateGlobalPrefix() << "tmp" << NextUniqueID++;
return CreateSymbol(NameSV);
}
unsigned MCContext::NextInstance(int64_t LocalLabelVal) {
MCLabel *&Label = Instances[LocalLabelVal];
if (!Label)
Label = new (*this) MCLabel(0);
return Label->incInstance();
}
unsigned MCContext::GetInstance(int64_t LocalLabelVal) {
MCLabel *&Label = Instances[LocalLabelVal];
if (!Label)
Label = new (*this) MCLabel(0);
return Label->getInstance();
}
MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) {
return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) +
Twine(LocalLabelVal) +
"\2" +
Twine(NextInstance(LocalLabelVal)));
}
MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal,
int bORf) {
return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) +
Twine(LocalLabelVal) +
"\2" +
Twine(GetInstance(LocalLabelVal) + bORf));
}
MCSymbol *MCContext::LookupSymbol(StringRef Name) const {
return Symbols.lookup(Name);
}
const MCSectionMachO *MCContext::
getMachOSection(StringRef Segment, StringRef Section,
unsigned TypeAndAttributes,
unsigned Reserved2, SectionKind Kind) {
if (MachOUniquingMap == 0)
MachOUniquingMap = new MachOUniqueMapTy();
MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap;
SmallString<64> Name;
Name += Segment;
Name.push_back(',');
Name += Section;
const MCSectionMachO *&Entry = Map[Name.str()];
if (Entry) return Entry;
return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes,
Reserved2, Kind);
}
const MCSectionELF *MCContext::
getELFSection(StringRef Section, unsigned Type, unsigned Flags,
SectionKind Kind) {
return getELFSection(Section, Type, Flags, Kind, 0, "");
}
const MCSectionELF *MCContext::
getELFSection(StringRef Section, unsigned Type, unsigned Flags,
SectionKind Kind, unsigned EntrySize, StringRef Group) {
if (ELFUniquingMap == 0)
ELFUniquingMap = new ELFUniqueMapTy();
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section);
if (Entry.getValue()) return Entry.getValue();
if (!EntrySize) {
EntrySize = MCSectionELF::DetermineEntrySize(Kind);
}
MCSymbol *GroupSym = NULL;
if (!Group.empty())
GroupSym = GetOrCreateSymbol(Group);
MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags,
Kind, EntrySize, GroupSym);
Entry.setValue(Result);
return Result;
}
const MCSectionELF *MCContext::CreateELFGroupSection() {
MCSectionELF *Result =
new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0,
SectionKind::getReadOnly(), 4, NULL);
return Result;
}
const MCSection *MCContext::getCOFFSection(StringRef Section,
unsigned Characteristics,
int Selection,
SectionKind Kind) {
if (COFFUniquingMap == 0)
COFFUniquingMap = new COFFUniqueMapTy();
COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap;
StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section);
if (Entry.getValue()) return Entry.getValue();
MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(),
Characteristics,
Selection, Kind);
Entry.setValue(Result);
return Result;
}
unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName,
unsigned FileNumber) {
if (FileNumber >= MCDwarfFiles.size()) {
MCDwarfFiles.resize(FileNumber + 1);
} else {
MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber];
if (ExistingFile)
return 0;
}
MCDwarfFile *&File = MCDwarfFiles[FileNumber];
if (Directory.empty()) {
std::pair<StringRef, StringRef> Slash = FileName.rsplit('/');
Directory = Slash.second;
if (!Directory.empty()) {
Directory = Slash.first;
FileName = Slash.second;
}
}
unsigned DirIndex;
if (Directory.empty()) {
DirIndex = 0;
} else {
DirIndex = 0;
for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) {
if (Directory == MCDwarfDirs[DirIndex])
break;
}
if (DirIndex >= MCDwarfDirs.size()) {
char *Buf = static_cast<char *>(Allocate(Directory.size()));
memcpy(Buf, Directory.data(), Directory.size());
MCDwarfDirs.push_back(StringRef(Buf, Directory.size()));
}
DirIndex++;
}
char *Buf = static_cast<char *>(Allocate(FileName.size()));
memcpy(Buf, FileName.data(), FileName.size());
File = new (*this) MCDwarfFile(StringRef(Buf, FileName.size()), DirIndex);
return FileNumber;
}
bool MCContext::isValidDwarfFileNumber(unsigned FileNumber) {
if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
return false;
return MCDwarfFiles[FileNumber] != 0;
}