Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2013, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ABCC_ABCC_H
     18 #define ABCC_ABCC_H
     19 
     20 #include <list>
     21 #include <map>
     22 #include <string>
     23 #include <vector>
     24 
     25 // Always use latest llvm for on-device abcc
     26 #if ON_DEVICE
     27 #include "llvm_35.h"
     28 #else
     29 #include "llvm_version.h"
     30 #endif
     31 
     32 namespace abcc {
     33 
     34 enum ReturnCode {
     35   RET_OK,
     36   RET_FAIL_RUN_CMD,
     37   RET_FAIL_UNSUPPORT_ABI,
     38   RET_FAIL_PREPARE_BITCODE,
     39   RET_FAIL_PREPARE_TOOL,
     40   RET_FAIL_CLEANUP,
     41   RET_FAIL_TRANSLATE,
     42   RET_FAIL_COMPILE,
     43   RET_FAIL_LINK
     44 };
     45 
     46 enum Command {
     47   CMD_TRANSLATE = 0,
     48   CMD_COMPILE,
     49   CMD_LINK,
     50   CMD_LINK_RUNTIME
     51 };
     52 
     53 class TargetAbi {
     54 public:
     55   enum Abi {
     56     ARMEABI = 0,
     57     ARMEABI_V7A,
     58     X86,
     59     MIPS,
     60     ARM64_V8A,
     61     X86_64,
     62     MIPS64
     63   };
     64 
     65 private:
     66   Abi mAbi;
     67 
     68 public:
     69   TargetAbi(const std::string &abi);
     70   operator int() const { return (int)mAbi; }
     71   operator const char*() const {
     72     if (mAbi == ARMEABI)  return "armeabi";
     73     if (mAbi == ARMEABI_V7A)  return "armeabi-v7a";
     74     if (mAbi == X86)  return "x86";
     75     if (mAbi == MIPS)  return "mips";
     76     if (mAbi == ARM64_V8A)  return "arm64-v8a";
     77     if (mAbi == X86_64)  return "x86_64";
     78     if (mAbi == MIPS64)  return "mips64";
     79     return 0;
     80   }
     81   const char* getArch() const {
     82     if (mAbi == ARMEABI || mAbi == ARMEABI_V7A)  return "arm";
     83     if (mAbi == X86)  return "x86";
     84     if (mAbi == MIPS) return "mips";
     85     if (mAbi == ARM64_V8A)  return "arm64";
     86     if (mAbi == X86_64)  return "x86_64";
     87     if (mAbi == MIPS64)  return "mips64";
     88     return 0;
     89   }
     90 };
     91 
     92 struct TargetAttributes {
     93   const char *mArch;
     94   const char *mTriple;
     95   const char *mLinkEmulation;
     96   const char *mBaseCFlags;
     97   const char *mBaseLDFlags;
     98 };
     99 
    100 const TargetAttributes kGlobalTargetAttrs[] = {
    101   {"arm", "armv5te-linux-androideabi", "armelf_linux_eabi", ARM_BASE_CFLAGS, "-dynamic-linker /system/bin/linker"},
    102 #ifdef FORCE_ARM
    103   {"arm", "armv7-linux-androideabi", "armelf_linux_eabi", ARM_BASE_CFLAGS, "-dynamic-linker /system/bin/linker"},
    104 #else
    105   {"arm", "thumbv7-linux-androideabi", "armelf_linux_eabi", ARM_BASE_CFLAGS, "-dynamic-linker /system/bin/linker"},
    106 #endif
    107   {"x86", "i686-linux-android", "elf_i386", "-disable-fp-elim -force-align-stack -mattr=+ssse3 -x86-force-gv-stack-cookie", "-dynamic-linker /system/bin/linker"},
    108   {"mips", "mipsel-linux-android", "elf32ltsmip", "-float-abi=hard", "-dynamic-linker /system/bin/linker"},
    109   {"arm64", "aarch64-linux-android", "aarch64linux", "", "-dynamic-linker /system/bin/linker64"},
    110   {"x86_64", "x86_64-linux-android", "elf_x86_64", "-disable-fp-elim -force-align-stack -mattr=+sse4.2,+popcnt -x86-force-gv-stack-cookie", "-dynamic-linker /system/bin/linker64"},
    111   {"mips64", "mips64el-linux-android", "elf64ltsmip", "", "-dynamic-linker /system/bin/linker64"},
    112 };
    113 
    114 // Used when computing mutual dependency
    115 class BitcodeCompiler;
    116 class BitcodeInfo;
    117 typedef std::map<std::string/*soname*/, BitcodeInfo> SONameMap;
    118 
    119 class BitcodeInfo {
    120 public:
    121   BitcodeInfo() {}  // Only for stl use
    122   BitcodeInfo(const std::string &bc);
    123   int readWrapper(BitcodeCompiler &);
    124   static void dropExternalLDLibs(SONameMap &map);
    125 
    126   bool mShared;
    127   bool mStatic;
    128   int mOptimizationLevel;
    129   std::string mBCPath;
    130   std::string mTargetBCPath;
    131   std::string mObjPath;
    132   std::string mOutPath;
    133   std::string mSOName;
    134   std::string mLDFlags; // --no-undefined, ...
    135   std::string mLDLocalLibsStr;  // i.e.: ./obj/local/.../libxxx.a
    136   std::list<std::string> mLDLibs;  // -lxxx, will be removed one-by-one until empty
    137   std::string mLDLibsStr; // Immutable once read in
    138 
    139 public:
    140   static int transferBytesToNumLe(const unsigned char *buffer, size_t n);
    141 };
    142 
    143 
    144 class BitcodeCompiler {
    145 protected:
    146   TargetAbi mAbi;
    147   std::string mSysroot;
    148   std::string mWorkingDir;
    149 
    150   // Target-independent, but global
    151   std::string mGlobalCFlags;
    152   std::string mGlobalLDFlags;
    153   std::string mGlobalLDLibs;
    154 
    155   ReturnCode mRet;
    156   std::vector<BitcodeInfo> mBitcodeFiles;
    157   SONameMap mSonameMap;
    158   std::string mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME+1];
    159 
    160 public:
    161   BitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &working_dir, const bool savetemps);
    162   virtual ~BitcodeCompiler();
    163   ReturnCode returnCode() const { return mRet; }
    164   virtual void cleanupPre() {}
    165   virtual void cleanupPost() {}
    166   void prepare() {
    167     prepareBitcodes();
    168     if (returnCode() != RET_OK)
    169       return;
    170 
    171     prepareToolchain();
    172     if (returnCode() != RET_OK)
    173       return;
    174   }
    175   void execute() {
    176     translate();
    177     if (returnCode() != RET_OK)
    178       return;
    179 
    180     compile();
    181     if (returnCode() != RET_OK)
    182       return;
    183 
    184     link();
    185     if (returnCode() != RET_OK)
    186       return;
    187   }
    188 
    189 private:
    190   bool mSaveTemps;
    191 
    192   void prepareBitcodes();
    193   void createSONameMapping();
    194   virtual void getBitcodeFiles() = 0;
    195   virtual void prepareToolchain() = 0;
    196   virtual void copyRuntime(const BitcodeInfo &info) = 0;
    197   virtual void removeIntermediateFile(const std::string &path) = 0;
    198   void translate();
    199   void compile();
    200   void link();
    201 
    202 public:
    203   virtual int parseLDFlags(BitcodeInfo &info, const std::string &str) = 0;
    204 
    205 protected:
    206   void runCmd(std::string cmd, bool dump = false);
    207 };
    208 
    209 } // namespace abcc
    210 
    211 // FIXME: We use LOGV, LOGE in Abcc.cpp, how to prevent this anti dependency?
    212 #if ON_DEVICE
    213 #include "Abcc_device.h"
    214 #else
    215 #include "Abcc_host.h"
    216 #endif
    217 
    218 #endif
    219