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