Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions bolt/lib/Profile/StaleProfileMatching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,22 +309,33 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
FlowFunction Func;

// Add a special "dummy" source so that there is always a unique entry point.
// Because of the extra source, for all other blocks in FlowFunction it holds
// that Block.Index == BB->getIndex() + 1
FlowBlock EntryBlock;
EntryBlock.Index = 0;
Func.Blocks.push_back(EntryBlock);

auto BinaryBlockIsExit = [&](const BinaryBasicBlock &BB) {
if (BB.successors().empty())
return true;
return false;
};

// Create FlowBlock for every basic block in the binary function
for (const BinaryBasicBlock *BB : BlockOrder) {
Func.Blocks.emplace_back();
FlowBlock &Block = Func.Blocks.back();
Block.Index = Func.Blocks.size() - 1;
Block.HasSuccessors = BinaryBlockIsExit(*BB);
(void)BB;
assert(Block.Index == BB->getIndex() + 1 &&
"incorrectly assigned basic block index");
}

// Add a special "dummy" sink block so there is always a unique sink
FlowBlock SinkBlock;
SinkBlock.Index = Func.Blocks.size();
Func.Blocks.push_back(SinkBlock);
Func.Sink = SinkBlock.Index;

// Create FlowJump for each jump between basic blocks in the binary function
std::vector<uint64_t> InDegree(Func.Blocks.size(), 0);
for (const BinaryBasicBlock *SrcBB : BlockOrder) {
Expand Down Expand Up @@ -360,25 +371,37 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
// Add dummy edges to the extra sources. If there are multiple entry blocks,
// add an unlikely edge from 0 to the subsequent ones
assert(InDegree[0] == 0 && "dummy entry blocks shouldn't have predecessors");
for (uint64_t I = 1; I < Func.Blocks.size(); I++) {
for (uint64_t I = 1; I < BlockOrder.size() + 1; I++) {
const BinaryBasicBlock *BB = BlockOrder[I - 1];
if (BB->isEntryPoint() || InDegree[I] == 0) {
Func.Jumps.emplace_back();
FlowJump &Jump = Func.Jumps.back();
Jump.Source = 0;
Jump.Source = Func.Entry;
Jump.Target = I;
if (!BB->isEntryPoint())
Jump.IsUnlikely = true;
}
}

// Add dummy edges from the exit blocks to the sink block.
for (uint64_t I = 1; I < BlockOrder.size() + 1; I++) {
FlowBlock &Block = Func.Blocks[I];
if (Block.HasSuccessors) {
Func.Jumps.emplace_back();
FlowJump &Jump = Func.Jumps.back();
Jump.Source = I;
Jump.Target = Func.Sink;
}
}

// Create necessary metadata for the flow function
for (FlowJump &Jump : Func.Jumps) {
assert(Jump.Source < Func.Blocks.size());
Func.Blocks[Jump.Source].SuccJumps.push_back(&Jump);
assert(Jump.Target < Func.Blocks.size());
Func.Blocks[Jump.Target].PredJumps.push_back(&Jump);
}

return Func;
}

Expand All @@ -395,7 +418,7 @@ void matchWeightsByHashes(BinaryContext &BC,
const BinaryFunction::BasicBlockOrderType &BlockOrder,
const yaml::bolt::BinaryFunctionProfile &YamlBF,
FlowFunction &Func) {
assert(Func.Blocks.size() == BlockOrder.size() + 1);
assert(Func.Blocks.size() == BlockOrder.size() + 2);

std::vector<FlowBlock *> Blocks;
std::vector<BlendedBlockHash> BlendedHashes;
Expand Down Expand Up @@ -618,7 +641,7 @@ void assignProfile(BinaryFunction &BF,
FlowFunction &Func) {
BinaryContext &BC = BF.getBinaryContext();

assert(Func.Blocks.size() == BlockOrder.size() + 1);
assert(Func.Blocks.size() == BlockOrder.size() + 2);
for (uint64_t I = 0; I < BlockOrder.size(); I++) {
FlowBlock &Block = Func.Blocks[I + 1];
BinaryBasicBlock *BB = BlockOrder[I];
Expand All @@ -640,6 +663,9 @@ void assignProfile(BinaryFunction &BF,
if (Jump->Flow == 0)
continue;

// Skip the artificial sink block
if (Jump->Target == Func.Sink)
continue;
BinaryBasicBlock &SuccBB = *BlockOrder[Jump->Target - 1];
// Check if the edge corresponds to a regular jump or a landing pad
if (BB->getSuccessor(SuccBB.getLabel())) {
Expand Down
44 changes: 44 additions & 0 deletions lldb/bindings/python/python-typemaps.swig
Original file line number Diff line number Diff line change
Expand Up @@ -696,3 +696,47 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
$1 = $input == Py_None;
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
}

// For lldb::SBPlatformResolveSourceFileCallback
%typemap(in) (lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
if (!($input == Py_None ||
PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
SWIG_fail;
}

if ($input == Py_None) {
$1 = nullptr;
$2 = nullptr;
} else {
PythonCallable callable = Retain<PythonCallable>($input);
if (!callable.IsValid()) {
PyErr_SetString(PyExc_TypeError, "Need a valid callable object");
SWIG_fail;
}

llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo();
if (!arg_info) {
PyErr_SetString(PyExc_TypeError,
("Could not get arguments: " +
llvm::toString(arg_info.takeError())).c_str());
SWIG_fail;
}

if (arg_info.get().max_positional_args != 3) {
PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object");
SWIG_fail;
}

Py_INCREF($input);

$1 = LLDBSwigPythonCallResolveSourceFileCallback;
$2 = $input;
}
}

%typemap(typecheck) (lldb::SBPlatformResolveSourceFileCallback callback,
void *callback_baton) {
$1 = $input == Py_None;
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
}
48 changes: 47 additions & 1 deletion lldb/bindings/python/python-wrapper.swig
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
auto pfunc = self.ResolveName<PythonCallable>("__call__");

if (!pfunc.IsAllocated()) {
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
return false;
}

Expand Down Expand Up @@ -1148,4 +1148,50 @@ static SBError LLDBSwigPythonCallLocateModuleCallback(

return *sb_error_ptr;
}

static SBError LLDBSwigPythonCallResolveSourceFileCallback(
void *callback_baton,
const char* build_id,
const SBFileSpec &original_source_file_spec_sb,
SBFileSpec &resolved_source_file_spec_sb) {
SWIG_Python_Thread_Block swig_thread_block;

PyErr_Cleaner py_err_cleaner(true);

PyObject *py_build_id = PyUnicode_FromString(build_id);
PythonObject build_id_arg(PyRefType::Borrowed,py_build_id);
PythonObject original_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
std::make_unique<SBFileSpec>(original_source_file_spec_sb));
PythonObject resolved_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
std::make_unique<SBFileSpec>(resolved_source_file_spec_sb));

PythonCallable callable =
Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton));
if (!callable.IsValid()) {
return SBError("The callback callable is not valid.");
}

PythonObject result = callable(build_id_arg, original_source_file_spec_arg,
resolved_source_file_spec_arg);

if (!result.IsAllocated())
return SBError("No result.");
lldb::SBError *sb_error_ptr = nullptr;
if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr,
SWIGTYPE_p_lldb__SBError, 0) == -1) {
return SBError("Result is not SBError.");
}

if (sb_error_ptr->Success()) {
lldb::SBFileSpec *sb_resolved_source_file_spec_ptr = nullptr;
if (SWIG_ConvertPtr(resolved_source_file_spec_arg.get(),
(void **)&sb_resolved_source_file_spec_ptr,
SWIGTYPE_p_lldb__SBFileSpec, 0) == -1)
return SBError("resolved_source_file_spec is not SBFileSpec.");

resolved_source_file_spec_sb = *sb_resolved_source_file_spec_ptr;
}

return *sb_error_ptr;
}
%}
8 changes: 7 additions & 1 deletion lldb/include/lldb/API/SBDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/lldb-types.h"
#include "lldb/lldb-versioning.h"

