From ad32fdb927a37dba26cb8b56f3a6b11667fe6584 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 25 Apr 2014 15:51:06 -0700 Subject: Introduce an Emscripten C++ ABI. Emscripten uses the Itanium C++ ABI for most things, except that it uses ARM C++ ABI pointers to member functions, to avoid the overhead of aligning functions. --- include/clang/Basic/TargetCXXABI.h | 8 ++++++++ lib/AST/ASTContext.cpp | 2 ++ lib/Basic/Targets.cpp | 5 +++++ lib/CodeGen/CodeGenModule.cpp | 1 + lib/CodeGen/ItaniumCXXABI.cpp | 17 +++++++++++------ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h index c9d28f8774..29e4e47076 100644 --- a/include/clang/Basic/TargetCXXABI.h +++ b/include/clang/Basic/TargetCXXABI.h @@ -71,6 +71,10 @@ public: /// - guard variables are smaller. GenericAArch64, + /// Emscripten uses the Itanium C++, with the exception that it uses + /// ARM-style pointers to member functions. + Emscripten, + /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and /// compatible compilers). /// @@ -104,6 +108,7 @@ public: case GenericAArch64: case GenericItanium: case GenericARM: + case Emscripten: case iOS: return true; @@ -119,6 +124,7 @@ public: case GenericAArch64: case GenericItanium: case GenericARM: + case Emscripten: case iOS: return false; @@ -187,6 +193,7 @@ public: case GenericAArch64: case GenericItanium: + case Emscripten: case iOS: // old iOS compilers did not follow this rule case Microsoft: return true; @@ -233,6 +240,7 @@ public: case GenericItanium: case GenericAArch64: case GenericARM: + case Emscripten: case iOS: return UseTailPaddingUnlessPOD03; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 176aec53a2..b77977f7fd 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -651,6 +651,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: return CreateARMCXXABI(*this); + case TargetCXXABI::Emscripten: // Same as Itanium at this level case TargetCXXABI::GenericAArch64: // Same as Itanium at this level case TargetCXXABI::GenericItanium: return CreateItaniumCXXABI(*this); @@ -7940,6 +7941,7 @@ MangleContext *ASTContext::createMangleContext() { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: + case TargetCXXABI::Emscripten: case TargetCXXABI::iOS: return createItaniumMangleContext(*this, getDiagnostics()); case TargetCXXABI::Microsoft: diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index b56b42c798..93da96f897 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -270,6 +270,11 @@ public: // beneficial. this->UserLabelPrefix = ""; this->MaxAtomicPromoteWidth = this->MaxAtomicInlineWidth = 32; + + // Emscripten uses the Itanium ABI mostly, but it uses ARM-style pointers + // to member functions so that it can avoid having to align function + // addresses. + this->TheCXXABI.set(TargetCXXABI::Emscripten); } }; diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0b03a3c4b6..15e4a50eaa 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -57,6 +57,7 @@ static CGCXXABI &createCXXABI(CodeGenModule &CGM) { switch (CGM.getTarget().getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericARM: + case TargetCXXABI::Emscripten: case TargetCXXABI::iOS: case TargetCXXABI::GenericItanium: return *CreateItaniumCXXABI(CGM); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 3767e4f278..1568284a7d 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -231,18 +231,23 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, /* UseARMGuardVarABI = */ true); + case TargetCXXABI::Emscripten: + // Use ARM-style method pointers so that generated code + // does not assume anything about the alignment of function + // pointers. + return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, + /* UseARMGuardVarABI = */ false); + case TargetCXXABI::GenericItanium: - switch (CGM.getContext().getTargetInfo().getTriple().getArch()) { - case llvm::Triple::le32: - case llvm::Triple::asmjs: - // Use ARM-style method pointers so that generated code + if (CGM.getContext().getTargetInfo().getTriple().getArch() + == llvm::Triple::le32) { + // For PNaCl, use ARM-style method pointers so that PNaCl code // does not assume anything about the alignment of function // pointers. return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true, /* UseARMGuardVarABI = */ false); - default: - return new ItaniumCXXABI(CGM); } + return new ItaniumCXXABI(CGM); case TargetCXXABI::Microsoft: llvm_unreachable("Microsoft ABI is not Itanium-based"); -- cgit v1.2.3-18-g5258 From 364355da26053c321180fa31ecd731d36c4cffae Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 25 Apr 2014 16:00:38 -0700 Subject: Don't align member functions. Emscripten uses the ARM ABI for pointers to member functions and doesn't require that member functions are aligned. --- include/clang/Basic/TargetCXXABI.h | 18 ++++++++++++++++++ lib/CodeGen/CodeGenModule.cpp | 8 +++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h index 29e4e47076..abdf899f5d 100644 --- a/include/clang/Basic/TargetCXXABI.h +++ b/include/clang/Basic/TargetCXXABI.h @@ -134,6 +134,24 @@ public: llvm_unreachable("bad ABI kind"); } + /// \brief Are pointers to member functions differently aligned? + bool arePointersToMemberFunctionsAligned() const { + switch (getKind()) { + case Emscripten: + case GenericARM: + case GenericAArch64: + // ARM-style pointers to member functions put the discriminator in the + // this adjustment, so they don't require functions to have any special + // alignment. + return false; + case GenericItanium: + case iOS: + case Microsoft: + return true; + } + llvm_unreachable("bad ABI kind"); + } + /// \brief Is the default C++ member function calling convention /// the same as the default calling convention? bool isMemberFunctionCCDefault() const { diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 15e4a50eaa..3fb7cba914 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -657,9 +657,11 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (alignment) F->setAlignment(alignment); - // C++ ABI requires 2-byte alignment for member functions. - if (F->getAlignment() < 2 && isa(D)) - F->setAlignment(2); + if (getTarget().getCXXABI().arePointersToMemberFunctionsAligned()) { + // C++ ABI requires 2-byte alignment for member functions. + if (F->getAlignment() < 2 && isa(D)) + F->setAlignment(2); + } } void CodeGenModule::SetCommonAttributes(const Decl *D, -- cgit v1.2.3-18-g5258 From dc171d8a2090ca1d46be0f164801edf8721ec5cc Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 6 May 2014 13:57:38 -0700 Subject: 1.17.0 --- emscripten-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emscripten-version.txt b/emscripten-version.txt index f488f67e2a..f9505a5cdc 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.16.0 +1.17.0 -- cgit v1.2.3-18-g5258