Skip to content
Merged
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
2 changes: 1 addition & 1 deletion demo/02_broken_struct_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define COUNT 5

// Comment out for heap allocation
//#define USE_STACK
// #define USE_STACK

struct particle {
int id;
Expand Down
2 changes: 1 addition & 1 deletion lib/passes/Commandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ CommandLineOptions::CommandLineOptions() {

std::optional<typeart::config::OptionValue> CommandLineOptions::getValue(std::string_view opt_path) const {
auto key = llvm::StringRef(opt_path.data());
if (mapping_.count(key) != 0U) {
if (occurence_mapping_.lookup(key)) {
return mapping_.lookup(key);
}
return {};
Expand Down
62 changes: 25 additions & 37 deletions lib/passes/TypeARTConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,58 +33,46 @@ TypeARTConfiguration::TypeARTConfiguration(std::unique_ptr<file::FileOptions> co
}

std::optional<OptionValue> TypeARTConfiguration::getValue(std::string_view opt_path) const {
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
LOG_DEBUG("Query " << source << " " << opt_path.data())
if (prioritize_commandline && options.valueSpecified(opt_path)) {
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
return options.getValue(opt_path);
if (prioritize_commandline) {
if (auto value = env_options_->getValue(opt_path)) {
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
if (auto value = commandline_options_->getValue(opt_path)) {
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
return std::nullopt;
};
if (auto value = get_value(*env_options_, "ENV")) {
return value;
}
if (auto value = get_value(*commandline_options_, "CL")) {
return value;
}
return configuration_options_->getValue(opt_path);
}

OptionValue TypeARTConfiguration::getValueOr(std::string_view opt_path, OptionValue alt) const {
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
LOG_DEBUG("Query " << source << " " << opt_path.data())
if (prioritize_commandline && options.valueSpecified(opt_path)) {
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
return options.getValueOr(opt_path, alt);
if (prioritize_commandline) {
if (auto value = env_options_->getValue(opt_path)) {
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
if (auto value = commandline_options_->getValue(opt_path)) {
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
return std::nullopt;
};
if (auto value = get_value(*env_options_, "ENV")) {
return value.value();
}
if (auto value = get_value(*commandline_options_, "CL")) {
return value.value();
}
return configuration_options_->getValueOr(opt_path, alt);
}

OptionValue TypeARTConfiguration::operator[](std::string_view opt_path) const {
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
LOG_DEBUG("Query " << source << " " << opt_path.data())
if (prioritize_commandline && options.valueSpecified(opt_path)) {
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
return options.operator[](opt_path);
if (prioritize_commandline) {
if (auto value = env_options_->getValue(opt_path)) {
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
if (auto value = commandline_options_->getValue(opt_path)) {
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
return value.value();
}
return std::nullopt;
};
if (auto value = get_value(*env_options_, "ENV")) {
return value.value();
}
if (auto value = get_value(*commandline_options_, "CL")) {
return value.value();
}
auto result = configuration_options_->operator[](opt_path);
LOG_DEBUG("Query file " << static_cast<std::string>(result))
LOG_DEBUG("Take File " << opt_path << "=" << (std::string(result)));
return result;
}

Expand Down
56 changes: 41 additions & 15 deletions lib/passes/TypeARTPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#include "configuration/Configuration.h"
#include "configuration/EnvironmentConfiguration.h"
#include "configuration/FileConfiguration.h"
#include "configuration/PassBuilderUtil.h"
#include "configuration/PassConfiguration.h"
#include "configuration/TypeARTOptions.h"
#include "instrumentation/MemOpArgCollector.h"
#include "instrumentation/MemOpInstrumentation.h"
#include "instrumentation/TypeARTFunctions.h"
Expand All @@ -41,6 +44,7 @@

#include <cassert>
#include <cstddef>
#include <llvm/Support/Error.h>
#include <optional>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -84,6 +88,7 @@ std::optional<std::string> get_configuration_file_path() {
}

class TypeArtPass : public llvm::PassInfoMixin<TypeArtPass> {
std::optional<config::TypeARTConfigOptions> pass_opts{std::nullopt};
std::unique_ptr<config::Configuration> pass_config;

struct TypeArtFunc {
Expand All @@ -109,20 +114,26 @@ class TypeArtPass : public llvm::PassInfoMixin<TypeArtPass> {
std::unique_ptr<InstrumentationContext> instrumentation_context;

public:
TypeArtPass() = default;
explicit TypeArtPass(config::TypeARTConfigOptions opts) : pass_opts(opts) {
// LOG_INFO("Created with \n" << opts)
}

bool doInitialization(Module& m) {
auto config_file_path = get_configuration_file_path();

const auto init = config_file_path.has_value()
? config::TypeARTConfigInit{config_file_path.value()}
: config::TypeARTConfigInit{{}, config::TypeARTConfigInit::FileConfigurationMode::Empty};
auto typeart_config = config::make_typeart_configuration(init);
const auto init = config_file_path.has_value()
? config::TypeARTConfigInit{config_file_path.value()}
: config::TypeARTConfigInit{{}, config::TypeARTConfigInit::FileConfigurationMode::Empty};

auto typeart_config = [&](const auto& init) {
if (init.mode == config::TypeARTConfigInit::FileConfigurationMode::Empty) {
return config::make_typeart_configuration_from_opts(pass_opts.value_or(config::TypeARTConfigOptions{}));
}
return config::make_typeart_configuration(init);
}(init);

if (typeart_config) {
// {
// std::string typeart_conf_str;
// llvm::raw_string_ostream conf_out_stream{typeart_conf_str};
// typeart_config->get()->emitTypeartFileConfiguration(conf_out_stream);
// LOG_INFO("Emitting TypeART file content\n" << conf_out_stream.str())
// }
LOG_INFO("Emitting TypeART configuration content\n" << typeart_config.get()->getOptions())
pass_config = std::move(*typeart_config);
} else {
Expand Down Expand Up @@ -214,8 +225,9 @@ class TypeArtPass : public llvm::PassInfoMixin<TypeArtPass> {
meminst_finder->printStats(out);

const auto get_ta_mode = [&]() {
const bool heap = (*pass_config)[config::ConfigStdArgs::heap];
const bool stack = (*pass_config)[config::ConfigStdArgs::stack];
const bool heap = (*pass_config)[config::ConfigStdArgs::heap];
const bool stack = (*pass_config)[config::ConfigStdArgs::stack];
const bool global = (*pass_config)[config::ConfigStdArgs::global];

if (heap) {
if (stack) {
Expand All @@ -228,7 +240,13 @@ class TypeArtPass : public llvm::PassInfoMixin<TypeArtPass> {
return " [Stack]";
}

llvm_unreachable("Did not find heap or stack, or combination thereof!");
if (global) {
return " [Global]";
}

LOG_ERROR("Did not find heap or stack, or combination thereof!");
assert((heap || stack || global) && "Needs stack, heap, global or combination thereof");
return " [Unknown]";
};

Table stats("TypeArtPass");
Expand Down Expand Up @@ -363,13 +381,21 @@ bool LegacyTypeArtPass::doFinalization(llvm::Module&) {
// New PM
//.....................
llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() {
using namespace llvm;
return {LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) {
pass_builder.registerPipelineParsingCallback(
[](StringRef name, ModulePassManager& module_pm, ArrayRef<PassBuilder::PipelineElement>) {
if (name == "typeart") {
module_pm.addPass(typeart::pass::TypeArtPass());
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;
});
}};
Expand Down
41 changes: 23 additions & 18 deletions lib/passes/analysis/MemInstFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "filter/Filter.h"
#include "filter/Matcher.h"
#include "filter/StdForwardFilter.h"
#include "support/ConfigurationBase.h"
#include "support/Logger.h"
#include "support/Table.h"
#include "support/TypeUtil.h"
Expand All @@ -43,6 +44,7 @@
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <string>
#include <utility>

using namespace llvm;
Expand All @@ -61,7 +63,7 @@ ALWAYS_ENABLED_STATISTIC(NumCallFilteredGlobals, "Number of filtered globals");

namespace typeart::analysis {

using MemInstFinderConfig = config::TypeARTConfigOptions;
using MemInstFinderConfig = config::Configuration;

namespace filter {
class CallFilter {
Expand All @@ -85,25 +87,27 @@ namespace filter {
namespace detail {
static std::unique_ptr<typeart::filter::Filter> make_filter(const MemInstFinderConfig& config) {
using namespace typeart::filter;
const auto filter_id = config.filter_config.implementation;
const std::string glob = config.filter_config.glob;
const bool filter = config[config::ConfigStdArgs::filter];
const FilterImplementation filter_id = config[config::ConfigStdArgs::filter_impl];
const std::string glob = config[config::ConfigStdArgs::filter_glob];

if (filter_id == FilterImplementation::none || !config.filter) {
if (filter_id == FilterImplementation::none || !filter) {
LOG_DEBUG("Return no-op filter")
return std::make_unique<NoOpFilter>();
} else if (filter_id == FilterImplementation::cg) {
if (config.filter_config.cg_file.empty()) {
const std::string cg_file = config[config::ConfigStdArgs::filter_cg_file];
if (cg_file.empty()) {
LOG_FATAL("CG File not set!");
std::exit(1);
}
LOG_DEBUG("Return CG filter with CG file @ " << config.filter_config.cg_file)
auto json_cg = JSONCG::getJSON(config.filter_config.cg_file);
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));
} else {
LOG_DEBUG("Return default filter")
auto matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(glob));
const auto deep_glob = config.filter_config.glob_deep;
const auto deep_glob = config[config::ConfigStdArgs::filter_glob_deep];
auto deep_matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(deep_glob));
return std::make_unique<StandardForwardFilter>(std::move(matcher), std::move(deep_matcher));
}
Expand Down Expand Up @@ -150,7 +154,7 @@ class MemInstFinderPass : public MemInstFinder {
MemOpVisitor mOpsCollector;
filter::CallFilter filter;
llvm::DenseMap<const llvm::Function*, FunctionData> functionMap;
MemInstFinderConfig config;
const MemInstFinderConfig& config;

public:
explicit MemInstFinderPass(const MemInstFinderConfig&);
Expand All @@ -167,14 +171,14 @@ class MemInstFinderPass : public MemInstFinder {
};

MemInstFinderPass::MemInstFinderPass(const MemInstFinderConfig& conf_)
: mOpsCollector(conf_.stack, conf_.heap), filter(conf_), config(conf_) {
: mOpsCollector(conf_), filter(conf_), config(conf_) {
}

bool MemInstFinderPass::runOnModule(Module& module) {
mOpsCollector.collectGlobals(module);
auto& globals = mOpsCollector.globals;
NumDetectedGlobals += globals.size();
if (config.analysis_config.filter_global) {
if (config[config::ConfigStdArgs::analysis_filter_global]) {
globals.erase(llvm::remove_if(
globals,
[&](const auto gdata) { // NOLINT
Expand Down Expand Up @@ -295,7 +299,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {

NumDetectedAllocs += mOpsCollector.allocas.size();

if (config.analysis_config.filter_alloca_non_array) {
if (config[config::ConfigStdArgs::analysis_filter_alloca_non_array]) {
auto& allocs = mOpsCollector.allocas;
allocs.erase(llvm::remove_if(allocs,
[&](const auto& data) {
Expand All @@ -308,7 +312,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
allocs.end());
}

if (config.analysis_config.filter_heap_alloc) {
if (config[config::ConfigStdArgs::analysis_filter_heap_alloc]) {
auto& allocs = mOpsCollector.allocas;
auto& mallocs = mOpsCollector.mallocs;

Expand Down Expand Up @@ -344,7 +348,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
allocs.end());
}

if (config.analysis_config.filter_pointer_alloc) {
if (config[config::ConfigStdArgs::analysis_filter_pointer_alloc]) {
auto& allocs = mOpsCollector.allocas;
allocs.erase(llvm::remove_if(allocs,
[&](const auto& data) {
Expand All @@ -359,7 +363,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
}

// if (config.filter.useCallFilter) {
if (config.filter) {
if (config[config::ConfigStdArgs::filter]) {
auto& allocs = mOpsCollector.allocas;
allocs.erase(llvm::remove_if(allocs,
[&](const auto& data) {
Expand Down Expand Up @@ -414,7 +418,8 @@ void MemInstFinderPass::printStats(llvm::raw_ostream& out) const {
Table stats("MemInstFinderPass");
stats.wrap_header = true;
stats.wrap_length = true;
stats.put(Row::make("Filter string", config.filter_config.glob));
std::string glob = config[config::ConfigStdArgs::filter_glob];
stats.put(Row::make("Filter string", glob));
stats.put(Row::make_row("> Heap Memory"));
stats.put(Row::make("Heap alloc", NumDetectedHeap.getValue()));
stats.put(Row::make("Heap call filtered %", call_filter_heap_p));
Expand Down Expand Up @@ -449,8 +454,8 @@ const GlobalDataList& MemInstFinderPass::getModuleGlobals() const {

std::unique_ptr<MemInstFinder> create_finder(const config::Configuration& config) {
LOG_DEBUG("Constructing MemInstFinder")
const auto meminst_conf = config::helper::config_to_options(config);
return std::make_unique<MemInstFinderPass>(meminst_conf);
// const auto meminst_conf = config::helper::config_to_options(config);
return std::make_unique<MemInstFinderPass>(config);
}

} // namespace typeart::analysis
5 changes: 5 additions & 0 deletions lib/passes/analysis/MemOpVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "analysis/MemOpData.h"
#include "compat/CallSite.h"
#include "configuration/Configuration.h"
#include "support/ConfigurationBase.h"
#include "support/Error.h"
#include "support/Logger.h"
#include "support/TypeUtil.h"
Expand Down Expand Up @@ -48,6 +50,9 @@ using namespace llvm;
MemOpVisitor::MemOpVisitor() : MemOpVisitor(true, true) {
}

MemOpVisitor::MemOpVisitor(const config::Configuration& config)
: MemOpVisitor(config[config::ConfigStdArgs::stack], config[config::ConfigStdArgs::heap]) {
}
MemOpVisitor::MemOpVisitor(bool collect_allocas, bool collect_heap)
: collect_allocas(collect_allocas), collect_heap(collect_heap) {
}
Expand Down
2 changes: 2 additions & 0 deletions lib/passes/analysis/MemOpVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LIB_MEMOPVISITOR_H_

#include "MemOpData.h"
#include "configuration/Configuration.h"

#include "llvm/IR/InstVisitor.h"

Expand Down Expand Up @@ -41,6 +42,7 @@ struct MemOpVisitor : public llvm::InstVisitor<MemOpVisitor> {

public:
MemOpVisitor();
explicit MemOpVisitor(const config::Configuration& config);
MemOpVisitor(bool collect_allocas, bool collect_heap);
void collect(llvm::Function& function);
void collectGlobals(llvm::Module& module);
Expand Down
Loading