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