Expand Down Expand Up @@ -141,9 +142,14 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
void *baton);

typedef SBError (*SBPlatformLocateModuleCallback)(
typedef lldb::SBError (*SBPlatformLocateModuleCallback)(
void *baton, const SBModuleSpec &module_spec, SBFileSpec &module_file_spec,
SBFileSpec &symbol_file_spec);

typedef lldb::SBError (*SBPlatformResolveSourceFileCallback)(
void *baton, const char *buildId,
const SBFileSpec &original_source_file_spec,
SBFileSpec &resolved_source_file_spec);
}

#endif // LLDB_API_SBDEFINES_H
3 changes: 3 additions & 0 deletions lldb/include/lldb/API/SBPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ class LLDB_API SBPlatform {
SBError SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback,
void *callback_baton);

SBError SetResolveSourceFileCallback(
lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton);

protected:
friend class SBDebugger;
friend class SBTarget;
Expand Down
3 changes: 2 additions & 1 deletion lldb/include/lldb/Symbol/LineEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct LineEntry {
///
/// \param[in] target_sp
/// Shared pointer to the target this LineEntry belongs to.
void ApplyFileMappings(lldb::TargetSP target_sp);
void ApplyFileMappings(lldb::TargetSP target_sp, const Address &address);

/// Helper to access the file.
const FileSpec &GetFile() const { return file_sp->GetSpecOnly(); }
Expand Down Expand Up @@ -181,6 +181,7 @@ struct LineEntry {
/// Returns \b true if lhs < rhs, false otherwise.
bool operator<(const LineEntry &lhs, const LineEntry &rhs);

// Add signature for CallFetchSourceFileCallBack
} // namespace lldb_private

#endif // LLDB_SYMBOL_LINEENTRY_H
14 changes: 14 additions & 0 deletions lldb/include/lldb/Target/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ class Platform : public PluginInterface {
virtual bool GetModuleSpec(const FileSpec &module_file_spec,
const ArchSpec &arch, ModuleSpec &module_spec);

void CallResolveSourceFileCallbackIfSet(
const char *build_id, const FileSpec &original_source_file_spec,
FileSpec &resolved_source_file_spec, bool *did_create_ptr);

virtual Status ConnectRemote(Args &args);

virtual Status DisconnectRemote();
Expand Down Expand Up @@ -921,6 +925,11 @@ class Platform : public PluginInterface {
FileSpec &symbol_file_spec)>
LocateModuleCallback;

typedef std::function<Status(const char *buildId,
const FileSpec &original_fileSpec,
FileSpec &newFileSpec)>
ResolveSourceFileCallback;

/// Set locate module callback. This allows users to implement their own
/// module cache system. For example, to leverage artifacts of build system,
/// to bypass pulling files from remote platform, or to search symbol files
Expand All @@ -929,6 +938,10 @@ class Platform : public PluginInterface {

LocateModuleCallback GetLocateModuleCallback() const;

void SetResolveSourceFileCallback(ResolveSourceFileCallback callback);

ResolveSourceFileCallback GetResolveSourceFileCallback() const;

protected:
/// Create a list of ArchSpecs with the given OS and a architectures. The
/// vendor field is left as an "unspecified unknown".
Expand Down Expand Up @@ -977,6 +990,7 @@ class Platform : public PluginInterface {
bool m_calculated_trap_handlers;
const std::unique_ptr<ModuleCache> m_module_cache;
LocateModuleCallback m_locate_module_callback;
ResolveSourceFileCallback m_resolve_source_file_callback;

/// Ask the Platform subclass to fill in the list of trap handler names
///
Expand Down
36 changes: 36 additions & 0 deletions lldb/source/API/SBPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,39 @@ SBError SBPlatform::SetLocateModuleCallback(
});
return SBError();
}

SBError SBPlatform::SetResolveSourceFileCallback(
lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
LLDB_INSTRUMENT_VA(this, callback, callback_baton);
PlatformSP platform_sp(GetSP());
if (!platform_sp) {
return SBError("invalid platform");
}

if (!callback) {
// Clear the callback.
platform_sp->SetResolveSourceFileCallback(nullptr);
return SBError("invalid callback");
}

// Platform.h does not accept lldb::SBPlatformFetchSourceFileCallback
// directly because of the SBFileSpec dependencies. Use a lambda to convert
// FileSpec <--> SBFileSpec for the callback arguments.
platform_sp->SetResolveSourceFileCallback(
[callback, callback_baton](const char *build_id,
const FileSpec &original_source_file_spec,
FileSpec &resolved_source_file_spec) {
SBFileSpec resolved_source_file_spec_sb(resolved_source_file_spec);

SBError error =
callback(callback_baton, build_id, original_source_file_spec,
resolved_source_file_spec_sb);

if (error.Success()) {
resolved_source_file_spec = resolved_source_file_spec_sb.ref();
}

return error.ref();
});
return SBError();
}
Loading
Loading