/*
* Copyright 2013, 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.
*/
#ifndef ABCC_ABCC_H
#define ABCC_ABCC_H
#include <list>
#include <map>
#include <string>
#include <vector>
namespace abcc {
enum ReturnCode {
RET_OK,
RET_FAIL_RUN_CMD,
RET_FAIL_UNSUPPORT_ABI,
RET_FAIL_PREPARE_BITCODE,
RET_FAIL_PREPARE_TOOL,
RET_FAIL_CLEANUP,
RET_FAIL_TRANSLATE,
RET_FAIL_COMPILE,
RET_FAIL_LINK
};
enum Command {
CMD_TRANSLATE = 0,
CMD_COMPILE,
CMD_LINK,
CMD_LINK_RUNTIME
};
class TargetAbi {
public:
enum Abi {
ARMEABI = 0,
ARMEABI_V7A,
X86,
MIPS
};
private:
Abi mAbi;
public:
TargetAbi(const std::string &abi);
operator int() const { return (int)mAbi; }
operator const char*() const {
if (mAbi == ARMEABI) return "armeabi";
if (mAbi == ARMEABI_V7A) return "armeabi-v7a";
if (mAbi == X86) return "x86";
if (mAbi == MIPS) return "mips";
return 0;
}
const char* getArch() const {
if (mAbi == ARMEABI || mAbi == ARMEABI_V7A) return "arm";
if (mAbi == X86) return "x86";
if (mAbi == MIPS) return "mips";
return 0;
}
};
struct TargetAttributes {
const char *mArch;
const char *mTriple;
const char *mLinkEmulation;
const char *mBaseCFlags;
const char *mBaseLDFlags;
};
const TargetAttributes kGlobalTargetAttrs[] = {
{"arm", "armv5te-linux-androideabi", "armelf_linux_eabi", "", ""},
#ifdef FORCE_ARM
{"arm", "armv7-linux-androideabi", "armelf_linux_eabi", "", ""},
#else
{"arm", "thumbv7-linux-androideabi", "armelf_linux_eabi", "", ""},
#endif
{"x86", "i686-linux-android", "elf_i386", "-disable-fp-elim -force-align-stack -mattr=-ssse3,-sse41,-sse42,-sse4a,-popcnt", ""},
{"mips", "mipsel-linux-android", "elf32ltsmip", "", ""},
};
// Used when computing mutual dependency
class BitcodeCompiler;
class BitcodeInfo;
typedef std::map<std::string/*soname*/, BitcodeInfo> SONameMap;
class BitcodeInfo {
public:
BitcodeInfo() {} // Only for stl use
BitcodeInfo(const std::string &bc);
int readWrapper(BitcodeCompiler &);
static void dropExternalLDLibs(SONameMap &map);
bool mShared;
int mOptimizationLevel;
std::string mBCPath;
std::string mTargetBCPath;
std::string mObjPath;
std::string mOutPath;
std::string mSOName;
std::string mLDFlags; // --no-undefined, ...
std::list<std::string> mLDLibs; // -lxxx, will be removed one-by-one until empty
std::string mLDLibsStr; // Immutable once read in
public:
static int transferBytesToNumLe(const unsigned char *buffer, size_t n);
};
class BitcodeCompiler {
protected:
TargetAbi mAbi;
std::string mSysroot;
std::string mWorkingDir;
// Target-independent, but global
std::string mGlobalCFlags;
std::string mGlobalLDFlags;
std::string mGlobalLDLibs;
ReturnCode mRet;
std::vector<BitcodeInfo> mBitcodeFiles;
SONameMap mSonameMap;
std::string mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME+1];
public:
BitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &working_dir, const bool savetemps);
const ReturnCode returnCode() const { return mRet; }
virtual void cleanupPre() {}
virtual void cleanupPost() {}
void prepare() {
prepareBitcodes();
if (returnCode() != RET_OK)
return;
prepareToolchain();
if (returnCode() != RET_OK)
return;
}
void execute() {
translate();
if (returnCode() != RET_OK)
return;
compile();
if (returnCode() != RET_OK)
return;
link();
if (returnCode() != RET_OK)
return;
}
private:
bool mSaveTemps;
void prepareBitcodes();
void createSONameMapping();
virtual void getBitcodeFiles() = 0;
virtual void prepareToolchain() = 0;
virtual void copyRuntime(const BitcodeInfo &info) = 0;
virtual void removeIntermediateFile(const std::string &path) = 0;
void translate();
void compile();
void link();
public:
virtual int parseLDFlags(BitcodeInfo &info, const std::string &str) = 0;
protected:
void runCmd(std::string cmd, bool dump = false);
};
} // namespace abcc
// FIXME: We use LOGV, LOGE in Abcc.cpp, how to prevent this anti dependency?
#if ON_DEVICE
#include "Abcc_device.h"
#else
#include "Abcc_host.h"
#endif
#endif