Change the mangling of metadata objects to be more consistent.

Swift SVN r2850
This commit is contained in:
John McCall
2012-09-13 21:26:02 +00:00
parent 5d3e130587
commit ab8677cf7f
2 changed files with 78 additions and 42 deletions

View File

@@ -10,6 +10,8 @@ Mangling
All Swift-mangled names begin with this prefix.
global ::= 'M' directness type // type metadata
global ::= 'MP' directness type // type metadata pattern
global ::= 'w' value-witness-kind type // value witness
global ::= 'WV' type // value witness table
global ::= local-marker? entity // some identifiable thing
@@ -18,13 +20,20 @@ All Swift-mangled names begin with this prefix.
entity ::= declaration 'g' // getter
entity ::= declaration 's' // setter
entity ::= declaration // other declaration
entity ::= context 'H' // class metadata
declaration ::= context identifier type
local-marker ::= 'L'
Entity manglings all start with a nominal-type-kind ([COV]), an
identifier ([0-9o]), or a substitution ([S]). Global manglings start
with any of those or [Ww].
with any of those or [MWw].
directness ::= 'd' // direct
directness ::= 'i' // indirect
A direct symbol resolves directly to the address of an object. An
indirect symbol resolves to the address of a pointer to the object.
They are distinct manglings to make a certain class of bugs
immediately obvious.
context ::= module
context ::= function

View File

@@ -93,12 +93,14 @@ namespace {
void mangleDeclName(ValueDecl *decl, IncludeType includeType);
void mangleDeclType(ValueDecl *decl, ExplosionKind kind,
unsigned uncurryingLevel);
void mangleEntity(ValueDecl *decl, ExplosionKind kind,
unsigned uncurryingLevel);
void mangleNominalType(NominalTypeDecl *decl, ExplosionKind explosionKind);
void mangleType(Type type, ExplosionKind kind, unsigned uncurryingLevel);
private:
void mangleFunctionType(AnyFunctionType *fn, ExplosionKind explosionKind,
unsigned uncurryingLevel);
void mangleNominalType(NominalTypeDecl *decl, ExplosionKind explosionKind);
void mangleProtocolList(ArrayRef<ProtocolDecl*> protocols);
void mangleProtocolList(ArrayRef<Type> protocols);
void mangleProtocolName(ProtocolDecl *protocol);
@@ -620,6 +622,16 @@ void Mangler::mangleFunctionType(AnyFunctionType *fn,
(uncurryLevel > 0 ? uncurryLevel - 1 : 0));
}
void Mangler::mangleEntity(ValueDecl *decl, ExplosionKind explosion,
unsigned uncurryLevel) {
mangleDeclName(decl, IncludeType::No);
// Mangle in a type as well. Note that we have to mangle the type
// on all kinds of declarations, even variables, because at the
// moment they can *all* be overloaded.
mangleDeclType(decl, explosion, uncurryLevel);
}
static StringRef mangleValueWitness(ValueWitness witness) {
// The ones with at least one capital are the composite ops, and the
// capitals correspond roughly to the positions of buffers (as
@@ -648,57 +660,72 @@ static StringRef mangleValueWitness(ValueWitness witness) {
}
void LinkEntity::mangle(raw_ostream &buffer) const {
// mangled-name ::= '_Tw' witness-kind type
if (getKind() == Kind::ValueWitness) {
buffer << "_Tw";
buffer << mangleValueWitness(getValueWitness());
Mangler mangler(buffer);
mangler.mangleType(getType(), ExplosionKind::Minimal, 0);
return;
}
// Declarations with asm names just use that.
assert(isDeclKind(getKind()));
if (!getDecl()->getAttrs().AsmName.empty()) {
// As a special case, functions can have external asm names.
if (getKind() == Kind::Function &&
!getDecl()->getAttrs().AsmName.empty()) {
buffer << getDecl()->getAttrs().AsmName;
return;
}
// mangled-name ::= '_T' identifier+ type?
// Add the prefix.
buffer << "_T"; // T is for Tigger
// Otherwise, everything gets the common prefix.
// mangled-name ::= '_T' global
buffer << "_T";
if (isLocalLinkage())
buffer << "L";
Mangler mangler(buffer);
switch (getKind()) {
case Kind::ClassMetadata:
// global ::= 'w' value-witness-kind type // value witness
case Kind::ValueWitness:
buffer << 'w';
buffer << mangleValueWitness(getValueWitness());
mangler.mangleType(getType(), ExplosionKind::Minimal, 0);
return;
// global ::= 'M' directness type // type metadata
// global ::= 'MP' directness type // type metadata pattern
case Kind::ClassMetadata: {
buffer << 'M';
ClassDecl *theClass = cast<ClassDecl>(getDecl());
if (theClass->getGenericParamsOfContext()) {
buffer << 'P';
}
buffer << 'd'; // always direct for now
mangler.mangleNominalType(theClass, ExplosionKind::Minimal);
return;
}
// For all the following, this rule was imposed above:
// global ::= local-marker? entity // some identifiable thing
// entity ::= context 'D' // destructor
case Kind::Destructor:
mangler.mangleDeclContext(cast<ClassDecl>(getDecl()));
break;
buffer << 'D';
return;
default:
mangler.mangleDeclName(getDecl(), IncludeType::No);
break;
}
// Mangle in a type as well. Note that we have to mangle the type
// on all kinds of declarations, even variables, because at the
// moment they can *all* be overloaded.
if (ValueDecl *valueDecl = dyn_cast<ValueDecl>(getDecl()))
mangler.mangleDeclType(valueDecl, getExplosionKind(), getUncurryLevel());
// Add a suffix if applicable.
switch (getKind()) {
case Kind::Function: break;
case Kind::Other: break;
case Kind::Getter: buffer << "g"; break;
case Kind::Setter: buffer << "s"; break;
case Kind::Destructor: buffer << "D"; break; // for 'destructor'
case Kind::ClassMetadata: buffer << 'H'; break; // for 'heap'
case Kind::ValueWitness: llvm_unreachable("filtered out!");
// entity ::= declaration // other declaration
// entity ::= context 'C' type // constructor
// The latter case is essentially as if 'C' were the name of the function.
case Kind::Function:
case Kind::Other:
mangler.mangleEntity(getDecl(), getExplosionKind(), getUncurryLevel());
return;
// entity ::= declaration 'g' // getter
case Kind::Getter:
mangler.mangleEntity(getDecl(), getExplosionKind(), getUncurryLevel());
buffer << 'g';
return;
// entity ::= declaration 's' // setter
case Kind::Setter:
mangler.mangleEntity(getDecl(), getExplosionKind(), getUncurryLevel());
buffer << 's';
return;
}
llvm_unreachable("bad entity kind!");
}