Skip to content

Commit 8ea2e79

Browse files
authored
Pass configuration parser (#152)
1 parent bddfb53 commit 8ea2e79

21 files changed

+501
-143
lines changed

demo/02_broken_struct_example.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#define COUNT 5
77

88
// Comment out for heap allocation
9-
//#define USE_STACK
9+
// #define USE_STACK
1010

1111
struct particle {
1212
int id;

lib/passes/Commandline.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ CommandLineOptions::CommandLineOptions() {
238238

239239
std::optional<typeart::config::OptionValue> CommandLineOptions::getValue(std::string_view opt_path) const {
240240
auto key = llvm::StringRef(opt_path.data());
241-
if (mapping_.count(key) != 0U) {
241+
if (occurence_mapping_.lookup(key)) {
242242
return mapping_.lookup(key);
243243
}
244244
return {};

lib/passes/TypeARTConfiguration.cpp

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,58 +33,46 @@ TypeARTConfiguration::TypeARTConfiguration(std::unique_ptr<file::FileOptions> co
3333
}
3434

3535
std::optional<OptionValue> TypeARTConfiguration::getValue(std::string_view opt_path) const {
36-
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
37-
LOG_DEBUG("Query " << source << " " << opt_path.data())
38-
if (prioritize_commandline && options.valueSpecified(opt_path)) {
39-
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
40-
return options.getValue(opt_path);
36+
if (prioritize_commandline) {
37+
if (auto value = env_options_->getValue(opt_path)) {
38+
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
39+
return value.value();
40+
}
41+
if (auto value = commandline_options_->getValue(opt_path)) {
42+
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
43+
return value.value();
4144
}
42-
return std::nullopt;
43-
};
44-
if (auto value = get_value(*env_options_, "ENV")) {
45-
return value;
46-
}
47-
if (auto value = get_value(*commandline_options_, "CL")) {
48-
return value;
4945
}
5046
return configuration_options_->getValue(opt_path);
5147
}
5248

5349
OptionValue TypeARTConfiguration::getValueOr(std::string_view opt_path, OptionValue alt) const {
54-
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
55-
LOG_DEBUG("Query " << source << " " << opt_path.data())
56-
if (prioritize_commandline && options.valueSpecified(opt_path)) {
57-
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
58-
return options.getValueOr(opt_path, alt);
50+
if (prioritize_commandline) {
51+
if (auto value = env_options_->getValue(opt_path)) {
52+
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
53+
return value.value();
54+
}
55+
if (auto value = commandline_options_->getValue(opt_path)) {
56+
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
57+
return value.value();
5958
}
60-
return std::nullopt;
61-
};
62-
if (auto value = get_value(*env_options_, "ENV")) {
63-
return value.value();
64-
}
65-
if (auto value = get_value(*commandline_options_, "CL")) {
66-
return value.value();
6759
}
6860
return configuration_options_->getValueOr(opt_path, alt);
6961
}
7062

7163
OptionValue TypeARTConfiguration::operator[](std::string_view opt_path) const {
72-
auto get_value = [&](const auto& options, const char* source) -> std::optional<OptionValue> {
73-
LOG_DEBUG("Query " << source << " " << opt_path.data())
74-
if (prioritize_commandline && options.valueSpecified(opt_path)) {
75-
LOG_DEBUG("Take " << source << " arg for " << opt_path.data());
76-
return options.operator[](opt_path);
64+
if (prioritize_commandline) {
65+
if (auto value = env_options_->getValue(opt_path)) {
66+
LOG_DEBUG("Take ENV " << opt_path << "=" << (std::string(value.value())));
67+
return value.value();
68+
}
69+
if (auto value = commandline_options_->getValue(opt_path)) {
70+
LOG_DEBUG("Take CL " << opt_path << "=" << (std::string(value.value())));
71+
return value.value();
7772
}
78-
return std::nullopt;
79-
};
80-
if (auto value = get_value(*env_options_, "ENV")) {
81-
return value.value();
82-
}
83-
if (auto value = get_value(*commandline_options_, "CL")) {
84-
return value.value();
8573
}
8674
auto result = configuration_options_->operator[](opt_path);
87-
LOG_DEBUG("Query file " << static_cast<std::string>(result))
75+
LOG_DEBUG("Take File " << opt_path << "=" << (std::string(result)));
8876
return result;
8977
}
9078

lib/passes/TypeARTPass.cpp

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include "configuration/Configuration.h"
1717
#include "configuration/EnvironmentConfiguration.h"
1818
#include "configuration/FileConfiguration.h"
19+
#include "configuration/PassBuilderUtil.h"
20+
#include "configuration/PassConfiguration.h"
21+
#include "configuration/TypeARTOptions.h"
1922
#include "instrumentation/MemOpArgCollector.h"
2023
#include "instrumentation/MemOpInstrumentation.h"
2124
#include "instrumentation/TypeARTFunctions.h"
@@ -41,6 +44,7 @@
4144

4245
#include <cassert>
4346
#include <cstddef>
47+
#include <llvm/Support/Error.h>
4448
#include <optional>
4549
#include <sstream>
4650
#include <string>
@@ -84,6 +88,7 @@ std::optional<std::string> get_configuration_file_path() {
8488
}
8589

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

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

111116
public:
117+
TypeArtPass() = default;
118+
explicit TypeArtPass(config::TypeARTConfigOptions opts) : pass_opts(opts) {
119+
// LOG_INFO("Created with \n" << opts)
120+
}
121+
112122
bool doInitialization(Module& m) {
113123
auto config_file_path = get_configuration_file_path();
114124

115-
const auto init = config_file_path.has_value()
116-
? config::TypeARTConfigInit{config_file_path.value()}
117-
: config::TypeARTConfigInit{{}, config::TypeARTConfigInit::FileConfigurationMode::Empty};
118-
auto typeart_config = config::make_typeart_configuration(init);
125+
const auto init = config_file_path.has_value()
126+
? config::TypeARTConfigInit{config_file_path.value()}
127+
: config::TypeARTConfigInit{{}, config::TypeARTConfigInit::FileConfigurationMode::Empty};
128+
129+
auto typeart_config = [&](const auto& init) {
130+
if (init.mode == config::TypeARTConfigInit::FileConfigurationMode::Empty) {
131+
return config::make_typeart_configuration_from_opts(pass_opts.value_or(config::TypeARTConfigOptions{}));
132+
}
133+
return config::make_typeart_configuration(init);
134+
}(init);
135+
119136
if (typeart_config) {
120-
// {
121-
// std::string typeart_conf_str;
122-
// llvm::raw_string_ostream conf_out_stream{typeart_conf_str};
123-
// typeart_config->get()->emitTypeartFileConfiguration(conf_out_stream);
124-
// LOG_INFO("Emitting TypeART file content\n" << conf_out_stream.str())
125-
// }
126137
LOG_INFO("Emitting TypeART configuration content\n" << typeart_config.get()->getOptions())
127138
pass_config = std::move(*typeart_config);
128139
} else {
@@ -214,8 +225,9 @@ class TypeArtPass : public llvm::PassInfoMixin<TypeArtPass> {
214225
meminst_finder->printStats(out);
215226

216227
const auto get_ta_mode = [&]() {
217-
const bool heap = (*pass_config)[config::ConfigStdArgs::heap];
218-
const bool stack = (*pass_config)[config::ConfigStdArgs::stack];
228+
const bool heap = (*pass_config)[config::ConfigStdArgs::heap];
229+
const bool stack = (*pass_config)[config::ConfigStdArgs::stack];
230+
const bool global = (*pass_config)[config::ConfigStdArgs::global];
219231

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

231-
llvm_unreachable("Did not find heap or stack, or combination thereof!");
243+
if (global) {
244+
return " [Global]";
245+
}
246+
247+
LOG_ERROR("Did not find heap or stack, or combination thereof!");
248+
assert((heap || stack || global) && "Needs stack, heap, global or combination thereof");
249+
return " [Unknown]";
232250
};
233251

234252
Table stats("TypeArtPass");
@@ -363,13 +381,21 @@ bool LegacyTypeArtPass::doFinalization(llvm::Module&) {
363381
// New PM
364382
//.....................
365383
llvm::PassPluginLibraryInfo getTypeartPassPluginInfo() {
384+
using namespace llvm;
366385
return {LLVM_PLUGIN_API_VERSION, "TypeART", LLVM_VERSION_STRING, [](PassBuilder& pass_builder) {
367386
pass_builder.registerPipelineParsingCallback(
368387
[](StringRef name, ModulePassManager& module_pm, ArrayRef<PassBuilder::PipelineElement>) {
369-
if (name == "typeart") {
370-
module_pm.addPass(typeart::pass::TypeArtPass());
388+
if (typeart::util::pass::checkParametrizedPassName(name, "typeart")) {
389+
auto parameters = typeart::util::pass::parsePassParameters(
390+
typeart::config::pass::parse_typeart_config, name, "typeart");
391+
if (!parameters) {
392+
LOG_FATAL("Error parsing params: " << parameters.takeError())
393+
return false;
394+
}
395+
module_pm.addPass(typeart::pass::TypeArtPass(parameters.get()));
371396
return true;
372397
}
398+
LOG_FATAL("Not a valid parametrized pass name: " << name)
373399
return false;
374400
});
375401
}};

lib/passes/analysis/MemInstFinder.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "filter/Filter.h"
2323
#include "filter/Matcher.h"
2424
#include "filter/StdForwardFilter.h"
25+
#include "support/ConfigurationBase.h"
2526
#include "support/Logger.h"
2627
#include "support/Table.h"
2728
#include "support/TypeUtil.h"
@@ -43,6 +44,7 @@
4344
#include <algorithm>
4445
#include <cstdlib>
4546
#include <sstream>
47+
#include <string>
4648
#include <utility>
4749

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

6264
namespace typeart::analysis {
6365

64-
using MemInstFinderConfig = config::TypeARTConfigOptions;
66+
using MemInstFinderConfig = config::Configuration;
6567

6668
namespace filter {
6769
class CallFilter {
@@ -85,25 +87,27 @@ namespace filter {
8587
namespace detail {
8688
static std::unique_ptr<typeart::filter::Filter> make_filter(const MemInstFinderConfig& config) {
8789
using namespace typeart::filter;
88-
const auto filter_id = config.filter_config.implementation;
89-
const std::string glob = config.filter_config.glob;
90+
const bool filter = config[config::ConfigStdArgs::filter];
91+
const FilterImplementation filter_id = config[config::ConfigStdArgs::filter_impl];
92+
const std::string glob = config[config::ConfigStdArgs::filter_glob];
9093

91-
if (filter_id == FilterImplementation::none || !config.filter) {
94+
if (filter_id == FilterImplementation::none || !filter) {
9295
LOG_DEBUG("Return no-op filter")
9396
return std::make_unique<NoOpFilter>();
9497
} else if (filter_id == FilterImplementation::cg) {
95-
if (config.filter_config.cg_file.empty()) {
98+
const std::string cg_file = config[config::ConfigStdArgs::filter_cg_file];
99+
if (cg_file.empty()) {
96100
LOG_FATAL("CG File not set!");
97101
std::exit(1);
98102
}
99-
LOG_DEBUG("Return CG filter with CG file @ " << config.filter_config.cg_file)
100-
auto json_cg = JSONCG::getJSON(config.filter_config.cg_file);
103+
LOG_DEBUG("Return CG filter with CG file @ " << cg_file)
104+
auto json_cg = JSONCG::getJSON(cg_file);
101105
auto matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(glob));
102106
return std::make_unique<CGForwardFilter>(glob, std::move(json_cg), std::move(matcher));
103107
} else {
104108
LOG_DEBUG("Return default filter")
105109
auto matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(glob));
106-
const auto deep_glob = config.filter_config.glob_deep;
110+
const auto deep_glob = config[config::ConfigStdArgs::filter_glob_deep];
107111
auto deep_matcher = std::make_unique<DefaultStringMatcher>(util::glob2regex(deep_glob));
108112
return std::make_unique<StandardForwardFilter>(std::move(matcher), std::move(deep_matcher));
109113
}
@@ -150,7 +154,7 @@ class MemInstFinderPass : public MemInstFinder {
150154
MemOpVisitor mOpsCollector;
151155
filter::CallFilter filter;
152156
llvm::DenseMap<const llvm::Function*, FunctionData> functionMap;
153-
MemInstFinderConfig config;
157+
const MemInstFinderConfig& config;
154158

155159
public:
156160
explicit MemInstFinderPass(const MemInstFinderConfig&);
@@ -167,14 +171,14 @@ class MemInstFinderPass : public MemInstFinder {
167171
};
168172

169173
MemInstFinderPass::MemInstFinderPass(const MemInstFinderConfig& conf_)
170-
: mOpsCollector(conf_.stack, conf_.heap), filter(conf_), config(conf_) {
174+
: mOpsCollector(conf_), filter(conf_), config(conf_) {
171175
}
172176

173177
bool MemInstFinderPass::runOnModule(Module& module) {
174178
mOpsCollector.collectGlobals(module);
175179
auto& globals = mOpsCollector.globals;
176180
NumDetectedGlobals += globals.size();
177-
if (config.analysis_config.filter_global) {
181+
if (config[config::ConfigStdArgs::analysis_filter_global]) {
178182
globals.erase(llvm::remove_if(
179183
globals,
180184
[&](const auto gdata) { // NOLINT
@@ -295,7 +299,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
295299

296300
NumDetectedAllocs += mOpsCollector.allocas.size();
297301

298-
if (config.analysis_config.filter_alloca_non_array) {
302+
if (config[config::ConfigStdArgs::analysis_filter_alloca_non_array]) {
299303
auto& allocs = mOpsCollector.allocas;
300304
allocs.erase(llvm::remove_if(allocs,
301305
[&](const auto& data) {
@@ -308,7 +312,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
308312
allocs.end());
309313
}
310314

311-
if (config.analysis_config.filter_heap_alloc) {
315+
if (config[config::ConfigStdArgs::analysis_filter_heap_alloc]) {
312316
auto& allocs = mOpsCollector.allocas;
313317
auto& mallocs = mOpsCollector.mallocs;
314318

@@ -344,7 +348,7 @@ bool MemInstFinderPass::runOnFunction(llvm::Function& function) {
344348
allocs.end());
345349
}
346350

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

361365
// if (config.filter.useCallFilter) {
362-
if (config.filter) {
366+
if (config[config::ConfigStdArgs::filter]) {
363367
auto& allocs = mOpsCollector.allocas;
364368
allocs.erase(llvm::remove_if(allocs,
365369
[&](const auto& data) {
@@ -414,7 +418,8 @@ void MemInstFinderPass::printStats(llvm::raw_ostream& out) const {
414418
Table stats("MemInstFinderPass");
415419
stats.wrap_header = true;
416420
stats.wrap_length = true;
417-
stats.put(Row::make("Filter string", config.filter_config.glob));
421+
std::string glob = config[config::ConfigStdArgs::filter_glob];
422+
stats.put(Row::make("Filter string", glob));
418423
stats.put(Row::make_row("> Heap Memory"));
419424
stats.put(Row::make("Heap alloc", NumDetectedHeap.getValue()));
420425
stats.put(Row::make("Heap call filtered %", call_filter_heap_p));
@@ -449,8 +454,8 @@ const GlobalDataList& MemInstFinderPass::getModuleGlobals() const {
449454

450455
std::unique_ptr<MemInstFinder> create_finder(const config::Configuration& config) {
451456
LOG_DEBUG("Constructing MemInstFinder")
452-
const auto meminst_conf = config::helper::config_to_options(config);
453-
return std::make_unique<MemInstFinderPass>(meminst_conf);
457+
// const auto meminst_conf = config::helper::config_to_options(config);
458+
return std::make_unique<MemInstFinderPass>(config);
454459
}
455460

456461
} // namespace typeart::analysis

lib/passes/analysis/MemOpVisitor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include "analysis/MemOpData.h"
1616
#include "compat/CallSite.h"
17+
#include "configuration/Configuration.h"
18+
#include "support/ConfigurationBase.h"
1719
#include "support/Error.h"
1820
#include "support/Logger.h"
1921
#include "support/TypeUtil.h"
@@ -48,6 +50,9 @@ using namespace llvm;
4850
MemOpVisitor::MemOpVisitor() : MemOpVisitor(true, true) {
4951
}
5052

53+
MemOpVisitor::MemOpVisitor(const config::Configuration& config)
54+
: MemOpVisitor(config[config::ConfigStdArgs::stack], config[config::ConfigStdArgs::heap]) {
55+
}
5156
MemOpVisitor::MemOpVisitor(bool collect_allocas, bool collect_heap)
5257
: collect_allocas(collect_allocas), collect_heap(collect_heap) {
5358
}

lib/passes/analysis/MemOpVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LIB_MEMOPVISITOR_H_
1515

1616
#include "MemOpData.h"
17+
#include "configuration/Configuration.h"
1718

1819
#include "llvm/IR/InstVisitor.h"
1920

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

4243
public:
4344
MemOpVisitor();
45+
explicit MemOpVisitor(const config::Configuration& config);
4446
MemOpVisitor(bool collect_allocas, bool collect_heap);
4547
void collect(llvm::Function& function);
4648
void collectGlobals(llvm::Module& module);

0 commit comments

Comments
 (0)