diff --git a/modcc/modcc.cpp b/modcc/modcc.cpp
index 975d35e36a680f3b7ba027af5784dd4a52467f9d..6036ac166d6e670f4e8e70da4a355cae97f20803 100644
--- a/modcc/modcc.cpp
+++ b/modcc/modcc.cpp
@@ -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;
}
@@ -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) {
@@ -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 {
@@ -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());
@@ -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"
@@ -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"
diff --git a/modcc/printer/infoprinter.cpp b/modcc/printer/infoprinter.cpp
index 596b7b80d01ded90e81b6d4d1a25541ba61816dd..f59f52f544513f3d56dbcc82d9fdbd3c45f060a4 100644
--- a/modcc/printer/infoprinter.cpp
+++ b/modcc/printer/infoprinter.cpp
@@ -1,5 +1,4 @@
#include <ostream>
-#include <set>
#include <string>
#include <regex>
@@ -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;