Skip to content

Commit

Permalink
Fix #2250 by using a consistent naming strategy. (#2251)
Browse files Browse the repository at this point in the history
Use the `module_name` string  to name files written by `modcc` consistently.

Fixes #2250
  • Loading branch information
thorstenhater authored Jan 19, 2024
1 parent 93fb291 commit 9f18a50
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 98 deletions.
180 changes: 85 additions & 95 deletions modcc/modcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@

#include <fmt/format.h>

using std::cout;
using std::cerr;
#include <filesystem>

namespace fs = std::filesystem;

// Options and option parsing:

int report_error(const std::string& message) {
cerr << red("error trace:\n") << message << "\n";
std::cerr << red("error trace:\n") << message << "\n";
return 1;
}

int report_ice(const std::string& message) {
cerr << red("internal compiler error:\n") << message << "\n"
<< "\nPlease report this error to the modcc developers.\n";
std::cerr << red("internal compiler error:\n") << message << "\n"
<< "\nPlease report this error to the modcc developers.\n";
return 1;
}

Expand Down Expand Up @@ -99,22 +100,19 @@ std::ostream& operator<<(std::ostream& out, const Options& opt) {
targets += " "+key_by_value(targetKindMap, t);
}

for (const auto& f: opt.modfiles) {
out << table_prefix{"file"} << f << line_end;
}
out << table_prefix{"output"} << (opt.outprefix.empty()? "-": opt.outprefix) << line_end <<
table_prefix{"verbose"} << noyes[opt.verbose] << line_end <<
table_prefix{"targets"} << targets << line_end <<
table_prefix{"analysis"} << noyes[opt.analysis] << line_end;
for (const auto& f: opt.modfiles) out << table_prefix{"file"} << f << line_end;
out << table_prefix{"output"} << (opt.outprefix.empty() ? "-" : opt.outprefix) << line_end
<< table_prefix{"verbose"} << noyes[opt.verbose] << line_end
<< table_prefix{"targets"} << targets << line_end
<< table_prefix{"analysis"} << noyes[opt.analysis] << line_end;
return out;
}

std::ostream& operator<<(std::ostream& out, const printer_options& popt) {
static const std::string line_end = cyan(" |") + "\n";

return out <<
table_prefix{"namespace"} << popt.cpp_namespace << line_end <<
table_prefix{"simd"} << popt.simd << line_end;
out << table_prefix{"namespace"} << popt.cpp_namespace << line_end
<< table_prefix{"simd"} << popt.simd << line_end;
return out;
}

