diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index e9f5b6e6..a1b0620b 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -2051,6 +2051,15 @@ static void defineAligns(raw_ostream &Out) { Out << "#endif\n\n"; } +static void defineFunctionAlign(raw_ostream &Out) { + Out << "#ifdef _MSC_VER\n"; + Out << "#define __FUNCTIONALIGN__(X) /* WARNING: THIS FEATURE IS NOT " + "SUPPORTED BY MSVC! */ \n"; + Out << "#else\n"; + Out << "#define __FUNCTIONALIGN__(X) __attribute__((aligned(X)))\n"; + Out << "#endif\n\n"; +} + static void defineUnreachable(raw_ostream &Out) { Out << "#ifdef _MSC_VER\n"; Out << "#define __builtin_unreachable() __assume(0)\n"; @@ -2355,6 +2364,8 @@ void CWriter::generateCompilerSpecificCode(raw_ostream &Out, defineUnalignedLoad(Out); if (headerIncAligns()) defineAligns(Out); + if (headerIncFunctionAlign()) + defineFunctionAlign(Out); if (headerIncNanInf()) defineNanInf(Out); if (headerIncInt128()) @@ -2632,6 +2643,7 @@ void CWriter::generateHeader(Module &M) { headerUseAttributeWeak(); Out << "__MSVC_INLINE__ "; } + printFunctionProto(Out, &*I, GetValueName(&*I)); printFunctionAttributes(Out, I->getAttributes()); if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) { @@ -2655,6 +2667,12 @@ void CWriter::generateHeader(Module &M) { Out << " __HIDDEN__"; } + unsigned Alignment = I->getAlignment(); + if (Alignment != 0) { + headerUseFunctionAlign(); + Out << " __FUNCTIONALIGN__(" << Alignment << ") "; + } + if (I->hasName() && I->getName()[0] == 1) Out << " __asm__ (\"" << I->getName().substr(1) << "\")"; diff --git a/lib/Target/CBackend/CBackend.h b/lib/Target/CBackend/CBackend.h index e45bae54..64b0a076 100644 --- a/lib/Target/CBackend/CBackend.h +++ b/lib/Target/CBackend/CBackend.h @@ -112,6 +112,7 @@ class CWriter : public FunctionPass, public InstVisitor { bool AttributeList : 1; bool UnalignedLoad : 1; bool Aligns : 1; + bool FunctionAlign : 1; bool NanInf : 1; bool Int128 : 1; bool ThreadFence : 1; @@ -148,6 +149,7 @@ class CWriter : public FunctionPass, public InstVisitor { USED_HEADERS_FLAG(AttributeList) USED_HEADERS_FLAG(UnalignedLoad) USED_HEADERS_FLAG(Aligns) + USED_HEADERS_FLAG(FunctionAlign) USED_HEADERS_FLAG(NanInf) USED_HEADERS_FLAG(Int128) USED_HEADERS_FLAG(ThreadFence) diff --git a/test/cpp_tests/test_virtual_function_calls.cpp b/test/cpp_tests/test_virtual_function_calls.cpp new file mode 100644 index 00000000..2860a71c --- /dev/null +++ b/test/cpp_tests/test_virtual_function_calls.cpp @@ -0,0 +1,31 @@ +#ifndef _MSC_VER +// Suppress "dereferencing type-punned pointer will break strict-aliasing rules" +// gcc_extra_args: -Wno-strict-aliasing +struct A { + int a; + int b; + int f1(int i) { return 1 + i; } + int f2(int i) { return 1 + i; } + typedef int (A::*Function)(int); + int function_wrapper(Function f, int i) __attribute__((noinline)) { + return (this->*f)(i); + } +}; + +int main() { + A a{}; + if (a.function_wrapper(&A::f1, 1) != 2) + return 0; + if (a.function_wrapper(&A::f2, 1) != 2) + return 0; + return 6; +} + +#else + +/* MSVC doesn't support adding alignment to functions, treat it as an expected + * failure */ + +int main() { return 25; } + +#endif