From b1efd16563bbb633705494ed979cdb7cac8084d3 Mon Sep 17 00:00:00 2001 From: Bart Coppens Date: Sun, 14 Jan 2024 20:24:03 +0100 Subject: [PATCH] Fix broken support for constructors and destructors (#190) --- lib/Target/CBackend/CBackend.cpp | 32 ++++++++++++++++++--------- lib/Target/CBackend/CBackend.h | 2 ++ test/c_tests/other/test_constructor.c | 13 +++++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 test/c_tests/other/test_constructor.c diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 689d21a1..3198f349 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -2112,8 +2112,6 @@ static void defineNanInf(raw_ostream &Out) { << "#define LLVM_INFF __builtin_inff() /* Float */\n" << "#define LLVM_PREFETCH(addr,rw,locality) " "__builtin_prefetch(addr,rw,locality)\n" - << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" - << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" << "#else\n" << "#define LLVM_NAN(NanStr) ((double)NAN) /* Double */\n" << "#define LLVM_NANF(NanStr) ((float)NAN)) /* Float */\n" @@ -2122,10 +2120,6 @@ static void defineNanInf(raw_ostream &Out) { << "#define LLVM_INF ((double)INFINITY) /* Double */\n" << "#define LLVM_INFF ((float)INFINITY) /* Float */\n" << "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n" - << "#define __ATTRIBUTE_CTOR__ \"__attribute__((constructor)) not " - "supported on this compiler\"\n" - << "#define __ATTRIBUTE_DTOR__ \"__attribute__((destructor)) not " - "supported on this compiler\"\n" << "#endif\n\n"; } @@ -2241,6 +2235,18 @@ static void defineTrap(raw_ostream &Out) { << "#endif\n\n"; } +static void defineConstructorsDestructors(raw_ostream &Out) { + Out << "#ifdef __GNUC__\n" + << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" + << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" + << "#else\n" + << "#define __ATTRIBUTE_CTOR__ \"__attribute__((constructor)) not " + "supported on this compiler\"\n" + << "#define __ATTRIBUTE_DTOR__ \"__attribute__((destructor)) not " + "supported on this compiler\"\n" + << "#endif\n\n"; +} + /// FindStaticTors - Given a static ctor/dtor list, unpack its contents into /// the StaticTors set. static void FindStaticTors(GlobalVariable *GV, @@ -2252,8 +2258,8 @@ static void FindStaticTors(GlobalVariable *GV, for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))) { - if (CS->getNumOperands() != 2) - return; // Not array of 2-element structs. + if (CS->getNumOperands() != 3) + return; // Not array of 3-element structs. if (CS->getOperand(1)->isNullValue()) return; // Found a null terminator, exit printing. @@ -2359,6 +2365,8 @@ void CWriter::generateCompilerSpecificCode(raw_ostream &Out, defineStackSaveRestore(Out); if (headerIncTrap()) defineTrap(Out); + if (headerIncConstructorsDestructors()) + defineConstructorsDestructors(Out); } bool CWriter::doInitialization(Module &M) { @@ -2632,10 +2640,14 @@ void CWriter::generateHeader(Module &M) { headerUseExternalWeak(); Out << " __EXTERNAL_WEAK__"; } - if (StaticCtors.count(&*I)) + if (StaticCtors.count(&*I)) { + headerUseConstructorsDestructors(); Out << " __ATTRIBUTE_CTOR__"; - if (StaticDtors.count(&*I)) + } + if (StaticDtors.count(&*I)) { + headerUseConstructorsDestructors(); Out << " __ATTRIBUTE_DTOR__"; + } if (I->hasHiddenVisibility()) { headerUseHidden(); Out << " __HIDDEN__"; diff --git a/lib/Target/CBackend/CBackend.h b/lib/Target/CBackend/CBackend.h index 2e435a97..e45bae54 100644 --- a/lib/Target/CBackend/CBackend.h +++ b/lib/Target/CBackend/CBackend.h @@ -122,6 +122,7 @@ class CWriter : public FunctionPass, public InstVisitor { bool ConstantFP128Ty : 1; bool ForceInline : 1; bool Trap : 1; + bool ConstructorsDestructors : 1; } UsedHeaders; #define USED_HEADERS_FLAG(Name) \ @@ -157,6 +158,7 @@ class CWriter : public FunctionPass, public InstVisitor { USED_HEADERS_FLAG(ConstantFP128Ty) USED_HEADERS_FLAG(ForceInline) USED_HEADERS_FLAG(Trap) + USED_HEADERS_FLAG(ConstructorsDestructors) llvm::SmallSet FCmpOps; void headerUseFCmpOp(CmpInst::Predicate P); diff --git a/test/c_tests/other/test_constructor.c b/test/c_tests/other/test_constructor.c new file mode 100644 index 00000000..8c9ba15b --- /dev/null +++ b/test/c_tests/other/test_constructor.c @@ -0,0 +1,13 @@ +#ifndef _MSC_VER +int global_var = 0; + +__attribute__((constructor)) static void update_global_var_in_constructor() { + global_var = 6; +} + +int main() { return global_var; } +#else +int main() { + return 25; /* constructor/destructor attributes not supported on MSVC */ +} +#endif