180814287SRaphael Isemann //===-- RenderScriptExpressionOpts.cpp ------------------------------------===//
219459580SLuke Drummond //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
619459580SLuke Drummond //
719459580SLuke Drummond //===----------------------------------------------------------------------===//
819459580SLuke Drummond
919459580SLuke Drummond #include <string>
1019459580SLuke Drummond
1119459580SLuke Drummond #include "llvm/ADT/None.h"
1219459580SLuke Drummond #include "llvm/ADT/StringRef.h"
1319459580SLuke Drummond #include "llvm/IR/Instruction.h"
1419459580SLuke Drummond #include "llvm/IR/Instructions.h"
1519459580SLuke Drummond #include "llvm/IR/LegacyPassManager.h"
1619459580SLuke Drummond #include "llvm/IR/Module.h"
1789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
1819459580SLuke Drummond #include "llvm/Target/TargetMachine.h"
1919459580SLuke Drummond #include "llvm/Target/TargetOptions.h"
2019459580SLuke Drummond
2119459580SLuke Drummond #include "clang/Basic/TargetOptions.h"
2219459580SLuke Drummond
2319459580SLuke Drummond #include "lldb/Target/Process.h"
2419459580SLuke Drummond #include "lldb/Target/Target.h"
25*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
266f9e6901SZachary Turner #include "lldb/Utility/Log.h"
2719459580SLuke Drummond
2819459580SLuke Drummond #include "RenderScriptExpressionOpts.h"
2919459580SLuke Drummond #include "RenderScriptRuntime.h"
3019459580SLuke Drummond #include "RenderScriptx86ABIFixups.h"
3119459580SLuke Drummond
3219459580SLuke Drummond using namespace lldb_private;
3319459580SLuke Drummond using namespace lldb_renderscript;
3419459580SLuke Drummond
3519459580SLuke Drummond // [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang),
36b9c1b51eSKate Stone // the compiler frontend for RenderScript embeds an ARM specific triple in IR
3705097246SAdrian Prantl // that is shipped in the app, after generating IR that has some assumptions
3805097246SAdrian Prantl // that an ARM device is the target. As the IR is then compiled on a device of
3905097246SAdrian Prantl // unknown (at time the IR was generated at least) architecture, when calling
4005097246SAdrian Prantl // RenderScript API function as part of debugger expressions, we have to
4105097246SAdrian Prantl // perform a fixup pass that removes those assumptions right before the module
4205097246SAdrian Prantl // is sent to be generated by the llvm backend.
4319459580SLuke Drummond
registerRSDefaultTargetOpts(clang::TargetOptions & proto,const llvm::Triple::ArchType & arch)4493c1b3caSPavel Labath static bool registerRSDefaultTargetOpts(clang::TargetOptions &proto,
45b9c1b51eSKate Stone const llvm::Triple::ArchType &arch) {
46b9c1b51eSKate Stone switch (arch) {
4719459580SLuke Drummond case llvm::Triple::ArchType::x86:
4819459580SLuke Drummond proto.Triple = "i686--linux-android";
4919459580SLuke Drummond proto.CPU = "atom";
5019459580SLuke Drummond proto.Features.push_back("+long64");
5119459580SLuke Drummond // Fallthrough for common x86 family features
52962364c6SGreg Clayton LLVM_FALLTHROUGH;
5319459580SLuke Drummond case llvm::Triple::ArchType::x86_64:
5419459580SLuke Drummond proto.Features.push_back("+mmx");
5519459580SLuke Drummond proto.Features.push_back("+sse");
5619459580SLuke Drummond proto.Features.push_back("+sse2");
5719459580SLuke Drummond proto.Features.push_back("+sse3");
5819459580SLuke Drummond proto.Features.push_back("+ssse3");
5919459580SLuke Drummond proto.Features.push_back("+sse4.1");
6019459580SLuke Drummond proto.Features.push_back("+sse4.2");
6119459580SLuke Drummond break;
6219459580SLuke Drummond case llvm::Triple::ArchType::mipsel:
6319459580SLuke Drummond // pretend this is `arm' for the front-end
6419459580SLuke Drummond proto.Triple = "armv7-none-linux-android";
6519459580SLuke Drummond proto.CPU = "";
6619459580SLuke Drummond proto.Features.push_back("+long64");
6719459580SLuke Drummond break;
6819459580SLuke Drummond case llvm::Triple::ArchType::mips64el:
6919459580SLuke Drummond // pretend this is `aarch64' for the front-end
7019459580SLuke Drummond proto.Triple = "aarch64-none-linux-android";
7119459580SLuke Drummond proto.CPU = "";
7219459580SLuke Drummond break;
7319459580SLuke Drummond default:
7419459580SLuke Drummond return false;
7519459580SLuke Drummond }
7619459580SLuke Drummond return true;
7719459580SLuke Drummond }
7819459580SLuke Drummond
runOnModule(llvm::Module & module)79b9c1b51eSKate Stone bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
8019459580SLuke Drummond bool changed_module = false;
81a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Expressions);
8219459580SLuke Drummond
8319459580SLuke Drummond std::string err;
84b9c1b51eSKate Stone llvm::StringRef real_triple =
85b9c1b51eSKate Stone m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple();
86b9c1b51eSKate Stone const llvm::Target *target_info =
87adcd0268SBenjamin Kramer llvm::TargetRegistry::lookupTarget(std::string(real_triple), err);
88b9c1b51eSKate Stone if (!target_info) {
8919459580SLuke Drummond if (log)
90b9c1b51eSKate Stone log->Warning("couldn't determine real target architecture: '%s'",
91b9c1b51eSKate Stone err.c_str());
9219459580SLuke Drummond return false;
9319459580SLuke Drummond }
9419459580SLuke Drummond
9519459580SLuke Drummond llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None;
9619459580SLuke Drummond assert(m_process_ptr && "no available lldb process");
97b9c1b51eSKate Stone switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) {
9819459580SLuke Drummond case llvm::Triple::ArchType::x86:
9919459580SLuke Drummond changed_module |= fixupX86FunctionCalls(module);
100b9c1b51eSKate Stone // For some reason this triple gets totally missed by the backend, and must
10105097246SAdrian Prantl // be set manually. There a reference in bcc/Main.cpp about auto feature-
10205097246SAdrian Prantl // detection being removed from LLVM3.5, but I can't see that discussion
10305097246SAdrian Prantl // anywhere public.
10419459580SLuke Drummond real_triple = "i686--linux-android";
10519459580SLuke Drummond break;
10619459580SLuke Drummond case llvm::Triple::ArchType::x86_64:
10719459580SLuke Drummond changed_module |= fixupX86_64FunctionCalls(module);
10819459580SLuke Drummond break;
10919459580SLuke Drummond case llvm::Triple::ArchType::mipsel:
11019459580SLuke Drummond case llvm::Triple::ArchType::mips64el:
11105097246SAdrian Prantl // No actual IR fixup pass is needed on MIPS, but the datalayout and
11205097246SAdrian Prantl // targetmachine do need to be explicitly set.
11319459580SLuke Drummond
11405097246SAdrian Prantl // bcc explicitly compiles MIPS code to use the static relocation model due
11505097246SAdrian Prantl // to an issue with relocations in mclinker. see
11605097246SAdrian Prantl // libbcc/support/CompilerConfig.cpp for details
11719459580SLuke Drummond reloc_model = llvm::Reloc::Static;
11819459580SLuke Drummond changed_module = true;
11919459580SLuke Drummond break;
12019459580SLuke Drummond case llvm::Triple::ArchType::arm:
12119459580SLuke Drummond case llvm::Triple::ArchType::aarch64:
122b9c1b51eSKate Stone // ARM subtargets need no fixup passes as they are the initial target as
123b9c1b51eSKate Stone // generated by the
12419459580SLuke Drummond // slang compiler frontend.
12519459580SLuke Drummond break;
12619459580SLuke Drummond default:
12719459580SLuke Drummond if (log)
12819459580SLuke Drummond log->Warning("Ignoring unknown renderscript target");
12919459580SLuke Drummond return false;
13019459580SLuke Drummond }
13119459580SLuke Drummond
132b9c1b51eSKate Stone if (changed_module) {
13319459580SLuke Drummond llvm::TargetOptions options;
134b9c1b51eSKate Stone llvm::TargetMachine *target_machine = target_info->createTargetMachine(
135b9c1b51eSKate Stone real_triple, "", "", options, reloc_model);
136b9c1b51eSKate Stone assert(target_machine &&
137b9c1b51eSKate Stone "failed to identify RenderScriptRuntime target machine");
138b9c1b51eSKate Stone // We've been using a triple and datalayout of some ARM variant all along,
13905097246SAdrian Prantl // so we need to let the backend know that this is no longer the case.
140b9c1b51eSKate Stone if (log) {
14163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Changing RS target triple to '%s'", __FUNCTION__,
142b9c1b51eSKate Stone real_triple.str().c_str());
14363e5fb76SJonas Devlieghere LLDB_LOGF(
14463e5fb76SJonas Devlieghere log, "%s - Changing RS datalayout to '%s'", __FUNCTION__,
14519459580SLuke Drummond target_machine->createDataLayout().getStringRepresentation().c_str());
14619459580SLuke Drummond }
14719459580SLuke Drummond module.setTargetTriple(real_triple);
14819459580SLuke Drummond module.setDataLayout(target_machine->createDataLayout());
14919459580SLuke Drummond }
15019459580SLuke Drummond return changed_module;
15119459580SLuke Drummond }
15219459580SLuke Drummond
15319459580SLuke Drummond char RenderScriptRuntimeModulePass::ID = 0;
15419459580SLuke Drummond
155b9c1b51eSKate Stone namespace lldb_private {
15619459580SLuke Drummond
GetOverrideExprOptions(clang::TargetOptions & proto)157b9c1b51eSKate Stone bool RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) {
15819459580SLuke Drummond auto *process = GetProcess();
15919459580SLuke Drummond assert(process);
160b9c1b51eSKate Stone return registerRSDefaultTargetOpts(
161b9c1b51eSKate Stone proto, process->GetTarget().GetArchitecture().GetMachine());
16219459580SLuke Drummond }
16319459580SLuke Drummond
GetIRPasses(LLVMUserExpression::IRPasses & passes)164b9c1b51eSKate Stone bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) {
16519459580SLuke Drummond if (!m_ir_passes)
16619459580SLuke Drummond m_ir_passes = new RSIRPasses(GetProcess());
16719459580SLuke Drummond assert(m_ir_passes);
16819459580SLuke Drummond
16919459580SLuke Drummond passes.EarlyPasses = m_ir_passes->EarlyPasses;
17019459580SLuke Drummond passes.LatePasses = m_ir_passes->LatePasses;
17119459580SLuke Drummond
17219459580SLuke Drummond return true;
17319459580SLuke Drummond }
17419459580SLuke Drummond
175b9c1b51eSKate Stone namespace lldb_renderscript {
17619459580SLuke Drummond
RSIRPasses(Process * process)177b9c1b51eSKate Stone RSIRPasses::RSIRPasses(Process *process) {
17819459580SLuke Drummond IRPasses();
17919459580SLuke Drummond assert(process);
18019459580SLuke Drummond
18119459580SLuke Drummond EarlyPasses = std::make_shared<llvm::legacy::PassManager>();
18219459580SLuke Drummond assert(EarlyPasses);
18319459580SLuke Drummond EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
18419459580SLuke Drummond }
18519459580SLuke Drummond
186fd2433e1SJonas Devlieghere RSIRPasses::~RSIRPasses() = default;
18719459580SLuke Drummond
18819459580SLuke Drummond } // namespace lldb_renderscript
18919459580SLuke Drummond } // namespace lldb_private
190