std::istream& operator>> (std::istream& i, simd_spec& spec) {
Expand Down Expand Up @@ -146,8 +144,6 @@ const char* usage_str =
"<filenames> [Files to be compiled]\n";

int main(int argc, char **argv) {
using namespace to;

Options opt;
printer_options popt;
try {
Expand Down Expand Up @@ -188,99 +184,96 @@ int main(int argc, char **argv) {

if (!opt.catalogue.empty()) popt.cpp_namespace += "::" + opt.catalogue + "_catalogue";

std::vector<std::string> modules;
std::vector<std::pair<std::string, std::string>> modules;


for (const auto& modfile: opt.modfiles) {
auto outdir = fs::path(opt.outprefix);

for (const auto& input: opt.modfiles) {
auto modfile = fs::path(input);
try {
auto emit_header = [&opt](const char* h) {
if (opt.verbose) {
cout << green("[") << h << green("]") << "\n";
std::cout << green("[") << h << green("]") << "\n";
}
};

if (opt.verbose) {
static const std::string tableline = cyan("."+std::string(60, '-')+".")+"\n";
cout << tableline;
cout << opt;
cout << popt;
cout << tableline;
std::cout << tableline
<< opt
<< popt
<< tableline;
}

// Load module file and initialize Module object.
Module m(io::read_all(modfile), modfile);

if (m.empty()) {
return report_error("empty file: "+modfile);
}
if (m.empty()) return report_error(fmt::format("Input file is empty: {}", modfile.string()));

// Perform parsing and semantic analysis passes.

emit_header("parsing");
Parser p(m, false);
if (!p.parse()) {
// Parser::parse() writes its own errors to stderr.
return 1;
}
if (!p.parse()) return 1;

emit_header("semantic analysis");
m.semantic();
if (m.has_warning()) {
cerr << yellow("Warnings:\n");
cerr << m.warning_string() << "\n";
}
if (m.has_error()) {
return report_error(m.error_string());
std::cerr << yellow("Warnings:\n")
<< m.warning_string() << "\n";
}

// Generate backend-specific sources for each backend provided.
if (m.has_error()) return report_error(m.error_string());

// Generate backend-specific sources for each backend provided.
emit_header("code generation");

std::string prefix = m.module_name();
if (!opt.outprefix.empty()) {
if (opt.outprefix.back() != '/') opt.outprefix += "/";
prefix = opt.outprefix + prefix;
}
std::string mod = m.module_name();

bool have_cpu = opt.targets.find(targetKind::cpu) != opt.targets.end();
bool have_gpu = opt.targets.find(targetKind::gpu) != opt.targets.end();

io::write_all(build_info_header(m, popt, have_cpu, have_gpu), prefix+".hpp");
auto prefix = modfile.filename().replace_extension("").string();

io::write_all(build_info_header(m, popt, have_cpu, have_gpu), outdir / (mod + ".hpp"));
for (targetKind target: opt.targets) {
std::string outfile = prefix;
switch (target) {
case targetKind::gpu:
io::write_all(emit_gpu_cpp_source(m, popt), outfile+"_gpu.cpp");
io::write_all(emit_gpu_cu_source(m, popt), outfile+"_gpu.cu");
case targetKind::gpu: {
fs::path fn = outdir / (mod + "_gpu.cpp");
io::write_all(emit_gpu_cpp_source(m, popt), fn.string());
fn.replace_extension(".cu");
io::write_all(emit_gpu_cu_source(m, popt), fn.string());
break;
case targetKind::cpu:
io::write_all(emit_cpp_source(m, popt), outfile+"_cpu.cpp");
}
case targetKind::cpu: {
fs::path fn = outdir / (mod + "_cpu");
fn.replace_extension(".cpp");
io::write_all(emit_cpp_source(m, popt), fn.string());
break;
}
}
}

// Optional analysis report.

if (opt.analysis) {
cout << green("performance analysis\n");
std::cout << green("performance analysis\n");
for (auto &symbol: m.symbols()) {
if (auto method = symbol.second->is_api_method()) {
cout << white("-------------------------\n");
cout << yellow("method " + method->name()) << "\n";
cout << white("-------------------------\n");

FlopVisitor flops;
method->accept(&flops);
cout << white("FLOPS\n") << flops.print() << "\n";

MemOpVisitor memops;
method->accept(&memops);
cout << white("MEMOPS\n") << memops.print() << "\n";

std::cout << white("-------------------------\n")
<< yellow("method " + method->name()) << "\n"
<< white("-------------------------\n")
<< white("FLOPS\n") << flops.print() << "\n"
<< white("MEMOPS\n") << memops.print() << "\n";
}
}
}

modules.push_back(m.module_name());
modules.push_back({mod, prefix});
}
catch (io::bulkio_error& e) {
return report_error(e.what());
Expand All @@ -297,45 +290,43 @@ int main(int argc, char **argv) {
}

if (!opt.catalogue.empty()) {
const auto prefix = std::regex_replace(popt.cpp_namespace, std::regex{"::"}, "_");
const auto ns = std::regex_replace(popt.cpp_namespace, std::regex{"::"}, "_");
{
std::ofstream out(opt.outprefix + opt.catalogue + "_catalogue.cpp");
std::ofstream out(outdir / (opt.catalogue + "_catalogue.cpp"));
out << "// Automatically generated by modcc\n"
"\n"
"#include <arbor/mechanism_abi.h>\n"
"\n";
"\n"
"#include <arbor/mechanism_abi.h>\n"
"\n";

for (const auto& mod: modules) {
out << fmt::format("#include \"{}.hpp\"\n", mod);
}
for (const auto& [mod, prefix]: modules) out << fmt::format("#include \"{}.hpp\"\n", mod);

out << "\n"
"#ifdef STANDALONE\n"
"extern \"C\" {\n"
" [[gnu::visibility(\"default\")]] const void* get_catalogue(int* n) {\n";
out << fmt::format(" *n = {0};\n"
"#ifdef STANDALONE\n"
"extern \"C\" {\n"
" [[gnu::visibility(\"default\")]] const void* get_catalogue(int* n) {\n"
<< fmt::format(" *n = {0};\n"
" static arb_mechanism cat[{0}] = {{\n",
opt.modfiles.size());
for (const auto& mod: modules) {
out << fmt::format(" make_{}_{}(),\n", prefix, mod);
for (const auto& [mod, prefix]: modules) {
out << fmt::format(" make_{}_{}(),\n", ns, mod);
}
out << " };\n"
" return (void*)cat;\n"
" }\n"
"}\n"
"\n"
"#else\n"
"\n"
"#include <arbor/mechanism.hpp>\n"
"#include <arbor/assert.hpp>\n"
"\n";
out << fmt::format("#include \"{0}_catalogue.hpp\"\n"
" return (void*)cat;\n"
" }\n"
"}\n"
"\n"
"#else\n"
"\n"
"#include <arbor/mechanism.hpp>\n"
"#include <arbor/assert.hpp>\n"
"\n"
<< fmt::format("#include \"{0}_catalogue.hpp\"\n"
"\n"
"namespace arb {{\n"
"mechanism_catalogue build_{0}_catalogue() {{\n"
" mechanism_catalogue cat;\n",
opt.catalogue);
for (const auto& mod: modules) {
for (const auto& [mod, prefix]: modules) {
out << fmt::format(" {{\n"
" auto mech = make_{}_{}();\n"
" auto ty = mech.type();\n"
Expand All @@ -347,22 +338,21 @@ int main(int argc, char **argv) {
" if (ic) cat.register_implementation(nm, std::make_unique<arb::mechanism>(ty, *ic));\n"
" if (ig) cat.register_implementation(nm, std::make_unique<arb::mechanism>(ty, *ig));\n"
" }}\n",
prefix, mod);
ns, mod);
}

out << " return cat;\n"
"}\n"
"\n";
out << fmt::format("ARB_ARBOR_API const mechanism_catalogue& global_{0}_catalogue() {{\n"
"}\n"
"\n"
<< fmt::format("ARB_ARBOR_API const mechanism_catalogue& global_{0}_catalogue() {{\n"
" static mechanism_catalogue cat = build_{0}_catalogue();\n"
" return cat;\n"
"}}\n",
opt.catalogue);
out << "} // namespace arb\n"
"#endif\n";
opt.catalogue)
<< "} // namespace arb\n"
"#endif\n";
}
{
std::ofstream out(opt.outprefix + opt.catalogue + "_catalogue.hpp");
std::ofstream out(outdir / (opt.catalogue + "_catalogue.hpp"));
out << fmt::format("#pragma once\n"
"\n"
"#include <arbor/mechcat.hpp>\n"
Expand Down
3 changes: 0 additions & 3 deletions modcc/printer/infoprinter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <ostream>
#include <set>
#include <string>
#include <regex>

Expand All @@ -15,8 +14,6 @@
#include "io/ostream_wrappers.hpp"
#include "io/prefixbuf.hpp"

using io::quote;

ARB_LIBMODCC_API std::string build_info_header(const Module& m, const printer_options& opt, bool cpu, bool gpu) {
using io::indent;
using io::popindent;
Expand Down

0 comments on commit 9f18a50

Please sign in to comment.