Skip to content

Commit

Permalink
mir: implement lowering for compiler.get_id()
Browse files Browse the repository at this point in the history
Fixes: #155
  • Loading branch information
dcbaker committed Nov 14, 2024
1 parent a67cb9b commit ec17dc1
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 30 deletions.
22 changes: 11 additions & 11 deletions src/mir/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,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 @@ -60,9 +60,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 @@ -88,7 +88,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',
)
13 changes: 0 additions & 13 deletions src/mir/mir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,6 @@ CFG::CFG(std::shared_ptr<CFGNode> n) : root{n} {};

Compiler::Compiler(std::shared_ptr<MIR::Toolchain::Toolchain> tc) : toolchain{std::move(tc)} {};

Instruction Compiler::get_id(const std::vector<Instruction> & args,
const std::unordered_map<std::string, Instruction> & kwargs) const {
if (!args.empty()) {
throw Util::Exceptions::InvalidArguments(
"compiler.get_id(): takes no positional arguments");
}
if (!kwargs.empty()) {
throw Util::Exceptions::InvalidArguments("compiler.get_id(): takes no keyword arguments");
}

return std::make_shared<Object>(String{toolchain->compiler->id()});
};

std::string Compiler::print() const {
return "Compiler { language = " + toolchain->compiler->language() +
"; id = " + toolchain->compiler->id() + " }";
Expand Down
3 changes: 0 additions & 3 deletions src/mir/mir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,6 @@ class Compiler {

const std::shared_ptr<MIR::Toolchain::Toolchain> toolchain;

Instruction get_id(const std::vector<Instruction> &,
const std::unordered_map<std::string, Instruction> &) const;

/// Print a human readable version of this
std::string print() const;
};
Expand Down
5 changes: 5 additions & 0 deletions src/mir/passes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ std::optional<Instruction> lower_string_objects(const Instruction & inst,
std::optional<Instruction> lower_dependency_objects(const Instruction & inst,
const State::Persistant & pstate);

/// @brief Lower compiler methods
/// @param inst the instruction to be evaluated
/// @return a new instruction of it can be lowered, otherwise nullopt
std::optional<Instruction> lower_compiler_methods(const Instruction & inst);

/// Delete any code that has become unreachable
bool delete_unreachable(std::shared_ptr<CFGNode> block);

Expand Down
42 changes: 42 additions & 0 deletions src/mir/passes/compilers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ using ToolchainMap =
std::unordered_map<MIR::Toolchain::Language,
MIR::Machines::PerMachine<std::shared_ptr<MIR::Toolchain::Toolchain>>>;

std::optional<Instruction> lower_get_id_method(const FunctionCall & func) {
if (!func.pos_args.empty()) {
throw Util::Exceptions::InvalidArguments(
"compiler.get_id(): takes no positional arguments");
}
if (!func.kw_args.empty()) {
throw Util::Exceptions::InvalidArguments("compiler.get_id(): takes no keyword arguments");
}

const auto & comp = std::get<Compiler>(func.holder.object());

return String{comp.toolchain->compiler->id()};
}

} // namespace

std::optional<Instruction> insert_compilers(const Instruction & obj, const ToolchainMap & tc) {
Expand Down Expand Up @@ -70,4 +84,32 @@ std::optional<Instruction> insert_compilers(const Instruction & obj, const Toolc
}
}

std::optional<Instruction> lower_compiler_methods(const Instruction & obj) {
if (!std::holds_alternative<FunctionCall>(*obj.obj_ptr)) {
return std::nullopt;
}
const auto & f = std::get<FunctionCall>(*obj.obj_ptr);

if (!std::holds_alternative<Compiler>(f.holder.object())) {
return std::nullopt;
}

if (!all_args_reduced(f.pos_args, f.kw_args)) {
return std::nullopt;
}

std::optional<Instruction> i = std::nullopt;
if (f.name == "get_id") {
i = lower_get_id_method(f);
}

if (i) {
i.value().var = obj.var;
return i;
}

// XXX: Shouldn't really be able to get here...
return std::nullopt;
}

} // namespace MIR::Passes
2 changes: 1 addition & 1 deletion src/mir/passes/free_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ void lower_project(std::shared_ptr<CFGNode> block, State::Persistant & pstate) {

if (!std::holds_alternative<FunctionCall>(*obj.obj_ptr)) {
throw Util::Exceptions::MesonException{
"First non-whitespace, non-lower_projectcomment must be a call to project()"};
"First non-whitespace, non-comment must be a call to project()"};
}
const auto & f = std::get<FunctionCall>(*obj.obj_ptr);

Expand Down
36 changes: 34 additions & 2 deletions src/mir/passes/tests/insert_compiler_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ bool wrapper(std::shared_ptr<MIR::CFGNode> & node, const ToolchainMap & tc) {
}});
}

} // namespace
bool method_wrapper(std::shared_ptr<MIR::CFGNode> & node) {
return MIR::Passes::instruction_walker(*node, {MIR::Passes::lower_compiler_methods});
}

TEST(insert_compiler, simple) {
ToolchainMap make_toolchain() {
const std::vector<std::string> init{"null"};
auto comp = std::make_unique<MIR::Toolchain::Compiler::CPP::Clang>(init);
auto tc = std::make_shared<MIR::Toolchain::Toolchain>(
Expand All @@ -40,7 +42,13 @@ TEST(insert_compiler, simple) {
ToolchainMap tc_map{};
tc_map[MIR::Toolchain::Language::CPP] =
MIR::Machines::PerMachine<std::shared_ptr<MIR::Toolchain::Toolchain>>{tc};
return tc_map;
}

} // namespace

TEST(insert_compiler, simple) {
ToolchainMap tc_map = make_toolchain();
auto irlist = lower("x = meson.get_compiler('cpp')");
bool progress = wrapper(irlist, tc_map);
ASSERT_TRUE(progress);
Expand All @@ -65,3 +73,27 @@ TEST(insert_compiler, unknown_language) {
ASSERT_EQ(m, "No compiler for language");
}
}

TEST(compiler_methods, get_id) {
auto irlist = lower("x = meson.get_compiler('cpp').get_id()");

ToolchainMap tc_map = make_toolchain();
MIR::Passes::Printer printer{};
printer(irlist);
printer.increment();
bool progress = wrapper(irlist, tc_map);
printer(irlist);
printer.increment();
ASSERT_TRUE(progress);

progress = method_wrapper(irlist);
printer(irlist);
ASSERT_TRUE(progress);
ASSERT_EQ(irlist->block->instructions.size(), 1);

const auto & e = irlist->block->instructions.front();
ASSERT_TRUE(std::holds_alternative<MIR::String>(*e.obj_ptr));

const auto & s = std::get<MIR::String>(*e.obj_ptr);
ASSERT_EQ(s.value, "clang");
}

0 comments on commit ec17dc1

Please sign in to comment.