Skip to content

Commit

Permalink
mir: replace custom_target string command with find_program call
Browse files Browse the repository at this point in the history
This is a pass that can be run once, in the early phase, to replace
cases where the first argument to `custom_target` is a string, not a
`file()`, `find_program()`, or `executable()`, and transform it into a
`find_program()` call.

Fixes: #86
  • Loading branch information
dcbaker committed Oct 16, 2024
1 parent f559607 commit a4ab157
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 13 deletions.
1 change: 0 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Checks: 'clang-diagnostic-*,clang-analyzer-*,bugprone-*,performance-faster-string-find,performance-unnecessary-value-param,modernize-raw-string-literal,modernize-pass-by-value,modernize-loop-convert,modernize-use-nullptr,modernize-use-using,readability-redundant-member-init,readability-const-return-type,readability-else-after-return,readability-container-size-empty,readability-redundant-string-init,readability-use-anyofallof,readability-redundant-smartptr-get'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
User: dylan
CheckOptions:
Expand Down
1 change: 1 addition & 0 deletions src/mir/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void lower(BasicBlock & block, State::Persistant & pstate) {
return Passes::machine_lower(b, pstate.machines) ||
Passes::insert_compilers(b, pstate.toolchains);
},
Passes::custom_target_program_replacement,
Passes::GlobalValueNumbering{},
});

Expand Down
24 changes: 13 additions & 11 deletions src/mir/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ libmir = static_library(
'passes/compilers.cpp',
'passes/constant_folding.cpp',
'passes/constant_propogation.cpp',
'passes/custom_target_program_replacement.cpp',
'passes/dead_code.cpp',
'passes/dependency_objects.cpp',
'passes/flatten.cpp',
Expand All @@ -28,26 +29,26 @@ libmir = static_library(
'passes/walkers.cpp',
locations_hpp,
],
include_directories : inc_frontend,
dependencies : [idep_util, idep_meson, dependency('threads')],
include_directories: inc_frontend,
dependencies: [idep_util, idep_meson, dependency('threads')],
)

inc_mir = include_directories('.')

idep_mir = declare_dependency(
link_with : libmir,
include_directories : inc_mir,
dependencies : [idep_meson],
link_with: libmir,
include_directories: inc_mir,
dependencies: [idep_meson],
)

test(
'ast_to_mir_test',
executable(
'ast_to_mir_test',
['ast_to_mir_test.cpp', locations_hpp],
dependencies : [idep_frontend, idep_mir, dep_gtest],
dependencies: [idep_frontend, idep_mir, dep_gtest],
),
protocol : 'gtest',
protocol: 'gtest',
)

test(
Expand All @@ -58,9 +59,9 @@ test(
'mir_tests.cpp',
locations_hpp,
],
dependencies : [idep_frontend, idep_mir, dep_gtest],
dependencies: [idep_frontend, idep_mir, dep_gtest],
),
protocol : 'gtest',
protocol: 'gtest',
)

test(
Expand All @@ -71,6 +72,7 @@ test(
'passes/tests/branch_pruning_test.cpp',
'passes/tests/const_folding_test.cpp',
'passes/tests/constant_propogation_test.cpp',
'passes/tests/custom_target_program_replacement_test.cpp',
'passes/tests/dead_code_test.cpp',
'passes/tests/fixup_phis_test.cpp',
'passes/tests/flatten_test.cpp',
Expand All @@ -85,7 +87,7 @@ test(
'passes/tests/walker_tests.cpp',
locations_hpp,
],
dependencies : [idep_frontend, idep_mir, idep_util, dep_gtest],
dependencies: [idep_frontend, idep_mir, idep_util, dep_gtest],
),
protocol : 'gtest',
protocol: 'gtest',
)
6 changes: 6 additions & 0 deletions src/mir/passes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ bool insert_compilers(BasicBlock &,
MIR::Toolchain::Language,
MIR::Machines::PerMachine<std::shared_ptr<MIR::Toolchain::Toolchain>>> &);

/**
* Find string arguments to custom_target's program space (intput[0]), and
* replace it with a call to `find_program()`
*/
bool custom_target_program_replacement(BasicBlock &);

