Skip to content

Commit 122fafb

Browse files
committed
[lldb] add architecture depended IR passes
Function calls support in LLDB expressions for RISCV: 5 of 6 Adds architecture depended IR passes handler, that can apply architecture specific IR passes before IRForTarget.
1 parent 89d56cb commit 122fafb

File tree

6 files changed

+191
-15
lines changed

6 files changed

+191
-15
lines changed

lldb/include/lldb/Core/Architecture.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/Core/PluginInterface.h"
1313
#include "lldb/Target/DynamicRegisterInfo.h"
1414
#include "lldb/Target/MemoryTagManager.h"
15+
#include "llvm/IR/LegacyPassManager.h"
1516

1617
namespace lldb_private {
1718

@@ -129,6 +130,17 @@ class Architecture : public PluginInterface {
129130
RegisterContext &reg_context) const {
130131
return false;
131132
}
133+
134+
// Takes a Pass Manager and adds passes for this Architecture that should be
135+
// run before IRForTarget
136+
virtual std::unique_ptr<llvm::legacy::PassManager>
137+
GetArchitectureCustomPasses(const ExecutionContext &exe_ctx,
138+
const llvm::StringRef expr) const {
139+
return nullptr;
140+
}
141+
142+
static constexpr llvm::StringLiteral s_target_incompatibility_marker =
143+
"target_incompatibility_detected";
132144
};
133145

134146
} // namespace lldb_private

lldb/source/Plugins/Architecture/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ add_subdirectory(Arm)
22
add_subdirectory(Mips)
33
add_subdirectory(PPC64)
44
add_subdirectory(AArch64)
5+
add_subdirectory(RISCV)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===-- ArchitectureRISCV.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 "Plugins/Architecture/RISCV/ArchitectureRISCV.h"
10+
#include "lldb/Core/PluginManager.h"
11+
#include "lldb/Target/RegisterContext.h"
12+
#include "lldb/Target/Thread.h"
13+
#include "lldb/Utility/ArchSpec.h"
14+
15+
#include "llvm/IR/LegacyPassManager.h"
16+
17+
#include "DirectCallReplacementPass.h"
18+
19+
using namespace lldb_private;
20+
using namespace lldb;
21+
22+
LLDB_PLUGIN_DEFINE(ArchitectureRISCV)
23+
24+
void ArchitectureRISCV::Initialize() {
25+
PluginManager::RegisterPlugin(GetPluginNameStatic(),
26+
"RISCV-specific algorithms",
27+
&ArchitectureRISCV::Create);
28+
}
29+
30+
void ArchitectureRISCV::Terminate() {
31+
PluginManager::UnregisterPlugin(&ArchitectureRISCV::Create);
32+
}
33+
34+
std::unique_ptr<Architecture> ArchitectureRISCV::Create(const ArchSpec &arch) {
35+
if (!arch.GetTriple().isRISCV())
36+
return nullptr;
37+
return std::unique_ptr<Architecture>(new ArchitectureRISCV());
38+
}
39+
40+
void ArchitectureRISCV::OverrideStopInfo(Thread &thread) const {}
41+
42+
std::unique_ptr<llvm::legacy::PassManager>
43+
ArchitectureRISCV::GetArchitectureCustomPasses(
44+
const ExecutionContext &exe_ctx, const llvm::StringRef expr) const {
45+
// LLDB generates additional support functions like
46+
// '_$__lldb_valid_pointer_check', that do not require custom passes
47+
if (expr != "$__lldb_expr")
48+
return nullptr;
49+
50+
std::unique_ptr<llvm::legacy::PassManager> custom_passes =
51+
std::make_unique<llvm::legacy::PassManager>();
52+
auto *P = createDirectCallReplacementPass(exe_ctx);
53+
custom_passes->add(P);
54+
return custom_passes;
55+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===-- ArchitectureRISCV.h -------------------------------------*- C++ -*-===//
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+
#ifndef LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H
10+
#define LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H
11+
12+
#include "lldb/Core/Architecture.h"
13+
14+
namespace lldb_private {
15+
16+
class ArchitectureRISCV : public Architecture {
17+
public:
18+
static llvm::StringRef GetPluginNameStatic() { return "riscv"; }
19+
static void Initialize();
20+
static void Terminate();
21+
22+
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
23+
24+
void OverrideStopInfo(Thread &thread) const override;
25+
26+
std::unique_ptr<llvm::legacy::PassManager>
27+
GetArchitectureCustomPasses(const ExecutionContext &exe_ctx,
28+
const llvm::StringRef expr) const override;
29+
30+
private:
31+
static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
32+
ArchitectureRISCV() = default;
33+
};
34+
35+
} // namespace lldb_private
36+
37+
#endif // LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_lldb_library(lldbPluginArchitectureRISCV PLUGIN
2+
ArchitectureRISCV.cpp
3+
DirectCallReplacementPass.cpp
4+
5+
LINK_LIBS
6+
lldbPluginProcessUtility
7+
lldbCore
8+
lldbTarget
9+
lldbUtility
10+
LINK_COMPONENTS
11+
Support
12+
)

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@
4343
#include "llvm/Support/Error.h"
4444
#include "llvm/Support/FileSystem.h"
4545
#include "llvm/Support/TargetSelect.h"
46+
#include "llvm/TargetParser/Triple.h"
4647

