diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index a396205a23..a36ef5e2b6 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -812,6 +812,8 @@ RUN(NAME callback_03 LABELS cpython llvm c) RUN(NAME lambda_01 LABELS cpython llvm) +RUN(NAME c_mangling LABELS cpython llvm c) + # callback_04 is to test emulation. So just run with cpython RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython) diff --git a/integration_tests/c_mangling.py b/integration_tests/c_mangling.py new file mode 100644 index 0000000000..5acc099f41 --- /dev/null +++ b/integration_tests/c_mangling.py @@ -0,0 +1,23 @@ +def f(): + int : str + int = "abc" + print(int) + + char : str + char = "char_variable" + print(char) + + void : str + void = "void_variable" + print(void) + + auto : str + auto = "auto_variable" + print(auto) + + + case : str + case = "case_variable" + print(case) + +f() diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index f03081eb1a..7f1f406c0d 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -1839,6 +1839,7 @@ int main(int argc, char *argv[]) return emit_cpp(arg_file, runtime_library_dir, compiler_options); } if (show_c) { + compiler_options.po.c_mangling = true; return emit_c(arg_file, runtime_library_dir, lpython_pass_manager, compiler_options); } @@ -1917,6 +1918,7 @@ int main(int argc, char *argv[]) err = compile_to_binary_wasm_to_x86(arg_file, outfile, runtime_library_dir, compiler_options, time_report, backend); } else if (backend == Backend::c) { + compiler_options.po.c_mangling = true; std::string emit_file_name = basename + "__tmp__generated__.c"; err = emit_c_to_file(arg_file, emit_file_name, runtime_library_dir, lpython_pass_manager, compiler_options); diff --git a/src/libasr/pass/unique_symbols.cpp b/src/libasr/pass/unique_symbols.cpp index 5a4aab01e3..1d08cb179a 100644 --- a/src/libasr/pass/unique_symbols.cpp +++ b/src/libasr/pass/unique_symbols.cpp @@ -7,7 +7,7 @@ #include #include #include - +#include extern std::string lcompilers_unique_ID; @@ -46,15 +46,28 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { bool all_symbols_mangling; bool bindc_mangling = false; bool fortran_mangling; + bool c_mangling; bool should_mangle = false; std::vector parent_function_name; std::string module_name = ""; SymbolTable* current_scope = nullptr; - SymbolRenameVisitor(bool mm, bool gm, bool im, bool am, bool bcm, bool fm) : + SymbolRenameVisitor(bool mm, bool gm, bool im, bool am, bool bcm, bool fm, bool cm) : module_name_mangling(mm), global_symbols_mangling(gm), intrinsic_symbols_mangling(im), - all_symbols_mangling(am), bindc_mangling(bcm), fortran_mangling(fm) {} + all_symbols_mangling(am), bindc_mangling(bcm), fortran_mangling(fm) , c_mangling(cm){} + + + const std::unordered_set reserved_keywords_c = { + "_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local", "auto", "break", "case", "char", "_Bool", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while" + }; +//TODO: Implement other backends mangling when refactoring the pass infrastructure + void mangle_c(ASR::symbol_t* sym, const std::string& name){ + if (reserved_keywords_c.find(name) != reserved_keywords_c.end()) { + sym_to_renamed[sym] = "_xx_"+std::string(name)+"_xx_"; + } + return; + } std::string update_name(std::string curr_name) { if (startswith(curr_name, "_lpython") || startswith(curr_name, "_lfortran") ) { @@ -147,7 +160,11 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { sym_to_renamed[sym] = current_scope->parent->get_unique_name( "f" + std::string(x.m_name)); } - } + } + } + if ( c_mangling ) { + ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); + mangle_c(sym , std::string(x.m_name)); } for (auto &a : x.m_symtab->get_scope()) { bool nested_function = is_nested_function(a.second); @@ -178,6 +195,10 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { std::string(x.m_name)); } } + + if ( c_mangling ) { + mangle_c(sym , std::string(x.m_name)); + } } void visit_GenericProcedure(const ASR::GenericProcedure_t &x) { @@ -204,6 +225,10 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { sym_to_renamed[sym] = update_name(x.m_name); } } + if ( c_mangling ) { + ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); + mangle_c(sym , std::string(x.m_name)); + } for (auto &a : x.m_symtab->get_scope()) { this->visit_symbol(*a.second); } @@ -232,6 +257,10 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { sym_to_renamed[sym] = update_name(x.m_name); } } + if (c_mangling ) { + ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); + mangle_c(sym , std::string(x.m_name)); + } } template @@ -240,6 +269,10 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); sym_to_renamed[sym] = update_name(x.m_name); } + if ( c_mangling ) { + ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); + mangle_c(sym , std::string(x.m_name)); + } for (auto &a : x.m_symtab->get_scope()) { this->visit_symbol(*a.second); } @@ -521,8 +554,9 @@ void pass_unique_symbols(Allocator &al, ASR::TranslationUnit_t &unit, if (pass_options.mangle_underscore) { lcompilers_unique_ID = ""; } - if (!any_present || (!(pass_options.mangle_underscore || - pass_options.fortran_mangling) && lcompilers_unique_ID.empty())) { + if ((!any_present || (!(pass_options.mangle_underscore || + pass_options.fortran_mangling) && lcompilers_unique_ID.empty())) && + !pass_options.c_mangling) { // `--mangle-underscore` doesn't require `lcompilers_unique_ID` // `lcompilers_unique_ID` is not mandatory for `--apply-fortran-mangling` return; @@ -532,7 +566,8 @@ void pass_unique_symbols(Allocator &al, ASR::TranslationUnit_t &unit, pass_options.intrinsic_symbols_mangling, pass_options.all_symbols_mangling, pass_options.bindc_mangling, - pass_options.fortran_mangling); + pass_options.fortran_mangling, + pass_options.c_mangling); v.visit_TranslationUnit(unit); UniqueSymbolVisitor u(al, v.sym_to_renamed); u.visit_TranslationUnit(unit); diff --git a/src/libasr/utils.h b/src/libasr/utils.h index 073a7bebe1..e65f1ce76f 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -55,6 +55,7 @@ struct PassOptions { bool visualize = false; bool tree = false; bool with_intrinsic_mods = false; + bool c_mangling = false; }; struct CompilerOptions {