aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLogan Chien <tzuhsiang.chien@gmail.com>2015-03-01 18:04:17 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2015-03-24 11:55:34 -0700
commitb6c0bb74a4f77b0aace74cf1dc88d4c3755661a4 (patch)
treedd4f7d0ecd7c3f1139e1772431ade25c7d572112
parentd9bd9d79d5d73efe6c102f8e34104ed44c67e47d (diff)
downloadllvm-b6c0bb74a4f77b0aace74cf1dc88d4c3755661a4.tar.gz
[ndk][pndk] Add PNDK 64-bit support.
This is ported from release_35 branch with following commits: * [ndk][pndk] Unknown arch support for 64bit. Also add PIE support. WenHan Gu <Wenhan.gu@mediatek.com> * [ndk][pndk] Fix ndk-link after rebasing to LLVM upstream 6/25. Logan Chien <tzuhsiang.chien@gmail.com> * [ndk][pndk] Implement ndk-translate on unknown 64-bit abi. WenHan Gu <Wenhan.gu@mediatek.com>
-rw-r--r--tools/Makefile2
-rw-r--r--tools/llc/llc.cpp10
-rwxr-xr-xtools/ndk-bc2native/ndk-bc2native.py4
-rw-r--r--tools/ndk-link/AndroidBitcodeLinker.cpp18
-rw-r--r--tools/ndk-link/AndroidBitcodeLinker.h10
-rw-r--r--tools/ndk-link/Archive.cpp58
-rw-r--r--tools/ndk-link/ArchiveReader.cpp72
-rw-r--r--tools/ndk-link/ArchiveWriter.cpp45
-rw-r--r--tools/ndk-link/ndk-link.cpp33
-rw-r--r--tools/ndk-strip/ndk-strip.cpp7
-rw-r--r--tools/ndk-translate/ARMExpandVAArg.cpp6
-rw-r--r--tools/ndk-translate/Arm64ExpandVAArg.cpp90
-rw-r--r--tools/ndk-translate/CMakeLists.txt5
-rw-r--r--tools/ndk-translate/ExpandVAArgPass.cpp100
-rw-r--r--tools/ndk-translate/ExpandVAArgPass.h31
-rw-r--r--tools/ndk-translate/Makefile2
-rw-r--r--tools/ndk-translate/Mips64ExpandVAArg.cpp91
-rw-r--r--tools/ndk-translate/MipsExpandVAArg.cpp6
-rw-r--r--tools/ndk-translate/ReplaceUnwindHeaderSizePass.cpp6
-rw-r--r--tools/ndk-translate/ReplaceUnwindHeaderSizePass.h4
-rw-r--r--tools/ndk-translate/X86ExpandVAArg.cpp4
-rw-r--r--tools/ndk-translate/X86_64ExpandVAArg.cpp211
-rw-r--r--tools/ndk-translate/ndk-translate.cpp60
23 files changed, 675 insertions, 200 deletions
diff --git a/tools/Makefile b/tools/Makefile
index c7f56d7a630..92a2f0bf026 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -42,7 +42,7 @@ ifeq ($(USE_INTEL_JITEVENTS), 1)
endif
ifeq ($(LLVM_CROSS_COMPILING),1)
- PARALLEL_DIRS := llc le32-none-ndk-translate
+ PARALLEL_DIRS := llc ndk-translate
endif
# Let users override the set of tools to build from the command line.
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 35f965b2a30..072e989553f 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -206,6 +206,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
SMDiagnostic Err;
std::unique_ptr<Module> M;
Triple TheTriple;
+ Triple OrigTriple;
bool SkipModule = MCPU == "help" ||
(!MAttrs.empty() && MAttrs.front() == "help");
@@ -224,6 +225,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
return 1;
}
+ OrigTriple.setTriple(M->getTargetTriple());
+
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
M->setTargetTriple(Triple::normalize(TargetTriple));
@@ -287,6 +290,13 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (GenerateSoftFloatCalls)
FloatABIForCalls = FloatABI::Soft;
+ if (OrigTriple.getOS() == llvm::Triple::NDK) {
+ if (OrigTriple.getArch() == llvm::Triple::le32 ||
+ OrigTriple.getArch() == llvm::Triple::le64) {
+ Options.MCOptions.MCNoExecStack = true;
+ }
+ }
+
// Figure out where we are going to send the output.
std::unique_ptr<tool_output_file> Out =
GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
diff --git a/tools/ndk-bc2native/ndk-bc2native.py b/tools/ndk-bc2native/ndk-bc2native.py
index caeb80001ad..8d6f886ca68 100755
--- a/tools/ndk-bc2native/ndk-bc2native.py
+++ b/tools/ndk-bc2native/ndk-bc2native.py
@@ -235,9 +235,9 @@ def locate_tools():
arch = get_arch_for_abi(ABI)
gcc_bin = gcc_toolchain_for_arch(arch) + '/bin/'
- (found_translate, TRANSLATE_CMD) = find_program('le32-none-ndk-translate', [pwd, llvm_bin])
+ (found_translate, TRANSLATE_CMD) = find_program('ndk-translate', [pwd, llvm_bin])
if found_translate != True:
- error('Cannot find le32-none-ndk-translate')
+ error('Cannot find ndk-translate')
(found_llc, LLC_CMD) = find_program('llc', [pwd, llvm_bin])
if found_llc != True:
diff --git a/tools/ndk-link/AndroidBitcodeLinker.cpp b/tools/ndk-link/AndroidBitcodeLinker.cpp
index 028d50ef927..f241c080a42 100644
--- a/tools/ndk-link/AndroidBitcodeLinker.cpp
+++ b/tools/ndk-link/AndroidBitcodeLinker.cpp
@@ -58,6 +58,7 @@ std::string* AndroidBitcodeLinker::GenerateBitcode() {
PMBuilder.Inliner = createFunctionInliningPass();
PMBuilder.populateLTOPassManager(PM);
}
+
// Doing clean up passes
if (!Config.isDisableOpt())
{
@@ -97,20 +98,21 @@ AndroidBitcodeLinker::LoadAndroidBitcode(AndroidBitcodeItem &Item) {
if (!BufferOrErr) {
Error = "Error reading file '" + FN.str() + "'" + ": " +
BufferOrErr.getError().message();
- return NULL;
+ return nullptr;
}
- std::unique_ptr<MemoryBuffer> &Buffer = BufferOrErr.get();
- BitcodeWrapper *wrapper = new BitcodeWrapper(Buffer->getBufferStart(),
- Buffer->getBufferSize());
+ std::unique_ptr<MemoryBuffer> buffer = std::move(BufferOrErr.get());
+ BitcodeWrapper *wrapper = new BitcodeWrapper(buffer->getBufferStart(),
+ buffer->getBufferSize());
Item.setWrapper(wrapper);
assert(Item.getWrapper() != 0);
- ErrorOr<Module*> Result = parseBitcodeFile(Buffer->getMemBufferRef(),
- Config.getContext());
+ ErrorOr<Module *> Result = parseBitcodeFile(buffer->getMemBufferRef(),
+ Config.getContext());
if (!Result) {
Error = "Bitcode file '" + FN.str() + "' could not be loaded."
+ Result.getError().message();
errs() << Error << '\n';
+ return nullptr;
}
return Result.get();
@@ -210,7 +212,8 @@ AndroidBitcodeLinker::LinkInAndroidBitcode(AndroidBitcodeItem &Item) {
Triple triple(M.get()->getTargetTriple());
- if (triple.getArch() != Triple::le32 || triple.getOS() != Triple::NDK) {
+ if ((triple.getArch() != Triple::le32 && triple.getArch() != Triple::le64) ||
+ triple.getOS() != Triple::NDK) {
Item.setNative(true);
return error("Cannot link '" + File.str() + "', triple:" + M.get()->getTargetTriple());
}
@@ -432,7 +435,6 @@ const StringRef &Filename = Item.getFile();
verbose(" Linking in module: " + aModule->getModuleIdentifier());
// Link it in
- std::string moduleErrorMsg;
if (linker->linkInModule(aModule))
return error("Cannot link in module '" +
aModule->getModuleIdentifier() + "'");
diff --git a/tools/ndk-link/AndroidBitcodeLinker.h b/tools/ndk-link/AndroidBitcodeLinker.h
index 16d6b75f4ad..42bd8203b60 100644
--- a/tools/ndk-link/AndroidBitcodeLinker.h
+++ b/tools/ndk-link/AndroidBitcodeLinker.h
@@ -17,6 +17,11 @@
#ifndef ANDROID_BITCODE_LINKER_H
#define ANDROID_BITCODE_LINKER_H
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <set>
+#include <vector>
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -24,11 +29,6 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Wrap/BitcodeWrapper.h"
-#include <cstdio>
-#include <cstring>
-#include <set>
-#include <string>
-#include <vector>
namespace llvm {
diff --git a/tools/ndk-link/Archive.cpp b/tools/ndk-link/Archive.cpp
index 02cd0aa37ba..27ba536f175 100644
--- a/tools/ndk-link/Archive.cpp
+++ b/tools/ndk-link/Archive.cpp
@@ -19,9 +19,11 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Process.h"
+
#include <cstring>
#include <memory>
#include <system_error>
+
using namespace llvm;
// getMemberSize - compute the actual physical size of the file member as seen
@@ -101,11 +103,10 @@ bool ArchiveMember::replaceWith(StringRef newFile, std::string* ErrMsg) {
else
flags &= ~HasLongFilenameFlag;
- // Get the file status info
+ // Get the status info
sys::fs::file_status Status;
- if (sys::fs::status(path, Status)) {
+ if (sys::fs::status(path, Status))
return true;
- }
User = Status.getUser();
Group = Status.getGroup();
@@ -115,9 +116,8 @@ bool ArchiveMember::replaceWith(StringRef newFile, std::string* ErrMsg) {
// Determine what kind of file it is.
sys::fs::file_magic magic = sys::fs::file_magic::unknown;
- if (sys::fs::identify_magic(path, magic)) {
+ if (sys::fs::identify_magic(path, magic))
return true;
- }
if (magic == sys::fs::file_magic::bitcode)
flags |= BitcodeFlag;
else
@@ -135,14 +135,14 @@ Archive::Archive(StringRef filename, LLVMContext &C)
bool
Archive::mapToMemory(std::string* ErrMsg) {
- ErrorOr<std::unique_ptr<MemoryBuffer> > FileOrErr =
+ ErrorOr<std::unique_ptr<MemoryBuffer> > File =
MemoryBuffer::getFile(archPath.str());
- if (!FileOrErr) {
+ if (!File) {
if (ErrMsg)
- *ErrMsg = FileOrErr.getError().message();
+ *ErrMsg = File.getError().message();
return true;
}
- mapfile = FileOrErr.get().release();
+ mapfile = File.get().release();
base = mapfile->getBufferStart();
return false;
}
@@ -196,34 +196,30 @@ static void getSymbols(Module*M, std::vector<std::string>& symbols) {
}
// Get just the externally visible defined symbols from the bitcode
-bool llvm::GetBitcodeSymbols(StringRef FileName,
+bool llvm::GetBitcodeSymbols(StringRef fName,
LLVMContext& Context,
std::vector<std::string>& symbols,
std::string* ErrMsg) {
ErrorOr<std::unique_ptr<MemoryBuffer> > BufferOrErr =
- MemoryBuffer::getFileOrSTDIN(FileName);
+ MemoryBuffer::getFileOrSTDIN(fName);
if (!BufferOrErr) {
- if (ErrMsg) {
- *ErrMsg = "Could not open file '" + FileName.str() + "'" + ": " +
- BufferOrErr.getError().message();
- }
+ if (ErrMsg) *ErrMsg = "Could not open file '" + fName.str() + "': " +
+ BufferOrErr.getError().message();
return true;
}
- ErrorOr<Module*> M =
+ ErrorOr<Module *> Result =
parseBitcodeFile(BufferOrErr.get()->getMemBufferRef(), Context);
- if (!M) {
- if (ErrMsg) {
- *ErrMsg = M.getError().message();
- }
+ if (!Result) {
+ if (ErrMsg) *ErrMsg = Result.getError().message();
return true;
}
// Get the symbols
- getSymbols(M.get(), symbols);
+ getSymbols(Result.get(), symbols);
// Done with the module.
- delete M.get();
+ delete Result.get();
return true;
}
@@ -234,20 +230,18 @@ llvm::GetBitcodeSymbols(const char *BufPtr, unsigned Length,
std::vector<std::string>& symbols,
std::string* ErrMsg) {
// Get the module.
- MemoryBufferRef Buffer(StringRef(BufPtr, Length), ModuleID.c_str());
-
- llvm::ErrorOr<Module*> M = parseBitcodeFile(Buffer, Context);
- if (!M) {
- if (ErrMsg) {
- *ErrMsg = M.getError().message();
- }
- return 0;
+ MemoryBufferRef Buffer(StringRef(BufPtr, Length), ModuleID);
+
+ ErrorOr<Module *> Result = parseBitcodeFile(Buffer, Context);
+ if (!Result) {
+ if (ErrMsg) *ErrMsg = Result.getError().message();
+ return nullptr;
}
// Get the symbols
- getSymbols(M.get(), symbols);
+ getSymbols(Result.get(), symbols);
// Done with the module. Note that it's the caller's responsibility to delete
// the Module.
- return M.get();
+ return Result.get();
}
diff --git a/tools/ndk-link/ArchiveReader.cpp b/tools/ndk-link/ArchiveReader.cpp
index 877155bbed8..4f6fa73b26d 100644
--- a/tools/ndk-link/ArchiveReader.cpp
+++ b/tools/ndk-link/ArchiveReader.cpp
@@ -18,27 +18,11 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
#include <cstdio>
#include <cstdlib>
-#include <memory>
using namespace llvm;
-#if 0
-/// Read a variable-bit-rate encoded unsigned integer
-static inline unsigned readInteger(const char*&At, const char*End) {
- unsigned Shift = 0;
- unsigned Result = 0;
-
- do {
- if (At == End)
- return Result;
- Result |= (unsigned)((*At++) & 0x7F) << Shift;
- Shift += 7;
- } while (At[-1] & 0x80);
- return Result;
-}
-#endif
-
// This member parses an ArchiveMemberHeader that is presumed to be pointed to
// by At. The At pointer is updated to the byte just after the header, which
// can be variable in size.
@@ -268,23 +252,23 @@ Archive::OpenAndLoad(StringRef File, LLVMContext& C,
}
// Get all the bitcode modules from the archive
-bool Archive::getAllModules(std::vector<Module*>& Modules,
- std::string* ErrMessage) {
- for (iterator I = begin(), E = end(); I != E; ++I) {
+bool
+Archive::getAllModules(std::vector<Module*>& Modules,
+ std::string* ErrMessage) {
+
+ for (iterator I=begin(), E=end(); I != E; ++I) {
if (I->isBitcode()) {
std::string FullMemberName =
archPath.str() + "(" + I->getPath().str() + ")";
+
MemoryBufferRef Buffer(StringRef(I->getData(), I->getSize()),
FullMemberName);
- ErrorOr<Module*> M = parseBitcodeFile(Buffer, Context);
- if (!M) {
- if (ErrMessage) {
- *ErrMessage = M.getError().message();
- }
+
+ ErrorOr<Module *> Result = parseBitcodeFile(Buffer, Context);
+ if (!Result)
return true;
- }
- Modules.push_back(M.get());
+ Modules.push_back(Result.get());
}
}
return false;
@@ -352,7 +336,7 @@ Archive::loadSymbolTable(std::string* ErrorMsg) {
Archive* Archive::OpenAndLoadSymbols(StringRef File,
LLVMContext& C,
std::string* ErrorMessage) {
- std::unique_ptr<Archive> result ( new Archive(File, C) );
+ std::unique_ptr<Archive> result(new Archive(File, C));
if (result->mapToMemory(ErrorMessage))
return NULL;
if (!result->loadSymbolTable(ErrorMessage))
@@ -394,22 +378,20 @@ Archive::findModuleDefiningSymbol(const std::string& symbol,
// Now, load the bitcode module to get the Module.
std::string FullMemberName =
archPath.str() + "(" + mbr->getPath().str() + ")";
-
std::unique_ptr<MemoryBuffer> Buffer =
- MemoryBuffer::getMemBufferCopy(StringRef(mbr->getData(), mbr->getSize()),
- FullMemberName.c_str());
-
- ErrorOr<Module*> m = getLazyBitcodeModule(std::move(Buffer), Context);
- if (!m) {
- if (ErrMsg) {
- *ErrMsg = m.getError().message();
- }
- return 0;
+ MemoryBuffer::getMemBufferCopy(StringRef(mbr->getData(),
+ mbr->getSize()),
+ FullMemberName.c_str());
+ ErrorOr<Module *> Result =
+ getLazyBitcodeModule(std::move(Buffer), Context);
+ if (!Result) {
+ if (ErrMsg) *ErrMsg = Result.getError().message();
+ return nullptr;
}
- modules.insert(std::make_pair(fileOffset, std::make_pair(m.get(), mbr)));
+ modules.insert(std::make_pair(fileOffset, std::make_pair(Result.get(), mbr)));
- return m.get();
+ return Result.get();
}
// Look up multiple symbols in the symbol table and return a set of
@@ -530,13 +512,15 @@ bool Archive::isBitcodeArchive() {
continue;
std::string FullMemberName =
- archPath.str() + "(" + I->getPath().str() + ")";
+ archPath.str() + "(" + I->getPath().str() + ")";
+
MemoryBufferRef Buffer(StringRef(I->getData(), I->getSize()),
FullMemberName);
- ErrorOr<Module*> M = parseBitcodeFile(Buffer, Context);
- if (!M)
+
+ ErrorOr<Module *> Result = parseBitcodeFile(Buffer, Context);
+ if (!Result)
return false; // Couldn't parse bitcode, not a bitcode archive.
- delete M.get();
+ delete Result.get();
return true;
}
diff --git a/tools/ndk-link/ArchiveWriter.cpp b/tools/ndk-link/ArchiveWriter.cpp
index 12196efdb4e..22a31dbe312 100644
--- a/tools/ndk-link/ArchiveWriter.cpp
+++ b/tools/ndk-link/ArchiveWriter.cpp
@@ -19,54 +19,13 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
+
#include <fstream>
#include <iomanip>
-#include <memory>
#include <ostream>
#include <system_error>
-using namespace llvm;
-
-#if 0
-// Write an integer using variable bit rate encoding. This saves a few bytes
-// per entry in the symbol table.
-static inline void writeInteger(unsigned num, std::ofstream& ARFile) {
- while (1) {
- if (num < 0x80) { // done?
- ARFile << (unsigned char)num;
- return;
- }
-
- // Nope, we are bigger than a character, output the next 7 bits and set the
- // high bit to say that there is more coming...
- ARFile << (unsigned char)(0x80 | ((unsigned char)num & 0x7F));
- num >>= 7; // Shift out 7 bits now...
- }
-}
-
-// Compute how many bytes are taken by a given VBR encoded value. This is needed
-// to pre-compute the size of the symbol table.
-static inline unsigned numVbrBytes(unsigned num) {
-
- // Note that the following nested ifs are somewhat equivalent to a binary
- // search. We split it in half by comparing against 2^14 first. This allows
- // most reasonable values to be done in 2 comparisons instead of 1 for
- // small ones and four for large ones. We expect this to access file offsets
- // in the 2^10 to 2^24 range and symbol lengths in the 2^0 to 2^8 range,
- // so this approach is reasonable.
- if (num < 1<<14) {
- if (num < 1<<7)
- return 1;
- else
- return 2;
- }
- if (num < 1<<21)
- return 3;
- if (num < 1<<28)
- return 4;
- return 5; // anything >= 2^28 takes 5 bytes
-}
-#endif
+using namespace llvm;
// Create an empty archive.
Archive* Archive::CreateEmpty(StringRef FilePath, LLVMContext& C) {
diff --git a/tools/ndk-link/ndk-link.cpp b/tools/ndk-link/ndk-link.cpp
index 7ebf7f513a8..eb09a88011d 100644
--- a/tools/ndk-link/ndk-link.cpp
+++ b/tools/ndk-link/ndk-link.cpp
@@ -33,6 +33,8 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Wrap/BitcodeWrapper.h"
+#include <memory>
+
using namespace llvm;
static cl::list<std::string>
@@ -100,6 +102,9 @@ NoUndefined("no-undefined", cl::desc("-z defs"));
static cl::list<std::string>
ZOptions("z", cl::desc("-z keyword"), cl::value_desc("keyword"));
+static cl::opt<bool>
+PIE("pie", cl::desc("position independent executable"));
+
static cl::list<std::string> CO1("Wl", cl::Prefix,
cl::desc("Compatibility option: ignored"));
@@ -208,7 +213,7 @@ sys::fs::file_magic Magic;
}
static bool isDynamicLibrary(StringRef FilePath) {
-sys::fs::file_magic Magic;
+ sys::fs::file_magic Magic;
if (sys::fs::identify_magic(FilePath, Magic))
return false;
@@ -221,8 +226,10 @@ static bool isBitcodeArchive(StringRef FilePath) {
return false;
std::string ErrMsg;
- std::auto_ptr<Archive> AutoArch(
- Archive::OpenAndLoad(FilePath, llvm::getGlobalContext(), &ErrMsg));
+ std::unique_ptr<Archive> AutoArch(
+ Archive::OpenAndLoad(FilePath,
+ llvm::getGlobalContext(),
+ &ErrMsg));
Archive* arch = AutoArch.get();
if (!arch) {
@@ -232,8 +239,7 @@ static bool isBitcodeArchive(StringRef FilePath) {
return arch->isBitcodeArchive();
}
-static StringRef IsLibrary(StringRef Name,
- StringRef Directory) {
+static StringRef IsLibrary(StringRef Name, StringRef Directory) {
SmallString<256> FullPath = Directory;
sys::path::append(FullPath, "lib"+Name);
@@ -290,7 +296,7 @@ static std::string getSOName(const std::string& Filename,
}
static std::string* ProcessArgv(int argc, char **argv,
- AndroidBitcodeLinker::ABCItemList& Items) {
+ AndroidBitcodeLinker::ABCItemList& Items) {
std::string *ArgvString = new std::string;
raw_string_ostream Output(*ArgvString);
@@ -385,13 +391,15 @@ static std::string* ProcessArgv(int argc, char **argv,
return ArgvString;
}
-static void WrapAndroidBitcode(std::vector<std::string*> &BCStrings, std::string& LDFlags, raw_ostream &Output) {
+static void WrapAndroidBitcode(std::vector<std::string*> &BCStrings,
+ std::string& LDFlags, raw_ostream &Output) {
std::vector<BCHeaderField> header_fields;
std::vector<uint8_t *> field_data;
size_t variable_header_size = 0;
// shared object or executable
- uint32_t BitcodeType = (Shared) ? BCHeaderField::BC_SharedObject : BCHeaderField::BC_Executable;
+ uint32_t BitcodeType = (Shared) ? BCHeaderField::BC_SharedObject
+ : BCHeaderField::BC_Executable;
field_data.push_back(new uint8_t[sizeof(uint32_t)]);
WriteInt32(field_data.back(), 0, BitcodeType);
BCHeaderField BitcodeTypeField(BCHeaderField::kAndroidBitcodeType,
@@ -447,8 +455,8 @@ static void WrapAndroidBitcode(std::vector<std::string*> &BCStrings, std::string
}
}
-void GenerateBitcode(std::vector<std::string*> &BCStrings, std::string& LDFlags, const std::string& FileName) {
-
+void GenerateBitcode(std::vector<std::string*> &BCStrings,
+ std::string& LDFlags, const std::string& FileName) {
if (Verbose)
errs() << "Generating Bitcode To " << FileName << '\n';
@@ -464,9 +472,8 @@ void GenerateBitcode(std::vector<std::string*> &BCStrings, std::string& LDFlags,
Out.keep();
}
-static void BuildLinkItems(
- AndroidBitcodeLinker::ABCItemList& Items,
- const cl::list<std::string>& Files) {
+static void BuildLinkItems(AndroidBitcodeLinker::ABCItemList& Items,
+ const cl::list<std::string>& Files) {
cl::list<bool>::const_iterator wholeIt = WholeArchive.begin();
cl::list<bool>::const_iterator noWholeIt = NoWholeArchive.begin();
int wholePos = -1, noWholePos = -1;
diff --git a/tools/ndk-strip/ndk-strip.cpp b/tools/ndk-strip/ndk-strip.cpp
index 19c679e5885..a6941764124 100644
--- a/tools/ndk-strip/ndk-strip.cpp
+++ b/tools/ndk-strip/ndk-strip.cpp
@@ -16,7 +16,6 @@
#include <fcntl.h>
#include <unistd.h>
-
#include <cstdlib>
#include <memory>
#include <utility>
@@ -130,9 +129,11 @@ static void StripBitcode(const char *Bitcode, size_t BitcodeSize, std::string &B
StringRef input_data(Bitcode, BitcodeSize);
MemoryBufferRef buffer(input_data, "");
- ErrorOr<Module*> Result = parseBitcodeFile(buffer, Context);
+ ErrorOr<Module *> Result = parseBitcodeFile(buffer, Context);
+
if (!Result) {
errs() << Result.getError().message() << '\n';
+ return;
}
std::unique_ptr<Module> M(Result.get());
@@ -192,7 +193,7 @@ int main(int argc, char **argv) {
// Output stripped bitcode
std::error_code EC;
- tool_output_file Out(OutputFilename, EC, sys::fs::F_None);
+ tool_output_file Out(OutputFilename.c_str(), EC, sys::fs::F_None);
if (EC) {
errs() << EC.message() << '\n';
return 1;
diff --git a/tools/ndk-translate/ARMExpandVAArg.cpp b/tools/ndk-translate/ARMExpandVAArg.cpp
index 4f1ad843d2c..c1086c410c0 100644
--- a/tools/ndk-translate/ARMExpandVAArg.cpp
+++ b/tools/ndk-translate/ARMExpandVAArg.cpp
@@ -41,7 +41,7 @@ private:
llvm::IRBuilder<> builder(pInst);
const llvm::DataLayoutPass *dlp =
getAnalysisIfAvailable<llvm::DataLayoutPass>();
- const llvm::DataLayout &dl = dlp->getDataLayout();
+ const llvm::DataLayout *dl = &dlp->getDataLayout();
llvm::Type *bp = llvm::Type::getInt8PtrTy(*mContext);
llvm::Type *bpp = bp->getPointerTo(0);
@@ -50,7 +50,7 @@ private:
builder.CreateBitCast(va_list_addr, bpp, "ap");
llvm::Value *addr = builder.CreateLoad(va_list_addr_bpp, "ap.cur");
// Handle address alignment for type alignment > 32 bits.
- uint64_t ty_align = dl.getABITypeAlignment(ty);
+ uint64_t ty_align = dl->getABITypeAlignment(ty);
if (ty_align > 4) {
assert((ty_align & (ty_align - 1)) == 0 &&
@@ -65,7 +65,7 @@ private:
}
llvm::Value *addr_typed = builder.CreateBitCast(addr, pty);
- uint64_t offset = llvm::RoundUpToAlignment(dl.getTypeSizeInBits(ty)/8, 4);
+ uint64_t offset = llvm::RoundUpToAlignment(dl->getTypeSizeInBits(ty)/8, 4);
llvm::Value *next_addr = builder.CreateGEP(addr,
llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), offset),
"ap.next");
diff --git a/tools/ndk-translate/Arm64ExpandVAArg.cpp b/tools/ndk-translate/Arm64ExpandVAArg.cpp
new file mode 100644
index 00000000000..722b4875bb8
--- /dev/null
+++ b/tools/ndk-translate/Arm64ExpandVAArg.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ExpandVAArgPass.h"
+
+#include <sstream>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+class Arm64ExpandVAArg : public ExpandVAArgPass {
+public:
+ virtual const char *getPassName() const {
+ return "Arm64 LLVM va_arg Instruction Expansion Pass";
+ }
+
+private:
+ // Derivative work from clang/lib/CodeGen/TargetInfo.cpp.
+ virtual llvm::Value *expandVAArg(llvm::Instruction *pInst);
+};
+
+llvm::Value *Arm64ExpandVAArg::expandVAArg(llvm::Instruction *pInst) {
+ // TODO: Support argument number > 8
+ // TODO: Support other types
+ // struct {
+ // void *__stack;
+ // void *__gr_top;
+ // void *__vr_top;
+ // int __gr_offs;
+ // int __vr_offs;
+ // };
+ llvm::Type *va_arg_type = pInst->getType();
+ llvm::Value *va_list_addr = pInst->getOperand(0);
+ llvm::IRBuilder<> builder(pInst);
+ unsigned reg_top_field = 1;
+ unsigned reg_offset_field = 3;
+ unsigned reg_used_size = 8 * 1; // 8 byte, we use 1 register
+ if (va_arg_type->isHalfTy() || va_arg_type->isFloatTy() ||
+ va_arg_type->isDoubleTy() || va_arg_type->isVectorTy()) {
+ reg_top_field = 2;
+ reg_offset_field = 4;
+ reg_used_size = 16 * 1;
+ }
+
+ llvm::Value *reg_offs_p =
+ builder.CreateStructGEP(va_list_addr, reg_offset_field, "gr_offs_p");
+ llvm::Value *reg_offs = builder.CreateLoad(reg_offs_p, "gr_offs");
+
+ // Update the gr/vr_offs pointer for next call to va_arg on this va_list.
+ llvm::Value *new_offset =
+ builder.CreateAdd(reg_offs,
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext),
+ reg_used_size),
+ "new_reg_offs");
+ builder.CreateStore(new_offset, reg_offs_p);
+
+ // Load the integer value
+ llvm::Value *reg_top_p = builder.CreateStructGEP(va_list_addr,
+ reg_top_field, "reg_top_p");
+ llvm::Value *reg_top = builder.CreateLoad(reg_top_p, "reg_top");
+ llvm::Value *base_addr = builder.CreateGEP(reg_top, reg_offs);
+ llvm::Value *valueTy_addr =
+ builder.CreateBitCast(base_addr, llvm::PointerType::getUnqual(va_arg_type));
+ llvm::Value *result = builder.CreateLoad(valueTy_addr);
+ return result;
+}
+
+ExpandVAArgPass* createArm64ExpandVAArgPass() {
+ return new Arm64ExpandVAArg();
+}
diff --git a/tools/ndk-translate/CMakeLists.txt b/tools/ndk-translate/CMakeLists.txt
index b870e64c18b..0c0e7dd69b7 100644
--- a/tools/ndk-translate/CMakeLists.txt
+++ b/tools/ndk-translate/CMakeLists.txt
@@ -10,14 +10,17 @@ set(LLVM_LINK_COMPONENTS
selectiondag
)
-add_llvm_tool(le32-none-ndk-translate
+add_llvm_tool(ndk-translate
ARMExpandVAArg.cpp
ARMReplaceUnwindHeaderSize.cpp
+ Arm64ExpandVAArg.cpp
ExpandVAArgPass.cpp
+ Mips64ExpandVAArg.cpp
MipsExpandVAArg.cpp
MipsReplaceUnwindHeaderSize.cpp
ReplaceUnwindHeaderSizePass.cpp
X86ExpandVAArg.cpp
X86ReplaceUnwindHeaderSize.cpp
+ X86_64ExpandVAArg.cpp
ndk-translate.cpp
)
diff --git a/tools/ndk-translate/ExpandVAArgPass.cpp b/tools/ndk-translate/ExpandVAArgPass.cpp
index 48697e4b9fc..c7515314d68 100644
--- a/tools/ndk-translate/ExpandVAArgPass.cpp
+++ b/tools/ndk-translate/ExpandVAArgPass.cpp
@@ -17,28 +17,104 @@
#include "ExpandVAArgPass.h"
#include <llvm/ADT/STLExtras.h>
-#include <llvm/IR/InstIterator.h>
+#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <iterator>
char ExpandVAArgPass::ID = 0;
-bool ExpandVAArgPass::runOnFunction(llvm::Function &pFunc) {
+bool ExpandVAArgPass::runOnModule(llvm::Module &pM) {
bool changed = false;
- mContext = &pFunc.getContext();
+ mContext = &pM.getContext();
+ llvm::SmallVector<llvm::Instruction*, 8> Insts;
// process va_arg inst
- for (llvm::inst_iterator inst = llvm::inst_begin(pFunc),
- inst_end = llvm::inst_end(pFunc), next_inst = std::next(inst);
- inst != inst_end; inst = next_inst++) {
- if (inst->getOpcode() == llvm::Instruction::VAArg) {
- llvm::Value *v = expandVAArg(&*inst);
- inst->replaceAllUsesWith(v);
- inst->eraseFromParent();
- changed = true;
- continue;
+ for (llvm::Module::iterator i = pM.begin(), e = pM.end(); i != e; ++i) {
+ for (llvm::Function::iterator fi = i->begin(), fe = i->end(); fi != fe; ++fi) {
+ for (llvm::BasicBlock::iterator bi = fi->begin(), be = fi->end();
+ bi != be; ++bi) {
+ llvm::Instruction *inst = &*bi;
+ if (inst->getOpcode() == llvm::Instruction::VAArg) {
+ llvm::VAArgInst* va_inst = llvm::cast<llvm::VAArgInst>(&*inst);
+ Insts.push_back(va_inst);
+ }
+ }
}
}
+
+ for (llvm::SmallVector<llvm::Instruction*, 8>::iterator i = Insts.begin(),
+ e = Insts.end(); i != e; ++i) {
+ llvm::Value *v = expandVAArg(*i);
+ (*i)->replaceAllUsesWith(v);
+ (*i)->eraseFromParent();
+ changed = true;
+ }
+
return changed;
}
+llvm::Value *NDK64ExpandVAArg::expandVAArg(llvm::Instruction *pInst) {
+ mVAArgInst = pInst;
+ mVAArgTy = pInst->getType();
+ llvm::Value *va_list_addr_ptr = pInst->getOperand(0);
+ llvm::IRBuilder<> builder(pInst);
+ mVAList = builder.CreateConstGEP1_32(va_list_addr_ptr, 0, "va_list");
+
+ llvm::Function *vaarg_func = getOrCreateFunc();
+ assert (vaarg_func->arg_begin()->getType()->isPointerTy() &&
+ "Parameter should be pointer type to va_list struct");
+ return builder.CreateCall(vaarg_func,
+ builder.CreateBitCast(mVAList,
+ vaarg_func->arg_begin()->getType()));
+}
+
+llvm::Function *NDK64ExpandVAArg::getOrCreateFunc() {
+ llvm::Function *func =
+ llvm::Function::Create(llvm::FunctionType::get(mVAArgTy, mVAList->getType(),
+ /*VarArg*/false),
+ llvm::GlobalValue::InternalLinkage,
+ getVAArgFuncName(),
+ mVAArgInst->getParent()->getParent()->getParent());
+
+ std::pair<VAArgFuncMapTy::iterator, bool> ret =
+ mVAArgFuncs.insert(std::make_pair(mVAArgTy, func));
+ if (!ret.second) {
+ assert (!ret.first->second->isDeclaration() && "Function should be defined");
+ func->eraseFromParent();
+ return ret.first->second;
+ }
+
+ fillupVAArgFunc(*func);
+ return func;
+}
+
+std::string NDK64ExpandVAArg::getVAArgFuncName() const {
+ std::string func_name = "va_arg";
+ if (mVAArgTy->isHalfTy())
+ func_name += ".f16";
+ else if (mVAArgTy->isFloatTy())
+ func_name += ".f32";
+ else if (mVAArgTy->isDoubleTy())
+ func_name += ".f64";
+ else if (mVAArgTy->isFP128Ty())
+ func_name += ".f128";
+ else if (mVAArgTy->isIntegerTy(8))
+ func_name += ".i8";
+ else if (mVAArgTy->isIntegerTy(16))
+ func_name += ".i16";
+ else if (mVAArgTy->isIntegerTy(32))
+ func_name += ".i32";
+ else if (mVAArgTy->isIntegerTy(64))
+ func_name += ".i64";
+ else if (mVAArgTy->isPointerTy())
+ func_name += ".p";
+ else {
+ mVAArgTy->dump();
+ assert (false && "va_arg for un-support type.");
+ }
+ return func_name;
+}
diff --git a/tools/ndk-translate/ExpandVAArgPass.h b/tools/ndk-translate/ExpandVAArgPass.h
index 869d26a0b61..c10acaee388 100644
--- a/tools/ndk-translate/ExpandVAArgPass.h
+++ b/tools/ndk-translate/ExpandVAArgPass.h
@@ -17,6 +17,7 @@
#ifndef EXPAND_VAARG_PASS_H
#define EXPAND_VAARG_PASS_H
+#include <map>
#include <llvm/Pass.h>
namespace llvm {
@@ -24,6 +25,7 @@ namespace llvm {
class Instruction;
class LLVMContext;
class Value;
+ class Type;
} // end llvm namespace
/*
@@ -35,7 +37,7 @@ namespace llvm {
* ExpandVAArg::expandVAArg to expand va_arg.
*/
-class ExpandVAArgPass : public llvm::FunctionPass {
+class ExpandVAArgPass : public llvm::ModulePass {
private:
static char ID;
@@ -46,9 +48,28 @@ private:
virtual llvm::Value *expandVAArg(llvm::Instruction *pInst) = 0;
public:
- ExpandVAArgPass() : llvm::FunctionPass(ID), mContext(NULL) { }
+ ExpandVAArgPass() : llvm::ModulePass(ID), mContext(NULL) { }
- virtual bool runOnFunction(llvm::Function &pFunc);
+ virtual bool runOnModule(llvm::Module &pM);
+};
+
+
+class NDK64ExpandVAArg : public ExpandVAArgPass {
+private:
+ // Derivative work from clang/lib/CodeGen/TargetInfo.cpp.
+ virtual llvm::Value *expandVAArg(llvm::Instruction *pInst);
+ virtual void fillupVAArgFunc(llvm::Function &) = 0;
+
+protected:
+ llvm::Instruction *mVAArgInst;
+ llvm::Type *mVAArgTy;
+ llvm::Value *mVAList;
+ typedef std::map<llvm::Type*, llvm::Function*> VAArgFuncMapTy;
+ VAArgFuncMapTy mVAArgFuncs;
+
+private:
+ llvm::Function *getOrCreateFunc();
+ std::string getVAArgFuncName() const;
};
@@ -56,4 +77,8 @@ ExpandVAArgPass* createARMExpandVAArgPass();
ExpandVAArgPass* createX86ExpandVAArgPass();
ExpandVAArgPass* createMipsExpandVAArgPass();
+ExpandVAArgPass* createArm64ExpandVAArgPass();
+ExpandVAArgPass* createX86_64ExpandVAArgPass();
+ExpandVAArgPass* createMips64ExpandVAArgPass();
+
#endif // EXPAND_VAARG_PASS_H
diff --git a/tools/ndk-translate/Makefile b/tools/ndk-translate/Makefile
index b8fb9f4e636..24fd163e0cd 100644
--- a/tools/ndk-translate/Makefile
+++ b/tools/ndk-translate/Makefile
@@ -1,6 +1,6 @@
LEVEL := ../..
-TOOLNAME = le32-none-ndk-translate
+TOOLNAME = ndk-translate
LINK_COMPONENTS := bitreader bitwriter
diff --git a/tools/ndk-translate/Mips64ExpandVAArg.cpp b/tools/ndk-translate/Mips64ExpandVAArg.cpp
new file mode 100644
index 00000000000..2a57d38d3e1
--- /dev/null
+++ b/tools/ndk-translate/Mips64ExpandVAArg.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ExpandVAArgPass.h"
+
+#include <sstream>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+class Mips64ExpandVAArg : public NDK64ExpandVAArg {
+public:
+ virtual const char *getPassName() const {
+ return "Mips64 LLVM va_arg Instruction Expansion Pass";
+ }
+
+private:
+ virtual void fillupVAArgFunc(llvm::Function &);
+
+private:
+ // Lookup the map to take an existing function, or it will
+ // create a new one and insert into the map.
+ llvm::Type *getNativeVAListType();
+ llvm::Value *emitVAArgFromMemory(llvm::IRBuilder<> &);
+};
+
+// ------------ Implementation -------------- //
+
+void Mips64ExpandVAArg::fillupVAArgFunc(llvm::Function &func) {
+ llvm::BasicBlock *entry_bb =
+ llvm::BasicBlock::Create(*mContext, "entry", &func);
+ llvm::Value *va_list_addr = func.getArgumentList().begin();
+ llvm::IRBuilder<> builder(entry_bb);
+
+ // First of all, replace it to native va_list type
+ va_list_addr = builder.CreateBitCast(va_list_addr,
+ llvm::PointerType::getUnqual(getNativeVAListType()));
+
+ llvm::Value *va_list_addr_as_bpp =
+ builder.CreateBitCast(va_list_addr,
+ llvm::PointerType::getUnqual(llvm::Type::getInt8PtrTy(*mContext)),
+ "ap");
+ llvm::Value *addr = builder.CreateLoad(va_list_addr_as_bpp, "ap.cur");
+
+ // TODO: Alignment?
+ llvm::Value *addr_typed =
+ builder.CreateBitCast(addr, llvm::PointerType::getUnqual(mVAArgTy));
+ llvm::Value *aligned_addr =
+ builder.CreateBitCast(addr_typed, llvm::Type::getInt8PtrTy(*mContext));
+
+ uint64_t offset = mVAArgTy->getPrimitiveSizeInBits() / 8;
+ assert (offset > 0 && "Cannot get size of va_arg");
+ llvm::Value *next_addr =
+ builder.CreateGEP(aligned_addr,
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(*mContext),
+ offset),
+ "ap.next");
+ builder.CreateStore(next_addr, va_list_addr_as_bpp);
+
+ builder.CreateRet(builder.CreateLoad(addr_typed));
+}
+
+
+llvm::Type *Mips64ExpandVAArg::getNativeVAListType() {
+ return llvm::Type::getInt8Ty(*mContext);
+}
+
+
+ExpandVAArgPass* createMips64ExpandVAArgPass() {
+ return new Mips64ExpandVAArg();
+}
diff --git a/tools/ndk-translate/MipsExpandVAArg.cpp b/tools/ndk-translate/MipsExpandVAArg.cpp
index 2dfa83c2a17..a1c5017c430 100644
--- a/tools/ndk-translate/MipsExpandVAArg.cpp
+++ b/tools/ndk-translate/MipsExpandVAArg.cpp
@@ -41,14 +41,14 @@ private:
llvm::IRBuilder<> builder(pInst);
const llvm::DataLayoutPass *dlp =
getAnalysisIfAvailable<llvm::DataLayoutPass>();
- const llvm::DataLayout &dl = dlp->getDataLayout();
+ const llvm::DataLayout *dl = &dlp->getDataLayout();
llvm::Type *bp = llvm::Type::getInt8PtrTy(*mContext);
llvm::Type *bpp = bp->getPointerTo(0);
llvm::Value *va_list_addr_bpp = builder.CreateBitCast(va_list_addr,
bpp, "ap");
llvm::Value *addr = builder.CreateLoad(va_list_addr_bpp, "ap.cur");
- int64_t type_align = dl.getABITypeAlignment(ty);
+ int64_t type_align = dl->getABITypeAlignment(ty);
llvm::Value *addr_typed;
llvm::IntegerType *int_ty = llvm::Type::getInt32Ty(*mContext);
@@ -67,7 +67,7 @@ private:
llvm::Value *aligned_addr = builder.CreateBitCast(addr_typed, bp);
type_align = std::max((unsigned)type_align, (unsigned) 4);
uint64_t offset =
- llvm::RoundUpToAlignment(dl.getTypeSizeInBits(ty) / 8, type_align);
+ llvm::RoundUpToAlignment(dl->getTypeSizeInBits(ty) / 8, type_align);
llvm::Value *next_addr =
builder.CreateGEP(aligned_addr, llvm::ConstantInt::get(int_ty, offset),
"ap.next");
diff --git a/tools/ndk-translate/ReplaceUnwindHeaderSizePass.cpp b/tools/ndk-translate/ReplaceUnwindHeaderSizePass.cpp
index 760fdc148a0..cebc4351269 100644
--- a/tools/ndk-translate/ReplaceUnwindHeaderSizePass.cpp
+++ b/tools/ndk-translate/ReplaceUnwindHeaderSizePass.cpp
@@ -26,9 +26,11 @@ char ReplaceUnwindHeaderSizePass::ID = 0;
bool ReplaceUnwindHeaderSizePass::runOnModule(llvm::Module &M) {
bool changed = false;
llvm::LLVMContext &ctx = M.getContext();
- llvm::APInt unwind_hdr_size(/*numBits=*/32, /*val=*/getTargetUnwindHeaderSize());
+ const llvm::DataLayout *dl = M.getDataLayout();
+ llvm::APInt unwind_hdr_size(/*numBits=*/dl->getPointerSizeInBits(),
+ /*val=*/getTargetUnwindHeaderSize());
llvm::ConstantInt *size_value = llvm::ConstantInt::get(ctx, unwind_hdr_size);
- const char *k_func_name = "__ndk_le32_getUnwindHeaderSize";
+ const char *k_func_name = "__ndk_unknown_getUnwindHeaderSize";
llvm::SmallVector<llvm::Instruction*, 8> Insts;
llvm::Function *Func = 0;
diff --git a/tools/ndk-translate/ReplaceUnwindHeaderSizePass.h b/tools/ndk-translate/ReplaceUnwindHeaderSizePass.h
index 56584f9a5d6..83de101d958 100644
--- a/tools/ndk-translate/ReplaceUnwindHeaderSizePass.h
+++ b/tools/ndk-translate/ReplaceUnwindHeaderSizePass.h
@@ -19,13 +19,13 @@
#include <llvm/Pass.h>
-/* This pass expands intrinsic __ndk_le32_getUnwindHeaderSize.
+/* This pass expands intrinsic __ndk_unknown_getUnwindHeaderSize.
*
* _Unwind_Exception has different size for each target.
*
* ARM: 88
* Mips: 24
- * X86: 32
+ * Arm64, x86, x86_64, Mips64: 32
*/
class ReplaceUnwindHeaderSizePass : public llvm::ModulePass {
private:
diff --git a/tools/ndk-translate/X86ExpandVAArg.cpp b/tools/ndk-translate/X86ExpandVAArg.cpp
index eb63fdbc932..5f27a6a802e 100644
--- a/tools/ndk-translate/X86ExpandVAArg.cpp
+++ b/tools/ndk-translate/X86ExpandVAArg.cpp
@@ -41,7 +41,7 @@ private:
llvm::IRBuilder<> builder(pInst);
const llvm::DataLayoutPass *dlp =
getAnalysisIfAvailable<llvm::DataLayoutPass>();
- const llvm::DataLayout &dl = dlp->getDataLayout();
+ const llvm::DataLayout *dl = &dlp->getDataLayout();
llvm::Type *bp = llvm::Type::getInt8PtrTy(*mContext);
llvm::Type *bpp = bp->getPointerTo(0);
@@ -52,7 +52,7 @@ private:
llvm::Value *addr_typed = builder.CreateBitCast(addr, pty);
// X86-32 stack type alignment is always 4.
- uint64_t offset = llvm::RoundUpToAlignment(dl.getTypeSizeInBits(ty)/8, 4);
+ uint64_t offset = llvm::RoundUpToAlignment(dl->getTypeSizeInBits(ty)/8, 4);
llvm::Value *next_addr = builder.CreateGEP(addr,
llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), offset),
"ap.next");
diff --git a/tools/ndk-translate/X86_64ExpandVAArg.cpp b/tools/ndk-translate/X86_64ExpandVAArg.cpp
new file mode 100644
index 00000000000..5bac013a922
--- /dev/null
+++ b/tools/ndk-translate/X86_64ExpandVAArg.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ExpandVAArgPass.h"
+
+#include <sstream>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+class X86_64ExpandVAArg : public NDK64ExpandVAArg {
+public:
+ virtual const char *getPassName() const {
+ return "X86_64 LLVM va_arg Instruction Expansion Pass";
+ }
+
+private:
+ virtual void fillupVAArgFunc(llvm::Function &);
+
+private:
+ // Lookup the map to take an existing function, or it will
+ // create a new one and insert into the map.
+ llvm::Type *getNativeVAListType();
+ llvm::Value *emitVAArgFromMemory(llvm::IRBuilder<> &);
+};
+
+// ------------ Implementation -------------- //
+
+void X86_64ExpandVAArg::fillupVAArgFunc(llvm::Function &func) {
+ // TODO: Support many argument numbers
+ // TODO: Support other types
+ llvm::BasicBlock *entry_bb =
+ llvm::BasicBlock::Create(*mContext, "entry", &func);
+ llvm::BasicBlock *next_bb = entry_bb->getNextNode();
+ llvm::Value *va_list_addr = func.getArgumentList().begin();
+ llvm::IRBuilder<> builder(entry_bb);
+
+ // First of all, replace it to native va_list type
+ va_list_addr = builder.CreateBitCast(va_list_addr,
+ llvm::PointerType::getUnqual(getNativeVAListType()));
+
+ unsigned neededInt = 1u, neededSSE = 0u;
+ if (mVAArgTy->isHalfTy() || mVAArgTy->isFloatTy() ||
+ mVAArgTy->isDoubleTy() || mVAArgTy->isVectorTy()) {
+ neededInt = 0u;
+ neededSSE = 1u;
+ }
+
+ // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
+ // in the registers. If not go to step 7.
+ if (!neededInt && !neededSSE) {
+ emitVAArgFromMemory(builder);
+ return;
+ }
+
+ // AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
+ // general purpose registers needed to pass type and num_fp to hold
+ // the number of floating point registers needed.
+
+ // AMD64-ABI 3.5.7p5: Step 3. Verify whether arguments fit into
+ // registers. In the case: l->gp_offset > 48 - num_gp * 8 or
+ // l->fp_offset > 304 - num_fp * 16 go to step 7.
+ //
+ // NOTE: 304 is a typo, there are (6 * 8 + 8 * 16) = 176 bytes of
+ // register save space).
+ llvm::Value *InRegs = 0;
+ llvm::Value *gp_offset_p = 0, *gp_offset = 0;
+ llvm::Value *fp_offset_p = 0, *fp_offset = 0;
+ if (neededInt) {
+ gp_offset_p = builder.CreateStructGEP(va_list_addr, 0, "gp_offset_p");
+ gp_offset = builder.CreateLoad(gp_offset_p, "gp_offset");
+ InRegs = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), 48 - neededInt * 8);
+ InRegs = builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp");
+ }
+ if (neededSSE) {
+ fp_offset_p = builder.CreateStructGEP(va_list_addr, 1, "fp_offset_p");
+ fp_offset = builder.CreateLoad(fp_offset_p, "fp_offset");
+ llvm::Value *FitsInFP =
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext), 176 - neededSSE * 16);
+ FitsInFP = builder.CreateICmpULE(fp_offset, FitsInFP, "fits_in_fp");
+ InRegs = InRegs ? builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
+ }
+
+ llvm::BasicBlock *InRegBlock = llvm::BasicBlock::Create(*mContext,
+ "vaarg.in_reg",
+ &func,
+ next_bb);
+ llvm::BasicBlock *InMemBlock = llvm::BasicBlock::Create(*mContext,
+ "vaarg.in_mem",
+ &func,
+ next_bb);
+ llvm::BasicBlock *ContBlock = llvm::BasicBlock::Create(*mContext,
+ "vaarg.end",
+ &func,
+ next_bb);
+ builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
+
+ llvm::Value *RegAddr = NULL, *MemAddr = NULL, *result = NULL;
+ llvm::PHINode *ResAddr = NULL;
+ // Emit code to load the value if it was passed in registers.
+ {
+ llvm::IRBuilder<> builder(InRegBlock);
+ // AMD64-ABI 3.5.7p5: Step 4. Fetch type from l->reg_save_area with
+ // an offset of l->gp_offset and/or l->fp_offset. This may require
+ // copying to a temporary location in case the parameter is passed
+ // in different register classes or requires an alignment greater
+ // than 8 for general purpose registers and 16 for XMM registers.
+ RegAddr =
+ builder.CreateLoad(builder.CreateStructGEP(va_list_addr, 3),
+ "reg_save_area");
+ if (neededInt && neededSSE) {
+ builder.CreateUnreachable();
+ } else if (neededInt) {
+ RegAddr = builder.CreateGEP(RegAddr, gp_offset);
+ RegAddr = builder.CreateBitCast(RegAddr,
+ llvm::PointerType::getUnqual(mVAArgTy));
+ } else if (neededSSE == 1) {
+ RegAddr = builder.CreateGEP(RegAddr, fp_offset);
+ RegAddr = builder.CreateBitCast(RegAddr,
+ llvm::PointerType::getUnqual(mVAArgTy));
+ } else {
+ builder.CreateUnreachable();
+ }
+
+ // AMD64-ABI 3.5.7p5: Step 5. Set:
+ // l->gp_offset = l->gp_offset + num_gp * 8
+ // l->fp_offset = l->fp_offset + num_fp * 16.
+ if (neededInt) {
+ llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext),
+ neededInt * 8);
+ builder.CreateStore(builder.CreateAdd(gp_offset, Offset),
+ gp_offset_p);
+ }
+ if (neededSSE) {
+ llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mContext),
+ neededSSE * 16);
+ builder.CreateStore(builder.CreateAdd(fp_offset, Offset),
+ fp_offset_p);
+ }
+ builder.CreateBr(ContBlock);
+ }
+
+ // Emit code to load the value if it was passed in memory.
+ {
+ llvm::IRBuilder<> builder(InMemBlock);
+ MemAddr = emitVAArgFromMemory(builder);
+ }
+
+ // Return the appropriate result.
+ {
+ llvm::IRBuilder<> builder(ContBlock);
+ //ResAddr = builder.CreatePHI(RegAddr->getType(), 2, "vaarg.addr");
+ //ResAddr->addIncoming(MemAddr, InMemBlock);
+ ResAddr = builder.CreatePHI(RegAddr->getType(), 1, "vaarg.addr");
+ ResAddr->addIncoming(RegAddr, InRegBlock);
+ result = builder.CreateLoad(ResAddr);
+ builder.CreateRet(result);
+ }
+}
+
+
+llvm::Type *X86_64ExpandVAArg::getNativeVAListType() {
+ // struct {
+ // unsigned gp_offset;
+ // unsigned fp_offset;
+ // void *overflow_arg_area;
+ // void *reg_save_area;
+ // };
+ static llvm::SmallVector<llvm::Type*, 4> va_list_ty_elmnts;
+ va_list_ty_elmnts.push_back(llvm::IntegerType::get(*mContext, /*bits*/32));
+ va_list_ty_elmnts.push_back(llvm::IntegerType::get(*mContext, /*bits*/32));
+ va_list_ty_elmnts.push_back(llvm::PointerType::getUnqual(
+ llvm::IntegerType::get(*mContext, /*bits*/8)));
+ va_list_ty_elmnts.push_back(llvm::PointerType::getUnqual(
+ llvm::IntegerType::get(*mContext, /*bits*/8)));
+ static llvm::StructType *va_list_ty =
+ llvm::StructType::get(*mContext, va_list_ty_elmnts);
+ return va_list_ty;
+}
+
+llvm::Value *X86_64ExpandVAArg::emitVAArgFromMemory(llvm::IRBuilder<> &pBuilder) {
+ // TODO: There's lots of code in clang/lib/CodeGen/TargetInfo.cpp, this is a
+ // big effort so that we only implement the simple part to make sure NDK tests
+ // work for now.
+ return pBuilder.CreateUnreachable();
+}
+
+
+ExpandVAArgPass* createX86_64ExpandVAArgPass() {
+ return new X86_64ExpandVAArg();
+}
diff --git a/tools/ndk-translate/ndk-translate.cpp b/tools/ndk-translate/ndk-translate.cpp
index 0bc657be4bb..38f3daa8789 100644
--- a/tools/ndk-translate/ndk-translate.cpp
+++ b/tools/ndk-translate/ndk-translate.cpp
@@ -16,9 +16,7 @@
#include <fcntl.h>
#include <unistd.h>
-
#include <cstdlib>
-#include <memory>
#include <utility>
#include "ExpandVAArgPass.h"
@@ -125,38 +123,58 @@ static void AddTargetTranslationPass(PassManager &PM) {
if (ArchName == "arm") {
VAArgPass = createARMExpandVAArgPass();
UnwindPass = createARMReplaceUnwindHeaderSizePass();
- }
- else if (ArchName == "x86") {
+ } else if (ArchName == "x86") {
VAArgPass = createX86ExpandVAArgPass();
UnwindPass = createX86ReplaceUnwindHeaderSizePass();
- }
- else if (ArchName == "mips") {
+ } else if (ArchName == "mips") {
VAArgPass = createMipsExpandVAArgPass();
UnwindPass = createMipsReplaceUnwindHeaderSizePass();
- }
- else {
+ } else if (ArchName == "arm64") {
+ VAArgPass = createArm64ExpandVAArgPass();
+ UnwindPass = createX86ReplaceUnwindHeaderSizePass(); // the same as x86
+ } else if (ArchName == "x86_64") {
+ VAArgPass = createX86_64ExpandVAArgPass();
+ UnwindPass = createX86ReplaceUnwindHeaderSizePass(); // the same as x86
+ } else if (ArchName == "mips64") {
+ VAArgPass = createMips64ExpandVAArgPass();
+ UnwindPass = createX86ReplaceUnwindHeaderSizePass(); // the same as x86
+ } else {
errs() << "'" << ArchName << "' is not supported!\n";
exit(1);
}
// Add target specific pass
PM.add(new DataLayoutPass());
- PM.add(VAArgPass);
- PM.add(UnwindPass);
+ if (VAArgPass)
+ PM.add(VAArgPass);
+ if (UnwindPass)
+ PM.add(UnwindPass);
}
-static void SetModuleTargetTriple(llvm::Module &M) {
+static void SetModuleTargetTriple(Module &M) {
if (ArchName == "arm") {
- M.setDataLayout("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-"
- "v64:64:64-v128:64:128-a0:0:64-n32-S64");
+ M.setTargetTriple("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "v64:64:64-v128:64:128-a0:0:64-n32-S64");
} else if (ArchName == "x86") {
- M.setDataLayout("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32-n8:16:32-S128");
+ M.setTargetTriple("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
+ "a0:0:64-f80:32:32-n8:16:32-S128");
} else if (ArchName == "mips") {
- M.setDataLayout("e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64");
+ M.setTargetTriple("e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64");
+ } else if (ArchName == "arm64") {
+ M.setTargetTriple("e-p:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-i128:128:128-f32:32:32-f64:64:64-"
+ "f128:128:128-n32:64-S128");
+ } else if (ArchName == "x86_64") {
+ M.setTargetTriple("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
+ } else if (ArchName == "mips64") {
+ M.setTargetTriple("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "f128:128:128-v64:64:64-n32:64-S128");
} else {
errs() << "'" << ArchName << "' is not supported!\n";
exit(1);
@@ -167,9 +185,11 @@ static void TranslateBitcode(const char *Bitcode, size_t BitcodeSize, std::strin
StringRef input_data(Bitcode, BitcodeSize);
MemoryBufferRef buffer(input_data, "");
- ErrorOr<Module*> Result = parseBitcodeFile(buffer, Context);
+ ErrorOr<Module *> Result = parseBitcodeFile(buffer, Context);
+
if (!Result) {
errs() << Result.getError().message() << '\n';
+ return;
}
std::unique_ptr<Module> M(Result.get());