diff --git a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc index db7c31afd2..ee9a76245f 100644 --- a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc +++ b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc @@ -984,8 +984,6 @@ FailureOr importDslxInstantiation( ::llvm::StringRef path = file_import_op.getFilename(); std::string module_name = "imported_module"; - std::string_view stdlib_path = ::xls::GetDefaultDslxStdlibPath(); - std::vector additional_search_paths = {}; absl::StatusOr package_string_or; // Note: this is not bullet proof. The experience if these are wrong would @@ -1006,9 +1004,12 @@ FailureOr importDslxInstantiation( // Note: using a different pathname here else XLS considers this a circular // import. - package_string_or = - ::xls::ConvertDslxToIr(dslx, "", module_name, - stdlib_path, additional_search_paths); + const ::xls::ConvertDslxToIrOptions options{ + .dslx_stdlib_path = ::xls::GetDefaultDslxStdlibPath(), + .warnings_as_errors = false, + }; + package_string_or = ::xls::ConvertDslxToIr(dslx, "", + module_name, options); if (!package_string_or.ok()) { llvm::errs() << "Failed to convert DSLX to IR: " << package_string_or.status().message() << "\n"; @@ -1769,8 +1770,12 @@ absl::StatusOr> DslxPackageCache::import( if (it != cache.end()) { return it->second; } - absl::StatusOr package_string_or = ::xls::ConvertDslxPathToIr( - fileName, ::xls::GetDefaultDslxStdlibPath(), {}); + const ::xls::ConvertDslxToIrOptions options{ + .dslx_stdlib_path = ::xls::GetDefaultDslxStdlibPath(), + .warnings_as_errors = false, + }; + absl::StatusOr package_string_or = + ::xls::ConvertDslxPathToIr(fileName, options); if (!package_string_or.ok()) { return package_string_or.status(); } diff --git a/xls/dslx/ir_convert/convert_options.h b/xls/dslx/ir_convert/convert_options.h index 202cd106be..ca49710fdd 100644 --- a/xls/dslx/ir_convert/convert_options.h +++ b/xls/dslx/ir_convert/convert_options.h @@ -40,10 +40,10 @@ struct ConvertOptions { // Should warnings be treated as errors? bool warnings_as_errors = true; - // Set of warnings that are enabled. + // Set of warnings used in DSLX typechecking. // // Note that this is only used in IR conversion routines that do typechecking. - WarningKindSet enabled_warnings = kDefaultWarningsSet; + WarningKindSet warnings = kDefaultWarningsSet; // Should #[test] and #[test_proc] entities be emitted to IR. bool convert_tests = false; diff --git a/xls/dslx/ir_convert/ir_converter.cc b/xls/dslx/ir_convert/ir_converter.cc index 5ccd18b62b..5e8e89823b 100644 --- a/xls/dslx/ir_convert/ir_converter.cc +++ b/xls/dslx/ir_convert/ir_converter.cc @@ -590,9 +590,9 @@ absl::StatusOr ConvertFilesToPackage( "path to know where to resolve the entry function"); } for (std::string_view path : paths) { - ImportData import_data(CreateImportData( - stdlib_path, dslx_paths, convert_options.enabled_warnings, - std::make_unique())); + ImportData import_data( + CreateImportData(stdlib_path, dslx_paths, convert_options.warnings, + std::make_unique())); XLS_ASSIGN_OR_RETURN(std::string text, import_data.vfs().GetFileContents(path)); XLS_ASSIGN_OR_RETURN(std::string module_name, PathToName(path)); diff --git a/xls/dslx/ir_convert/ir_converter_main.cc b/xls/dslx/ir_convert/ir_converter_main.cc index 61eed37aaa..d4c98d4ceb 100644 --- a/xls/dslx/ir_convert/ir_converter_main.cc +++ b/xls/dslx/ir_convert/ir_converter_main.cc @@ -111,7 +111,7 @@ absl::Status RealMain(absl::Span paths) { .emit_fail_as_assert = emit_fail_as_assert, .verify_ir = verify_ir, .warnings_as_errors = warnings_as_errors, - .enabled_warnings = warnings, + .warnings = warnings, .convert_tests = convert_tests, .default_fifo_config = default_fifo_config, }; diff --git a/xls/dslx/run_routines/ir_test_runner.cc b/xls/dslx/run_routines/ir_test_runner.cc index d094f70096..4d2384baa8 100644 --- a/xls/dslx/run_routines/ir_test_runner.cc +++ b/xls/dslx/run_routines/ir_test_runner.cc @@ -204,7 +204,7 @@ absl::StatusOr> MakeRunner( .emit_fail_as_assert = true, .verify_ir = false, .warnings_as_errors = false, - .enabled_warnings = kNoWarningsSet, + .warnings = kNoWarningsSet, .convert_tests = true, }; absl::flat_hash_map> packages; diff --git a/xls/dslx/warning_collector.h b/xls/dslx/warning_collector.h index 6cdce6f26f..7ea2323663 100644 --- a/xls/dslx/warning_collector.h +++ b/xls/dslx/warning_collector.h @@ -48,6 +48,8 @@ class WarningCollector { const std::vector& warnings() const { return warnings_; } + bool empty() const { return warnings_.empty(); } + private: const WarningKindSet enabled_; std::vector warnings_; diff --git a/xls/public/c_api.cc b/xls/public/c_api.cc index 6c104686eb..e28af4f100 100644 --- a/xls/public/c_api.cc +++ b/xls/public/c_api.cc @@ -58,22 +58,104 @@ void xls_init_xls(const char* usage, int argc, char* argv[]) { (void)(xls::InitXls(usage, argc, argv)); } +bool xls_convert_dslx_to_ir_with_warnings( + const char* dslx, const char* path, const char* module_name, + const char* dslx_stdlib_path, const char* additional_search_paths[], + size_t additional_search_paths_count, const char* enable_warnings[], + size_t enable_warnings_count, const char* disable_warnings[], + size_t disable_warnings_count, bool warnings_as_errors, + char*** warnings_out, size_t* warnings_out_count, char** error_out, + char** ir_out) { + CHECK(dslx != nullptr); + CHECK(path != nullptr); + CHECK(dslx_stdlib_path != nullptr); + CHECK(error_out != nullptr); + + std::vector additional_search_paths_cpp = + xls::ToCppPaths(additional_search_paths, additional_search_paths_count); + std::vector enable_warnings_cpp = + xls::ToCppStringViews(enable_warnings, enable_warnings_count); + std::vector disable_warnings_cpp = + xls::ToCppStringViews(disable_warnings, disable_warnings_count); + + std::vector warnings_out_cpp; + + const xls::ConvertDslxToIrOptions options = { + .dslx_stdlib_path = dslx_stdlib_path, + .additional_search_paths = additional_search_paths_cpp, + .enable_warnings = enable_warnings_cpp, + .disable_warnings = disable_warnings_cpp, + .warnings_as_errors = warnings_as_errors, + .warnings_out = &warnings_out_cpp, + }; + + absl::StatusOr result = + xls::ConvertDslxToIr(dslx, path, module_name, options); + + if (warnings_out != nullptr) { + xls::ToOwnedCStrings(warnings_out_cpp, warnings_out, warnings_out_count); + } else if (warnings_out_count != nullptr) { + *warnings_out_count = warnings_out_cpp.size(); + } + + return xls::ReturnStringHelper(result, error_out, ir_out); +} + bool xls_convert_dslx_to_ir(const char* dslx, const char* path, const char* module_name, const char* dslx_stdlib_path, const char* additional_search_paths[], size_t additional_search_paths_count, char** error_out, char** ir_out) { - CHECK(dslx != nullptr); + const char* enable_warnings[] = {}; + const char* disable_warnings[] = {}; + return xls_convert_dslx_to_ir_with_warnings( + dslx, path, module_name, dslx_stdlib_path, additional_search_paths, + additional_search_paths_count, enable_warnings, 0, disable_warnings, 0, + /*warnings_as_errors=*/false, + /*warnings_out=*/nullptr, + /*warnings_out_count=*/nullptr, error_out, ir_out); +} + +bool xls_convert_dslx_path_to_ir_with_warnings( + const char* path, const char* dslx_stdlib_path, + const char* additional_search_paths[], size_t additional_search_paths_count, + const char* enable_warnings[], size_t enable_warnings_count, + const char* disable_warnings[], size_t disable_warnings_count, + bool warnings_as_errors, char*** warnings_out, size_t* warnings_out_count, + char** error_out, char** ir_out) { CHECK(path != nullptr); CHECK(dslx_stdlib_path != nullptr); CHECK(error_out != nullptr); + if (warnings_out != nullptr) { + CHECK(warnings_out_count != nullptr); + } std::vector additional_search_paths_cpp = - xls::ToCpp(additional_search_paths, additional_search_paths_count); + xls::ToCppPaths(additional_search_paths, additional_search_paths_count); + std::vector enable_warnings_cpp = + xls::ToCppStringViews(enable_warnings, enable_warnings_count); + std::vector disable_warnings_cpp = + xls::ToCppStringViews(disable_warnings, disable_warnings_count); + + std::vector warnings_out_cpp; + + const xls::ConvertDslxToIrOptions options = { + .dslx_stdlib_path = dslx_stdlib_path, + .additional_search_paths = additional_search_paths_cpp, + .enable_warnings = enable_warnings_cpp, + .disable_warnings = disable_warnings_cpp, + .warnings_as_errors = warnings_as_errors, + .warnings_out = &warnings_out_cpp, + }; + absl::StatusOr result = xls::ConvertDslxPathToIr(path, options); + + if (warnings_out != nullptr) { + xls::ToOwnedCStrings(warnings_out_cpp, warnings_out, warnings_out_count); + } else if (warnings_out_count != nullptr) { + *warnings_out_count = warnings_out_cpp.size(); + } - absl::StatusOr result = xls::ConvertDslxToIr( - dslx, path, module_name, dslx_stdlib_path, additional_search_paths_cpp); return xls::ReturnStringHelper(result, error_out, ir_out); } @@ -81,16 +163,14 @@ bool xls_convert_dslx_path_to_ir(const char* path, const char* dslx_stdlib_path, const char* additional_search_paths[], size_t additional_search_paths_count, char** error_out, char** ir_out) { - CHECK(path != nullptr); - CHECK(dslx_stdlib_path != nullptr); - CHECK(error_out != nullptr); - - std::vector additional_search_paths_cpp = - xls::ToCpp(additional_search_paths, additional_search_paths_count); - - absl::StatusOr result = xls::ConvertDslxPathToIr( - path, dslx_stdlib_path, additional_search_paths_cpp); - return xls::ReturnStringHelper(result, error_out, ir_out); + const char* enable_warnings[] = {}; + const char* disable_warnings[] = {}; + return xls_convert_dslx_path_to_ir_with_warnings( + path, dslx_stdlib_path, additional_search_paths, + additional_search_paths_count, enable_warnings, 0, disable_warnings, 0, + /*warnings_as_errors=*/false, + /*warnings_out=*/nullptr, + /*warnings_out_count=*/nullptr, error_out, ir_out); } bool xls_optimize_ir(const char* ir, const char* top, char** error_out, @@ -461,8 +541,22 @@ void xls_package_free(struct xls_package* p) { delete reinterpret_cast(p); } -void xls_c_str_free(char* c_str) { - free(c_str); +void xls_c_str_free(char* c_str) { free(c_str); } + +void xls_c_strs_free(char** c_strs, size_t count) { + CHECK_EQ(count == 0, c_strs == nullptr) << absl::StreamFormat( + "xls_c_strs_free expected consistency between zero-size and " + "array being nullptr; count = %d, c_strs = %p", + count, c_strs); + + if (c_strs == nullptr) { + return; + } + + for (size_t i = 0; i < count; ++i) { + free(c_strs[i]); + } + delete[] c_strs; } bool xls_value_to_string(const struct xls_value* v, char** string_out) { diff --git a/xls/public/c_api.h b/xls/public/c_api.h index 24db706fdc..6648ae2557 100644 --- a/xls/public/c_api.h +++ b/xls/public/c_api.h @@ -60,11 +60,39 @@ bool xls_convert_dslx_to_ir(const char* dslx, const char* path, size_t additional_search_paths_count, char** error_out, char** ir_out); +// As above, but also takes `enable_warnings` and `disable_warnings` which +// are arrays of warning names to enable or disable respectively against the +// default warning set. +// +// Precondition: if `warnings_out` is provided then `warnings_out_count` must +// also be provided. +// +// Note that if the `warnings_out_count` is populated with zero (i.e. there were +// no warnings) then we can return `nullptr` for `warnings_out`. +bool xls_convert_dslx_to_ir_with_warnings( + const char* dslx, const char* path, const char* module_name, + const char* dslx_stdlib_path, const char* additional_search_paths[], + size_t additional_search_paths_count, const char* enable_warnings[], + size_t enable_warnings_count, const char* disable_warnings[], + size_t disable_warnings_count, bool warnings_as_errors, + char*** warnings_out, size_t* warnings_out_count, char** error_out, + char** ir_out); + bool xls_convert_dslx_path_to_ir(const char* path, const char* dslx_stdlib_path, const char* additional_search_paths[], size_t additional_search_paths_count, char** error_out, char** ir_out); +// As above `xls_convert_dslx_to_ir_with_warnings`, but for a filesystem path +// instead of DSLX text. +bool xls_convert_dslx_path_to_ir_with_warnings( + const char* path, const char* dslx_stdlib_path, + const char* additional_search_paths[], size_t additional_search_paths_count, + const char* enable_warnings[], size_t enable_warnings_count, + const char* disable_warnings[], size_t disable_warnings_count, + bool warnings_as_errors, char*** warnings_out, size_t* warnings_out_count, + char** error_out, char** ir_out); + bool xls_optimize_ir(const char* ir, const char* top, char** error_out, char** ir_out); @@ -237,6 +265,9 @@ void xls_package_free(struct xls_package* p); // just call `free` directly). void xls_c_str_free(char* c_str); +// Frees an array of C strings that were provided by this XLS public API. +void xls_c_strs_free(char** c_strs, size_t count); + // Returns a string representation of the given IR package `p`. bool xls_package_to_string(const struct xls_package* p, char** string_out); diff --git a/xls/public/c_api_dslx.cc b/xls/public/c_api_dslx.cc index 2d33f673b3..861527fad8 100644 --- a/xls/public/c_api_dslx.cc +++ b/xls/public/c_api_dslx.cc @@ -67,7 +67,7 @@ struct xls_dslx_import_data* xls_dslx_import_data_create( size_t additional_search_paths_count) { std::filesystem::path cpp_stdlib_path{dslx_stdlib_path}; std::vector cpp_additional_search_paths = - xls::ToCpp(additional_search_paths, additional_search_paths_count); + xls::ToCppPaths(additional_search_paths, additional_search_paths_count); xls::dslx::ImportData import_data = CreateImportData( cpp_stdlib_path, cpp_additional_search_paths, xls::dslx::kAllWarningsSet, std::make_unique()); diff --git a/xls/public/c_api_impl_helpers.cc b/xls/public/c_api_impl_helpers.cc index 851a074e73..9810a0ffee 100644 --- a/xls/public/c_api_impl_helpers.cc +++ b/xls/public/c_api_impl_helpers.cc @@ -29,8 +29,9 @@ namespace xls { -std::vector ToCpp(const char* additional_search_paths[], - size_t additional_search_paths_count) { +std::vector ToCppPaths( + const char* additional_search_paths[], + size_t additional_search_paths_count) { std::vector additional_search_paths_cpp; additional_search_paths_cpp.reserve(additional_search_paths_count); for (size_t i = 0; i < additional_search_paths_count; ++i) { @@ -41,10 +42,39 @@ std::vector ToCpp(const char* additional_search_paths[], return additional_search_paths_cpp; } +std::vector ToCppStringViews(const char* strings[], + size_t strings_count) { + std::vector strings_cpp; + strings_cpp.reserve(strings_count); + for (size_t i = 0; i < strings_count; ++i) { + const char* string = strings[i]; + CHECK(string != nullptr); + strings_cpp.push_back(string); + } + return strings_cpp; +} + char* ToOwnedCString(std::string_view s) { return strndup(s.data(), s.size()); } -// Helper function that we can use to adapt to the common C API pattern when -// we're returning an `absl::StatusOr` value. +void ToOwnedCStrings(absl::Span cpp, char*** c_out, + size_t* c_out_count) { + CHECK(c_out != nullptr); + CHECK(c_out_count != nullptr); + + // For the empty array case we avoid a needless zero-sized allocation. + if (cpp.empty()) { + *c_out = nullptr; + *c_out_count = 0; + return; + } + + *c_out = new char*[cpp.size()]; + *c_out_count = cpp.size(); + for (size_t i = 0; i < cpp.size(); ++i) { + (*c_out)[i] = ToOwnedCString(cpp[i]); + } +} + bool ReturnStringHelper(absl::StatusOr& to_return, char** error_out, char** value_out) { if (to_return.ok()) { diff --git a/xls/public/c_api_impl_helpers.h b/xls/public/c_api_impl_helpers.h index eb6f84b5e3..7be43f7b86 100644 --- a/xls/public/c_api_impl_helpers.h +++ b/xls/public/c_api_impl_helpers.h @@ -46,10 +46,25 @@ bool ReturnStringHelper(absl::StatusOr& to_return, // caller. char* ToOwnedCString(std::string_view s); +// Converts a C++ vector of strings into a C array of strings and a count of the +// number of strings. +// +// Precondition: `c_out` and `c_out_count` must not be `nullptr`. +// +// Note: if the `cpp` span is empty, then `c_out` will be set to a `nullptr` +// (and `c_out_count` will be set to 0) so callers should not rely on the value +// of `c_out` to determine if the conversion was successful. +void ToOwnedCStrings(absl::Span cpp, char*** c_out, + size_t* c_out_count); + // Converts the C representation of filesystem search paths into a C++ // representation. -std::vector ToCpp(const char* additional_search_paths[], - size_t additional_search_paths_count); +std::vector ToCppPaths(const char* paths[], + size_t paths_count); + +// Converts the C representation of warnings into a C++ representation. +std::vector ToCppStringViews(const char* strings[], + size_t strings_count); } // namespace xls diff --git a/xls/public/c_api_symbols.txt b/xls/public/c_api_symbols.txt index 415fe9586b..39b78ef513 100644 --- a/xls/public/c_api_symbols.txt +++ b/xls/public/c_api_symbols.txt @@ -21,8 +21,11 @@ xls_bits_umul xls_bits_width_slice xls_bits_xor xls_c_str_free +xls_c_strs_free xls_convert_dslx_path_to_ir +xls_convert_dslx_path_to_ir_with_warnings xls_convert_dslx_to_ir +xls_convert_dslx_to_ir_with_warnings xls_dslx_colon_ref_get_attr xls_dslx_colon_ref_resolve_import_subject xls_dslx_constant_def_get_name diff --git a/xls/public/c_api_test.cc b/xls/public/c_api_test.cc index 00b2d148a6..d845ed8fa6 100644 --- a/xls/public/c_api_test.cc +++ b/xls/public/c_api_test.cc @@ -20,11 +20,11 @@ #include #include -#include "gmock/gmock.h" -#include "gtest/gtest.h" #include "absl/base/macros.h" #include "absl/cleanup/cleanup.h" #include "absl/log/log.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" #include "xls/common/file/filesystem.h" #include "xls/common/file/temp_directory.h" #include "xls/common/logging/log_lines.h" @@ -63,6 +63,106 @@ TEST(XlsCApiTest, ConvertDslxToIrSimple) { EXPECT_THAT(ir_out, HasSubstr("fn __my_module__id")); } +TEST(XlsCApiTest, ConvertDslxToIrWithWarningsSet) { + const std::string kProgram = "fn id() { let x = u32:1; }"; + const char* additional_search_paths[] = {}; + const std::string dslx_stdlib_path = std::string(xls::kDefaultDslxStdlibPath); + + { + char* error_out = nullptr; + char* ir_out = nullptr; + + absl::Cleanup free_cstrs([&] { + xls_c_str_free(error_out); + xls_c_str_free(ir_out); + }); + + LOG(INFO) + << "converting with warnings in default state, should see warning..."; + char** warnings = nullptr; + size_t warnings_count = 0; + absl::Cleanup free_warnings( + [&] { xls_c_strs_free(warnings, warnings_count); }); + + bool ok = xls_convert_dslx_to_ir_with_warnings( + kProgram.c_str(), "my_module.x", "my_module", + /*dslx_stdlib_path=*/dslx_stdlib_path.c_str(), additional_search_paths, + 0, + /*enable_warnings=*/nullptr, 0, /*disable_warnings=*/nullptr, 0, + /*warnings_as_errors=*/true, &warnings, &warnings_count, &error_out, + &ir_out); + + // Check we got the warning data even though the return code is non-ok. + ASSERT_EQ(warnings_count, 1); + ASSERT_NE(warnings, nullptr); + ASSERT_NE(warnings[0], nullptr); + EXPECT_THAT(warnings[0], HasSubstr("is not used in function")); + + // Since we set warnings-as-errors to true, we should have gotten "not ok" + // back. + ASSERT_FALSE(ok); + ASSERT_EQ(ir_out, nullptr); + EXPECT_THAT(error_out, HasSubstr("Conversion of DSLX to IR failed due to " + "warnings during parsing/typechecking.")); + } + + // Now try with the warning disabled. + { + char* error_out = nullptr; + char* ir_out = nullptr; + + absl::Cleanup free_cstrs([&] { + xls_c_str_free(error_out); + xls_c_str_free(ir_out); + }); + const char* enable_warnings[] = {}; + const char* disable_warnings[] = {"unused_definition"}; + LOG(INFO) << "converting with warning disabled, should not see warning..."; + bool ok = xls_convert_dslx_to_ir_with_warnings( + kProgram.c_str(), "my_module.x", "my_module", + /*dslx_stdlib_path=*/dslx_stdlib_path.c_str(), additional_search_paths, + 0, enable_warnings, 0, disable_warnings, 1, /*warnings_as_errors=*/true, + /*warnings_out=*/nullptr, /*warnings_out_count=*/nullptr, &error_out, + &ir_out); + ASSERT_TRUE(ok); + ASSERT_EQ(error_out, nullptr); + ASSERT_NE(ir_out, nullptr); + } +} + +TEST(XlsCApiTest, ConvertWithNoWarnings) { + const std::string kProgram = "fn id(x: u32) -> u32 { x }"; + const std::string dslx_stdlib_path = std::string(xls::kDefaultDslxStdlibPath); + const char* additional_search_paths[] = {}; + char* error_out = nullptr; + char* ir_out = nullptr; + + absl::Cleanup free_cstrs([&] { + xls_c_str_free(error_out); + xls_c_str_free(ir_out); + }); + + char** warnings = nullptr; + size_t warnings_count = 0; + absl::Cleanup free_warnings( + [&] { xls_c_strs_free(warnings, warnings_count); }); + + bool ok = xls_convert_dslx_to_ir_with_warnings( + kProgram.c_str(), "my_module.x", "my_module", + /*dslx_stdlib_path=*/dslx_stdlib_path.c_str(), additional_search_paths, 0, + /*enable_warnings=*/nullptr, 0, /*disable_warnings=*/nullptr, 0, + /*warnings_as_errors=*/true, &warnings, &warnings_count, &error_out, + &ir_out); + ASSERT_TRUE(ok); + ASSERT_EQ(error_out, nullptr); + ASSERT_NE(ir_out, nullptr); + EXPECT_THAT(ir_out, HasSubstr("fn __my_module__id")); + // Validate that in the no-warnings case we get a zero count and also a + // nullptr value populating our warnings ptr. + ASSERT_EQ(warnings_count, 0); + ASSERT_EQ(warnings, nullptr); +} + TEST(XlsCApiTest, ConvertDslxToIrError) { const std::string kInvalidProgram = "@!"; const char* additional_search_paths[] = {}; diff --git a/xls/public/runtime_build_actions.cc b/xls/public/runtime_build_actions.cc index 20c8859cde..e55476ace7 100644 --- a/xls/public/runtime_build_actions.cc +++ b/xls/public/runtime_build_actions.cc @@ -50,27 +50,50 @@ std::string_view GetDefaultDslxStdlibPath() { return kDefaultDslxStdlibPath; } absl::StatusOr ConvertDslxToIr( std::string_view dslx, std::string_view path, std::string_view module_name, - std::string_view dslx_stdlib_path, - absl::Span additional_search_paths) { - VLOG(5) << "path: " << path << " module name: " << module_name - << " stdlib_path: " << dslx_stdlib_path; + const ConvertDslxToIrOptions& options) { + VLOG(5) << "ConvertDslxToIr; path: " << path + << " module name: " << module_name + << " warnings_as_errors: " << options.warnings_as_errors; + + std::string enable_warnings_str = absl::StrJoin(options.enable_warnings, ","); + std::string disable_warnings_str = + absl::StrJoin(options.disable_warnings, ","); + XLS_ASSIGN_OR_RETURN( + dslx::WarningKindSet warnings_set, + dslx::GetWarningsSetFromFlags(enable_warnings_str, disable_warnings_str)); + dslx::ImportData import_data(dslx::CreateImportData( - std::string(dslx_stdlib_path), additional_search_paths, - dslx::kDefaultWarningsSet, std::make_unique())); + std::string(options.dslx_stdlib_path), options.additional_search_paths, + warnings_set, std::make_unique())); + XLS_ASSIGN_OR_RETURN( dslx::TypecheckedModule typechecked, dslx::ParseAndTypecheck(dslx, path, module_name, &import_data)); - return dslx::ConvertModule(typechecked.module, &import_data, - dslx::ConvertOptions{}); + + const dslx::WarningCollector& warnings = typechecked.warnings; + if (options.warnings_out != nullptr) { + for (const dslx::WarningCollector::Entry& entry : warnings.warnings()) { + options.warnings_out->push_back(entry.message); + } + } + if (options.warnings_as_errors && !warnings.empty()) { + return absl::InvalidArgumentError( + "Conversion of DSLX to IR failed due to warnings during " + "parsing/typechecking."); + } + + return dslx::ConvertModule( + typechecked.module, &import_data, + dslx::ConvertOptions{ + .warnings_as_errors = options.warnings_as_errors, + }); } absl::StatusOr ConvertDslxPathToIr( - const std::filesystem::path& path, std::string_view dslx_stdlib_path, - absl::Span additional_search_paths) { + const std::filesystem::path& path, const ConvertDslxToIrOptions& options) { XLS_ASSIGN_OR_RETURN(std::string dslx, GetFileContents(path)); XLS_ASSIGN_OR_RETURN(std::string module_name, dslx::ExtractModuleName(path)); - return ConvertDslxToIr(dslx, std::string{path}, module_name, dslx_stdlib_path, - additional_search_paths); + return ConvertDslxToIr(dslx, std::string{path}, module_name, options); } absl::StatusOr OptimizeIr(std::string_view ir, diff --git a/xls/public/runtime_build_actions.h b/xls/public/runtime_build_actions.h index 21927ca8aa..f776c261e4 100644 --- a/xls/public/runtime_build_actions.h +++ b/xls/public/runtime_build_actions.h @@ -52,6 +52,15 @@ namespace xls { // command line flag option that indicates what DSL stdlib path to use instead. std::string_view GetDefaultDslxStdlibPath(); +struct ConvertDslxToIrOptions { + std::string_view dslx_stdlib_path; + absl::Span additional_search_paths; + absl::Span enable_warnings; + absl::Span disable_warnings; + bool warnings_as_errors = true; + std::vector* warnings_out = nullptr; +}; + // Converts the specified DSLX text into XLS IR text. // // Args: @@ -66,14 +75,12 @@ std::string_view GetDefaultDslxStdlibPath(); // modules. absl::StatusOr ConvertDslxToIr( std::string_view dslx, std::string_view path, std::string_view module_name, - std::string_view dslx_stdlib_path, - absl::Span additional_search_paths); + const ConvertDslxToIrOptions& options); // As above, but uses a filesystem path to retrieve the DSLX module contents. // "path" should end with ".x" suffix, the path will determine the module name. absl::StatusOr ConvertDslxPathToIr( - const std::filesystem::path& path, std::string_view dslx_stdlib_path, - absl::Span additional_search_paths); + const std::filesystem::path& path, const ConvertDslxToIrOptions& options); // Optimizes the generated XLS IR with the given top-level entity (e.g., // function, proc, etc).