Skip to content

Commit

Permalink
Sanitize C++ keywords in DSLX->C++ type converter.
Browse files Browse the repository at this point in the history
C++ keywords are prefixed with an underscore.

PiperOrigin-RevId: 650810801
  • Loading branch information
meheffernan authored and copybara-github committed Jul 10, 2024
1 parent 8d456ed commit a6143a7
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 16 deletions.
4 changes: 4 additions & 0 deletions xls/dslx/cpp_transpiler/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ cc_library(
srcs = ["cpp_emitter.cc"],
hdrs = ["cpp_emitter.h"],
deps = [
"@com_google_absl//absl/base:no_destructor",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
Expand All @@ -75,7 +77,9 @@ cc_library(
hdrs = ["cpp_type_generator.h"],
deps = [
":cpp_emitter",
"@com_google_absl//absl/base:no_destructor",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
Expand Down
109 changes: 108 additions & 1 deletion xls/dslx/cpp_transpiler/cpp_emitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
#include <variant>
#include <vector>

#include "absl/base/no_destructor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
Expand Down Expand Up @@ -626,8 +628,113 @@ class TupleCppEmitter : public CppEmitter {

} // namespace

std::string SanitizeCppName(std::string_view name) {
static const absl::NoDestructor<absl::flat_hash_set<std::string>>
kCppKeywords({"alignas",
"alignof",
"and",
"and_eq",
"asm",
"atomic_cancel",
"atomic_commit",
"atomic_noexcept",
"auto",
"bitand",
"bitor",
"bool",
"break",
"case",
"catch",
"char",
"char8_t",
"char16_t",
"char32_t",
"class",
"compl",
"concept",
"const",
"consteval",
"constexpr",
"constinit",
"const_cast",
"continue",
"co_await",
"co_return",
"co_yield",
"decltype",
"default",
"delete",
"do",
"double",
"dynamic_cast",
"else",
"enum",
"explicit",
"export",
"extern",
"false",
"float",
"for",
"friend",
"goto",
"if",
"inline",
"int",
"long",
"mutable",
"namespace",
"new",
"noexcept",
"not",
"not_eq",
"nullptr",
"operator",
"or",
"or_eq",
"private",
"protected",
"public",
"reflexpr",
"register",
"reinterpret_cast",
"requires",
"return",
"short",
"signed",
"sizeof",
"static",
"static_assert",
"static_cast",
"struct",
"switch",
"synchronized",
"template",
"this",
"thread_local",
"throw",
"true",
"try",
"typedef",
"typeid",
"typename",
"union",
"unsigned",
"using",
"virtual",
"void",
"volatile",
"wchar_t",
"while",
"xor",
"xor_eq"});
if (kCppKeywords->contains(name)) {
return absl::StrCat("_", name);
}
return std::string{name};
}

std::string DslxTypeNameToCpp(std::string_view dslx_type) {
return Camelize(dslx_type);
return SanitizeCppName(Camelize(dslx_type));
}

/* static */ absl::StatusOr<std::unique_ptr<CppEmitter>> CppEmitter::Create(
Expand Down
3 changes: 3 additions & 0 deletions xls/dslx/cpp_transpiler/cpp_emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

namespace xls::dslx {

// Sanitizes the given name for C++. C++ keywords are prefixed with "_".
std::string SanitizeCppName(std::string_view name);

// Returns the C++ type name used to represent the given DSLX type name.
std::string DslxTypeNameToCpp(std::string_view dslx_type);

Expand Down
37 changes: 22 additions & 15 deletions xls/dslx/cpp_transpiler/cpp_type_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,15 @@ class StructCppTypeGenerator : public CppTypeGenerator {
std::vector<std::unique_ptr<CppEmitter>> member_emitters)
: CppTypeGenerator(cpp_type, dslx_type),
struct_def_(struct_def),
member_emitters_(std::move(member_emitters)) {}
member_emitters_(std::move(member_emitters)),
cpp_member_names_([struct_def]() {
std::vector<std::string> names;
names.reserve(struct_def->size());
for (int64_t i = 0; i < struct_def->size(); ++i) {
names.push_back(SanitizeCppName(struct_def->GetMemberName(i)));
}
return names;
}()) {}
~StructCppTypeGenerator() override = default;

static absl::StatusOr<std::unique_ptr<StructCppTypeGenerator>> Create(
Expand All @@ -440,7 +448,7 @@ class StructCppTypeGenerator : public CppTypeGenerator {
std::vector<std::string> member_decls;
std::vector<std::string> scalar_widths;
for (int64_t i = 0; i < struct_def_->size(); ++i) {
std::string member_name = struct_def_->GetMemberName(i);
std::string member_name = cpp_member_names_[i];
member_decls.push_back(absl::StrFormat(
"%s %s;", member_emitters_[i]->cpp_type(), member_name));
std::optional<int64_t> width =
Expand Down Expand Up @@ -506,7 +514,7 @@ class StructCppTypeGenerator : public CppTypeGenerator {
pieces.push_back(absl::StrFormat("%s result;", cpp_type()));
for (int i = 0; i < struct_def_->members().size(); i++) {
std::string assignment = member_emitters_[i]->AssignFromValue(
/*lhs=*/absl::StrFormat("result.%s", struct_def_->GetMemberName(i)),
/*lhs=*/absl::StrFormat("result.%s", cpp_member_names_[i]),
/*rhs=*/absl::StrFormat("value.element(%d)", i), /*nesting=*/0);
pieces.push_back(assignment);
}
Expand All @@ -531,7 +539,7 @@ class StructCppTypeGenerator : public CppTypeGenerator {
for (int i = 0; i < struct_def_->members().size(); i++) {
std::string assignment = member_emitters_[i]->AssignToValue(
/*lhs=*/absl::StrFormat("members[%d]", i),
/*rhs=*/struct_def_->GetMemberName(i), /*nesting=*/0);
/*rhs=*/cpp_member_names_[i], /*nesting=*/0);
pieces.push_back(assignment);
}
pieces.push_back("return ::xls::Value::Tuple(members);");
Expand All @@ -548,8 +556,8 @@ class StructCppTypeGenerator : public CppTypeGenerator {
std::vector<std::string> pieces;
for (int i = 0; i < struct_def_->members().size(); i++) {
std::string verification = member_emitters_[i]->Verify(
struct_def_->GetMemberName(i),
absl::StrFormat("%s.%s", cpp_type(), struct_def_->GetMemberName(i)),
cpp_member_names_[i],
absl::StrFormat("%s.%s", cpp_type(), cpp_member_names_[i]),
/*nesting=*/0);
pieces.push_back(verification);
}
Expand All @@ -567,11 +575,10 @@ class StructCppTypeGenerator : public CppTypeGenerator {
pieces.push_back(
absl::StrFormat("std::string result = \"%s {\\n\";", cpp_type()));
for (int i = 0; i < struct_def_->members().size(); i++) {
pieces.push_back(
absl::StrFormat("result += __indent(indent + 1) + \"%s: \";",
struct_def_->GetMemberName(i)));
pieces.push_back(absl::StrFormat(
"result += __indent(indent + 1) + \"%s: \";", cpp_member_names_[i]));
std::string to_string = member_emitters_[i]->ToString(
"result", "indent + 2", struct_def_->GetMemberName(i), /*nesting=*/0);
"result", "indent + 2", cpp_member_names_[i], /*nesting=*/0);
pieces.push_back(to_string);
pieces.push_back("result += \",\\n\";");
}
Expand All @@ -590,11 +597,10 @@ class StructCppTypeGenerator : public CppTypeGenerator {
pieces.push_back(
absl::StrFormat("std::string result = \"%s {\\n\";", dslx_type()));
for (int i = 0; i < struct_def_->members().size(); i++) {
pieces.push_back(
absl::StrFormat("result += __indent(indent + 1) + \"%s: \";",
struct_def_->GetMemberName(i)));
pieces.push_back(absl::StrFormat(
"result += __indent(indent + 1) + \"%s: \";", cpp_member_names_[i]));
std::string to_string = member_emitters_[i]->ToDslxString(
"result", "indent + 2", struct_def_->GetMemberName(i), /*nesting=*/0);
"result", "indent + 2", cpp_member_names_[i], /*nesting=*/0);
pieces.push_back(to_string);
pieces.push_back("result += \",\\n\";");
}
Expand All @@ -617,7 +623,7 @@ class StructCppTypeGenerator : public CppTypeGenerator {
} else {
std::vector<std::string> member_comparisons;
for (int i = 0; i < struct_def_->members().size(); i++) {
const std::string& member_name = struct_def_->GetMemberName(i);
const std::string& member_name = cpp_member_names_[i];
member_comparisons.push_back(
absl::StrFormat("%s == other.%s", member_name, member_name));
}
Expand Down Expand Up @@ -650,6 +656,7 @@ class StructCppTypeGenerator : public CppTypeGenerator {

const StructDef* struct_def_;
std::vector<std::unique_ptr<CppEmitter>> member_emitters_;
std::vector<std::string> cpp_member_names_;
};

} // namespace
Expand Down
12 changes: 12 additions & 0 deletions xls/dslx/cpp_transpiler/test_types.x
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,15 @@ struct snake_case_struct_t {
some_field: snake_case_type_t,
some_other_field: snake_case_enum_t,
}

struct StructWithKeywordFields {
float: u32,
int: u42,
}

enum EnumWithKeywordValues : u8 {
float = 0,
static = 1,
}

type float = u33;
9 changes: 9 additions & 0 deletions xls/dslx/cpp_transpiler/test_types_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -618,5 +618,14 @@ TEST(TestTypesTest, SnakeCaseToString) {
})");
}

TEST(TestTypesTest, StructWithKeywordFields) {
test::StructWithKeywordFields a{._float = 42, ._int = 1};

EXPECT_EQ(a.ToString(), R"(StructWithKeywordFields {
_float: bits[32]:0x2a,
_int: bits[42]:0x1,
})");
}

} // namespace
} // namespace xls

0 comments on commit a6143a7

Please sign in to comment.