4748
#include "llvm/IR/LLVMContext.h"
49+
#include "llvm/IR/LegacyPassManager.h"
4850
#include "llvm/IR/Module.h"
4951
#include "llvm/Support/DynamicLibrary.h"
5052
#include "llvm/Support/ErrorHandling.h"
@@ -407,24 +409,50 @@ static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
407409
/// \return
408410
/// A string representing target ABI for the current architecture.
409411
static std::string GetClangTargetABI(const ArchSpec &target_arch) {
410-
std::string abi;
411-
412412
if (target_arch.IsMIPS()) {
413413
switch (target_arch.GetFlags() & ArchSpec::eMIPSABI_mask) {
414414
case ArchSpec::eMIPSABI_N64:
415-
abi = "n64";
416-
break;
415+
return "n64";
417416
case ArchSpec::eMIPSABI_N32:
418-
abi = "n32";
419-
break;
417+
return "n32";
420418
case ArchSpec::eMIPSABI_O32:
421-
abi = "o32";
422-
break;
419+
return "o32";
423420
default:
424-
break;
421+
return {};
422+
}
423+
}
424+
425+
if (target_arch.GetTriple().isRISCV64()) {
426+
switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
427+
case ArchSpec::eRISCV_float_abi_soft:
428+
return "lp64";
429+
case ArchSpec::eRISCV_float_abi_single:
430+
return "lp64f";
431+
case ArchSpec::eRISCV_float_abi_double:
432+
return "lp64d";
433+
case ArchSpec::eRISCV_float_abi_quad:
434+
return "lp64q";
435+
default:
436+
return {};
437+
}
438+
}
439+
440+
if (target_arch.GetTriple().isRISCV32()) {
441+
switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
442+
case ArchSpec::eRISCV_float_abi_soft:
443+
return "ilp32";
444+
case ArchSpec::eRISCV_float_abi_single:
445+
return "ilp32f";
446+
case ArchSpec::eRISCV_float_abi_double:
447+
return "ilp32d";
448+
case ArchSpec::eRISCV_float_abi_soft | ArchSpec::eRISCV_rve:
449+
return "ilp32e";
450+
default:
451+
return {};
425452
}
426453
}
427-
return abi;
454+
455+
return {};
428456
}
429457

