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   }
getArch()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:
BitcodeInfo()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();
returnCode()163   ReturnCode returnCode() const { return mRet; }
cleanupPre()164   virtual void cleanupPre() {}
cleanupPost()165   virtual void cleanupPost() {}
prepare()166   void prepare() {
167     prepareBitcodes();
168     if (returnCode() != RET_OK)
169       return;
170 
171     prepareToolchain();
172     if (returnCode() != RET_OK)
173       return;
174   }
execute()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