Add mangling support for calls, sizeof/alignof, constructor calls,

float literals, and unresolved lookups (which required hand-wavey extensions).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95273 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2010-02-04 01:42:13 +00:00
Родитель 40c37e1a62
Коммит 1dd7383dc4
3 изменённых файлов: 199 добавлений и 29 удалений

Просмотреть файл

@ -1602,11 +1602,24 @@ public:
arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
arg_iterator arg_end() { return arg_begin() + NumArgs; }
typedef const Expr* const * const_arg_iterator;
const_arg_iterator arg_begin() const {
return reinterpret_cast<const Expr* const *>(this + 1);
}
const_arg_iterator arg_end() const {
return arg_begin() + NumArgs;
}
Expr *getArg(unsigned I) {
assert(I < NumArgs && "Argument index out-of-range");
return *(arg_begin() + I);
}
const Expr *getArg(unsigned I) const {
assert(I < NumArgs && "Argument index out-of-range");
return *(arg_begin() + I);
}
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}

Просмотреть файл

@ -44,6 +44,8 @@ static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
return MD;
}
static const unsigned UnknownArity = ~0U;
/// CXXNameMangler - Manage the mangling of a single name.
class CXXNameMangler {
@ -55,6 +57,8 @@ class CXXNameMangler {
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
ASTContext &getASTContext() const { return Context.getASTContext(); }
public:
CXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
: Context(C), Out(Res), Structor(0), StructorType(0) { }
@ -89,10 +93,19 @@ private:
void addSubstitution(QualType T);
void addSubstitution(uintptr_t Ptr);
void mangleUnresolvedScope(NestedNameSpecifier *Qualifier);
void mangleUnresolvedName(NestedNameSpecifier *Qualifier,
DeclarationName Name,
unsigned KnownArity = UnknownArity);
void mangleName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
void mangleUnqualifiedName(const NamedDecl *ND);
void mangleUnqualifiedName(const NamedDecl *ND) {
mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
}
void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
unsigned KnownArity);
void mangleUnscopedName(const NamedDecl *ND);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
void mangleSourceName(const IdentifierInfo *II);
@ -119,6 +132,7 @@ private:
bool MangleReturnType);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
void mangleCalledExpression(const Expr *E, unsigned KnownArity);
void mangleExpression(const Expr *E);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
@ -398,28 +412,50 @@ void CXXNameMangler::mangleCallOffset(const ThunkAdjustment &Adjustment) {
Out << '_';
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
Qualifier = getASTContext().getCanonicalNestedNameSpecifier(Qualifier);
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
// nothing
break;
case NestedNameSpecifier::Namespace:
mangleName(Qualifier->getAsNamespace());
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
mangleType(QualType(Qualifier->getAsType(), 0));
break;
case NestedNameSpecifier::Identifier:
mangleUnresolvedScope(Qualifier->getPrefix());
mangleSourceName(Qualifier->getAsIdentifier());
break;
}
}
/// Mangles a name which was not resolved to a specific entity.
void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier,
DeclarationName Name,
unsigned KnownArity) {
if (Qualifier)
mangleUnresolvedScope(Qualifier);
// FIXME: ambiguity of unqualified lookup with ::
mangleUnqualifiedName(0, Name, KnownArity);
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name,
unsigned KnownArity) {
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name>
// ::= <source-name>
DeclarationName Name = ND->getDeclName();
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
// This is how gcc mangles these names. It's apparently
// always '1', no matter how many different anonymous
// namespaces appear in a context.
Out << "12_GLOBAL__N_1";
break;
}
}
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
// We must avoid conflicts between internally- and externally-
// linked names in the same TU. This naming convention is the
// same as that followed by GCC, though it shouldn't actually matter.
if (ND->getLinkage() == InternalLinkage &&
if (ND && ND->getLinkage() == InternalLinkage &&
ND->getDeclContext()->isFileContext())
Out << 'L';
@ -427,6 +463,17 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
break;
}
// Otherwise, an anonymous entity. We must have a declaration.
assert(ND && "mangling empty name without declaration");
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
if (NS->isAnonymousNamespace()) {
// This is how gcc mangles these names.
Out << "12_GLOBAL__N_1";
break;
}
}
// We must have an anonymous struct.
const TagDecl *TD = cast<TagDecl>(ND);
if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
@ -488,13 +535,18 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
break;
case DeclarationName::CXXOperatorName: {
unsigned Arity = cast<FunctionDecl>(ND)->getNumParams();
unsigned Arity;
if (ND) {
Arity = cast<FunctionDecl>(ND)->getNumParams();
// If we have a C++ member function, we need to include the 'this' pointer.
// FIXME: This does not make sense for operators that are static, but their
// names stay the same regardless of the arity (operator new for instance).
if (isa<CXXMethodDecl>(ND))
Arity++;
// If we have a C++ member function, we need to include the 'this' pointer.
// FIXME: This does not make sense for operators that are static, but their
// names stay the same regardless of the arity (operator new for instance).
if (isa<CXXMethodDecl>(ND))
Arity++;
} else
Arity = KnownArity;
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
break;
}
@ -1053,6 +1105,19 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
if (E->getType() != getASTContext().OverloadTy)
mangleExpression(E);
llvm::PointerIntPair<OverloadExpr*,1> R
= OverloadExpr::find(const_cast<Expr*>(E));
if (R.getInt())
Out << "an"; // &
const OverloadExpr *Ovl = R.getPointer();
mangleUnresolvedName(Ovl->getQualifier(), Ovl->getName(), Arity);
}
void CXXNameMangler::mangleExpression(const Expr *E) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
@ -1068,25 +1133,68 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
// ::= sZ <template-param> # size of a parameter pack
// ::= <expr-primary>
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type <value float> E # floating literal
// ::= L <mangled-name> E # external name
switch (E->getStmtClass()) {
default:
llvm_unreachable("unexpected statement kind");
break;
case Expr::CallExprClass:
// FIXME: implement
llvm_unreachable("mangling not implemented for calls");
case Expr::CallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
Out << "cl";
mangleCalledExpression(CE->getCallee(), CE->getNumArgs());
for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
mangleExpression(CE->getArg(I));
Out << "E";
break;
}
case Expr::CXXConstructExprClass:
// FIXME: implement
llvm_unreachable("mangling not implemented for construct exprs");
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), UnknownArity);
break;
}
case Expr::CXXUnresolvedConstructExprClass: {
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
unsigned N = CE->arg_size();
Out << "cv";
mangleType(CE->getType());
if (N != 1) Out << "_";
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
if (N != 1) Out << "E";
break;
}
case Expr::SizeOfAlignOfExprClass:
// FIXME: implement
llvm_unreachable("mangling not implemented for sizeof/alignof");
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXConstructExprClass: {
const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
unsigned N = CE->getNumArgs();
Out << "cv";
mangleType(CE->getType());
if (N != 1) Out << "_";
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
if (N != 1) Out << "E";
break;
}
case Expr::SizeOfAlignOfExprClass: {
const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
if (SAE->isSizeOf()) Out << "s";
else Out << "a";
if (SAE->isArgumentType()) {
Out << "t";
mangleType(SAE->getArgumentType());
} else {
Out << "z";
mangleExpression(SAE->getArgumentExpr());
}
break;
}
case Expr::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(E);
@ -1178,6 +1286,20 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
break;
}
case Expr::FloatingLiteralClass: {
const FloatingLiteral *FL = cast<FloatingLiteral>(E);
Out << "L";
mangleType(FL->getType());
// TODO: avoid this copy with careful stream management.
llvm::SmallVector<char,20> Buffer;
FL->getValue().bitcastToAPInt().toString(Buffer, 16, false);
Out.write(Buffer.data(), Buffer.size());
Out << "E";
break;
}
case Expr::IntegerLiteralClass:
mangleIntegerLiteral(E->getType(),
llvm::APSInt(cast<IntegerLiteral>(E)->getValue()));

Просмотреть файл

@ -322,3 +322,38 @@ static int pr5966_i;
void pr5966_bar() {
pr5966_i = 0;
}
namespace test0 {
int ovl(int x);
char ovl(double x);
template <class T> void f(T, char (&buffer)[sizeof(ovl(T()))]) {}
void test0() {
char buffer[1];
f(0.0, buffer);
}
// CHECK: define void @_ZN5test05test0Ev()
// CHECK: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c(
void test1() {
char buffer[sizeof(int)];
f(1, buffer);
}
// CHECK: define void @_ZN5test05test1Ev()
// CHECK: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c(
template <class T> void g(char (&buffer)[sizeof(T() + 5.0f)]) {}
void test2() {
char buffer[sizeof(float)];
g<float>(buffer);
}
// CHECK: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40A00000E_c(
template <class T> void h(char (&buffer)[sizeof(T() + 5.0)]) {}
void test3() {
char buffer[sizeof(double)];
h<float>(buffer);
}
// CHECK: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c(
}