Skip to content
Open
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
34 changes: 34 additions & 0 deletions lib/mpi_interceptor/InterceptorFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef struct MPISemCounter {
} MPICounter;

static MPICounter mcounter = {0, 0, 0};
static int log_buffer_srcloc = 0;

TYPEART_NO_EXPORT void ta_check_send(const char* name, const void* called_from, const void* sendbuf, int count,
MPI_Datatype dtype) {
Expand Down Expand Up @@ -115,6 +116,33 @@ TYPEART_NO_EXPORT int ta_check_buffer(const char* mpi_name, const void* called_f
ta_print_loc(called_from);
return 0;
}

const void *ret_addr;
typeart_status_v = typeart_get_return_address(buf, &ret_addr);
if (typeart_status_v != TYPEART_OK) {
return 0;
}

if (log_buffer_srcloc == 0) {
return 0;
}

typeart_source_location src_loc;
typeart_status_v = typeart_get_source_location(ret_addr, &src_loc);
if (typeart_status_v != TYPEART_OK) {
++mcounter.error;
const char* msg = ta_get_error_message(typeart_status_v);
printf("R[%d][Error][%d] %s: failed to get source location for buffer %p at loc %p - %s\n",
rank, const_adr, mpi_name, buf, called_from, msg);
return 0;
}

printf("R[%d][Info][%d] %s: buffer %p @ %s:%s:%u\n", rank, const_adr, mpi_name, buf,
src_loc.file, src_loc.function, src_loc.line);

free(src_loc.file);
free(src_loc.function);

// if (mpi_count > count) {
// TODO: Count check not really sensible without taking the MPI type into account
// printf("R[%d][Error][%d] Call '%s' buffer %p too small\n", rank, const_adr, mpi_name, buf);
Expand Down Expand Up @@ -144,6 +172,12 @@ TYPEART_NO_EXPORT void ta_print_loc(const void* call_adr) {
}
}

TYPEART_NO_EXPORT void ta_init() {
const char *var = getenv("TYPEART_LOG_BUF_SRCLOC");
if (var && strncmp(var, "TRUE", 4) == 0)
log_buffer_srcloc = 1;
}

