Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,14 @@ def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Assert that the compilation takes place in a freestanding environment">,
MarshallingInfoFlag<LangOpts<"Freestanding">>;

// Changes made for symbolic map
def symbolic_map : Flag<["-"], "symbolic-map">,
Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Automatically generate a map of symbolic names for enumerators">,
MarshallingInfoFlag<LangOpts<"SymbolicMap">>;

def fgnuc_version_EQ : Joined<["-"], "fgnuc-version=">, Group<f_Group>,
HelpText<"Sets various macros to claim compatibility with the given GCC version (default is 4.2.1)">,
Visibility<[ClangOption, CC1Option, CLOption]>;
Expand Down
65 changes: 60 additions & 5 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7372,11 +7372,22 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(D)));
break;

case Decl::Enum:
if (CGDebugInfo *DI = getModuleDebugInfo())
if (cast<EnumDecl>(D)->getDefinition())
DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(D)));
break;
case Decl::Enum: {
// Cast the declaration to the specific Enum type
auto *ED = cast<EnumDecl>(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<HLSLBufferDecl>(D));
Expand Down Expand Up @@ -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<llvm::Constant *> 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
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
14 changes: 14 additions & 0 deletions test1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// using namespace std;
#include <iostream>

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;
}
Binary file added test1.exe
Binary file not shown.
32 changes: 32 additions & 0 deletions test_enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <iostream>
#include <cassert>
#include <cstring>

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;
}
Binary file added test_enum.o
Binary file not shown.