/**
* Lowering for free functions
*
Expand Down
58 changes: 58 additions & 0 deletions src/mir/passes/custom_target_program_replacement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright © 2024 Intel Corporation

#include "argument_extractors.hpp"
#include "passes.hpp"
#include "private.hpp"

namespace MIR::Passes {

namespace {

bool program_replacement_impl(Instruction & obj) {
if (!std::holds_alternative<MIR::FunctionCall>(*obj.obj_ptr)) {
return false;
}

auto & fc = std::get<MIR::FunctionCall>(*obj.obj_ptr);
if (fc.name != "custom_target") {
return false;
}

const auto & cmd_obj_v =
extract_keyword_argument_v<MIR::Array, MIR::String>(fc.kw_args, "command");
// TODO: should this be an error?
if (std::holds_alternative<std::monostate>(cmd_obj_v)) {
return false;
}

if (std::holds_alternative<MIR::Array>(cmd_obj_v)) {
auto commands = std::get<MIR::Array>(cmd_obj_v).value;
// TODO: should this be an error?
if (commands.empty()) {
return false;
}
const Instruction & cmd = commands.at(0);
if (std::holds_alternative<MIR::String>(*cmd.obj_ptr)) {
auto s = std::get<MIR::String>(*cmd.obj_ptr);
MIR::FunctionCall fp{"find_program", {std::move(s)}, fc.source_dir};
commands[0] = std::move(fp);
fc.kw_args["command"] = Array{std::move(commands)};
}
} else if (std::holds_alternative<MIR::String>(cmd_obj_v)) {
auto s = std::get<MIR::String>(cmd_obj_v);
MIR::FunctionCall fp{"find_program", {std::move(s)}, fc.source_dir};
fc.kw_args["command"] = Array{{std::move(fp)}};
} else {
return false;
}
return true;
}

} // namespace

bool custom_target_program_replacement(BasicBlock & block) {
return instruction_walker(block, {program_replacement_impl});
}

} // namespace MIR::Passes
65 changes: 65 additions & 0 deletions src/mir/passes/tests/custom_target_program_replacement_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright © 2024 Intel Corporation

#include "passes.hpp"
#include "passes/argument_extractors.hpp"
#include "passes/private.hpp"
#include "test_utils.hpp"

#include <gtest/gtest.h>

TEST(custom_target_program_replacement, string) {
auto irlist = lower(R"EOF(
x = custom_target('name', command : 'foo.py')
)EOF");

MIR::Passes::block_walker(irlist, {MIR::Passes::custom_target_program_replacement});

ASSERT_EQ(irlist.instructions.size(), 1);

const auto & fc_obj = irlist.instructions.front();
const auto & fc = std::get<MIR::FunctionCall>(*fc_obj.obj_ptr);

const auto & commands_o =
MIR::Passes::extract_keyword_argument<MIR::Array>(fc.kw_args, "command");
ASSERT_TRUE(commands_o.has_value());

const auto & commands = commands_o.value();
ASSERT_EQ(commands.value.size(), 1);

const auto & cmd0 = std::get<MIR::FunctionCall>(*commands.value.at(0).obj_ptr);
EXPECT_EQ(cmd0.name, "find_program");

ASSERT_EQ(cmd0.pos_args.size(), 1);
const auto & arg_o = MIR::Passes::extract_positional_argument<MIR::String>(cmd0.pos_args.at(0));
ASSERT_TRUE(arg_o.has_value());
ASSERT_EQ(arg_o.value().value, "foo.py");
}

TEST(custom_target_program_replacement, array) {
auto irlist = lower(R"EOF(
x = custom_target('name', command : ['foo.py', '@INPUT@', '@OUTPUT@'])
)EOF");

MIR::Passes::block_walker(irlist, {MIR::Passes::custom_target_program_replacement});

ASSERT_EQ(irlist.instructions.size(), 1);

const auto & fc_obj = irlist.instructions.front();
const auto & fc = std::get<MIR::FunctionCall>(*fc_obj.obj_ptr);

const auto & commands_o =
MIR::Passes::extract_keyword_argument<MIR::Array>(fc.kw_args, "command");
ASSERT_TRUE(commands_o.has_value());

const auto & commands = commands_o.value();
ASSERT_EQ(commands.value.size(), 3);

const auto & cmd0 = std::get<MIR::FunctionCall>(*commands.value.at(0).obj_ptr);
EXPECT_EQ(cmd0.name, "find_program");

ASSERT_EQ(cmd0.pos_args.size(), 1);
const auto & arg_o = MIR::Passes::extract_positional_argument<MIR::String>(cmd0.pos_args.at(0));
ASSERT_TRUE(arg_o.has_value());
ASSERT_EQ(arg_o.value().value, "foo.py");
}
2 changes: 1 addition & 1 deletion src/mir/passes/tests/lower_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ TEST(lower, after_files) {
custom_target(
'gen',
output : 'gen.c',
command : ['prog', files('foo'), '@OUTPUT@']
command : ['cp', files('foo'), '@OUTPUT@']
)
)EOF");
MIR::State::Persistant pstate{src_root, build_root};
Expand Down

0 comments on commit a4ab157

Please sign in to comment.