upload android base code part1
This commit is contained in:
parent
e02f198e2d
commit
0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions
22
android/frameworks/compile/mclinker/lib/Support/Android.bp
Normal file
22
android/frameworks/compile/mclinker/lib/Support/Android.bp
Normal file
|
@ -0,0 +1,22 @@
|
|||
cc_library_static {
|
||||
name: "libmcldSupport",
|
||||
defaults: ["mcld-defaults"],
|
||||
host_supported: true,
|
||||
srcs: [
|
||||
"Demangle.cpp",
|
||||
"Directory.cpp",
|
||||
"FileHandle.cpp",
|
||||
"FileOutputBuffer.cpp",
|
||||
"FileSystem.cpp",
|
||||
"LEB128.cpp",
|
||||
"MemoryArea.cpp",
|
||||
"MemoryAreaFactory.cpp",
|
||||
"MsgHandling.cpp",
|
||||
"Path.cpp",
|
||||
"raw_ostream.cpp",
|
||||
"RealPath.cpp",
|
||||
"SystemUtils.cpp",
|
||||
"Target.cpp",
|
||||
"TargetRegistry.cpp",
|
||||
],
|
||||
}
|
73
android/frameworks/compile/mclinker/lib/Support/Demangle.cpp
Normal file
73
android/frameworks/compile/mclinker/lib/Support/Demangle.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
//===- Demangle.cpp -------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/CXADemangle.tcc"
|
||||
#include "mcld/Support/Demangle.h"
|
||||
|
||||
#ifdef HAVE_CXXABI_H
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
namespace mcld {
|
||||
|
||||
std::string demangleName(const std::string& pName) {
|
||||
#ifdef HAVE_CXXABI_H
|
||||
// Spoil names of symbols with C linkage, so use an heuristic approach to
|
||||
// check if the name should be demangled.
|
||||
if (pName.substr(0, 2) != "_Z")
|
||||
return pName;
|
||||
// __cxa_demangle needs manually handle the memory release, so we wrap
|
||||
// it into this helper function.
|
||||
size_t output_leng;
|
||||
int status;
|
||||
char* buffer =
|
||||
abi::__cxa_demangle(pName.c_str(), /*buffer=*/0, &output_leng, &status);
|
||||
if (status != 0) { // Failed
|
||||
return pName;
|
||||
}
|
||||
std::string result(buffer);
|
||||
free(buffer);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return pName;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isCtorOrDtor(const char* pName, size_t pLength) {
|
||||
arena<bs> a;
|
||||
Db db(a);
|
||||
db.cv = 0;
|
||||
db.ref = 0;
|
||||
db.encoding_depth = 0;
|
||||
db.parsed_ctor_dtor_cv = false;
|
||||
db.tag_templates = true;
|
||||
db.template_param.emplace_back(a);
|
||||
db.fix_forward_references = false;
|
||||
db.try_to_parse_template_args = true;
|
||||
int internal_status = success;
|
||||
demangle(pName, pName + pLength, db, internal_status);
|
||||
if (internal_status == success && db.fix_forward_references &&
|
||||
!db.template_param.empty() && !db.template_param.front().empty()) {
|
||||
db.fix_forward_references = false;
|
||||
db.tag_templates = false;
|
||||
db.names.clear();
|
||||
db.subs.clear();
|
||||
demangle(pName, pName + pLength, db, internal_status);
|
||||
if (db.fix_forward_references)
|
||||
internal_status = invalid_mangled_name;
|
||||
}
|
||||
|
||||
if (internal_status != success) {
|
||||
db.parsed_ctor_dtor_cv = false;
|
||||
}
|
||||
return db.parsed_ctor_dtor_cv;
|
||||
}
|
||||
|
||||
} // namespace mcld
|
238
android/frameworks/compile/mclinker/lib/Support/Directory.cpp
Normal file
238
android/frameworks/compile/mclinker/lib/Support/Directory.cpp
Normal file
|
@ -0,0 +1,238 @@
|
|||
//===- Directory.cpp ------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/Directory.h"
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
|
||||
namespace { // anonymous
|
||||
|
||||
bool status_known(FileStatus f) {
|
||||
return f.type() != StatusError;
|
||||
}
|
||||
|
||||
bool is_symlink(FileStatus f) {
|
||||
return f.type() == SymlinkFile;
|
||||
}
|
||||
|
||||
const Path dot_path(".");
|
||||
const Path dot_dot_path("..");
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Directory
|
||||
//===----------------------------------------------------------------------===//
|
||||
Directory::Directory()
|
||||
: m_Path(),
|
||||
m_FileStatus(),
|
||||
m_SymLinkStatus(),
|
||||
m_Handler(0),
|
||||
m_Cache(),
|
||||
m_CacheFull(false) {
|
||||
}
|
||||
|
||||
Directory::Directory(const Path& pPath, FileStatus st, FileStatus symlink_st)
|
||||
: m_Path(pPath),
|
||||
m_FileStatus(st),
|
||||
m_SymLinkStatus(symlink_st),
|
||||
m_Handler(0),
|
||||
m_Cache(),
|
||||
m_CacheFull(false) {
|
||||
if (m_Path == dot_path)
|
||||
detail::get_pwd(m_Path);
|
||||
m_Path.m_append_separator_if_needed();
|
||||
detail::open_dir(*this);
|
||||
}
|
||||
|
||||
Directory::Directory(const char* pPath, FileStatus st, FileStatus symlink_st)
|
||||
: Directory(sys::fs::Path(pPath), st, symlink_st) {
|
||||
}
|
||||
|
||||
Directory::Directory(const Directory& pCopy)
|
||||
: m_Path(pCopy.m_Path),
|
||||
m_FileStatus(pCopy.m_FileStatus),
|
||||
m_SymLinkStatus(pCopy.m_SymLinkStatus),
|
||||
m_Handler(0),
|
||||
m_Cache(),
|
||||
m_CacheFull(false) {
|
||||
detail::open_dir(*this);
|
||||
}
|
||||
|
||||
Directory::~Directory() {
|
||||
detail::close_dir(*this);
|
||||
}
|
||||
|
||||
bool Directory::isGood() const {
|
||||
return (0 != m_Handler);
|
||||
}
|
||||
|
||||
Directory& Directory::operator=(const Directory& pCopy) {
|
||||
assign(pCopy.m_Path, pCopy.m_FileStatus, pCopy.m_SymLinkStatus);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Directory::assign(const Path& pPath,
|
||||
FileStatus st,
|
||||
FileStatus symlink_st) {
|
||||
if (isGood())
|
||||
clear();
|
||||
|
||||
m_Path = pPath;
|
||||
if (m_Path == dot_path)
|
||||
detail::get_pwd(m_Path);
|
||||
m_Path.m_append_separator_if_needed();
|
||||
|
||||
m_FileStatus = st;
|
||||
m_SymLinkStatus = symlink_st;
|
||||
detail::open_dir(*this);
|
||||
}
|
||||
|
||||
FileStatus Directory::status() const {
|
||||
if (!status_known(m_FileStatus)) {
|
||||
// optimization: if the symlink status is known, and it isn't a symlink,
|
||||
// then status and symlink_status are identical so just copy the
|
||||
// symlink status to the regular status.
|
||||
if (status_known(m_SymLinkStatus) && !is_symlink(m_SymLinkStatus)) {
|
||||
m_FileStatus = m_SymLinkStatus;
|
||||
} else
|
||||
detail::status(m_Path, m_FileStatus);
|
||||
}
|
||||
return m_FileStatus;
|
||||
}
|
||||
|
||||
FileStatus Directory::symlinkStatus() const {
|
||||
if (!status_known(m_SymLinkStatus))
|
||||
detail::symlink_status(m_Path, m_SymLinkStatus);
|
||||
return m_SymLinkStatus;
|
||||
}
|
||||
|
||||
Directory::iterator Directory::begin() {
|
||||
if (m_CacheFull && m_Cache.empty())
|
||||
return end();
|
||||
PathCache::iterator iter = m_Cache.begin();
|
||||
if (iter.getEntry() == NULL)
|
||||
++iter;
|
||||
return iterator(this, iter);
|
||||
}
|
||||
|
||||
Directory::iterator Directory::end() {
|
||||
return iterator(0, m_Cache.end());
|
||||
}
|
||||
|
||||
void Directory::clear() {
|
||||
m_Path.native().clear();
|
||||
m_FileStatus = FileStatus();
|
||||
m_SymLinkStatus = FileStatus();
|
||||
m_Cache.clear();
|
||||
detail::close_dir(*this);
|
||||
}
|
||||
|
||||
//==========================
|
||||
// DirIterator
|
||||
DirIterator::DirIterator(Directory* pParent,
|
||||
const DirIterator::DirCache::iterator& pIter)
|
||||
: m_pParent(pParent), m_Iter(pIter) {
|
||||
m_pEntry = m_Iter.getEntry();
|
||||
}
|
||||
|
||||
DirIterator::DirIterator(const DirIterator& pCopy)
|
||||
: m_pParent(pCopy.m_pParent),
|
||||
m_Iter(pCopy.m_Iter),
|
||||
m_pEntry(pCopy.m_pEntry) {
|
||||
}
|
||||
|
||||
DirIterator::~DirIterator() {
|
||||
}
|
||||
|
||||
Path* DirIterator::path() {
|
||||
if (m_pParent == NULL)
|
||||
return NULL;
|
||||
return &m_pEntry->value();
|
||||
}
|
||||
|
||||
const Path* DirIterator::path() const {
|
||||
if (m_pParent == NULL)
|
||||
return NULL;
|
||||
return &m_pEntry->value();
|
||||
}
|
||||
|
||||
DirIterator& DirIterator::operator=(const DirIterator& pCopy) {
|
||||
m_pParent = pCopy.m_pParent;
|
||||
m_Iter = pCopy.m_Iter;
|
||||
m_pEntry = pCopy.m_pEntry;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
DirIterator& DirIterator::operator++() {
|
||||
if (m_pParent == 0)
|
||||
return *this;
|
||||
|
||||
// move forward one step first.
|
||||
++m_Iter;
|
||||
|
||||
if (m_pParent->m_Cache.end() == m_Iter) {
|
||||
if (!m_pParent->m_CacheFull) {
|
||||
m_pEntry = detail::bring_one_into_cache(*this);
|
||||
if (m_pEntry == 0 && m_pParent->m_CacheFull)
|
||||
m_pParent = 0;
|
||||
return *this;
|
||||
}
|
||||
m_pParent = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_pEntry = m_Iter.getEntry();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DirIterator DirIterator::operator++(int pIn) {
|
||||
DirIterator tmp(*this);
|
||||
|
||||
// move forward one step first.
|
||||
++m_Iter;
|
||||
|
||||
if (m_pParent->m_Cache.end() == m_Iter) {
|
||||
if (!m_pParent->m_CacheFull) {
|
||||
m_pEntry = detail::bring_one_into_cache(*this);
|
||||
if (m_pEntry == 0 && m_pParent->m_CacheFull)
|
||||
m_pParent = 0;
|
||||
return tmp;
|
||||
}
|
||||
m_pParent = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
m_pEntry = m_Iter.getEntry();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool DirIterator::operator==(const DirIterator& y) const {
|
||||
if (m_pParent != y.m_pParent)
|
||||
return false;
|
||||
if (m_pParent == 0)
|
||||
return true;
|
||||
const Path* x_path = path();
|
||||
const Path* y_path = y.path();
|
||||
if (x_path == 0 && y_path == 0)
|
||||
return true;
|
||||
if (x_path == 0 || y_path == 0)
|
||||
return false;
|
||||
return (*x_path == *y_path);
|
||||
}
|
||||
|
||||
bool DirIterator::operator!=(const DirIterator& y) const {
|
||||
return !this->operator==(y);
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
247
android/frameworks/compile/mclinker/lib/Support/FileHandle.cpp
Normal file
247
android/frameworks/compile/mclinker/lib/Support/FileHandle.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
//===- FileHandle.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/FileHandle.h"
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(HAVE_FCNTL_H)
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FileHandle
|
||||
//===----------------------------------------------------------------------===//
|
||||
FileHandle::FileHandle()
|
||||
: m_Path(),
|
||||
m_Handler(-1),
|
||||
m_Size(0),
|
||||
m_State(GoodBit),
|
||||
m_OpenMode(NotOpen) {
|
||||
}
|
||||
|
||||
FileHandle::~FileHandle() {
|
||||
if (isOpened())
|
||||
close();
|
||||
}
|
||||
|
||||
inline static int oflag(FileHandle::OpenMode pMode) {
|
||||
int result = 0x0;
|
||||
if (FileHandle::Unknown == pMode)
|
||||
return result;
|
||||
|
||||
if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
|
||||
result |= O_RDWR;
|
||||
else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
|
||||
result |= O_RDONLY;
|
||||
else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
|
||||
result |= O_WRONLY;
|
||||
|
||||
if (FileHandle::Append == (pMode & FileHandle::Append))
|
||||
result |= O_APPEND;
|
||||
|
||||
if (FileHandle::Create == (pMode & FileHandle::Create))
|
||||
result |= O_CREAT;
|
||||
|
||||
if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
|
||||
result |= O_TRUNC;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static bool get_size(int pHandler, unsigned int& pSize) {
|
||||
struct ::stat file_stat;
|
||||
if (-1 == ::fstat(pHandler, &file_stat)) {
|
||||
pSize = 0;
|
||||
return false;
|
||||
}
|
||||
pSize = file_stat.st_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::open(const sys::fs::Path& pPath,
|
||||
FileHandle::OpenMode pMode,
|
||||
FileHandle::Permission pPerm) {
|
||||
if (isOpened() || Unknown == pMode) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_OpenMode = pMode;
|
||||
if (System == pPerm)
|
||||
m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
|
||||
else
|
||||
m_Handler = sys::fs::detail::open(pPath, oflag(pMode),
|
||||
static_cast<int>(pPerm));
|
||||
|
||||
m_Path = pPath;
|
||||
if (m_Handler == -1) {
|
||||
m_OpenMode = OpenMode(NotOpen);
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!get_size(m_Handler, m_Size)) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::delegate(int pFD, FileHandle::OpenModeEnum pMode) {
|
||||
if (isOpened()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Handler = pFD;
|
||||
m_OpenMode = OpenMode(pMode);
|
||||
m_State = (GoodBit | DeputedBit);
|
||||
|
||||
if (!get_size(m_Handler, m_Size)) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::close() {
|
||||
if (!isOpened()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isOwned()) {
|
||||
if (::close(m_Handler) == -1) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_Path.native().clear();
|
||||
m_Size = 0;
|
||||
m_OpenMode = OpenMode(NotOpen);
|
||||
cleanState();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::truncate(size_t pSize) {
|
||||
if (!isOpened() || !isWritable()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sys::fs::detail::ftruncate(m_Handler, pSize) == -1) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Size = pSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength) {
|
||||
if (!isOpened() || !isReadable()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pLength == 0)
|
||||
return true;
|
||||
|
||||
ssize_t read_bytes =
|
||||
sys::fs::detail::pread(m_Handler, pMemBuffer, pLength, pStartOffset);
|
||||
|
||||
if (read_bytes == -1) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::write(const void* pMemBuffer,
|
||||
size_t pStartOffset,
|
||||
size_t pLength) {
|
||||
if (!isOpened() || !isWritable()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pLength == 0)
|
||||
return true;
|
||||
|
||||
ssize_t write_bytes =
|
||||
sys::fs::detail::pwrite(m_Handler, pMemBuffer, pLength, pStartOffset);
|
||||
|
||||
if (write_bytes == -1) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileHandle::setState(FileHandle::IOState pState) {
|
||||
m_State |= pState;
|
||||
}
|
||||
|
||||
void FileHandle::cleanState(FileHandle::IOState pState) {
|
||||
m_State = pState;
|
||||
}
|
||||
|
||||
bool FileHandle::isOpened() const {
|
||||
if (m_Handler != -1 && m_OpenMode != NotOpen && isGood())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assume Unknown OpenMode is readable
|
||||
bool FileHandle::isReadable() const {
|
||||
return (m_OpenMode & ReadOnly);
|
||||
}
|
||||
|
||||
// Assume Unknown OpenMode is writable
|
||||
bool FileHandle::isWritable() const {
|
||||
return (m_OpenMode & WriteOnly);
|
||||
}
|
||||
|
||||
// Assume Unknown OpenMode is both readable and writable
|
||||
bool FileHandle::isReadWrite() const {
|
||||
return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
|
||||
}
|
||||
|
||||
bool FileHandle::isGood() const {
|
||||
return !(m_State & (BadBit | FailBit));
|
||||
}
|
||||
|
||||
bool FileHandle::isBad() const {
|
||||
return (m_State & BadBit);
|
||||
}
|
||||
|
||||
bool FileHandle::isFailed() const {
|
||||
return (m_State & (BadBit | FailBit));
|
||||
}
|
||||
|
||||
bool FileHandle::isOwned() const {
|
||||
return !(m_State & DeputedBit);
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,59 @@
|
|||
//===- FileOutputBuffer.cpp -----------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/FileOutputBuffer.h"
|
||||
#include "mcld/Support/FileHandle.h"
|
||||
#include "mcld/Support/Path.h"
|
||||
|
||||
namespace mcld {
|
||||
|
||||
FileOutputBuffer::FileOutputBuffer(llvm::sys::fs::mapped_file_region* pRegion,
|
||||
FileHandle& pFileHandle)
|
||||
: m_pRegion(pRegion), m_FileHandle(pFileHandle) {
|
||||
}
|
||||
|
||||
FileOutputBuffer::~FileOutputBuffer() {
|
||||
// Unmap buffer, letting OS flush dirty pages to file on disk.
|
||||
m_pRegion.reset();
|
||||
}
|
||||
|
||||
std::error_code
|
||||
FileOutputBuffer::create(FileHandle& pFileHandle,
|
||||
size_t pSize,
|
||||
std::unique_ptr<FileOutputBuffer>& pResult) {
|
||||
std::error_code ec;
|
||||
|
||||
// Resize the file before mapping the file region.
|
||||
ec = llvm::sys::fs::resize_file(pFileHandle.handler(), pSize);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
std::unique_ptr<llvm::sys::fs::mapped_file_region> mapped_file(
|
||||
new llvm::sys::fs::mapped_file_region(pFileHandle.handler(),
|
||||
llvm::sys::fs::mapped_file_region::readwrite, pSize, 0, ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
pResult.reset(new FileOutputBuffer(mapped_file.get(), pFileHandle));
|
||||
if (pResult)
|
||||
mapped_file.release();
|
||||
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
MemoryRegion FileOutputBuffer::request(size_t pOffset, size_t pLength) {
|
||||
if (pOffset > getBufferSize() || (pOffset + pLength) > getBufferSize())
|
||||
return MemoryRegion();
|
||||
return MemoryRegion(getBufferStart() + pOffset, pLength);
|
||||
}
|
||||
|
||||
llvm::StringRef FileOutputBuffer::getPath() const {
|
||||
return m_FileHandle.path().native();
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,37 @@
|
|||
//===- FileSystem.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
#include "mcld/Support/Path.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// non-member functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool mcld::sys::fs::exists(const Path& pPath) {
|
||||
mcld::sys::fs::FileStatus file_status;
|
||||
mcld::sys::fs::detail::status(pPath, file_status);
|
||||
return (file_status.type() != mcld::sys::fs::StatusError) &&
|
||||
(file_status.type() != mcld::sys::fs::FileNotFound);
|
||||
}
|
||||
|
||||
bool mcld::sys::fs::is_directory(const Path& pPath) {
|
||||
FileStatus file_status;
|
||||
detail::status(pPath, file_status);
|
||||
return (file_status.type() == mcld::sys::fs::DirectoryFile);
|
||||
}
|
||||
|
||||
// Include the truly platform-specific parts.
|
||||
#if defined(MCLD_ON_UNIX)
|
||||
#include "Unix/FileSystem.inc"
|
||||
#include "Unix/PathV3.inc"
|
||||
#endif
|
||||
#if defined(MCLD_ON_WIN32)
|
||||
#include "Windows/FileSystem.inc"
|
||||
#include "Windows/PathV3.inc"
|
||||
#endif
|
224
android/frameworks/compile/mclinker/lib/Support/LEB128.cpp
Normal file
224
android/frameworks/compile/mclinker/lib/Support/LEB128.cpp
Normal file
|
@ -0,0 +1,224 @@
|
|||
//===- LEB128.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/LEB128.h"
|
||||
|
||||
namespace mcld {
|
||||
|
||||
namespace leb128 {
|
||||
|
||||
//===---------------------- LEB128 Encoding APIs -------------------------===//
|
||||
template <>
|
||||
size_t encode<uint64_t>(ByteType*& pBuf, uint64_t pValue) {
|
||||
size_t size = 0;
|
||||
do {
|
||||
ByteType byte = pValue & 0x7f;
|
||||
pValue >>= 7;
|
||||
if (pValue)
|
||||
byte |= 0x80;
|
||||
*pBuf++ = byte;
|
||||
size++;
|
||||
} while (pValue);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast version for encoding 32-bit integer. This unrolls the loop in the
|
||||
* generic version defined above.
|
||||
*/
|
||||
template <>
|
||||
size_t encode<uint32_t>(ByteType*& pBuf, uint32_t pValue) {
|
||||
if ((pValue & ~0x7f) == 0) {
|
||||
*pBuf++ = static_cast<ByteType>(pValue);
|
||||
return 1;
|
||||
} else if ((pValue & ~0x3fff) == 0) {
|
||||
*pBuf++ = static_cast<ByteType>((pValue & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>((pValue >> 7) & 0x7f);
|
||||
return 2;
|
||||
} else if ((pValue & ~0x1fffff) == 0) {
|
||||
*pBuf++ = static_cast<ByteType>((pValue & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 7) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>((pValue >> 14) & 0x7f);
|
||||
return 3;
|
||||
} else if ((pValue & ~0xfffffff) == 0) {
|
||||
*pBuf++ = static_cast<ByteType>((pValue & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 7) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 14) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>((pValue >> 21) & 0x7f);
|
||||
return 4;
|
||||
} else {
|
||||
*pBuf++ = static_cast<ByteType>((pValue & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 7) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 14) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>(((pValue >> 21) & 0x7f) | 0x80);
|
||||
*pBuf++ = static_cast<ByteType>((pValue >> 28) & 0x7f);
|
||||
return 5;
|
||||
}
|
||||
// unreachable
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t encode<int64_t>(ByteType*& pBuf, int64_t pValue) {
|
||||
size_t size = 0;
|
||||
bool more = true;
|
||||
|
||||
do {
|
||||
ByteType byte = pValue & 0x7f;
|
||||
pValue >>= 7;
|
||||
|
||||
if (((pValue == 0) && ((byte & 0x40) == 0)) ||
|
||||
((pValue == -1) && ((byte & 0x40) == 0x40)))
|
||||
more = false;
|
||||
else
|
||||
byte |= 0x80;
|
||||
|
||||
*pBuf++ = byte;
|
||||
size++;
|
||||
} while (more);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t encode<int32_t>(ByteType*& pBuf, int32_t pValue) {
|
||||
return encode<int64_t>(pBuf, static_cast<int64_t>(pValue));
|
||||
}
|
||||
|
||||
//===---------------------- LEB128 Decoding APIs -------------------------===//
|
||||
|
||||
template <>
|
||||
uint64_t decode<uint64_t>(const ByteType* pBuf, size_t& pSize) {
|
||||
uint64_t result = 0;
|
||||
|
||||
if ((*pBuf & 0x80) == 0) {
|
||||
pSize = 1;
|
||||
return *pBuf;
|
||||
} else if ((*(pBuf + 1) & 0x80) == 0) {
|
||||
pSize = 2;
|
||||
return ((*(pBuf + 1) & 0x7f) << 7) | (*pBuf & 0x7f);
|
||||
} else if ((*(pBuf + 2) & 0x80) == 0) {
|
||||
pSize = 3;
|
||||
return ((*(pBuf + 2) & 0x7f) << 14) | ((*(pBuf + 1) & 0x7f) << 7) |
|
||||
(*pBuf & 0x7f);
|
||||
} else {
|
||||
pSize = 4;
|
||||
result = ((*(pBuf + 3) & 0x7f) << 21) | ((*(pBuf + 2) & 0x7f) << 14) |
|
||||
((*(pBuf + 1) & 0x7f) << 7) | (*pBuf & 0x7f);
|
||||
}
|
||||
|
||||
if ((*(pBuf + 3) & 0x80) != 0) {
|
||||
// Large number which is an unusual case.
|
||||
unsigned shift;
|
||||
ByteType byte;
|
||||
|
||||
// Start the read from the 4th byte.
|
||||
shift = 28;
|
||||
pBuf += 4;
|
||||
do {
|
||||
byte = *pBuf;
|
||||
pBuf++;
|
||||
pSize++;
|
||||
result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
|
||||
shift += 7;
|
||||
} while (byte & 0x80);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <>
|
||||
uint64_t decode<uint64_t>(const ByteType*& pBuf) {
|
||||
ByteType byte;
|
||||
uint64_t result;
|
||||
|
||||
byte = *pBuf++;
|
||||
result = byte & 0x7f;
|
||||
if ((byte & 0x80) == 0) {
|
||||
return result;
|
||||
} else {
|
||||
byte = *pBuf++;
|
||||
result |= ((byte & 0x7f) << 7);
|
||||
if ((byte & 0x80) == 0) {
|
||||
return result;
|
||||
} else {
|
||||
byte = *pBuf++;
|
||||
result |= (byte & 0x7f) << 14;
|
||||
if ((byte & 0x80) == 0) {
|
||||
return result;
|
||||
} else {
|
||||
byte = *pBuf++;
|
||||
result |= (byte & 0x7f) << 21;
|
||||
if ((byte & 0x80) == 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Large number which is an unusual case.
|
||||
unsigned shift;
|
||||
|
||||
// Start the read from the 4th byte.
|
||||
shift = 28;
|
||||
do {
|
||||
byte = *pBuf++;
|
||||
result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
|
||||
shift += 7;
|
||||
} while (byte & 0x80);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signed LEB128 decoding is Similar to the unsigned version but setup the sign
|
||||
* bit if necessary. This is rarely used, therefore we don't provide unrolling
|
||||
* version like decode() to save the code size.
|
||||
*/
|
||||
template <>
|
||||
int64_t decode<int64_t>(const ByteType* pBuf, size_t& pSize) {
|
||||
uint64_t result = 0;
|
||||
ByteType byte;
|
||||
unsigned shift = 0;
|
||||
|
||||
pSize = 0;
|
||||
do {
|
||||
byte = *pBuf;
|
||||
pBuf++;
|
||||
pSize++;
|
||||
result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
|
||||
shift += 7;
|
||||
} while (byte & 0x80);
|
||||
|
||||
if ((shift < (8 * sizeof(result))) && (byte & 0x40))
|
||||
result |= ((static_cast<uint64_t>(-1)) << shift);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <>
|
||||
int64_t decode<int64_t>(const ByteType*& pBuf) {
|
||||
uint64_t result = 0;
|
||||
ByteType byte;
|
||||
unsigned shift = 0;
|
||||
|
||||
do {
|
||||
byte = *pBuf;
|
||||
pBuf++;
|
||||
result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
|
||||
shift += 7;
|
||||
} while (byte & 0x80);
|
||||
|
||||
if ((shift < (8 * sizeof(result))) && (byte & 0x40))
|
||||
result |= ((static_cast<uint64_t>(-1)) << shift);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace leb128
|
||||
} // namespace mcld
|
|
@ -0,0 +1,49 @@
|
|||
//===- MemoryArea.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/MemoryArea.h"
|
||||
#include "mcld/Support/MsgHandling.h"
|
||||
|
||||
#include <llvm/Support/ErrorOr.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <system_error>
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// MemoryArea
|
||||
//===--------------------------------------------------------------------===//
|
||||
MemoryArea::MemoryArea(llvm::StringRef pFilename) {
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer> > buffer_or_error =
|
||||
llvm::MemoryBuffer::getFile(pFilename,
|
||||
/*FileSize*/ -1,
|
||||
/*RequiresNullTerminator*/ false);
|
||||
if (!buffer_or_error) {
|
||||
fatal(diag::fatal_cannot_read_input) << pFilename.str();
|
||||
}
|
||||
m_pMemoryBuffer = std::move(buffer_or_error.get());
|
||||
}
|
||||
|
||||
MemoryArea::MemoryArea(const char* pMemBuffer, size_t pSize) {
|
||||
llvm::StringRef mem(pMemBuffer, pSize);
|
||||
m_pMemoryBuffer =
|
||||
llvm::MemoryBuffer::getMemBuffer(mem,
|
||||
/*BufferName*/ "NaN",
|
||||
/*RequiresNullTerminator*/ false);
|
||||
}
|
||||
|
||||
llvm::StringRef MemoryArea::request(size_t pOffset, size_t pLength) {
|
||||
return llvm::StringRef(m_pMemoryBuffer->getBufferStart() + pOffset, pLength);
|
||||
}
|
||||
|
||||
size_t MemoryArea::size() const {
|
||||
return m_pMemoryBuffer->getBufferSize();
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,75 @@
|
|||
//===- MemoryAreaFactory.cpp ----------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/MemoryAreaFactory.h"
|
||||
#include "mcld/Support/MsgHandling.h"
|
||||
#include "mcld/Support/SystemUtils.h"
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MemoryAreaFactory
|
||||
//===----------------------------------------------------------------------===//
|
||||
MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
|
||||
: GCFactory<MemoryArea, 0>(pNum) {
|
||||
}
|
||||
|
||||
MemoryAreaFactory::~MemoryAreaFactory() {
|
||||
}
|
||||
|
||||
MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath,
|
||||
FileHandle::OpenMode pMode) {
|
||||
llvm::StringRef name(pPath.native());
|
||||
if (m_AreaMap.find(name) == m_AreaMap.end()) {
|
||||
MemoryArea* result = allocate();
|
||||
new (result) MemoryArea(name);
|
||||
m_AreaMap[name] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
return m_AreaMap[name];
|
||||
}
|
||||
|
||||
MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath,
|
||||
FileHandle::OpenMode pMode,
|
||||
FileHandle::Permission pPerm) {
|
||||
llvm::StringRef name(pPath.native());
|
||||
if (m_AreaMap.find(name) == m_AreaMap.end()) {
|
||||
MemoryArea* result = allocate();
|
||||
new (result) MemoryArea(name);
|
||||
m_AreaMap[name] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
return m_AreaMap[name];
|
||||
}
|
||||
|
||||
MemoryArea* MemoryAreaFactory::produce(void* pMemBuffer, size_t pSize) {
|
||||
const char* base = reinterpret_cast<const char*>(pMemBuffer);
|
||||
llvm::StringRef name(base, pSize);
|
||||
if (m_AreaMap.find(name) == m_AreaMap.end()) {
|
||||
MemoryArea* result = allocate();
|
||||
new (result) MemoryArea(base, pSize);
|
||||
m_AreaMap[name] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
return m_AreaMap[name];
|
||||
}
|
||||
|
||||
MemoryArea* MemoryAreaFactory::produce(int pFD, FileHandle::OpenMode pMode) {
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MemoryAreaFactory::destruct(MemoryArea* pArea) {
|
||||
destroy(pArea);
|
||||
deallocate(pArea);
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,63 @@
|
|||
//===- MsgHandling.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/LD/DiagnosticEngine.h"
|
||||
#include "mcld/LD/DiagnosticLineInfo.h"
|
||||
#include "mcld/LD/DiagnosticPrinter.h"
|
||||
#include "mcld/LD/MsgHandler.h"
|
||||
#include "mcld/LD/TextDiagnosticPrinter.h"
|
||||
#include "mcld/Support/MsgHandling.h"
|
||||
#include "mcld/Support/raw_ostream.h"
|
||||
|
||||
#include <llvm/Support/ManagedStatic.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <llvm/Support/Signals.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// static variables
|
||||
//===----------------------------------------------------------------------===//
|
||||
static llvm::ManagedStatic<DiagnosticEngine> g_pEngine;
|
||||
|
||||
void InitializeDiagnosticEngine(const LinkerConfig& pConfig,
|
||||
DiagnosticPrinter* pPrinter) {
|
||||
g_pEngine->reset(pConfig);
|
||||
if (pPrinter != NULL)
|
||||
g_pEngine->setPrinter(*pPrinter, false);
|
||||
else {
|
||||
DiagnosticPrinter* printer =
|
||||
new TextDiagnosticPrinter(errs(), pConfig);
|
||||
g_pEngine->setPrinter(*printer, true);
|
||||
}
|
||||
}
|
||||
|
||||
DiagnosticEngine& getDiagnosticEngine() {
|
||||
return *g_pEngine;
|
||||
}
|
||||
|
||||
bool Diagnose() {
|
||||
if (g_pEngine->getPrinter()->getNumErrors() > 0) {
|
||||
// If we reached here, we are failing ungracefully. Run the interrupt
|
||||
// handlers
|
||||
// to make sure any special cleanups get done, in particular that we remove
|
||||
// files registered with RemoveFileOnSignal.
|
||||
llvm::sys::RunInterruptHandlers();
|
||||
g_pEngine->getPrinter()->finish();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FinalizeDiagnosticEngine() {
|
||||
g_pEngine->getPrinter()->finish();
|
||||
}
|
||||
|
||||
} // namespace mcld
|
207
android/frameworks/compile/mclinker/lib/Support/Path.cpp
Normal file
207
android/frameworks/compile/mclinker/lib/Support/Path.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
//===- Path.cpp -----------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/Path.h"
|
||||
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
|
||||
#include <istream>
|
||||
#include <locale>
|
||||
#include <ostream>
|
||||
#include <string.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Helper
|
||||
//===--------------------------------------------------------------------===//
|
||||
namespace {
|
||||
#if defined(MCLD_ON_WIN32)
|
||||
bool is_separator(char value) {
|
||||
return (value == separator || value == preferred_separator);
|
||||
}
|
||||
|
||||
const Path::StringType separator_str("/");
|
||||
|
||||
#else
|
||||
bool is_separator(char value) {
|
||||
return (value == separator);
|
||||
}
|
||||
|
||||
const Path::StringType separator_str("/");
|
||||
|
||||
#endif
|
||||
} // anonymous namespace
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Path
|
||||
//===--------------------------------------------------------------------===//
|
||||
Path::Path() : m_PathName() {
|
||||
}
|
||||
|
||||
Path::Path(const Path::ValueType* s) : m_PathName(s) {
|
||||
}
|
||||
|
||||
Path::Path(const Path::StringType& s) : m_PathName(s) {
|
||||
}
|
||||
|
||||
Path::Path(const Path& pCopy) : m_PathName(pCopy.m_PathName) {
|
||||
}
|
||||
|
||||
Path::~Path() {
|
||||
}
|
||||
|
||||
bool Path::isFromRoot() const {
|
||||
if (m_PathName.empty())
|
||||
return false;
|
||||
return (separator == m_PathName[0]);
|
||||
}
|
||||
|
||||
bool Path::isFromPWD() const {
|
||||
if (m_PathName.size() < 2)
|
||||
return false;
|
||||
return ('.' == m_PathName[0] && separator == m_PathName[1]);
|
||||
}
|
||||
|
||||
Path& Path::assign(const Path::StringType& s) {
|
||||
m_PathName.assign(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Path& Path::assign(const Path::ValueType* s, unsigned int length) {
|
||||
if (s == 0 || length == 0)
|
||||
assert(0 && "assign a null or empty string to Path");
|
||||
m_PathName.assign(s, length);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// a,/b a/,b a/,b/ a,b is a/b
|
||||
Path& Path::append(const Path& pPath) {
|
||||
// first path is a/,second path is /b
|
||||
if (m_PathName[m_PathName.length() - 1] == separator &&
|
||||
pPath.native()[0] == separator) {
|
||||
llvm::StringRef path(pPath.native());
|
||||
m_PathName.append(path.begin() + 1, path.end());
|
||||
} else if (this->native()[this->native().size() - 1] != separator &&
|
||||
pPath.native()[0] != separator) {
|
||||
// first path is a,second path is b
|
||||
m_PathName.append(separator_str);
|
||||
m_PathName.append(pPath.native());
|
||||
} else {
|
||||
// a/,b or a,/b just append
|
||||
m_PathName.append(pPath.native());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// a,/b a/,b a/,b/ a,b is a/b
|
||||
Path& Path::append(const StringType& pPath) {
|
||||
Path path(pPath);
|
||||
this->append(path);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Path::empty() const {
|
||||
return m_PathName.empty();
|
||||
}
|
||||
|
||||
Path::StringType Path::generic_string() const {
|
||||
StringType result = m_PathName;
|
||||
detail::canonicalize(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Path::canonicalize() {
|
||||
return detail::canonicalize(m_PathName);
|
||||
}
|
||||
|
||||
Path::StringType::size_type Path::m_append_separator_if_needed() {
|
||||
#if defined(MCLD_ON_WIN32)
|
||||
// On Windows platform, path can not append separator.
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
StringType::value_type last_char = m_PathName[m_PathName.size() - 1];
|
||||
if (!m_PathName.empty() && !is_separator(last_char)) {
|
||||
StringType::size_type tmp(m_PathName.size());
|
||||
m_PathName += separator_str;
|
||||
return tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos) {
|
||||
size_t begin = pSepPos;
|
||||
// skip '/' or '\\'
|
||||
while (separator == m_PathName[pSepPos]) {
|
||||
#if defined(MCLD_ON_WIN32)
|
||||
pSepPos += 2;
|
||||
#else
|
||||
++pSepPos;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (begin != pSepPos)
|
||||
m_PathName.erase(begin + 1, pSepPos - begin - 1);
|
||||
}
|
||||
|
||||
Path Path::parent_path() const {
|
||||
size_t end_pos = m_PathName.find_last_of(separator);
|
||||
if (end_pos != StringType::npos)
|
||||
return Path(m_PathName.substr(0, end_pos));
|
||||
return Path();
|
||||
}
|
||||
|
||||
Path Path::filename() const {
|
||||
size_t pos = m_PathName.find_last_of(separator);
|
||||
if (pos != StringType::npos) {
|
||||
++pos;
|
||||
return Path(m_PathName.substr(pos));
|
||||
}
|
||||
return Path(*this);
|
||||
}
|
||||
|
||||
Path Path::stem() const {
|
||||
size_t begin_pos = m_PathName.find_last_of(separator) + 1;
|
||||
size_t end_pos = m_PathName.find_last_of(dot);
|
||||
Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
|
||||
return result_path;
|
||||
}
|
||||
|
||||
Path Path::extension() const {
|
||||
size_t pos = m_PathName.find_last_of('.');
|
||||
if (pos == StringType::npos)
|
||||
return Path();
|
||||
return Path(m_PathName.substr(pos));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// non-member functions
|
||||
//===--------------------------------------------------------------------===//
|
||||
bool operator==(const Path& pLHS, const Path& pRHS) {
|
||||
return (pLHS.generic_string() == pRHS.generic_string());
|
||||
}
|
||||
|
||||
bool operator!=(const Path& pLHS, const Path& pRHS) {
|
||||
return !(pLHS == pRHS);
|
||||
}
|
||||
|
||||
Path operator+(const Path& pLHS, const Path& pRHS) {
|
||||
mcld::sys::fs::Path result = pLHS;
|
||||
result.append(pRHS);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
56
android/frameworks/compile/mclinker/lib/Support/RealPath.cpp
Normal file
56
android/frameworks/compile/mclinker/lib/Support/RealPath.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
//===- RealPath.cpp -------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/RealPath.h"
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
|
||||
//==========================
|
||||
// RealPath
|
||||
RealPath::RealPath() : Path() {
|
||||
}
|
||||
|
||||
RealPath::RealPath(const RealPath::ValueType* s) : Path(s) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
RealPath::RealPath(const RealPath::StringType& s) : Path(s) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
RealPath::RealPath(const Path& pPath) : Path(pPath) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
RealPath::~RealPath() {
|
||||
}
|
||||
|
||||
RealPath& RealPath::assign(const Path& pPath) {
|
||||
Path::m_PathName.assign(pPath.native());
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void RealPath::initialize() {
|
||||
if (isFromRoot()) {
|
||||
detail::canonicalize(m_PathName);
|
||||
} else if (isFromPWD()) {
|
||||
Path path_name;
|
||||
detail::get_pwd(path_name);
|
||||
path_name.native() += preferred_separator;
|
||||
path_name.native() += m_PathName;
|
||||
detail::canonicalize(path_name.native());
|
||||
m_PathName = path_name.native();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
|
@ -0,0 +1,19 @@
|
|||
//===- SystemUtils.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/SystemUtils.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-member functions
|
||||
#if defined(MCLD_ON_UNIX)
|
||||
#include "Unix/System.inc"
|
||||
#endif
|
||||
#if defined(MCLD_ON_WIN32)
|
||||
#include "Windows/System.inc"
|
||||
#endif
|
75
android/frameworks/compile/mclinker/lib/Support/Target.cpp
Normal file
75
android/frameworks/compile/mclinker/lib/Support/Target.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
//===- Target.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/Target.h"
|
||||
|
||||
#include <llvm/ADT/Triple.h>
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target
|
||||
//===----------------------------------------------------------------------===//
|
||||
Target::Target()
|
||||
: Name(NULL),
|
||||
TripleMatchQualityFn(NULL),
|
||||
TargetMachineCtorFn(NULL),
|
||||
MCLinkerCtorFn(NULL),
|
||||
TargetLDBackendCtorFn(NULL),
|
||||
DiagnosticLineInfoCtorFn(NULL) {
|
||||
}
|
||||
|
||||
unsigned int Target::getTripleQuality(const llvm::Triple& pTriple) const {
|
||||
if (TripleMatchQualityFn == NULL)
|
||||
return 0;
|
||||
return TripleMatchQualityFn(pTriple);
|
||||
}
|
||||
|
||||
MCLDTargetMachine* Target::createTargetMachine(const std::string& pTriple,
|
||||
const llvm::Target& pTarget,
|
||||
llvm::TargetMachine& pTM) const {
|
||||
if (TargetMachineCtorFn == NULL)
|
||||
return NULL;
|
||||
return TargetMachineCtorFn(pTarget, *this, pTM, pTriple);
|
||||
}
|
||||
|
||||
/// createMCLinker - create target-specific MCLinker
|
||||
MCLinker* Target::createMCLinker(const std::string& pTriple,
|
||||
LinkerConfig& pConfig,
|
||||
Module& pModule,
|
||||
FileHandle& pFileHandle) const {
|
||||
if (MCLinkerCtorFn == NULL)
|
||||
return NULL;
|
||||
return MCLinkerCtorFn(pTriple, pConfig, pModule, pFileHandle);
|
||||
}
|
||||
|
||||
/// emulate - given MCLinker default values for the other aspects of the
|
||||
/// target system.
|
||||
bool Target::emulate(LinkerScript& pScript, LinkerConfig& pConfig) const {
|
||||
if (EmulationFn == NULL)
|
||||
return false;
|
||||
return EmulationFn(pScript, pConfig);
|
||||
}
|
||||
|
||||
/// createLDBackend - create target-specific LDBackend
|
||||
TargetLDBackend* Target::createLDBackend(const LinkerConfig& pConfig) const {
|
||||
if (TargetLDBackendCtorFn == NULL)
|
||||
return NULL;
|
||||
return TargetLDBackendCtorFn(pConfig);
|
||||
}
|
||||
|
||||
/// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
|
||||
DiagnosticLineInfo* Target::createDiagnosticLineInfo(
|
||||
const mcld::Target& pTarget,
|
||||
const std::string& pTriple) const {
|
||||
if (DiagnosticLineInfoCtorFn == NULL)
|
||||
return NULL;
|
||||
return DiagnosticLineInfoCtorFn(pTarget, pTriple);
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,103 @@
|
|||
//===- TargetRegistry.cpp -------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/TargetRegistry.h"
|
||||
|
||||
namespace mcld {
|
||||
|
||||
TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TargetRegistry
|
||||
//===----------------------------------------------------------------------===//
|
||||
void TargetRegistry::RegisterTarget(Target& pTarget,
|
||||
const char* pName,
|
||||
Target::TripleMatchQualityFnTy pQualityFn) {
|
||||
pTarget.Name = pName;
|
||||
pTarget.TripleMatchQualityFn = pQualityFn;
|
||||
|
||||
s_TargetList.push_back(&pTarget);
|
||||
}
|
||||
|
||||
const Target* TargetRegistry::lookupTarget(const std::string& pTriple,
|
||||
std::string& pError) {
|
||||
if (empty()) {
|
||||
pError = "Unable to find target for this triple (no target are registered)";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llvm::Triple triple(pTriple);
|
||||
Target* best = NULL, * ambiguity = NULL;
|
||||
unsigned int highest = 0;
|
||||
|
||||
for (iterator target = begin(), ie = end(); target != ie; ++target) {
|
||||
unsigned int quality = (*target)->getTripleQuality(triple);
|
||||
if (quality > 0) {
|
||||
if (best == NULL || highest < quality) {
|
||||
highest = quality;
|
||||
best = *target;
|
||||
ambiguity = NULL;
|
||||
} else if (highest == quality) {
|
||||
ambiguity = *target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best == NULL) {
|
||||
pError = "No availaible targets are compatible with this triple.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL != ambiguity) {
|
||||
pError = std::string("Ambiguous targets: \"") + best->name() + "\" and \"" +
|
||||
ambiguity->name() + "\"";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
const Target* TargetRegistry::lookupTarget(const std::string& pArchName,
|
||||
llvm::Triple& pTriple,
|
||||
std::string& pError) {
|
||||
const Target* result = NULL;
|
||||
if (!pArchName.empty()) {
|
||||
for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
|
||||
ie = mcld::TargetRegistry::end();
|
||||
it != ie;
|
||||
++it) {
|
||||
if (pArchName == (*it)->name()) {
|
||||
result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
pError = std::string("invalid target '") + pArchName + "'.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Adjust the triple to match (if known), otherwise stick with the
|
||||
// module/host triple.
|
||||
llvm::Triple::ArchType type =
|
||||
llvm::Triple::getArchTypeForLLVMName(pArchName);
|
||||
if (llvm::Triple::UnknownArch != type)
|
||||
pTriple.setArch(type);
|
||||
} else {
|
||||
std::string error;
|
||||
result = lookupTarget(pTriple.getTriple(), error);
|
||||
if (result == NULL) {
|
||||
pError = std::string("unable to get target for `") + pTriple.getTriple() +
|
||||
"'\n" + "(Detail: " + error + ")\n";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,206 @@
|
|||
//===- FileSystem.inc -----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/FileHandle.h"
|
||||
#include "mcld/Support/Directory.h"
|
||||
|
||||
#include <llvm/Support/ErrorHandling.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
namespace detail {
|
||||
|
||||
std::string static_library_extension = ".a";
|
||||
std::string shared_library_extension = ".so";
|
||||
std::string executable_extension = "";
|
||||
std::string relocatable_extension = ".o";
|
||||
std::string assembly_extension = ".s";
|
||||
std::string bitcode_extension = ".bc";
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Helper Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// read_dir - return true if we read one entry
|
||||
// @return value -1: read error
|
||||
// 0: read the end
|
||||
// 1: success
|
||||
static int read_dir(intptr_t& pDir, std::string& pOutFilename) {
|
||||
errno = 0;
|
||||
dirent* cur_dir = ::readdir(reinterpret_cast<DIR*>(pDir));
|
||||
if (0 == cur_dir && 0 != errno)
|
||||
return -1;
|
||||
|
||||
// idx does not stay at the end, but all elements had beed put into cache.
|
||||
if (NULL == cur_dir) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
llvm::StringRef name(cur_dir->d_name, strlen(cur_dir->d_name));
|
||||
if ((name.size() == 1 && name[0] == '.') ||
|
||||
(name.size() == 2 && name[0] == '.' && name[1] == '.'))
|
||||
return read_dir(pDir, pOutFilename);
|
||||
|
||||
// find a new directory
|
||||
pOutFilename.append(name.data(), name.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
void open_dir(Directory& pDir) {
|
||||
pDir.m_Handler = reinterpret_cast<intptr_t>(opendir(pDir.path().c_str()));
|
||||
if (0 == pDir.m_Handler) {
|
||||
errno = 0; // opendir() will set errno if it failed to open directory.
|
||||
// set cache is full, then Directory::begin() can return end().
|
||||
pDir.m_CacheFull = true;
|
||||
return;
|
||||
}
|
||||
// read one entry for advance the end element of the cache.
|
||||
std::string path(pDir.path().native());
|
||||
switch (read_dir(pDir.m_Handler, path)) {
|
||||
case 1: {
|
||||
// find a new directory
|
||||
bool exist = false;
|
||||
mcld::sys::fs::PathCache::entry_type* entry =
|
||||
pDir.m_Cache.insert(path, exist);
|
||||
if (!exist)
|
||||
entry->setValue(sys::fs::Path(path));
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
// FIXME: a warning function
|
||||
pDir.m_CacheFull = true;
|
||||
return;
|
||||
default:
|
||||
case -1:
|
||||
llvm::report_fatal_error(std::string("Can't read directory: ") +
|
||||
pDir.path().native());
|
||||
}
|
||||
}
|
||||
|
||||
void close_dir(Directory& pDir) {
|
||||
if (pDir.m_Handler)
|
||||
closedir(reinterpret_cast<DIR*>(pDir.m_Handler));
|
||||
pDir.m_Handler = 0;
|
||||
}
|
||||
|
||||
int open(const Path& pPath, int pOFlag) {
|
||||
return ::open(pPath.native().c_str(), pOFlag);
|
||||
}
|
||||
|
||||
int open(const Path& pPath, int pOFlag, int pPerm) {
|
||||
mode_t perm = 0;
|
||||
if (pPerm & FileHandle::ReadOwner)
|
||||
perm |= S_IRUSR;
|
||||
if (pPerm & FileHandle::WriteOwner)
|
||||
perm |= S_IWUSR;
|
||||
if (pPerm & FileHandle::ExeOwner)
|
||||
perm |= S_IXUSR;
|
||||
if (pPerm & FileHandle::ReadGroup)
|
||||
perm |= S_IRGRP;
|
||||
if (pPerm & FileHandle::WriteGroup)
|
||||
perm |= S_IWGRP;
|
||||
if (pPerm & FileHandle::ExeGroup)
|
||||
perm |= S_IXGRP;
|
||||
if (pPerm & FileHandle::ReadOther)
|
||||
perm |= S_IROTH;
|
||||
if (pPerm & FileHandle::WriteOther)
|
||||
perm |= S_IWOTH;
|
||||
if (pPerm & FileHandle::ExeOther)
|
||||
perm |= S_IXOTH;
|
||||
|
||||
return ::open(pPath.native().c_str(), pOFlag, perm);
|
||||
}
|
||||
|
||||
ssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset) {
|
||||
return ::pread(pFD, pBuf, pCount, pOffset);
|
||||
}
|
||||
|
||||
ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset) {
|
||||
return ::pwrite(pFD, pBuf, pCount, pOffset);
|
||||
}
|
||||
|
||||
int ftruncate(int pFD, size_t pLength) {
|
||||
return ::ftruncate(pFD, pLength);
|
||||
}
|
||||
|
||||
void get_pwd(Path& pPWD) {
|
||||
char* pwd = (char*)malloc(PATH_MAX);
|
||||
pPWD.assign(getcwd(pwd, PATH_MAX));
|
||||
free(pwd);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FileHandler
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) {
|
||||
if (!isOpened()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == pLength)
|
||||
return true;
|
||||
|
||||
int prot, flag;
|
||||
if (isReadable() && !isWritable()) {
|
||||
// read-only
|
||||
prot = PROT_READ;
|
||||
flag = MAP_FILE | MAP_PRIVATE;
|
||||
} else if (!isReadable() && isWritable()) {
|
||||
// write-only
|
||||
prot = PROT_WRITE;
|
||||
flag = MAP_FILE | MAP_SHARED;
|
||||
} else if (isReadWrite()) {
|
||||
// read and write
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
flag = MAP_FILE | MAP_SHARED;
|
||||
} else {
|
||||
// can not read/write
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
|
||||
|
||||
if (MAP_FAILED == pMemBuffer) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileHandle::munmap(void* pMemBuffer, size_t pLength) {
|
||||
if (!isOpened()) {
|
||||
setState(BadBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (-1 == ::munmap(pMemBuffer, pLength)) {
|
||||
setState(FailBit);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mcld
|
216
android/frameworks/compile/mclinker/lib/Support/Unix/PathV3.inc
Normal file
216
android/frameworks/compile/mclinker/lib/Support/Unix/PathV3.inc
Normal file
|
@ -0,0 +1,216 @@
|
|||
//===- PathV3.inc ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/FileSystem.h"
|
||||
#include "mcld/Support/Path.h"
|
||||
|
||||
#include <llvm/Support/ErrorHandling.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <stack>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// mcld::sys::fs::detail
|
||||
//===----------------------------------------------------------------------===//
|
||||
namespace detail {
|
||||
|
||||
// return the last charactor being handled.
|
||||
size_t canonicalize(std::string& pathname) {
|
||||
// Variable Index //
|
||||
// SepTable - stack of result separators
|
||||
// LR(1) Algorithm //
|
||||
// traverse pPathName
|
||||
// if we meet '//', '///', '////', ...
|
||||
// -> ignore it
|
||||
// -> push current into stack
|
||||
// -> jump to the next not '/'
|
||||
// if we meet '/./'
|
||||
// -> ignore
|
||||
// -> jump to the next not '/'
|
||||
// if we meet '/../'
|
||||
// -> pop previous position of '/' P
|
||||
// -> erase P+1 to now
|
||||
// if we meet other else
|
||||
// -> go go go
|
||||
// if we meet '/.../', '/..../', ... -> illegal
|
||||
if (pathname.empty())
|
||||
return 0;
|
||||
|
||||
size_t handler = 0;
|
||||
std::stack<size_t> slash_stack;
|
||||
slash_stack.push(-1);
|
||||
while (handler < pathname.size()) {
|
||||
if (separator == pathname[handler]) { // handler = 1st '/'
|
||||
size_t next = handler + 1;
|
||||
if (next >= pathname.size())
|
||||
return handler;
|
||||
switch (pathname[next]) { // next = handler + 1;
|
||||
case separator: { // '//'
|
||||
while (next < pathname.size() && separator == pathname[next])
|
||||
++next;
|
||||
// next is the last not '/'
|
||||
pathname.erase(handler, next - handler - 1);
|
||||
// handler is the first '/'
|
||||
slash_stack.push(handler);
|
||||
break;
|
||||
}
|
||||
case '.': { // '/.'
|
||||
++next; // next = handler + 2
|
||||
if (next >= pathname.size()) // '/.'
|
||||
return handler;
|
||||
switch (pathname[next]) {
|
||||
case separator: { // '/./'
|
||||
pathname.erase(handler, 2);
|
||||
break;
|
||||
}
|
||||
case '.': { // '/..'
|
||||
++next; // next = handler + 3;
|
||||
if (next >= pathname.size()) // '/..?'
|
||||
return handler;
|
||||
switch (pathname[next]) {
|
||||
case separator: { // '/../'
|
||||
handler = slash_stack.top();
|
||||
slash_stack.pop();
|
||||
pathname.erase(handler + 1, next - handler);
|
||||
if (static_cast<size_t>(-1) == handler) {
|
||||
slash_stack.push(-1);
|
||||
handler = pathname.find_first_of(separator, handler);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '.': { // '/...', illegal
|
||||
return handler;
|
||||
break;
|
||||
}
|
||||
default: { // '/..a'
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // '/.a'
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // '/a
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler = pathname.find_first_of(separator, handler);
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
bool not_found_error(int perrno) {
|
||||
return perrno == ENOENT || perrno == ENOTDIR;
|
||||
}
|
||||
|
||||
void status(const Path& p, FileStatus& pFileStatus) {
|
||||
struct stat path_stat;
|
||||
if (stat(p.c_str(), &path_stat) != 0) {
|
||||
if (not_found_error(errno)) {
|
||||
pFileStatus.setType(FileNotFound);
|
||||
} else
|
||||
pFileStatus.setType(StatusError);
|
||||
} else if (S_ISDIR(path_stat.st_mode))
|
||||
pFileStatus.setType(DirectoryFile);
|
||||
else if (S_ISREG(path_stat.st_mode))
|
||||
pFileStatus.setType(RegularFile);
|
||||
else if (S_ISBLK(path_stat.st_mode))
|
||||
pFileStatus.setType(BlockFile);
|
||||
else if (S_ISCHR(path_stat.st_mode))
|
||||
pFileStatus.setType(CharacterFile);
|
||||
else if (S_ISFIFO(path_stat.st_mode))
|
||||
pFileStatus.setType(FifoFile);
|
||||
else if (S_ISSOCK(path_stat.st_mode))
|
||||
pFileStatus.setType(SocketFile);
|
||||
else
|
||||
pFileStatus.setType(TypeUnknown);
|
||||
}
|
||||
|
||||
void symlink_status(const Path& p, FileStatus& pFileStatus) {
|
||||
struct stat path_stat;
|
||||
if (lstat(p.c_str(), &path_stat) != 0) {
|
||||
if (errno == ENOENT || errno == ENOTDIR) // these are not errors
|
||||
{
|
||||
pFileStatus.setType(FileNotFound);
|
||||
} else
|
||||
pFileStatus.setType(StatusError);
|
||||
}
|
||||
if (S_ISREG(path_stat.st_mode))
|
||||
pFileStatus.setType(RegularFile);
|
||||
if (S_ISDIR(path_stat.st_mode))
|
||||
pFileStatus.setType(DirectoryFile);
|
||||
if (S_ISLNK(path_stat.st_mode))
|
||||
pFileStatus.setType(SymlinkFile);
|
||||
if (S_ISBLK(path_stat.st_mode))
|
||||
pFileStatus.setType(BlockFile);
|
||||
if (S_ISCHR(path_stat.st_mode))
|
||||
pFileStatus.setType(CharacterFile);
|
||||
if (S_ISFIFO(path_stat.st_mode))
|
||||
pFileStatus.setType(FifoFile);
|
||||
if (S_ISSOCK(path_stat.st_mode))
|
||||
pFileStatus.setType(SocketFile);
|
||||
else
|
||||
pFileStatus.setType(TypeUnknown);
|
||||
}
|
||||
|
||||
/// directory_iterator_increment - increment function implementation
|
||||
//
|
||||
// iterator will call this function in two situations:
|
||||
// 1. All elements have been put into cache, and iterator stays at the end
|
||||
// of cache. (a real end)
|
||||
// 2. Some but not all elements had been put into cache, and we stoped.
|
||||
// An iterator now is staying at the end of cache. (a temporal end)
|
||||
mcld::sys::fs::PathCache::entry_type* bring_one_into_cache(DirIterator& pIter) {
|
||||
mcld::sys::fs::PathCache::entry_type* entry = 0;
|
||||
std::string path(pIter.m_pParent->m_Path.native());
|
||||
switch (read_dir(pIter.m_pParent->m_Handler, path)) {
|
||||
case 1: {
|
||||
// read one
|
||||
bool exist = false;
|
||||
entry = pIter.m_pParent->m_Cache.insert(path, exist);
|
||||
if (!exist)
|
||||
entry->setValue(sys::fs::Path(path));
|
||||
break;
|
||||
}
|
||||
case 0: // meet real end
|
||||
pIter.m_pParent->m_CacheFull = true;
|
||||
break;
|
||||
default:
|
||||
case -1:
|
||||
llvm::report_fatal_error(std::string("Can't read directory: ") +
|
||||
pIter.m_pParent->path().native());
|
||||
break;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
|
@ -0,0 +1,80 @@
|
|||
//===- System.inc ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
|
||||
char* strerror(int errnum) {
|
||||
return std::strerror(errnum);
|
||||
}
|
||||
|
||||
static std::string getOSVersion() {
|
||||
struct utsname info;
|
||||
|
||||
if (uname(&info))
|
||||
return "";
|
||||
|
||||
return info.release;
|
||||
}
|
||||
|
||||
std::string getDefaultTargetTriple() {
|
||||
llvm::StringRef TargetTripleString(MCLD_DEFAULT_TARGET_TRIPLE);
|
||||
std::pair<llvm::StringRef, llvm::StringRef> ArchSplit =
|
||||
TargetTripleString.split('-');
|
||||
|
||||
// Normalize the arch, since the target triple may not actually match the
|
||||
// target.
|
||||
std::string Arch = ArchSplit.first;
|
||||
|
||||
std::string Triple(Arch);
|
||||
Triple += '-';
|
||||
Triple += ArchSplit.second;
|
||||
|
||||
// Force i<N>86 to i386.
|
||||
if (Triple[0] == 'i' && isdigit(Triple[1]) && Triple[2] == '8' &&
|
||||
Triple[3] == '6')
|
||||
Triple[1] = '3';
|
||||
|
||||
// On darwin, we want to update the version to match that of the
|
||||
// target.
|
||||
std::string::size_type DarwinDashIdx = Triple.find("-darwin");
|
||||
if (DarwinDashIdx != std::string::npos) {
|
||||
Triple.resize(DarwinDashIdx + strlen("-darwin"));
|
||||
Triple += getOSVersion();
|
||||
}
|
||||
|
||||
return Triple;
|
||||
}
|
||||
|
||||
int GetPageSize() {
|
||||
return getpagesize();
|
||||
}
|
||||
|
||||
/// random - generate a random number.
|
||||
long GetRandomNum() {
|
||||
return ::random();
|
||||
}
|
||||
|
||||
/// srandom - set the initial seed value for future calls to random().
|
||||
void SetRandomSeed(unsigned pSeed) {
|
||||
::srandom(pSeed);
|
||||
}
|
||||
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
|
@ -0,0 +1,162 @@
|
|||
//===- FileSystem.inc -----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/FileHandle.h"
|
||||
#include "mcld/Support/Directory.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
namespace detail {
|
||||
|
||||
// FIXME: the extension depends on target machine, not host machine.
|
||||
Path::StringType static_library_extension = ".a";
|
||||
Path::StringType shared_library_extension = ".so";
|
||||
Path::StringType executable_extension = ".exe";
|
||||
Path::StringType relocatable_extension = ".o";
|
||||
Path::StringType assembly_extension = ".s";
|
||||
Path::StringType bitcode_extension = ".bc";
|
||||
|
||||
void open_dir(Directory& pDir) {
|
||||
fs::Path file_filter(pDir.path());
|
||||
file_filter.append("*");
|
||||
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
HANDLE hFile = FindFirstFile(file_filter.c_str(), &FindFileData);
|
||||
pDir.m_Handler = reinterpret_cast<intptr_t>(hFile);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hFile) {
|
||||
// set cache is full, then Directory::begin() can return end().
|
||||
pDir.m_CacheFull = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// find a new directory and file
|
||||
bool exist = false;
|
||||
std::string path(FindFileData.cFileName);
|
||||
fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
|
||||
if (!exist)
|
||||
entry->setValue(path);
|
||||
}
|
||||
|
||||
void close_dir(Directory& pDir) {
|
||||
if (pDir.m_Handler)
|
||||
FindClose(reinterpret_cast<HANDLE>(pDir.m_Handler));
|
||||
pDir.m_Handler = 0;
|
||||
}
|
||||
|
||||
int open(const Path& pPath, int pOFlag) {
|
||||
return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY);
|
||||
}
|
||||
|
||||
int open(const Path& pPath, int pOFlag, int pPerm) {
|
||||
int perm = 0;
|
||||
if (pPerm & FileHandle::ReadOwner || pPerm & FileHandle::ReadGroup ||
|
||||
pPerm & FileHandle::ReadOther)
|
||||
perm |= _S_IREAD;
|
||||
|
||||
if (pPerm & FileHandle::WriteOwner || pPerm & FileHandle::WriteGroup ||
|
||||
pPerm & FileHandle::WriteOther)
|
||||
perm |= _S_IWRITE;
|
||||
|
||||
return ::_open(pPath.native().c_str(), pOFlag | _O_BINARY, perm);
|
||||
}
|
||||
|
||||
ssize_t pread(int pFD, void* pBuf, size_t pCount, off_t pOffset) {
|
||||
ssize_t ret;
|
||||
off_t old_pos;
|
||||
if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
|
||||
return -1;
|
||||
|
||||
if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
|
||||
return -1;
|
||||
|
||||
if (-1 == (ret = ::read(pFD, pBuf, pCount))) {
|
||||
int err = errno;
|
||||
::lseek(pFD, old_pos, SEEK_SET);
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, off_t pOffset) {
|
||||
ssize_t ret;
|
||||
off_t old_pos;
|
||||
if (-1 == (old_pos = ::lseek(pFD, 0, SEEK_CUR)))
|
||||
return -1;
|
||||
|
||||
if (-1 == ::lseek(pFD, pOffset, SEEK_SET))
|
||||
return -1;
|
||||
|
||||
if (-1 == (ret = ::write(pFD, pBuf, pCount))) {
|
||||
int err = errno;
|
||||
::lseek(pFD, old_pos, SEEK_SET);
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == ::lseek(pFD, old_pos, SEEK_SET))
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ftruncate(int pFD, size_t pLength) {
|
||||
return ::_chsize(pFD, pLength);
|
||||
}
|
||||
|
||||
void get_pwd(Path& pPWD) {
|
||||
char* pwd = (char*)malloc(PATH_MAX);
|
||||
pPWD.assign(_getcwd(pwd, PATH_MAX));
|
||||
free(pwd);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FileHandle
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength) {
|
||||
// FIXME: This implementation reduces mmap to read. Use Windows APIs.
|
||||
pMemBuffer = (void*)::malloc(pLength);
|
||||
return read(pMemBuffer, pStartOffset, pLength);
|
||||
}
|
||||
|
||||
bool FileHandle::munmap(void* pMemBuffer, size_t pLength) {
|
||||
// FIXME: This implementation reduces mmap to read. Use Windows APIs.
|
||||
free(pMemBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mcld
|
|
@ -0,0 +1,188 @@
|
|||
//===- PathV3.inc ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Support/Path.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
namespace fs {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// mcld::sys::fs::detail
|
||||
//===----------------------------------------------------------------------===//
|
||||
namespace detail {
|
||||
|
||||
// return the last charactor being handled.
|
||||
size_t canonicalize(std::string& pathname) {
|
||||
// Variable Index //
|
||||
// SepTable - stack of result separators
|
||||
// LR(1) Algorithm //
|
||||
// traverse pPathName
|
||||
// if we meet '//', '///', '////', ...
|
||||
// -> ignore it
|
||||
// -> push current into stack
|
||||
// -> jump to the next not '/'
|
||||
// if we meet '/./'
|
||||
// -> ignore
|
||||
// -> jump to the next not '/'
|
||||
// if we meet '/../'
|
||||
// -> pop previous position of '/' P
|
||||
// -> erase P+1 to now
|
||||
// if we meet other else
|
||||
// -> go go go
|
||||
// if we meet '/.../', '/..../', ... -> illegal
|
||||
if (pathname.empty())
|
||||
return 0;
|
||||
|
||||
size_t handler = 0;
|
||||
std::stack<size_t> slash_stack;
|
||||
slash_stack.push(-1);
|
||||
while (handler < pathname.size()) {
|
||||
if (separator == pathname[handler]) { // handler = 1st '/'
|
||||
size_t next = handler + 1;
|
||||
if (next >= pathname.size())
|
||||
return handler;
|
||||
switch (pathname[next]) { // next = handler + 1;
|
||||
case separator: { // '//'
|
||||
while (next < pathname.size() && separator == pathname[next])
|
||||
++next;
|
||||
// next is the last not '/'
|
||||
pathname.erase(handler, next - handler - 1);
|
||||
// handler is the first '/'
|
||||
slash_stack.push(handler);
|
||||
break;
|
||||
}
|
||||
case '.': { // '/.'
|
||||
++next; // next = handler + 2
|
||||
if (next >= pathname.size()) // '/.'
|
||||
return handler;
|
||||
switch (pathname[next]) {
|
||||
case separator: { // '/./'
|
||||
pathname.erase(handler, 2);
|
||||
break;
|
||||
}
|
||||
case '.': { // '/..'
|
||||
++next; // next = handler + 3;
|
||||
if (next >= pathname.size()) // '/..?'
|
||||
return handler;
|
||||
switch (pathname[next]) {
|
||||
case separator: { // '/../'
|
||||
handler = slash_stack.top();
|
||||
slash_stack.pop();
|
||||
pathname.erase(handler + 1, next - handler);
|
||||
if (static_cast<size_t>(-1) == handler) {
|
||||
slash_stack.push(-1);
|
||||
handler = pathname.find_first_of(separator, handler);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '.': { // '/...', illegal
|
||||
return handler;
|
||||
break;
|
||||
}
|
||||
default: { // '/..a'
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // '/.a'
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { // '/a
|
||||
slash_stack.push(handler);
|
||||
handler = pathname.find_first_of(separator, handler + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler = pathname.find_first_of(separator, handler);
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
bool not_found_error(int perrno) {
|
||||
return perrno == ENOENT || perrno == ENOTDIR;
|
||||
}
|
||||
|
||||
void status(const Path& p, FileStatus& pFileStatus) {
|
||||
struct ::_stat path_stat;
|
||||
if (::_stat(p.c_str(), &path_stat) != 0) {
|
||||
if (not_found_error(errno)) {
|
||||
pFileStatus.setType(FileNotFound);
|
||||
} else
|
||||
pFileStatus.setType(StatusError);
|
||||
} else if (S_ISDIR(path_stat.st_mode))
|
||||
pFileStatus.setType(DirectoryFile);
|
||||
else if (S_ISREG(path_stat.st_mode))
|
||||
pFileStatus.setType(RegularFile);
|
||||
else if (S_ISBLK(path_stat.st_mode))
|
||||
pFileStatus.setType(BlockFile);
|
||||
else if (S_ISCHR(path_stat.st_mode))
|
||||
pFileStatus.setType(CharacterFile);
|
||||
else if (S_ISFIFO(path_stat.st_mode))
|
||||
pFileStatus.setType(FifoFile);
|
||||
else
|
||||
pFileStatus.setType(TypeUnknown);
|
||||
}
|
||||
|
||||
void symlink_status(const Path& p, FileStatus& pFileStatus) {
|
||||
pFileStatus.setType(FileNotFound);
|
||||
}
|
||||
|
||||
/// directory_iterator_increment - increment function implementation
|
||||
//
|
||||
// iterator will call this function in two situations:
|
||||
// 1. All elements have been put into cache, and iterator stays at the end
|
||||
// of cache. (a real end)
|
||||
// 2. Some but not all elements had beed put into cache, and we stoped.
|
||||
// An iterator now is staying at the end of cache. (a temporal end)
|
||||
mcld::sys::fs::PathCache::entry_type* bring_one_into_cache(DirIterator& pIter) {
|
||||
mcld::sys::fs::PathCache::entry_type* entry = 0;
|
||||
fs::Path file_filter(pIter.m_pParent->m_Path);
|
||||
file_filter.append("*");
|
||||
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
if (FindNextFile(reinterpret_cast<HANDLE>(pIter.m_pParent->m_Handler),
|
||||
&FindFileData)) {
|
||||
// read one
|
||||
bool exist = false;
|
||||
std::string path(pIter.m_pParent->m_Path.native());
|
||||
path += separator;
|
||||
path += std::string(FindFileData.cFileName);
|
||||
entry = pIter.m_pParent->m_Cache.insert(path, exist);
|
||||
if (!exist)
|
||||
entry->setValue(path);
|
||||
} else if (ERROR_NO_MORE_FILES == GetLastError()) {
|
||||
// meet real end
|
||||
pIter.m_pParent->m_CacheFull = true;
|
||||
} else {
|
||||
llvm::report_fatal_error(std::string("Can't read directory: ") +
|
||||
pIter.m_pParent->path().native());
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace fs
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
|
@ -0,0 +1,50 @@
|
|||
//===- System.inc ---------------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include <string>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
|
||||
namespace mcld {
|
||||
namespace sys {
|
||||
|
||||
char* strerror(int errnum) {
|
||||
return std::strerror(errnum);
|
||||
}
|
||||
|
||||
std::string getDefaultTargetTriple() {
|
||||
return MCLD_DEFAULT_TARGET_TRIPLE;
|
||||
}
|
||||
|
||||
int GetPageSize() {
|
||||
static int _pagesize = 0;
|
||||
if (!_pagesize) {
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
_pagesize = sysinfo.dwPageSize;
|
||||
}
|
||||
return _pagesize;
|
||||
}
|
||||
|
||||
/// random - generate a random number.
|
||||
long GetRandomNum() {
|
||||
return ::rand();
|
||||
}
|
||||
|
||||
/// srandom - set the initial seed value for future calls to random().
|
||||
void SetRandomSeed(unsigned pSeed) {
|
||||
::srand(pSeed);
|
||||
}
|
||||
|
||||
} // namespace sys
|
||||
} // namespace mcld
|
104
android/frameworks/compile/mclinker/lib/Support/raw_ostream.cpp
Normal file
104
android/frameworks/compile/mclinker/lib/Support/raw_ostream.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
//===- raw_ostream.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// The MCLinker Project
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mcld/Config/Config.h"
|
||||
#include "mcld/Support/raw_ostream.h"
|
||||
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace mcld {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// raw_ostream
|
||||
//===----------------------------------------------------------------------===//
|
||||
raw_fd_ostream::raw_fd_ostream(const char* pFilename,
|
||||
std::error_code& pErrorCode,
|
||||
llvm::sys::fs::OpenFlags pFlags)
|
||||
: llvm::raw_fd_ostream(pFilename, pErrorCode, pFlags),
|
||||
m_bConfigColor(false),
|
||||
m_bSetColor(false) {
|
||||
}
|
||||
|
||||
raw_fd_ostream::raw_fd_ostream(int pFD,
|
||||
bool pShouldClose,
|
||||
bool pUnbuffered)
|
||||
: llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered),
|
||||
m_bConfigColor(false),
|
||||
m_bSetColor(false) {
|
||||
}
|
||||
|
||||
raw_fd_ostream::~raw_fd_ostream() {
|
||||
}
|
||||
|
||||
void raw_fd_ostream::setColor(bool pEnable) {
|
||||
m_bConfigColor = true;
|
||||
m_bSetColor = pEnable;
|
||||
}
|
||||
|
||||
llvm::raw_ostream& raw_fd_ostream::changeColor(
|
||||
enum llvm::raw_ostream::Colors pColor,
|
||||
bool pBold,
|
||||
bool pBackground) {
|
||||
if (!is_displayed())
|
||||
return *this;
|
||||
return llvm::raw_fd_ostream::changeColor(pColor, pBold, pBackground);
|
||||
}
|
||||
|
||||
llvm::raw_ostream& raw_fd_ostream::resetColor() {
|
||||
if (!is_displayed())
|
||||
return *this;
|
||||
return llvm::raw_fd_ostream::resetColor();
|
||||
}
|
||||
|
||||
llvm::raw_ostream& raw_fd_ostream::reverseColor() {
|
||||
if (!is_displayed())
|
||||
return *this;
|
||||
return llvm::raw_ostream::reverseColor();
|
||||
}
|
||||
|
||||
bool raw_fd_ostream::is_displayed() const {
|
||||
if (m_bConfigColor)
|
||||
return m_bSetColor;
|
||||
|
||||
return llvm::raw_fd_ostream::is_displayed();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// outs(), errs(), nulls()
|
||||
//===----------------------------------------------------------------------===//
|
||||
raw_fd_ostream& outs() {
|
||||
// Set buffer settings to model stdout behavior.
|
||||
static raw_fd_ostream S(STDOUT_FILENO, false);
|
||||
return S;
|
||||
}
|
||||
|
||||
raw_fd_ostream& errs() {
|
||||
// Set standard error to be unbuffered by default.
|
||||
static raw_fd_ostream S(STDERR_FILENO, false, true);
|
||||
return S;
|
||||
}
|
||||
|
||||
} // namespace mcld
|
Loading…
Add table
Add a link
Reference in a new issue