TYPEART_NO_EXPORT void ta_exit() {
// Called at MPI_Finalize time
int rank = 0;
Expand Down
7 changes: 7 additions & 0 deletions lib/mpi_interceptor/mpi_interceptor_tmpl.impl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ extern "C" {

#include "InterceptorFunctions.h"

{{fn fn_name MPI_Init}}
{
ta_init();
return P{{fn_name}}({{args}});
}
{{endfn}}

{{fn fn_name MPI_Finalize}}
{
ta_exit();
Expand Down
10 changes: 6 additions & 4 deletions lib/passes/Commandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <charconv>
#include <string>
#include <string_view>
#include <support/TypeUtil.h>
#include <type_traits>

using namespace llvm;
Expand Down Expand Up @@ -126,10 +127,11 @@ static cl::opt<ConfigStdArgTypes::filter_ty> cl_typeart_call_filter(CommandlineS

static cl::opt<typeart::analysis::FilterImplementation> cl_typeart_call_filter_implementation(
CommandlineStdArgs::filter_impl, cl::desc(ConfigStdArgDescriptions::filter_impl),
cl::values(clEnumValN(typeart::analysis::FilterImplementation::none, "none", "No filter"),
clEnumValN(typeart::analysis::FilterImplementation::standard, "std",
"Standard forward filter (default)"),
clEnumValN(typeart::analysis::FilterImplementation::cg, "cg", "Call-graph-based filter")),
cl::values(
clEnumValN(typeart::analysis::FilterImplementation::none, "none", "No filter"),
clEnumValN(typeart::analysis::FilterImplementation::standard, "std", "Standard forward filter (default)"),
clEnumValN(typeart::analysis::FilterImplementation::cg, "cg", "Call-graph-based filter"),
clEnumValN(typeart::analysis::FilterImplementation::acg, "acg", "MetaCG with argument flow based filter")),
cl::Hidden, cl::init(typeart::analysis::FilterImplementation::standard), cl::cat(typeart_analysis_category));

static cl::opt<ConfigStdArgTypes::filter_glob_ty> cl_typeart_call_filter_glob(
Expand Down
77 changes: 35 additions & 42 deletions lib/passes/TypeARTPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,48 +403,41 @@ bool LegacyTypeArtPass::doFinalization(llvm::Module&) {
//.....................
llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() {
using namespace llvm;
return {
LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) {
pass_builder.registerPipelineStartEPCallback([](auto& MPM, OptimizationLevel) {
auto parameters = typeart::util::pass::parsePassParameters(
typeart::config::pass::parse_typeart_config, "typeart<heap;stats;type-serialization=hybrid>", "typeart");
if (!parameters) {
LOG_FATAL("Error parsing heap params: " << parameters.takeError())
return;
}
MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get())));
});
#if LLVM_VERSION_MAJOR > 19
pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel, ThinOrFullLTOPhase) {
#else
pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel) {
#endif
auto parameters = typeart::util::pass::parsePassParameters(
typeart::config::pass::parse_typeart_config, "typeart<no-heap;stack;stats;type-serialization=hybrid>",
"typeart");
if (!parameters) {
LOG_FATAL("Error parsing stack params: " << parameters.takeError())
return;
}
MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get())));
});
pass_builder.registerPipelineParsingCallback([](StringRef name, ModulePassManager& module_pm,
ArrayRef<PassBuilder::PipelineElement>) {
if (typeart::util::pass::checkParametrizedPassName(name, "typeart")) {
auto parameters =
typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config, name, "typeart");
if (!parameters) {
LOG_FATAL("Error parsing params: " << parameters.takeError())
return false;
}
module_pm.addPass(typeart::pass::TypeArtPass(parameters.get()));
return true;
}
LOG_FATAL("Not a valid parametrized pass name: " << name)
return false;
});
}
};
return {LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) {
pass_builder.registerPipelineStartEPCallback([](auto& MPM, OptimizationLevel) {
auto parameters = typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config,
"typeart<heap;stats>", "typeart");
if (!parameters) {
LOG_FATAL("Error parsing heap params: " << parameters.takeError())
return;
}
MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get())));
});
pass_builder.registerOptimizerLastEPCallback([](auto& MPM, OptimizationLevel) {
auto parameters = typeart::util::pass::parsePassParameters(typeart::config::pass::parse_typeart_config,
"typeart<no-heap;stack;stats>", "typeart");
if (!parameters) {
LOG_FATAL("Error parsing stack params: " << parameters.takeError())
return;
}
MPM.addPass(typeart::pass::TypeArtPass(typeart::pass::TypeArtPass(parameters.get())));
});
pass_builder.registerPipelineParsingCallback(
[](StringRef name, ModulePassManager& module_pm, ArrayRef<PassBuilder::PipelineElement>) {
if (typeart::util::pass::checkParametrizedPassName(name, "typeart")) {
auto parameters = typeart::util::pass::parsePassParameters(
typeart::config::pass::parse_typeart_config, name, "typeart");
if (!parameters) {
LOG_FATAL("Error parsing params: " << parameters.takeError())
return false;
}
module_pm.addPass(typeart::pass::TypeArtPass(parameters.get()));
return true;
}
LOG_FATAL("Not a valid parametrized pass name: " << name)
return false;
});
}};
}

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() {
Expand Down
41 changes: 34 additions & 7 deletions lib/passes/analysis/MemInstFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
#include "analysis/MemOpData.h"
#include "configuration/Configuration.h"
#include "configuration/TypeARTOptions.h"
#include "filter/ACGFilter.h"
#include "filter/CGForwardFilter.h"
#include "filter/CGInterface.h"
#include "filter/Filter.h"
#include "filter/Matcher.h"
#include "filter/MetaCG.h"
#include "filter/StdForwardFilter.h"
#include "support/ConfigurationBase.h"
#include "support/Logger.h"
Expand All @@ -44,6 +46,7 @@
#include <algorithm>
#include <cstdlib>
#include <llvm/ADT/ScopeExit.h>
#include <llvm/Support/MemoryBuffer.h>
#include <sstream>
#include <string>
#include <utility>
Expand Down Expand Up @@ -96,15 +99,39 @@ static std::unique_ptr<typeart::filter::Filter> make_filter(const MemInstFinderC
LOG_DEBUG("Return no-op filter")
return std::make_unique<NoOpFilter>();
} else if (filter_id == FilterImplementation::cg) {
const std::string cg_file = config[config::ConfigStdArgs::filter_cg_file];
if (cg_file.empty()) {
LOG_FATAL("CG File not set!");
LOG_DEBUG("Return CGForward filter");

std::string cg_file = config[config::ConfigStdArgs::filter_cg_file];
const auto buf = MemoryBuffer::getFile(std::move(cg_file), true);
if (!buf) {
LOG_FATAL("Failed to load MCG file");
std::exit(1);
}

auto mcg = metacg::parse((*buf)->getBuffer());
if (!mcg) {
LOG_FATAL(mcg.takeError() << '\n');
std::exit(1);
}

return std::make_unique<CGForwardFilter>(std::move(mcg.get()), Regex{util::glob2regex(glob), Regex::NoFlags});

} else if (filter_id == FilterImplementation::acg) {
LOG_DEBUG("Return Argflow filter");
std::string cg_file = config[config::ConfigStdArgs::filter_cg_file];
const auto buf = MemoryBuffer::getFile(std::move(cg_file), true);
if (!buf) {
LOG_FATAL("Failed to load MCG file");
std::exit(1);
}

auto mcg = metacg::parse((*buf)->getBuffer());
if (!mcg) {
LOG_FATAL(mcg.takeError() << '\n');
std::exit(1);
}
LOG_DEBUG("Return CG filter with CG file @ " << cg_file)
auto json_cg = JSONCG::getJSON(cg_file);
auto matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(glob));
return std::make_unique<CGForwardFilter>(glob, std::move(json_cg), std::move(matcher));

return std::make_unique<AcgFilter>(std::move(mcg.get()), Regex{util::glob2regex(glob), Regex::NoFlags});
} else {
LOG_DEBUG("Return default filter")
auto matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(glob));
Expand Down
2 changes: 1 addition & 1 deletion lib/passes/analysis/MemInstFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Configuration;

namespace typeart::analysis {

enum class FilterImplementation { none, standard, cg };
enum class FilterImplementation { none, standard, cg, acg };

struct FunctionData {
MallocDataList mallocs;
Expand Down
18 changes: 18 additions & 0 deletions lib/passes/compat/CallSite.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
#ifndef COMPAT_LLVM_IR_CALLSITE_H
#define COMPAT_LLVM_IR_CALLSITE_H

#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Instruction.h"

#include <llvm/IR/InstrTypes.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Value.h>
#include <llvm/Support/Casting.h>
#include <utility>

namespace llvm {
class CallSite {
Expand Down Expand Up @@ -53,6 +55,10 @@ class CallSite {
return true;
}

[[nodiscard]] Function* getFunction() const {
return instruction_->getFunction();
}

[[nodiscard]] llvm::Function* getCalledFunction() const {
if (auto* call_base = llvm::dyn_cast_or_null<llvm::CallBase>(instruction_)) {
return call_base->getCalledFunction();
Expand Down Expand Up @@ -83,6 +89,18 @@ class CallSite {
auto* call_base = llvm::cast<llvm::CallBase>(instruction_);
return call_base->getIntrinsicID();
}

[[nodiscard]] const DILocation* getLocation() const {
SmallVector<std::pair<unsigned, MDNode*>> mds;
instruction_->getAllMetadata(mds);

for (const auto& [_, md] : mds) {
if (const auto* loc = dyn_cast<DILocation>(md); loc)
return loc;
}

return nullptr;
}
};
} // namespace llvm

Expand Down
1 change: 1 addition & 0 deletions lib/passes/configuration/OptionsUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ ClType string_to_enum(llvm::StringRef cl_value) {
if constexpr (std::is_same_v<FilterImplementation, ClType>) {
auto val = llvm::StringSwitch<ClType>(cl_value)
.Case("cg", FilterImplementation::cg)
.Case("acg", FilterImplementation::acg)
.Case("none", FilterImplementation::none)
.Case("std", FilterImplementation::standard)
.Default(FilterImplementation::standard);
Expand Down
4 changes: 2 additions & 2 deletions lib/passes/configuration/PassBuilderUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ inline bool checkParametrizedPassName(llvm::StringRef Name, llvm::StringRef Pass
/// Expected<> template class.
///
template <typename ParametersParseCallableT>
inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name,
llvm::StringRef PassName) -> decltype(Parser(llvm::StringRef{})) {
inline auto parsePassParameters(ParametersParseCallableT&& Parser, llvm::StringRef Name, llvm::StringRef PassName)
-> decltype(Parser(llvm::StringRef{})) {
using namespace llvm;
using ParametersT = typename decltype(Parser(StringRef{}))::value_type;

Expand Down
5 changes: 3 additions & 2 deletions lib/passes/configuration/TypeARTOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct llvm::yaml::ScalarEnumerationTraits<typeart::TypeSerializationImplementat
template <>
struct llvm::yaml::ScalarEnumerationTraits<typeart::analysis::FilterImplementation> {
static void enumeration(IO& io, typeart::analysis::FilterImplementation& value) {
io.enumCase(value, "acg", typeart::analysis::FilterImplementation::acg);
io.enumCase(value, "cg", typeart::analysis::FilterImplementation::cg);
io.enumCase(value, "std", typeart::analysis::FilterImplementation::standard);
io.enumCase(value, "none", typeart::analysis::FilterImplementation::none);
Expand Down Expand Up @@ -172,8 +173,8 @@ TypeARTConfigOptions config_to_options(const Configuration& configuration) {
}

template <typename T>
auto make_entry(std::string_view key,
const T& field_value) -> std::pair<llvm::StringRef, typename OptionsMap::mapped_type> {
auto make_entry(std::string_view key, const T& field_value)
-> std::pair<llvm::StringRef, typename OptionsMap::mapped_type> {
if constexpr (std::is_enum_v<T>) {
return {key, config::OptionValue{static_cast<int>(field_value)}};
} else {
Expand Down
Loading
Loading