diff options
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp')
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp | 191 | 
1 files changed, 191 insertions, 0 deletions
| diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp new file mode 100644 index 000000000000..b396781e6726 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -0,0 +1,191 @@ +//===-- RenderScriptExpressionOpts.cpp --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <string> + +#include "llvm/ADT/None.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +#include "clang/Basic/TargetOptions.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/Log.h" + +#include "RenderScriptExpressionOpts.h" +#include "RenderScriptRuntime.h" +#include "RenderScriptx86ABIFixups.h" + +using namespace lldb_private; +using namespace lldb_renderscript; + +// [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang), +// the compiler frontend for RenderScript embeds an ARM specific triple in IR +// that is shipped in the app, after generating IR that has some assumptions +// that an ARM device is the target. As the IR is then compiled on a device of +// unknown (at time the IR was generated at least) architecture, when calling +// RenderScript API function as part of debugger expressions, we have to +// perform a fixup pass that removes those assumptions right before the module +// is sent to be generated by the llvm backend. + +namespace { +bool registerRSDefaultTargetOpts(clang::TargetOptions &proto, +                                 const llvm::Triple::ArchType &arch) { +  switch (arch) { +  case llvm::Triple::ArchType::x86: +    proto.Triple = "i686--linux-android"; +    proto.CPU = "atom"; +    proto.Features.push_back("+long64"); +    // Fallthrough for common x86 family features +    LLVM_FALLTHROUGH; +  case llvm::Triple::ArchType::x86_64: +    proto.Features.push_back("+mmx"); +    proto.Features.push_back("+sse"); +    proto.Features.push_back("+sse2"); +    proto.Features.push_back("+sse3"); +    proto.Features.push_back("+ssse3"); +    proto.Features.push_back("+sse4.1"); +    proto.Features.push_back("+sse4.2"); +    break; +  case llvm::Triple::ArchType::mipsel: +    // pretend this is `arm' for the front-end +    proto.Triple = "armv7-none-linux-android"; +    proto.CPU = ""; +    proto.Features.push_back("+long64"); +    break; +  case llvm::Triple::ArchType::mips64el: +    // pretend this is `aarch64' for the front-end +    proto.Triple = "aarch64-none-linux-android"; +    proto.CPU = ""; +    break; +  default: +    return false; +  } +  return true; +} +} // end anonymous namespace + +bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { +  bool changed_module = false; +  Log *log( +      GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS)); + +  std::string err; +  llvm::StringRef real_triple = +      m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple(); +  const llvm::Target *target_info = +      llvm::TargetRegistry::lookupTarget(real_triple, err); +  if (!target_info) { +    if (log) +      log->Warning("couldn't determine real target architecture: '%s'", +                   err.c_str()); +    return false; +  } + +  llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None; +  assert(m_process_ptr && "no available lldb process"); +  switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) { +  case llvm::Triple::ArchType::x86: +    changed_module |= fixupX86FunctionCalls(module); +    // For some reason this triple gets totally missed by the backend, and must +    // be set manually. There a reference in bcc/Main.cpp about auto feature- +    // detection being removed from LLVM3.5, but I can't see that discussion +    // anywhere public. +    real_triple = "i686--linux-android"; +    break; +  case llvm::Triple::ArchType::x86_64: +    changed_module |= fixupX86_64FunctionCalls(module); +    break; +  case llvm::Triple::ArchType::mipsel: +  case llvm::Triple::ArchType::mips64el: +    // No actual IR fixup pass is needed on MIPS, but the datalayout and +    // targetmachine do need to be explicitly set. + +    // bcc explicitly compiles MIPS code to use the static relocation model due +    // to an issue with relocations in mclinker. see +    // libbcc/support/CompilerConfig.cpp for details +    reloc_model = llvm::Reloc::Static; +    changed_module = true; +    break; +  case llvm::Triple::ArchType::arm: +  case llvm::Triple::ArchType::aarch64: +    // ARM subtargets need no fixup passes as they are the initial target as +    // generated by the +    // slang compiler frontend. +    break; +  default: +    if (log) +      log->Warning("Ignoring unknown renderscript target"); +    return false; +  } + +  if (changed_module) { +    llvm::TargetOptions options; +    llvm::TargetMachine *target_machine = target_info->createTargetMachine( +        real_triple, "", "", options, reloc_model); +    assert(target_machine && +           "failed to identify RenderScriptRuntime target machine"); +    // We've been using a triple and datalayout of some ARM variant all along, +    // so we need to let the backend know that this is no longer the case. +    if (log) { +      LLDB_LOGF(log, "%s - Changing RS target triple to '%s'", __FUNCTION__, +                real_triple.str().c_str()); +      LLDB_LOGF( +          log, "%s - Changing RS datalayout to '%s'", __FUNCTION__, +          target_machine->createDataLayout().getStringRepresentation().c_str()); +    } +    module.setTargetTriple(real_triple); +    module.setDataLayout(target_machine->createDataLayout()); +  } +  return changed_module; +} + +char RenderScriptRuntimeModulePass::ID = 0; + +namespace lldb_private { + +bool RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) { +  auto *process = GetProcess(); +  assert(process); +  return registerRSDefaultTargetOpts( +      proto, process->GetTarget().GetArchitecture().GetMachine()); +} + +bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) { +  if (!m_ir_passes) +    m_ir_passes = new RSIRPasses(GetProcess()); +  assert(m_ir_passes); + +  passes.EarlyPasses = m_ir_passes->EarlyPasses; +  passes.LatePasses = m_ir_passes->LatePasses; + +  return true; +} + +namespace lldb_renderscript { + +RSIRPasses::RSIRPasses(Process *process) { +  IRPasses(); +  assert(process); + +  EarlyPasses = std::make_shared<llvm::legacy::PassManager>(); +  assert(EarlyPasses); +  EarlyPasses->add(new RenderScriptRuntimeModulePass(process)); +} + +RSIRPasses::~RSIRPasses() {} + +} // namespace lldb_renderscript +} // namespace lldb_private | 
