1*19459580SLuke Drummond //===-- ExpressionOpts.cpp --------------------------------------*- C++ -*-===// 2*19459580SLuke Drummond // 3*19459580SLuke Drummond // The LLVM Compiler Infrastructure 4*19459580SLuke Drummond // 5*19459580SLuke Drummond // This file is distributed under the University of Illinois Open Source 6*19459580SLuke Drummond // License. See LICENSE.TXT for details. 7*19459580SLuke Drummond // 8*19459580SLuke Drummond //===----------------------------------------------------------------------===// 9*19459580SLuke Drummond 10*19459580SLuke Drummond // C Includes 11*19459580SLuke Drummond // C++ Includes 12*19459580SLuke Drummond #include <string> 13*19459580SLuke Drummond 14*19459580SLuke Drummond // Other libraries and framework includes 15*19459580SLuke Drummond #include "llvm/ADT/None.h" 16*19459580SLuke Drummond #include "llvm/ADT/StringRef.h" 17*19459580SLuke Drummond #include "llvm/IR/Instruction.h" 18*19459580SLuke Drummond #include "llvm/IR/Instructions.h" 19*19459580SLuke Drummond #include "llvm/IR/LegacyPassManager.h" 20*19459580SLuke Drummond #include "llvm/IR/Module.h" 21*19459580SLuke Drummond #include "llvm/Support/TargetRegistry.h" 22*19459580SLuke Drummond #include "llvm/Target/TargetMachine.h" 23*19459580SLuke Drummond #include "llvm/Target/TargetOptions.h" 24*19459580SLuke Drummond 25*19459580SLuke Drummond #include "clang/Basic/TargetOptions.h" 26*19459580SLuke Drummond 27*19459580SLuke Drummond // Project includes 28*19459580SLuke Drummond #include "lldb/Core/Log.h" 29*19459580SLuke Drummond #include "lldb/Target/Process.h" 30*19459580SLuke Drummond #include "lldb/Target/Target.h" 31*19459580SLuke Drummond 32*19459580SLuke Drummond #include "RenderScriptExpressionOpts.h" 33*19459580SLuke Drummond #include "RenderScriptRuntime.h" 34*19459580SLuke Drummond #include "RenderScriptx86ABIFixups.h" 35*19459580SLuke Drummond 36*19459580SLuke Drummond using namespace lldb_private; 37*19459580SLuke Drummond using namespace lldb_renderscript; 38*19459580SLuke Drummond 39*19459580SLuke Drummond // [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang), 40*19459580SLuke Drummond // the compiler frontend for RenderScript embeds an ARM specific triple in IR that is shipped in the app, after 41*19459580SLuke Drummond // generating IR that has some assumptions that an ARM device is the target. 42*19459580SLuke Drummond // As the IR is then compiled on a device of unknown (at time the IR was generated at least) architecture, 43*19459580SLuke Drummond // when calling RenderScript API function as part of debugger expressions, we have to perform a fixup pass that 44*19459580SLuke Drummond // removes those assumptions right before the module is sent to be generated by the llvm backend. 45*19459580SLuke Drummond 46*19459580SLuke Drummond namespace 47*19459580SLuke Drummond { 48*19459580SLuke Drummond bool 49*19459580SLuke Drummond registerRSDefaultTargetOpts(clang::TargetOptions &proto, const llvm::Triple::ArchType &arch) 50*19459580SLuke Drummond { 51*19459580SLuke Drummond switch (arch) 52*19459580SLuke Drummond { 53*19459580SLuke Drummond case llvm::Triple::ArchType::x86: 54*19459580SLuke Drummond proto.Triple = "i686--linux-android"; 55*19459580SLuke Drummond proto.CPU = "atom"; 56*19459580SLuke Drummond proto.Features.push_back("+long64"); 57*19459580SLuke Drummond // Fallthrough for common x86 family features 58*19459580SLuke Drummond case llvm::Triple::ArchType::x86_64: 59*19459580SLuke Drummond proto.Features.push_back("+mmx"); 60*19459580SLuke Drummond proto.Features.push_back("+sse"); 61*19459580SLuke Drummond proto.Features.push_back("+sse2"); 62*19459580SLuke Drummond proto.Features.push_back("+sse3"); 63*19459580SLuke Drummond proto.Features.push_back("+ssse3"); 64*19459580SLuke Drummond proto.Features.push_back("+sse4.1"); 65*19459580SLuke Drummond proto.Features.push_back("+sse4.2"); 66*19459580SLuke Drummond break; 67*19459580SLuke Drummond case llvm::Triple::ArchType::mipsel: 68*19459580SLuke Drummond // pretend this is `arm' for the front-end 69*19459580SLuke Drummond proto.Triple = "armv7-none-linux-android"; 70*19459580SLuke Drummond proto.CPU = ""; 71*19459580SLuke Drummond proto.Features.push_back("+long64"); 72*19459580SLuke Drummond break; 73*19459580SLuke Drummond case llvm::Triple::ArchType::mips64el: 74*19459580SLuke Drummond // pretend this is `aarch64' for the front-end 75*19459580SLuke Drummond proto.Triple = "aarch64-none-linux-android"; 76*19459580SLuke Drummond proto.CPU = ""; 77*19459580SLuke Drummond break; 78*19459580SLuke Drummond default: 79*19459580SLuke Drummond return false; 80*19459580SLuke Drummond } 81*19459580SLuke Drummond return true; 82*19459580SLuke Drummond } 83*19459580SLuke Drummond } // end anonymous namespace 84*19459580SLuke Drummond 85*19459580SLuke Drummond bool 86*19459580SLuke Drummond RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) 87*19459580SLuke Drummond { 88*19459580SLuke Drummond bool changed_module = false; 89*19459580SLuke Drummond Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS)); 90*19459580SLuke Drummond 91*19459580SLuke Drummond std::string err; 92*19459580SLuke Drummond llvm::StringRef real_triple = m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple(); 93*19459580SLuke Drummond const llvm::Target *target_info = llvm::TargetRegistry::lookupTarget(real_triple, err); 94*19459580SLuke Drummond if (!target_info) 95*19459580SLuke Drummond { 96*19459580SLuke Drummond if (log) 97*19459580SLuke Drummond log->Warning("couldn't determine real target architecture: '%s'", err.c_str()); 98*19459580SLuke Drummond return false; 99*19459580SLuke Drummond } 100*19459580SLuke Drummond 101*19459580SLuke Drummond llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None; 102*19459580SLuke Drummond assert(m_process_ptr && "no available lldb process"); 103*19459580SLuke Drummond switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) 104*19459580SLuke Drummond { 105*19459580SLuke Drummond case llvm::Triple::ArchType::x86: 106*19459580SLuke Drummond changed_module |= fixupX86FunctionCalls(module); 107*19459580SLuke Drummond // For some reason this triple gets totally missed by the backend, and must be set manually. 108*19459580SLuke Drummond // There a reference in bcc/Main.cpp about auto feature-detection being removed from LLVM3.5, but I can't 109*19459580SLuke Drummond // see that discussion anywhere public. 110*19459580SLuke Drummond real_triple = "i686--linux-android"; 111*19459580SLuke Drummond break; 112*19459580SLuke Drummond case llvm::Triple::ArchType::x86_64: 113*19459580SLuke Drummond changed_module |= fixupX86_64FunctionCalls(module); 114*19459580SLuke Drummond break; 115*19459580SLuke Drummond case llvm::Triple::ArchType::mipsel: 116*19459580SLuke Drummond case llvm::Triple::ArchType::mips64el: 117*19459580SLuke Drummond // No actual IR fixup pass is needed on MIPS, but the datalayout 118*19459580SLuke Drummond // and targetmachine do need to be explicitly set. 119*19459580SLuke Drummond 120*19459580SLuke Drummond // bcc explicitly compiles MIPS code to use the static relocation 121*19459580SLuke Drummond // model due to an issue with relocations in mclinker. 122*19459580SLuke Drummond // see libbcc/support/CompilerConfig.cpp for details 123*19459580SLuke Drummond reloc_model = llvm::Reloc::Static; 124*19459580SLuke Drummond changed_module = true; 125*19459580SLuke Drummond break; 126*19459580SLuke Drummond case llvm::Triple::ArchType::arm: 127*19459580SLuke Drummond case llvm::Triple::ArchType::aarch64: 128*19459580SLuke Drummond // ARM subtargets need no fixup passes as they are the initial target as generated by the 129*19459580SLuke Drummond // slang compiler frontend. 130*19459580SLuke Drummond break; 131*19459580SLuke Drummond default: 132*19459580SLuke Drummond if (log) 133*19459580SLuke Drummond log->Warning("Ignoring unknown renderscript target"); 134*19459580SLuke Drummond return false; 135*19459580SLuke Drummond } 136*19459580SLuke Drummond 137*19459580SLuke Drummond if (changed_module) 138*19459580SLuke Drummond { 139*19459580SLuke Drummond llvm::TargetOptions options; 140*19459580SLuke Drummond llvm::TargetMachine *target_machine = 141*19459580SLuke Drummond target_info->createTargetMachine(real_triple, "", "", options, reloc_model); 142*19459580SLuke Drummond assert(target_machine && "failed to identify RenderScriptRuntime target machine"); 143*19459580SLuke Drummond // We've been using a triple and datalayout of some ARM variant all along, so 144*19459580SLuke Drummond // we need to let the backend know that this is no longer the case. 145*19459580SLuke Drummond if (log) 146*19459580SLuke Drummond { 147*19459580SLuke Drummond log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, real_triple.str().c_str()); 148*19459580SLuke Drummond log->Printf("%s - Changing RS datalayout to '%s'", __FUNCTION__, 149*19459580SLuke Drummond target_machine->createDataLayout().getStringRepresentation().c_str()); 150*19459580SLuke Drummond } 151*19459580SLuke Drummond module.setTargetTriple(real_triple); 152*19459580SLuke Drummond module.setDataLayout(target_machine->createDataLayout()); 153*19459580SLuke Drummond } 154*19459580SLuke Drummond return changed_module; 155*19459580SLuke Drummond } 156*19459580SLuke Drummond 157*19459580SLuke Drummond char RenderScriptRuntimeModulePass::ID = 0; 158*19459580SLuke Drummond 159*19459580SLuke Drummond namespace lldb_private 160*19459580SLuke Drummond { 161*19459580SLuke Drummond 162*19459580SLuke Drummond bool 163*19459580SLuke Drummond RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) 164*19459580SLuke Drummond { 165*19459580SLuke Drummond auto *process = GetProcess(); 166*19459580SLuke Drummond assert(process); 167*19459580SLuke Drummond return registerRSDefaultTargetOpts(proto, process->GetTarget().GetArchitecture().GetMachine()); 168*19459580SLuke Drummond } 169*19459580SLuke Drummond 170*19459580SLuke Drummond bool 171*19459580SLuke Drummond RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) 172*19459580SLuke Drummond { 173*19459580SLuke Drummond if (!m_ir_passes) 174*19459580SLuke Drummond m_ir_passes = new RSIRPasses(GetProcess()); 175*19459580SLuke Drummond assert(m_ir_passes); 176*19459580SLuke Drummond 177*19459580SLuke Drummond passes.EarlyPasses = m_ir_passes->EarlyPasses; 178*19459580SLuke Drummond passes.LatePasses = m_ir_passes->LatePasses; 179*19459580SLuke Drummond 180*19459580SLuke Drummond return true; 181*19459580SLuke Drummond } 182*19459580SLuke Drummond 183*19459580SLuke Drummond namespace lldb_renderscript 184*19459580SLuke Drummond { 185*19459580SLuke Drummond 186*19459580SLuke Drummond RSIRPasses::RSIRPasses(Process *process) 187*19459580SLuke Drummond { 188*19459580SLuke Drummond IRPasses(); 189*19459580SLuke Drummond assert(process); 190*19459580SLuke Drummond 191*19459580SLuke Drummond EarlyPasses = std::make_shared<llvm::legacy::PassManager>(); 192*19459580SLuke Drummond assert(EarlyPasses); 193*19459580SLuke Drummond EarlyPasses->add(new RenderScriptRuntimeModulePass(process)); 194*19459580SLuke Drummond } 195*19459580SLuke Drummond 196*19459580SLuke Drummond RSIRPasses::~RSIRPasses() 197*19459580SLuke Drummond { 198*19459580SLuke Drummond } 199*19459580SLuke Drummond 200*19459580SLuke Drummond } // namespace lldb_renderscript 201*19459580SLuke Drummond } // namespace lldb_private 202