430458
static void SetupTargetOpts(CompilerInstance &compiler,
@@ -471,6 +499,18 @@ static void SetupTargetOpts(CompilerInstance &compiler,
471499
// Set the target ABI
472500
if (std::string abi = GetClangTargetABI(target_arch); !abi.empty())
473501
compiler.getTargetOpts().ABI = std::move(abi);
502+
503+
if ((target_machine == llvm::Triple::riscv64 &&
504+
compiler.getTargetOpts().ABI == "lp64f") ||
505+
(target_machine == llvm::Triple::riscv32 &&
506+
compiler.getTargetOpts().ABI == "ilp32f"))
507+
m_compiler->getTargetOpts().FeaturesAsWritten.emplace_back("+f");
508+
509+
if ((target_machine == llvm::Triple::riscv64 &&
510+
compiler.getTargetOpts().ABI == "lp64d") ||
511+
(target_machine == llvm::Triple::riscv32 &&
512+
compiler.getTargetOpts().ABI == "ilp32d"))
513+
m_compiler->getTargetOpts().FeaturesAsWritten.emplace_back("+d");
474514
}
475515

476516
static void SetupLangOpts(CompilerInstance &compiler,
@@ -722,7 +762,7 @@ ClangExpressionParser::ClangExpressionParser(
722762
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
723763
m_compiler->getCodeGenOpts().InstrumentFunctions = false;
724764
m_compiler->getCodeGenOpts().setFramePointer(
725-
CodeGenOptions::FramePointerKind::All);
765+
CodeGenOptions::FramePointerKind::All);
726766
if (generate_debug_info)
727767
m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
728768
else
@@ -736,7 +776,7 @@ ClangExpressionParser::ClangExpressionParser(
736776
// FIXME: We shouldn't need to do this, the target should be immutable once
737777
// created. This complexity should be lifted elsewhere.
738778
m_compiler->getTarget().adjust(m_compiler->getDiagnostics(),
739-
m_compiler->getLangOpts());
779+
m_compiler->getLangOpts());
740780

741781
// 5. Set up the diagnostic buffer for reporting errors
742782

@@ -1157,8 +1197,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
11571197
if (auto fileEntry = m_compiler->getFileManager().getOptionalFileRef(
11581198
result_path)) {
11591199
source_mgr.setMainFileID(source_mgr.createFileID(
1160-
*fileEntry,
1161-
SourceLocation(), SrcMgr::C_User));
1200+
*fileEntry, SourceLocation(), SrcMgr::C_User));
11621201
created_main_file = true;
11631202
}
11641203
}
@@ -1441,6 +1480,25 @@ lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
14411480
custom_passes.EarlyPasses->run(*llvm_module_up);
14421481
}
14431482

1483+
std::unique_ptr<llvm::legacy::PassManager> arch_passes;
1484+
if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) {
1485+
Architecture *arch = target_sp->GetArchitecturePlugin();
1486+
if (arch)
1487+
arch_passes =
1488+
arch->GetArchitectureCustomPasses(exe_ctx, m_expr.FunctionName());
1489+
}
1490+
1491+
if (arch_passes)
1492+
arch_passes->run(*llvm_module_up);
1493+
1494+
if (llvm_module_up->getNamedMetadata(
1495+
Architecture::s_target_incompatibility_marker)) {
1496+
err = Status::FromErrorStringWithFormat(
1497+
"%s - Architecture passes failure on function %s\n. Function "
1498+
"contains unsupported function calls",
1499+
__FUNCTION__, m_expr.FunctionName());
1500+
}
1501+
14441502
execution_unit_sp = std::make_shared<IRExecutionUnit>(
14451503
m_llvm_context, // handed off here
14461504
llvm_module_up, // handed off here
@@ -1506,7 +1564,8 @@ lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
15061564

15071565
DiagnosticManager install_diags;
15081566
if (Error Err = dynamic_checkers->Install(install_diags, exe_ctx)) {
1509-
std::string ErrMsg = "couldn't install checkers: " + toString(std::move(Err));
1567+
std::string ErrMsg =
1568+
"couldn't install checkers: " + toString(std::move(Err));
15101569
if (install_diags.Diagnostics().size())
15111570
ErrMsg = ErrMsg + "\n" + install_diags.GetString().c_str();
15121571
err = Status(ErrMsg);

0 commit comments

Comments
 (0)