diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 789761c1f3647..ec948235c0eca 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -39,7 +39,7 @@ //===----------------------------------------------------------------------===// #ifndef LANGOPT -# error Define the LANGOPT macro to handle language options +# define LANGOPT(Name, Bits, Default, Description) #endif #ifndef COMPATIBLE_LANGOPT @@ -250,6 +250,9 @@ ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default LANGOPT(ShortEnums , 1, 0, "short enum types") +// Changes made for symbolic map +LANGOPT(SymbolicMap, 1, 0, "Automatically generate a map of symbolic names for enumerators") + LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL C version") LANGOPT(OpenCLCPlusPlus , 1, 0, "C++ for OpenCL") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1b07deb4a8482..b62c36545a5ea 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2807,6 +2807,14 @@ def ffreestanding : Flag<["-"], "ffreestanding">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">, MarshallingInfoFlag>; + +// Changes made for symbolic map +def symbolic_map : Flag<["-"], "symbolic-map">, + Group, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Automatically generate a map of symbolic names for enumerators">, + MarshallingInfoFlag>; + def fgnuc_version_EQ : Joined<["-"], "fgnuc-version=">, Group, HelpText<"Sets various macros to claim compatibility with the given GCC version (default is 4.2.1)">, Visibility<[ClangOption, CC1Option, CLOption]>; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c036902b0b130..693b098b91e01 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7372,11 +7372,22 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { DI->EmitAndRetainType(getContext().getRecordType(cast(D))); break; - case Decl::Enum: - if (CGDebugInfo *DI = getModuleDebugInfo()) - if (cast(D)->getDefinition()) - DI->EmitAndRetainType(getContext().getEnumType(cast(D))); - break; + case Decl::Enum: { + // Cast the declaration to the specific Enum type + auto *ED = cast(D); + + // Call the symbolic map emitter if the option is enabled. + if (getLangOpts().SymbolicMap) { + EmitEnumSymbolicMap(ED); + } + + // Handle debug info, which is standard for enums + if (CGDebugInfo *DI = getModuleDebugInfo()) + if (ED->getDefinition()) + DI->EmitAndRetainType(getContext().getEnumType(ED)); + + break; + } case Decl::HLSLBuffer: getHLSLRuntime().addBuffer(cast(D)); @@ -7476,6 +7487,50 @@ void CodeGenModule::EmitDeferredUnusedCoverageMappings() { } } +// Additions to support symbolic maps for enums. +void CodeGenModule::EmitEnumSymbolicMap(const EnumDecl *ED) { + // Skip anonymous or unnamed enums. + if (!ED->getDeclName() || ED->getName().empty()) { + return; + } + + // Skip empty enums. + if (ED->enumerator_begin() == ED->enumerator_end()) { + return; + } + + // Only handle definitions, not forward declarations. + if (!ED->isThisDeclarationADefinition()) { + return; + } + + std::vector EnumeratorNames; + + for (const EnumConstantDecl *ECD : ED->enumerators()) { + EnumeratorNames.push_back( + GetAddrOfConstantCString(ECD->getName().str()).getPointer()); + } + + llvm::Type *I8Ty = llvm::Type::getInt8Ty(getLLVMContext()); + llvm::PointerType *CharPtrTy = llvm::PointerType::get(I8Ty, 0); + + llvm::ArrayType *ArrayTy = llvm::ArrayType::get(CharPtrTy, EnumeratorNames.size()); + llvm::Constant *Initializer = llvm::ConstantArray::get(ArrayTy, EnumeratorNames); + + std::string VarName = "__nameof_" + ED->getNameAsString(); + + auto *GV = new llvm::GlobalVariable( + getModule(), + ArrayTy, + true, + llvm::GlobalValue::WeakODRLinkage, + Initializer, + VarName + ); + + GV->setAlignment(llvm::MaybeAlign(getDataLayout().getPointerABIAlignment(0))); +} + void CodeGenModule::EmitMainVoidAlias() { // In order to transition away from "__original_main" gracefully, emit an // alias for "main" in the no-argument case so that libc can detect when diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 1b67d4354efc0..f3f8f2d38c628 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1820,6 +1820,9 @@ class CodeGenModule : public CodeGenTypeCache { } private: + /// Emit the symbolic map for an enum declaration. + void EmitEnumSymbolicMap(const EnumDecl *ED); + bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const; llvm::Constant *GetOrCreateLLVMFunction( diff --git a/test1.cpp b/test1.cpp new file mode 100644 index 0000000000000..048af36b493a7 --- /dev/null +++ b/test1.cpp @@ -0,0 +1,14 @@ +// using namespace std; +#include + +int main() +{ + int a = 5; + int b = 10; + int sum = a + b; + + // Print the result + printf("The sum of %d and %d is %d\n", a, b, sum); + + return 0; +} \ No newline at end of file diff --git a/test1.exe b/test1.exe new file mode 100644 index 0000000000000..dfcbcf99ef68f Binary files /dev/null and b/test1.exe differ diff --git a/test_enum.cpp b/test_enum.cpp new file mode 100644 index 0000000000000..0f67a8885b8ec --- /dev/null +++ b/test_enum.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +enum Day { + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday +}; + +// Tell C++ that this variable is defined externally by the compiler +extern const char *__nameof_Day[]; + +int main() { + std::cout << "Symbolic map for enum Day:" << std::endl; + + // Loop through the enum and print the names from our generated array + for (int i = Monday; i <= Sunday; ++i) { + std::cout << "Value " << i << " -> Name: " << __nameof_Day[i] << std::endl; + } + + // Prove it's correct with an assertion + assert(strcmp(__nameof_Day[Friday], "Friday") == 0); + + std::cout << "\nAssertion passed." << std::endl; + + return 0; +} \ No newline at end of file diff --git a/test_enum.o b/test_enum.o new file mode 100644 index 0000000000000..03d2a0b428b78 Binary files /dev/null and b/test_enum.o differ