1/* 2 * Copyright 2012, 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#include <string> 18#include <vector> 19 20#include <dlfcn.h> 21#include <stdlib.h> 22 23#include <llvm/ADT/STLExtras.h> 24#include <llvm/ADT/SmallString.h> 25#include <llvm/Config/config.h> 26#include <llvm/Support/CommandLine.h> 27#include <llvm/Support/FileSystem.h> 28#include <llvm/Support/MemoryBuffer.h> 29#include <llvm/Support/PluginLoader.h> 30#include <llvm/Support/raw_ostream.h> 31 32#include <bcc/BCCContext.h> 33#include <bcc/Compiler.h> 34#include <bcc/Config/Config.h> 35#include <bcc/ExecutionEngine/CompilerRTSymbolResolver.h> 36#include <bcc/ExecutionEngine/ObjectLoader.h> 37#include <bcc/ExecutionEngine/SymbolResolverProxy.h> 38#include <bcc/ExecutionEngine/SymbolResolvers.h> 39#include <bcc/Renderscript/RSCompilerDriver.h> 40#include <bcc/Script.h> 41#include <bcc/Source.h> 42#include <bcc/Support/CompilerConfig.h> 43#include <bcc/Support/Initialization.h> 44#include <bcc/Support/InputFile.h> 45#include <bcc/Support/OutputFile.h> 46 47using namespace bcc; 48 49#define STR2(a) #a 50#define STR(a) STR2(a) 51 52//===----------------------------------------------------------------------===// 53// General Options 54//===----------------------------------------------------------------------===// 55namespace { 56 57llvm::cl::opt<std::string> 58OptInputFilename(llvm::cl::Positional, llvm::cl::ValueRequired, 59 llvm::cl::desc("<input bitcode file>")); 60 61llvm::cl::opt<std::string> 62OptOutputFilename("o", llvm::cl::desc("Specify the output filename"), 63 llvm::cl::value_desc("filename"), 64 llvm::cl::init("bcc_output")); 65 66llvm::cl::opt<std::string> 67OptBCLibFilename("bclib", llvm::cl::desc("Specify the bclib filename"), 68 llvm::cl::value_desc("bclib")); 69 70llvm::cl::opt<std::string> 71OptOutputPath("output_path", llvm::cl::desc("Specify the output path"), 72 llvm::cl::value_desc("output path"), 73 llvm::cl::init(".")); 74 75llvm::cl::opt<bool> 76OptEmitLLVM("emit-llvm", 77 llvm::cl::desc("Emit an LLVM-IR version of the generated program")); 78 79llvm::cl::opt<std::string> 80OptTargetTriple("mtriple", 81 llvm::cl::desc("Specify the target triple (default: " 82 DEFAULT_TARGET_TRIPLE_STRING ")"), 83 llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING), 84 llvm::cl::value_desc("triple")); 85 86llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden, 87 llvm::cl::desc("Alias for -mtriple"), 88 llvm::cl::aliasopt(OptTargetTriple)); 89 90llvm::cl::opt<bool> 91OptRSDebugContext("rs-debug-ctx", 92 llvm::cl::desc("Enable build to work with a RenderScript debug context")); 93 94//===----------------------------------------------------------------------===// 95// Compiler Options 96//===----------------------------------------------------------------------===// 97 98// RenderScript uses -O3 by default 99llvm::cl::opt<char> 100OptOptLevel("O", llvm::cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " 101 "(default: -O3)"), 102 llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::init('3')); 103 104// Override "bcc -version" since the LLVM version information is not correct on 105// Android build. 106void BCCVersionPrinter() { 107 llvm::raw_ostream &os = llvm::outs(); 108 os << "libbcc (The Android Open Source Project, http://www.android.com/):\n" 109 << " Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n\n" 110 << "LLVM (http://llvm.org/):\n" 111 << " Version: " << PACKAGE_VERSION << "\n"; 112 return; 113} 114 115} // end anonymous namespace 116 117static inline 118bool ConfigCompiler(RSCompilerDriver &pRSCD) { 119 RSCompiler *RSC = pRSCD.getCompiler(); 120 CompilerConfig *config = NULL; 121 122 config = new (std::nothrow) CompilerConfig(OptTargetTriple); 123 if (config == NULL) { 124 llvm::errs() << "Out of memory when create the compiler configuration!\n"; 125 return false; 126 } 127 128 // llvm3.5 has removed the auto-detect feature for x86 subtarget, 129 // so set features explicitly in bcc. 130 if ((config->getTriple().find("i686") != std::string::npos) || 131 (config->getTriple().find("x86_64") != std::string::npos)) { 132 std::vector<std::string> fv; 133 134#if defined(__SSE3__) 135 fv.push_back("+sse3"); 136#endif 137#if defined(__SSSE3__) 138 fv.push_back("+ssse3"); 139#endif 140#if defined(__SSE4_1__) 141 fv.push_back("+sse4.1"); 142#endif 143#if defined(__SSE4_2__) 144 fv.push_back("+sse4.2"); 145#endif 146 147 if (fv.size()) { 148 config->setFeatureString(fv); 149 } 150 } 151 152 switch (OptOptLevel) { 153 case '0': config->setOptimizationLevel(llvm::CodeGenOpt::None); break; 154 case '1': config->setOptimizationLevel(llvm::CodeGenOpt::Less); break; 155 case '2': config->setOptimizationLevel(llvm::CodeGenOpt::Default); break; 156 case '3': 157 default: { 158 config->setOptimizationLevel(llvm::CodeGenOpt::Aggressive); 159 break; 160 } 161 } 162 163 pRSCD.setConfig(config); 164 Compiler::ErrorCode result = RSC->config(*config); 165 166 if (OptRSDebugContext) { 167 pRSCD.setDebugContext(true); 168 } 169 170 if (result != Compiler::kSuccess) { 171 llvm::errs() << "Failed to configure the compiler! (detail: " 172 << Compiler::GetErrorString(result) << ")\n"; 173 return false; 174 } 175 176 return true; 177} 178 179int main(int argc, char **argv) { 180 llvm::cl::SetVersionPrinter(BCCVersionPrinter); 181 llvm::cl::ParseCommandLineOptions(argc, argv); 182 std::string commandLine = bcc::getCommandLine(argc, argv); 183 init::Initialize(); 184 185 BCCContext context; 186 RSCompilerDriver RSCD; 187 188 if (OptBCLibFilename.empty()) { 189 ALOGE("Failed to compile bit code, -bclib was not specified"); 190 return EXIT_FAILURE; 191 } 192 193 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error = 194 llvm::MemoryBuffer::getFile(OptInputFilename.c_str()); 195 if (mb_or_error.getError()) { 196 ALOGE("Failed to load bitcode from path %s! (%s)", 197 OptInputFilename.c_str(), mb_or_error.getError().message().c_str()); 198 return EXIT_FAILURE; 199 } 200 std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get()); 201 202 const char *bitcode = input_data->getBufferStart(); 203 size_t bitcodeSize = input_data->getBufferSize(); 204 205 if (!ConfigCompiler(RSCD)) { 206 ALOGE("Failed to configure compiler"); 207 return EXIT_FAILURE; 208 } 209 210 // Attempt to dynamically initialize the compiler driver if such a function 211 // is present. It is only present if passed via "-load libFOO.so". 212 RSCompilerDriverInit_t rscdi = (RSCompilerDriverInit_t) 213 dlsym(RTLD_DEFAULT, STR(RS_COMPILER_DRIVER_INIT_FN)); 214 if (rscdi != NULL) { 215 rscdi(&RSCD); 216 } 217 218 bool built = RSCD.build(context, OptOutputPath.c_str(), OptOutputFilename.c_str(), bitcode, 219 bitcodeSize, commandLine.c_str(), OptBCLibFilename.c_str(), NULL, 220 OptEmitLLVM); 221 222 if (!built) { 223 return EXIT_FAILURE; 224 } 225 226 return EXIT_SUCCESS; 227} 228