1696bd635SAlexander Shaposhnikov //===-- RenderScriptExpressionOpts.cpp --------------------------*- C++ -*-===// 219459580SLuke Drummond // 319459580SLuke Drummond // The LLVM Compiler Infrastructure 419459580SLuke Drummond // 519459580SLuke Drummond // This file is distributed under the University of Illinois Open Source 619459580SLuke Drummond // License. See LICENSE.TXT for details. 719459580SLuke Drummond // 819459580SLuke Drummond //===----------------------------------------------------------------------===// 919459580SLuke Drummond 1019459580SLuke Drummond // C Includes 1119459580SLuke Drummond // C++ Includes 1219459580SLuke Drummond #include <string> 1319459580SLuke Drummond 1419459580SLuke Drummond // Other libraries and framework includes 1519459580SLuke Drummond #include "llvm/ADT/None.h" 1619459580SLuke Drummond #include "llvm/ADT/StringRef.h" 1719459580SLuke Drummond #include "llvm/IR/Instruction.h" 1819459580SLuke Drummond #include "llvm/IR/Instructions.h" 1919459580SLuke Drummond #include "llvm/IR/LegacyPassManager.h" 2019459580SLuke Drummond #include "llvm/IR/Module.h" 2119459580SLuke Drummond #include "llvm/Support/TargetRegistry.h" 2219459580SLuke Drummond #include "llvm/Target/TargetMachine.h" 2319459580SLuke Drummond #include "llvm/Target/TargetOptions.h" 2419459580SLuke Drummond 2519459580SLuke Drummond #include "clang/Basic/TargetOptions.h" 2619459580SLuke Drummond 2719459580SLuke Drummond // Project includes 2819459580SLuke Drummond #include "lldb/Target/Process.h" 2919459580SLuke Drummond #include "lldb/Target/Target.h" 306f9e6901SZachary Turner #include "lldb/Utility/Log.h" 3119459580SLuke Drummond 3219459580SLuke Drummond #include "RenderScriptExpressionOpts.h" 3319459580SLuke Drummond #include "RenderScriptRuntime.h" 3419459580SLuke Drummond #include "RenderScriptx86ABIFixups.h" 3519459580SLuke Drummond 3619459580SLuke Drummond using namespace lldb_private; 3719459580SLuke Drummond using namespace lldb_renderscript; 3819459580SLuke Drummond 3919459580SLuke Drummond // [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang), 40b9c1b51eSKate Stone // the compiler frontend for RenderScript embeds an ARM specific triple in IR 41*05097246SAdrian Prantl // that is shipped in the app, after generating IR that has some assumptions 42*05097246SAdrian Prantl // that an ARM device is the target. As the IR is then compiled on a device of 43*05097246SAdrian Prantl // unknown (at time the IR was generated at least) architecture, when calling 44*05097246SAdrian Prantl // RenderScript API function as part of debugger expressions, we have to 45*05097246SAdrian Prantl // perform a fixup pass that removes those assumptions right before the module 46*05097246SAdrian Prantl // is sent to be generated by the llvm backend. 4719459580SLuke Drummond 48b9c1b51eSKate Stone namespace { 49b9c1b51eSKate Stone bool registerRSDefaultTargetOpts(clang::TargetOptions &proto, 50b9c1b51eSKate Stone const llvm::Triple::ArchType &arch) { 51b9c1b51eSKate Stone switch (arch) { 5219459580SLuke Drummond case llvm::Triple::ArchType::x86: 5319459580SLuke Drummond proto.Triple = "i686--linux-android"; 5419459580SLuke Drummond proto.CPU = "atom"; 5519459580SLuke Drummond proto.Features.push_back("+long64"); 5619459580SLuke Drummond // Fallthrough for common x86 family features 57962364c6SGreg Clayton LLVM_FALLTHROUGH; 5819459580SLuke Drummond case llvm::Triple::ArchType::x86_64: 5919459580SLuke Drummond proto.Features.push_back("+mmx"); 6019459580SLuke Drummond proto.Features.push_back("+sse"); 6119459580SLuke Drummond proto.Features.push_back("+sse2"); 6219459580SLuke Drummond proto.Features.push_back("+sse3"); 6319459580SLuke Drummond proto.Features.push_back("+ssse3"); 6419459580SLuke Drummond proto.Features.push_back("+sse4.1"); 6519459580SLuke Drummond proto.Features.push_back("+sse4.2"); 6619459580SLuke Drummond break; 6719459580SLuke Drummond case llvm::Triple::ArchType::mipsel: 6819459580SLuke Drummond // pretend this is `arm' for the front-end 6919459580SLuke Drummond proto.Triple = "armv7-none-linux-android"; 7019459580SLuke Drummond proto.CPU = ""; 7119459580SLuke Drummond proto.Features.push_back("+long64"); 7219459580SLuke Drummond break; 7319459580SLuke Drummond case llvm::Triple::ArchType::mips64el: 7419459580SLuke Drummond // pretend this is `aarch64' for the front-end 7519459580SLuke Drummond proto.Triple = "aarch64-none-linux-android"; 7619459580SLuke Drummond proto.CPU = ""; 7719459580SLuke Drummond break; 7819459580SLuke Drummond default: 7919459580SLuke Drummond return false; 8019459580SLuke Drummond } 8119459580SLuke Drummond return true; 8219459580SLuke Drummond } 8319459580SLuke Drummond } // end anonymous namespace 8419459580SLuke Drummond 85b9c1b51eSKate Stone bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { 8619459580SLuke Drummond bool changed_module = false; 87b9c1b51eSKate Stone Log *log( 88b9c1b51eSKate Stone GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS)); 8919459580SLuke Drummond 9019459580SLuke Drummond std::string err; 91b9c1b51eSKate Stone llvm::StringRef real_triple = 92b9c1b51eSKate Stone m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple(); 93b9c1b51eSKate Stone const llvm::Target *target_info = 94b9c1b51eSKate Stone llvm::TargetRegistry::lookupTarget(real_triple, err); 95b9c1b51eSKate Stone if (!target_info) { 9619459580SLuke Drummond if (log) 97b9c1b51eSKate Stone log->Warning("couldn't determine real target architecture: '%s'", 98b9c1b51eSKate Stone err.c_str()); 9919459580SLuke Drummond return false; 10019459580SLuke Drummond } 10119459580SLuke Drummond 10219459580SLuke Drummond llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None; 10319459580SLuke Drummond assert(m_process_ptr && "no available lldb process"); 104b9c1b51eSKate Stone switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) { 10519459580SLuke Drummond case llvm::Triple::ArchType::x86: 10619459580SLuke Drummond changed_module |= fixupX86FunctionCalls(module); 107b9c1b51eSKate Stone // For some reason this triple gets totally missed by the backend, and must 108*05097246SAdrian Prantl // be set manually. There a reference in bcc/Main.cpp about auto feature- 109*05097246SAdrian Prantl // detection being removed from LLVM3.5, but I can't see that discussion 110*05097246SAdrian Prantl // anywhere public. 11119459580SLuke Drummond real_triple = "i686--linux-android"; 11219459580SLuke Drummond break; 11319459580SLuke Drummond case llvm::Triple::ArchType::x86_64: 11419459580SLuke Drummond changed_module |= fixupX86_64FunctionCalls(module); 11519459580SLuke Drummond break; 11619459580SLuke Drummond case llvm::Triple::ArchType::mipsel: 11719459580SLuke Drummond case llvm::Triple::ArchType::mips64el: 118*05097246SAdrian Prantl // No actual IR fixup pass is needed on MIPS, but the datalayout and 119*05097246SAdrian Prantl // targetmachine do need to be explicitly set. 12019459580SLuke Drummond 121*05097246SAdrian Prantl // bcc explicitly compiles MIPS code to use the static relocation model due 122*05097246SAdrian Prantl // to an issue with relocations in mclinker. see 123*05097246SAdrian Prantl // libbcc/support/CompilerConfig.cpp for details 12419459580SLuke Drummond reloc_model = llvm::Reloc::Static; 12519459580SLuke Drummond changed_module = true; 12619459580SLuke Drummond break; 12719459580SLuke Drummond case llvm::Triple::ArchType::arm: 12819459580SLuke Drummond case llvm::Triple::ArchType::aarch64: 129b9c1b51eSKate Stone // ARM subtargets need no fixup passes as they are the initial target as 130b9c1b51eSKate Stone // generated by the 13119459580SLuke Drummond // slang compiler frontend. 13219459580SLuke Drummond break; 13319459580SLuke Drummond default: 13419459580SLuke Drummond if (log) 13519459580SLuke Drummond log->Warning("Ignoring unknown renderscript target"); 13619459580SLuke Drummond return false; 13719459580SLuke Drummond } 13819459580SLuke Drummond 139b9c1b51eSKate Stone if (changed_module) { 14019459580SLuke Drummond llvm::TargetOptions options; 141b9c1b51eSKate Stone llvm::TargetMachine *target_machine = target_info->createTargetMachine( 142b9c1b51eSKate Stone real_triple, "", "", options, reloc_model); 143b9c1b51eSKate Stone assert(target_machine && 144b9c1b51eSKate Stone "failed to identify RenderScriptRuntime target machine"); 145b9c1b51eSKate Stone // We've been using a triple and datalayout of some ARM variant all along, 146*05097246SAdrian Prantl // so we need to let the backend know that this is no longer the case. 147b9c1b51eSKate Stone if (log) { 148b9c1b51eSKate Stone log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, 149b9c1b51eSKate Stone real_triple.str().c_str()); 150b9c1b51eSKate Stone log->Printf( 151b9c1b51eSKate Stone "%s - Changing RS datalayout to '%s'", __FUNCTION__, 15219459580SLuke Drummond target_machine->createDataLayout().getStringRepresentation().c_str()); 15319459580SLuke Drummond } 15419459580SLuke Drummond module.setTargetTriple(real_triple); 15519459580SLuke Drummond module.setDataLayout(target_machine->createDataLayout()); 15619459580SLuke Drummond } 15719459580SLuke Drummond return changed_module; 15819459580SLuke Drummond } 15919459580SLuke Drummond 16019459580SLuke Drummond char RenderScriptRuntimeModulePass::ID = 0; 16119459580SLuke Drummond 162b9c1b51eSKate Stone namespace lldb_private { 16319459580SLuke Drummond 164b9c1b51eSKate Stone bool RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) { 16519459580SLuke Drummond auto *process = GetProcess(); 16619459580SLuke Drummond assert(process); 167b9c1b51eSKate Stone return registerRSDefaultTargetOpts( 168b9c1b51eSKate Stone proto, process->GetTarget().GetArchitecture().GetMachine()); 16919459580SLuke Drummond } 17019459580SLuke Drummond 171b9c1b51eSKate Stone bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) { 17219459580SLuke Drummond if (!m_ir_passes) 17319459580SLuke Drummond m_ir_passes = new RSIRPasses(GetProcess()); 17419459580SLuke Drummond assert(m_ir_passes); 17519459580SLuke Drummond 17619459580SLuke Drummond passes.EarlyPasses = m_ir_passes->EarlyPasses; 17719459580SLuke Drummond passes.LatePasses = m_ir_passes->LatePasses; 17819459580SLuke Drummond 17919459580SLuke Drummond return true; 18019459580SLuke Drummond } 18119459580SLuke Drummond 182b9c1b51eSKate Stone namespace lldb_renderscript { 18319459580SLuke Drummond 184b9c1b51eSKate Stone RSIRPasses::RSIRPasses(Process *process) { 18519459580SLuke Drummond IRPasses(); 18619459580SLuke Drummond assert(process); 18719459580SLuke Drummond 18819459580SLuke Drummond EarlyPasses = std::make_shared<llvm::legacy::PassManager>(); 18919459580SLuke Drummond assert(EarlyPasses); 19019459580SLuke Drummond EarlyPasses->add(new RenderScriptRuntimeModulePass(process)); 19119459580SLuke Drummond } 19219459580SLuke Drummond 193b9c1b51eSKate Stone RSIRPasses::~RSIRPasses() {} 19419459580SLuke Drummond 19519459580SLuke Drummond } // namespace lldb_renderscript 19619459580SLuke Drummond } // namespace lldb_private 197