mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
2188 lines
59 KiB
C++
2188 lines
59 KiB
C++
#include "BfMangler.h"
|
|
#include "BfDemangler.h"
|
|
#include "BfCompiler.h"
|
|
#pragma warning(disable:4996)
|
|
|
|
USING_NS_BF;
|
|
|
|
int BfGNUMangler::ParseSubIdx(StringImpl& name, int strIdx)
|
|
{
|
|
const char* charPtr = name.c_str() + strIdx + 1;
|
|
if (*charPtr == '_')
|
|
return 0;
|
|
int idx = atoi(charPtr) + 1;
|
|
return idx;
|
|
}
|
|
|
|
void BfGNUMangler::AddSubIdx(StringImpl& name, int subIdx)
|
|
{
|
|
name += 'S';
|
|
if (subIdx != 0)
|
|
{
|
|
int showIdx = subIdx - 1;
|
|
if (showIdx > 36)
|
|
{
|
|
name += '0' + (showIdx / 36);
|
|
showIdx %= 36;
|
|
}
|
|
if (showIdx < 10)
|
|
name += '0' + showIdx;
|
|
else
|
|
name += 'A' + (showIdx - 10);
|
|
}
|
|
name += '_';
|
|
}
|
|
|
|
void BfGNUMangler::AddSizedString(StringImpl& name, const StringImpl& addStr)
|
|
{
|
|
char str[16];
|
|
itoa((int)addStr.length(), str, 10);
|
|
name += str;
|
|
name += addStr;
|
|
}
|
|
|
|
BfTypeCode BfGNUMangler::GetPrimTypeAt(MangleContext& mangleContext, StringImpl& name, int strIdx)
|
|
{
|
|
char startChar = name[strIdx];
|
|
|
|
auto module = mangleContext.mModule;
|
|
switch (startChar)
|
|
{
|
|
case 'v': return BfTypeCode_None;
|
|
case 'b': return BfTypeCode_Boolean;
|
|
case 'a': return BfTypeCode_Int8;
|
|
case 'h': return BfTypeCode_UInt8;
|
|
case 's': return BfTypeCode_Int16;
|
|
case 't': return BfTypeCode_UInt16;
|
|
case 'i': return BfTypeCode_Int32;
|
|
case 'j': return BfTypeCode_UInt32;
|
|
#if __SIZEOF_LONG__ == 8
|
|
case 'l': return BfTypeCode_Int64;
|
|
case 'm': return BfTypeCode_UInt64;
|
|
#else
|
|
case 'x': return BfTypeCode_Int64;
|
|
case 'y': return BfTypeCode_UInt64;
|
|
#endif
|
|
case 'u':
|
|
if (name[strIdx + 1] == '3')
|
|
return BfTypeCode_IntPtr;
|
|
if (name[strIdx + 1] == '4')
|
|
return BfTypeCode_UIntPtr;
|
|
break;
|
|
case 'c': return BfTypeCode_Char8;
|
|
case 'D':
|
|
if (name[strIdx + 1] == 'i')
|
|
return BfTypeCode_Char32;
|
|
else if (name[strIdx + 1] == 's')
|
|
return BfTypeCode_Char16;
|
|
break;
|
|
case 'f': return BfTypeCode_Single;
|
|
case 'd': return BfTypeCode_Double;
|
|
}
|
|
return (BfTypeCode)-1;
|
|
}
|
|
|
|
void BfGNUMangler::AddPrefix(MangleContext& mangleContext, StringImpl& name, int startIdx, const char* prefix)
|
|
{
|
|
int subIdx;
|
|
char startChar = name[startIdx];
|
|
if (startChar == 'S')
|
|
{
|
|
subIdx = ParseSubIdx(name, startIdx);
|
|
for (int matchIdx = subIdx + 1; matchIdx < (int)mangleContext.mSubstituteList.size(); matchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[matchIdx];
|
|
if ((entry.mKind == NameSubstitute::Kind_Prefix) && (entry.mExtendsIdx == subIdx) && (entry.mPrefix == prefix))
|
|
{
|
|
BF_ASSERT(name.EndsWith('_'));
|
|
name.RemoveToEnd(startIdx);
|
|
AddSubIdx(name, matchIdx);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto typeCode = GetPrimTypeAt(mangleContext, name, startIdx);
|
|
if (typeCode != (BfTypeCode)-1)
|
|
{
|
|
for (int matchIdx = 0; matchIdx < (int)mangleContext.mSubstituteList.size(); matchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[matchIdx];
|
|
if ((entry.mKind == NameSubstitute::Kind_PrimitivePrefix) && (entry.mExtendsTypeCode == typeCode) && (entry.mPrefix == prefix))
|
|
{
|
|
name.RemoveToEnd(startIdx);
|
|
AddSubIdx(name, matchIdx);
|
|
return;
|
|
}
|
|
}
|
|
|
|
NameSubstitute nameSub;
|
|
nameSub.mKind = NameSubstitute::Kind_PrimitivePrefix;
|
|
nameSub.mExtendsTypeCode = typeCode;
|
|
nameSub.mPrefix = prefix;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name.Insert(startIdx, prefix);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Applies to last-added one
|
|
subIdx = (int)mangleContext.mSubstituteList.size() - 1;
|
|
BF_ASSERT(isdigit(startChar) || (startChar == 'A') || (startChar == 'N') || (startChar == 'P') || (startChar == 'R') || (startChar == 'U'));
|
|
}
|
|
}
|
|
|
|
NameSubstitute nameSub;
|
|
nameSub.mKind = NameSubstitute::Kind_Prefix;
|
|
nameSub.mExtendsIdx = subIdx;
|
|
nameSub.mPrefix = prefix;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name.Insert(startIdx, prefix);
|
|
}
|
|
|
|
void BfGNUMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl& name, const NameSubstitute& newNameSub)
|
|
{
|
|
int curMatchIdx = -1;
|
|
bool matchFailed = false;
|
|
FindOrCreateNameSub(mangleContext, name, newNameSub, curMatchIdx, matchFailed);
|
|
if (!matchFailed)
|
|
AddSubIdx(name, curMatchIdx);
|
|
}
|
|
|
|
void BfGNUMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl& name, const NameSubstitute& newNameSub, int& curMatchIdx, bool& matchFailed)
|
|
{
|
|
int parentIdx = curMatchIdx;
|
|
if (!matchFailed)
|
|
{
|
|
curMatchIdx++;
|
|
for ( ; curMatchIdx < (int)mangleContext.mSubstituteList.size(); curMatchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[curMatchIdx];
|
|
if ((entry.mExtendsIdx == parentIdx) && (entry.mKind == newNameSub.mKind) && (entry.mParam == newNameSub.mParam))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
matchFailed = true;
|
|
if (newNameSub.mKind != BfGNUMangler::NameSubstitute::Kind_GenericParam)
|
|
name += "N";
|
|
if (parentIdx != -1)
|
|
AddSubIdx(name, parentIdx);
|
|
}
|
|
|
|
if (newNameSub.mKind == NameSubstitute::Kind_NamespaceAtom)
|
|
{
|
|
AddSizedString(name, newNameSub.mAtom->mString.mPtr);
|
|
}
|
|
else if (newNameSub.mKind == NameSubstitute::Kind_TypeInstName)
|
|
{
|
|
auto typeDef = newNameSub.mTypeInst->mTypeDef;
|
|
// Mixing this in could create linking errors since the references to the "correct" version won't necessarily be recompiled
|
|
// when we remove the "incorrect" version. I believe this is no longer needed since our compilation model has changed
|
|
/*if (typeDef->mDupDetectedRevision != -1)
|
|
{
|
|
char str[64];
|
|
sprintf(str, "_%p", typeDef);
|
|
name += str;
|
|
}*/
|
|
if ((typeDef->mIsDelegate) && (newNameSub.mTypeInst->IsClosure()))
|
|
{
|
|
auto closureType = (BfClosureType*)newNameSub.mTypeInst;
|
|
if (!closureType->mCreatedTypeDef)
|
|
name += closureType->mNameAdd;
|
|
}
|
|
AddSizedString(name, typeDef->mName->mString.mPtr);
|
|
}
|
|
else if (newNameSub.mKind == BfGNUMangler::NameSubstitute::Kind_TypeGenericArgs)
|
|
{
|
|
int genericParamStart = 0;
|
|
if (newNameSub.mTypeInst->mTypeDef->mOuterType != NULL)
|
|
genericParamStart = (int)newNameSub.mTypeInst->mTypeDef->mOuterType->mGenericParamDefs.size();
|
|
|
|
name += "I";
|
|
|
|
auto typeDef = newNameSub.mTypeInst->mTypeDef;
|
|
|
|
BfType* checkType = newNameSub.mTypeInst;
|
|
if (checkType->IsClosure())
|
|
{
|
|
checkType = ((BfClosureType*)checkType)->mSrcDelegate;
|
|
}
|
|
|
|
BF_ASSERT(checkType->IsGenericTypeInstance());
|
|
BfGenericTypeInstance* genericTypeInstance = (BfGenericTypeInstance*)checkType;
|
|
|
|
for (int genericParamIdx = genericParamStart; genericParamIdx < (int) typeDef->mGenericParamDefs.size(); genericParamIdx++)
|
|
{
|
|
auto genericParam = genericTypeInstance->mTypeGenericArguments[genericParamIdx];
|
|
|
|
Mangle(mangleContext, name, genericParam);
|
|
}
|
|
|
|
name += "E";
|
|
}
|
|
else if (newNameSub.mKind == BfGNUMangler::NameSubstitute::Kind_GenericParam)
|
|
{
|
|
auto genericParamType = (BfGenericParamType*)newNameSub.mType;
|
|
char str[16];
|
|
if (genericParamType->mGenericParamIdx < 10)
|
|
name += "3";
|
|
else
|
|
name += "4";
|
|
if (genericParamType->mGenericParamKind == BfGenericParamKind_Method)
|
|
name += "@M";
|
|
else
|
|
name += "@T";
|
|
itoa(genericParamType->mGenericParamIdx, str, 10);
|
|
name += str;
|
|
}
|
|
|
|
curMatchIdx = (int)mangleContext.mSubstituteList.size();
|
|
mangleContext.mSubstituteList.push_back(newNameSub);
|
|
|
|
auto& nameSubRef = mangleContext.mSubstituteList.back();
|
|
nameSubRef.mExtendsIdx = parentIdx;
|
|
}
|
|
|
|
void BfGNUMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl& name, BfTypeInstance* typeInst, int& curMatchIdx, bool& matchFailed)
|
|
{
|
|
auto typeDef = typeInst->mTypeDef;
|
|
if (typeDef->IsGlobalsContainer())
|
|
return;
|
|
|
|
int numOuterGenericParams = 0;
|
|
if (typeDef->mOuterType != NULL)
|
|
{
|
|
numOuterGenericParams = (int)typeDef->mOuterType->mGenericParamDefs.size();
|
|
auto useModule = typeInst->mModule;
|
|
if (useModule == NULL)
|
|
useModule = mangleContext.mModule;
|
|
auto outerType = useModule->GetOuterType(typeInst);
|
|
FindOrCreateNameSub(mangleContext, name, outerType, curMatchIdx, matchFailed);
|
|
}
|
|
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_TypeInstName, typeInst), curMatchIdx, matchFailed);
|
|
|
|
if (typeDef->mGenericParamDefs.size() != numOuterGenericParams)
|
|
{
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_TypeGenericArgs, typeInst), curMatchIdx, matchFailed);
|
|
}
|
|
}
|
|
|
|
void BfGNUMangler::MangleTypeInst(MangleContext& mangleContext, StringImpl& name, BfTypeInstance* typeInst, BfTypeInstance* postfixTypeInstance, bool* isEndOpen)
|
|
{
|
|
static int sCallCount = 0;
|
|
sCallCount++;
|
|
|
|
if (typeInst->IsTuple())
|
|
{
|
|
auto tupleType = (BfTupleType*)typeInst;
|
|
name += "N7__TUPLEI";
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for '__TUPLE'
|
|
for (int fieldIdx = 0; fieldIdx < (int)tupleType->mFieldInstances.size(); fieldIdx++)
|
|
{
|
|
BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx];
|
|
BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
|
|
String fieldName = fieldDef->mName;
|
|
if ((fieldName[0] < '0') || (fieldName[0] > '9'))
|
|
name += StrFormat("U%d@%s", fieldName.length() + 1, fieldName.c_str());
|
|
Mangle(mangleContext, name, fieldInstance->mResolvedType, postfixTypeInstance);
|
|
}
|
|
name += "E";
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for '__TUPLE<T>'
|
|
if (isEndOpen != NULL)
|
|
*isEndOpen = true;
|
|
else
|
|
name += "E";
|
|
return;
|
|
}
|
|
else if ((typeInst->IsDelegateFromTypeRef()) || (typeInst->IsFunctionFromTypeRef()))
|
|
{
|
|
auto invokeMethodInst = mangleContext.mModule->GetDelegateInvokeMethod(typeInst);
|
|
if (typeInst->IsDelegate())
|
|
name += "N8delegateI";
|
|
else
|
|
name += "N8functionI";
|
|
BfTypeVector typeVec;
|
|
typeVec.push_back(invokeMethodInst->mReturnType);
|
|
for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
|
|
{
|
|
name += "_";
|
|
name += invokeMethodInst->GetParamName(paramIdx);
|
|
typeVec.Add(invokeMethodInst->GetParamType(paramIdx));
|
|
}
|
|
for (auto type : typeVec)
|
|
Mangle(mangleContext, name, type, postfixTypeInstance);
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Delegate'
|
|
name += "E";
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Delegate<T>'
|
|
if (isEndOpen != NULL)
|
|
*isEndOpen = true;
|
|
else
|
|
name += "E";
|
|
name += "E";
|
|
}
|
|
else if (typeInst->IsBoxed())
|
|
{
|
|
auto boxedType = (BfBoxedType*)typeInst;
|
|
name += "N3BoxI";
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Box'
|
|
Mangle(mangleContext, name, boxedType->GetModifiedElementType(), postfixTypeInstance);
|
|
name += "E";
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Box<T>'
|
|
if (isEndOpen != NULL)
|
|
*isEndOpen = true;
|
|
else
|
|
name += "E";
|
|
return;
|
|
}
|
|
|
|
int curMatchIdx = -1;
|
|
bool matchFailed = false;
|
|
for (int typeIdx = 0; typeIdx < 2; typeIdx++)
|
|
{
|
|
BfTypeInstance* useTypeInst = typeInst;
|
|
if (typeIdx == 1)
|
|
{
|
|
if (postfixTypeInstance == NULL)
|
|
break;
|
|
useTypeInst = postfixTypeInstance;
|
|
}
|
|
|
|
auto typeDef = useTypeInst->mTypeDef;
|
|
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_NamespaceAtom, typeInst->mModule->mSystem->mBfAtom), curMatchIdx, matchFailed);
|
|
|
|
for (int i = 0; i < typeDef->mNamespace.mSize; i++)
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_NamespaceAtom, typeDef->mNamespace.mParts[i]), curMatchIdx, matchFailed);
|
|
|
|
FindOrCreateNameSub(mangleContext, name, useTypeInst, curMatchIdx, matchFailed);
|
|
}
|
|
if (isEndOpen != NULL)
|
|
{
|
|
if (!matchFailed)
|
|
{
|
|
if (curMatchIdx != -1)
|
|
{
|
|
name += "N";
|
|
AddSubIdx(name, curMatchIdx);
|
|
*isEndOpen = true;
|
|
}
|
|
else
|
|
*isEndOpen = false;
|
|
}
|
|
else
|
|
*isEndOpen = true;
|
|
return;
|
|
}
|
|
|
|
if (matchFailed)
|
|
{
|
|
name += "E";
|
|
}
|
|
else
|
|
{
|
|
AddSubIdx(name, curMatchIdx);
|
|
}
|
|
}
|
|
|
|
void BfGNUMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* type, BfType* postfixType)
|
|
{
|
|
static int sCallCount = 0;
|
|
sCallCount++;
|
|
|
|
if (type->IsPrimitiveType())
|
|
{
|
|
auto primType = (BfPrimitiveType*)type;
|
|
|
|
switch (primType->mTypeDef->mTypeCode)
|
|
{
|
|
case BfTypeCode_NullPtr:
|
|
{
|
|
auto pointerType = (BfPointerType*)type;
|
|
int startIdx = (int)name.length();
|
|
name += "v";
|
|
AddPrefix(mangleContext, name, startIdx, "P");
|
|
}
|
|
return;
|
|
case BfTypeCode_Dot:
|
|
name += "U3dot";
|
|
return;
|
|
case BfTypeCode_None:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
name += "v";
|
|
else
|
|
name += "U4void";
|
|
return;
|
|
case BfTypeCode_Var:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
name += "v";
|
|
else
|
|
name += "U3var";
|
|
return;
|
|
case BfTypeCode_Self:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
name += "U8concrete";
|
|
else
|
|
name += "U4self";
|
|
return;
|
|
case BfTypeCode_Boolean:
|
|
name += "b"; return;
|
|
case BfTypeCode_Int8:
|
|
name += "a"; return;
|
|
case BfTypeCode_UInt8:
|
|
name += "h"; return;
|
|
case BfTypeCode_Int16:
|
|
name += "s"; return;
|
|
case BfTypeCode_UInt16:
|
|
name += "t"; return;
|
|
case BfTypeCode_Int32:
|
|
name += "i"; return;
|
|
case BfTypeCode_UInt32:
|
|
name += "j"; return;
|
|
#if __SIZEOF_LONG__ == 8
|
|
case BfTypeCode_Int64:
|
|
name += "l"; return;
|
|
case BfTypeCode_UInt64:
|
|
name += "m"; return;
|
|
#else
|
|
case BfTypeCode_Int64:
|
|
name += "x"; return;
|
|
case BfTypeCode_UInt64:
|
|
name += "y"; return;
|
|
#endif
|
|
case BfTypeCode_UIntPtr:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
{
|
|
#if __SIZEOF_LONG__ == 8
|
|
name += (primType->mSize == 8) ? "m" : "j";
|
|
#else
|
|
name += (primType->mSize == 8) ? "y" : "j";
|
|
#endif
|
|
return;
|
|
}
|
|
name += "u4uint";
|
|
return;
|
|
case BfTypeCode_IntPtr:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
{
|
|
#if __SIZEOF_LONG__ == 8
|
|
name += (primType->mSize == 8) ? "l" : "i";
|
|
#else
|
|
name += (primType->mSize == 8) ? "x" : "i";
|
|
#endif
|
|
return;
|
|
}
|
|
name += "u3int";
|
|
return;
|
|
case BfTypeCode_Char8:
|
|
name += "c"; return;
|
|
case BfTypeCode_Char16:
|
|
name += "Ds"; return;
|
|
case BfTypeCode_Char32:
|
|
name += "Di"; return;
|
|
case BfTypeCode_Single:
|
|
name += "f"; return;
|
|
case BfTypeCode_Double:
|
|
name += "d"; return;
|
|
}
|
|
|
|
name += "?"; return;
|
|
//name += Mangle(primType->mTypeDef, NULL, addName, NULL, substituteList);
|
|
}
|
|
else if (type->IsTypeInstance())
|
|
{
|
|
BfTypeInstance* postfixTypeInst = NULL;
|
|
if (postfixType != NULL)
|
|
postfixTypeInst = postfixType->ToTypeInstance();
|
|
|
|
auto typeInstance = (BfTypeInstance*)type;
|
|
|
|
int startIdx = (int)name.length();
|
|
MangleTypeInst(mangleContext, name, typeInstance, postfixTypeInst);
|
|
if ((type->IsObjectOrInterface()) && (mangleContext.mPrefixObjectPointer))
|
|
AddPrefix(mangleContext, name, startIdx, "P");
|
|
}
|
|
else if (type->IsGenericParam())
|
|
{
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_GenericParam, type));
|
|
}
|
|
else if (type->IsPointer())
|
|
{
|
|
auto pointerType = (BfPointerType*)type;
|
|
int startIdx = (int)name.length();
|
|
Mangle(mangleContext, name, pointerType->mElementType);
|
|
AddPrefix(mangleContext, name, startIdx, "P");
|
|
return;
|
|
}
|
|
else if (type->IsRef())
|
|
{
|
|
BfRefType* refType = (BfRefType*)type;
|
|
if ((refType->mRefKind == BfRefType::RefKind_Mut) && (!mangleContext.mCCompat))
|
|
{
|
|
name += "U3mut";
|
|
Mangle(mangleContext, name, refType->mElementType);
|
|
return;
|
|
}
|
|
else if ((refType->mRefKind == BfRefType::RefKind_Out) && (!mangleContext.mCCompat))
|
|
{
|
|
name += "U3out";
|
|
Mangle(mangleContext, name, refType->mElementType);
|
|
return;
|
|
}
|
|
int startIdx = (int)name.length();
|
|
Mangle(mangleContext, name, refType->mElementType);
|
|
AddPrefix(mangleContext, name, startIdx, "R");
|
|
return;
|
|
}
|
|
else if (type->IsRetTypeType())
|
|
{
|
|
BfRetTypeType* retTypeType = (BfRetTypeType*)type;
|
|
name += "U7rettype";
|
|
Mangle(mangleContext, name, retTypeType->mElementType);
|
|
return;
|
|
}
|
|
else if (type->IsConcreteInterfaceType())
|
|
{
|
|
BfConcreteInterfaceType* concreteInterfaceType = (BfConcreteInterfaceType*)type;
|
|
name += "U8concrete";
|
|
Mangle(mangleContext, name, concreteInterfaceType->mInterface);
|
|
return;
|
|
}
|
|
else if (type->IsSizedArray())
|
|
{
|
|
BfSizedArrayType* arrayType = (BfSizedArrayType*)type;
|
|
name += StrFormat("A%d_");
|
|
Mangle(mangleContext, name, arrayType->mElementType);
|
|
return;
|
|
}
|
|
else if (type->IsMethodRef())
|
|
{
|
|
auto methodRefType = (BfMethodRefType*)type;
|
|
String mrefName = "mref_";
|
|
String mangleName;
|
|
BfMethodInstance* methodInstance = methodRefType->mMethodRef;
|
|
if (methodInstance == NULL)
|
|
{
|
|
BF_ASSERT(!methodRefType->mMangledMethodName.IsEmpty());
|
|
mangleName = methodRefType->mMangledMethodName;
|
|
}
|
|
else
|
|
{
|
|
if (methodInstance->mIsAutocompleteMethod)
|
|
name += "AUTOCOMPLETE";
|
|
|
|
auto module = methodInstance->GetOwner()->mModule;
|
|
if (module->mCompiler->mIsResolveOnly)
|
|
{
|
|
// There are cases where we will reprocess a method in ResolveOnly for things like
|
|
// GetSymbolReferences, so we will have duplicate live local methodInstances in those cases
|
|
mrefName += HashEncode64((uint64)methodRefType->mMethodRef);
|
|
}
|
|
else
|
|
{
|
|
mangleName = Mangle(methodInstance);
|
|
methodRefType->mMangledMethodName = mangleName;
|
|
}
|
|
}
|
|
|
|
if (!mangleName.IsEmpty())
|
|
{
|
|
Val128 val128 = Hash128(mangleName.c_str(), (int)mangleName.length());
|
|
mrefName += HashEncode128(val128);
|
|
}
|
|
|
|
//TODO: Make a 'U' name?
|
|
name += mrefName;
|
|
}
|
|
else if (type->IsConstExprValue())
|
|
{
|
|
BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type;
|
|
int64 val = constExprValueType->mValue.mInt64;
|
|
|
|
if ((!constExprValueType->mType->IsPrimitiveType()) ||
|
|
(((BfPrimitiveType*)constExprValueType->mType)->mTypeDef->mTypeCode != BfTypeCode_IntPtr))
|
|
{
|
|
Mangle(mangleContext, name, constExprValueType->mType);
|
|
}
|
|
|
|
name += "$0";
|
|
|
|
if (val < 0)
|
|
{
|
|
name += "?";
|
|
val = -val;
|
|
}
|
|
if ((val >= 1) && (val < 10))
|
|
{
|
|
val += (char)('0' + val - 1);
|
|
}
|
|
else
|
|
{
|
|
char str[64];
|
|
char* strP = str + 63;
|
|
*strP = 0;
|
|
|
|
while (val > 0)
|
|
{
|
|
*(strP--) = (char)((val % 0x10) + 'A');
|
|
val /= 0x10;
|
|
}
|
|
|
|
name += strP;
|
|
name += '@';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BF_FATAL("Not handled");
|
|
}
|
|
}
|
|
|
|
String BfGNUMangler::Mangle(BfType* type, BfModule* module)
|
|
{
|
|
StringT<256> name;
|
|
name += "_ZTS";
|
|
MangleContext mangleContext;
|
|
mangleContext.mModule = module;
|
|
Mangle(mangleContext, name, type);
|
|
return name;
|
|
}
|
|
|
|
String BfGNUMangler::Mangle(BfMethodInstance* methodInst)
|
|
{
|
|
StringT<256> name;
|
|
|
|
if ((methodInst->mMethodDef->mCLink) && (!methodInst->mMangleWithIdx))
|
|
{
|
|
return methodInst->mMethodDef->mName;
|
|
}
|
|
|
|
MangleContext mangleContext;
|
|
mangleContext.mModule = methodInst->GetOwner()->mModule;
|
|
mangleContext.mCCompat = methodInst->mMethodDef->mIsExtern;
|
|
//auto substituteListPtr = doSubstitute ? &mangleContext.mSubstituteList : NULL;
|
|
|
|
auto typeInst = methodInst->GetOwner();
|
|
auto methodDef = methodInst->mMethodDef;
|
|
|
|
bool mangledMethodIdx = false;
|
|
bool prefixLen = false;
|
|
|
|
bool isNameOpen = false;
|
|
name += "_Z";
|
|
MangleTypeInst(mangleContext, name, methodInst->mMethodInstanceGroup->mOwner, methodInst->GetExplicitInterface(), &isNameOpen);
|
|
|
|
if (methodInst->GetForeignType() != NULL)
|
|
{
|
|
// This won't demangle correctly. TODO: Do this 'correctly'
|
|
MangleTypeInst(mangleContext, name, methodInst->GetForeignType());
|
|
}
|
|
|
|
mangleContext.mPrefixObjectPointer = true;
|
|
String methodName = methodInst->mMethodDef->mName;
|
|
|
|
if (methodInst->mMethodDef->mIsOperator)
|
|
{
|
|
auto operatorDef = (BfOperatorDef*)methodInst->mMethodDef;
|
|
if (operatorDef->mOperatorDeclaration->mIsConvOperator)
|
|
{
|
|
methodName = "cv";
|
|
Mangle(mangleContext, methodName, methodInst->mReturnType);
|
|
}
|
|
else
|
|
{
|
|
switch (operatorDef->mOperatorDeclaration->mBinOp)
|
|
{
|
|
case BfBinaryOp_Add:
|
|
methodName = "pl";
|
|
break;
|
|
case BfBinaryOp_Subtract:
|
|
methodName = "mi";
|
|
break;
|
|
case BfBinaryOp_Multiply:
|
|
methodName = "ml";
|
|
break;
|
|
case BfBinaryOp_Divide:
|
|
methodName = "dv";
|
|
break;
|
|
case BfBinaryOp_Modulus:
|
|
methodName = "rm";
|
|
break;
|
|
case BfBinaryOp_BitwiseAnd:
|
|
methodName = "an";
|
|
break;
|
|
case BfBinaryOp_BitwiseOr:
|
|
methodName = "or";
|
|
break;
|
|
case BfBinaryOp_ExclusiveOr:
|
|
methodName = "eo";
|
|
break;
|
|
case BfBinaryOp_LeftShift:
|
|
methodName = "ls";
|
|
break;
|
|
case BfBinaryOp_RightShift:
|
|
methodName = "rs";
|
|
break;
|
|
case BfBinaryOp_Equality:
|
|
methodName = "eq";
|
|
break;
|
|
case BfBinaryOp_InEquality:
|
|
methodName = "ne";
|
|
break;
|
|
case BfBinaryOp_GreaterThan:
|
|
methodName = "gt";
|
|
break;
|
|
case BfBinaryOp_LessThan:
|
|
methodName = "lt";
|
|
break;
|
|
case BfBinaryOp_GreaterThanOrEqual:
|
|
methodName = "ge";
|
|
break;
|
|
case BfBinaryOp_LessThanOrEqual:
|
|
methodName = "le";
|
|
break;
|
|
case BfBinaryOp_ConditionalAnd:
|
|
methodName = "aa";
|
|
break;
|
|
case BfBinaryOp_ConditionalOr:
|
|
methodName = "oo";
|
|
break;
|
|
case BfBinaryOp_NullCoalesce:
|
|
methodName = "2nc";
|
|
break;
|
|
case BfBinaryOp_Is:
|
|
methodName = "2is";
|
|
break;
|
|
case BfBinaryOp_As:
|
|
methodName = "2as";
|
|
break;
|
|
}
|
|
|
|
switch (operatorDef->mOperatorDeclaration->mUnaryOp)
|
|
{
|
|
case BfUnaryOp_AddressOf:
|
|
methodName = "ad";
|
|
break;
|
|
case BfUnaryOp_Dereference:
|
|
methodName = "de";
|
|
break;
|
|
case BfUnaryOp_Negate:
|
|
methodName = "ng";
|
|
break;
|
|
case BfUnaryOp_Not:
|
|
methodName = "nt";
|
|
break;
|
|
case BfUnaryOp_Positive:
|
|
methodName = "ps";
|
|
break;
|
|
case BfUnaryOp_InvertBits:
|
|
methodName = "co";
|
|
break;
|
|
case BfUnaryOp_Increment:
|
|
methodName = "pp";
|
|
break;
|
|
case BfUnaryOp_Decrement:
|
|
methodName = "mm";
|
|
break;
|
|
case BfUnaryOp_PostIncrement:
|
|
methodName = "pp";
|
|
break;
|
|
case BfUnaryOp_PostDecrement:
|
|
methodName = "mm";
|
|
break;
|
|
case BfUnaryOp_Ref:
|
|
methodName = "3ref";
|
|
break;
|
|
case BfUnaryOp_Mut:
|
|
methodName = "3mut";
|
|
break;
|
|
case BfUnaryOp_Out:
|
|
methodName = "3out";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (methodInst->mMethodDef->mMethodType == BfMethodType_Ctor)
|
|
{
|
|
if (methodInst->mMethodDef->mIsStatic)
|
|
{
|
|
methodName = "__BfStaticCtor";
|
|
prefixLen = true;
|
|
}
|
|
else
|
|
methodName = "C1";
|
|
}
|
|
else if (methodInst->mMethodDef->mMethodType == BfMethodType_Dtor)
|
|
{
|
|
if (methodInst->mMethodDef->mIsStatic)
|
|
{
|
|
methodName = "__BfStaticDtor";
|
|
prefixLen = true;
|
|
}
|
|
else
|
|
methodName = "D1";
|
|
}
|
|
else
|
|
{
|
|
if (methodInst->mMangleWithIdx)
|
|
{
|
|
methodName += StrFormat("@%d", methodInst->mMethodDef->mIdx);
|
|
mangledMethodIdx = true;
|
|
}
|
|
|
|
prefixLen = true;
|
|
}
|
|
|
|
if (methodDef->mCheckedKind == BfCheckedKind_Checked)
|
|
name += "@CHK";
|
|
else if (methodDef->mCheckedKind == BfCheckedKind_Unchecked)
|
|
name += "@UCHK";
|
|
|
|
if ((methodInst->mMethodDef->mDeclaringType->mPartialIdx != -1) && (!methodInst->mIsForeignMethodDef))
|
|
{
|
|
auto declType = methodInst->mMethodDef->mDeclaringType;
|
|
BF_ASSERT(methodInst->GetOwner()->mTypeDef->mIsCombinedPartial);
|
|
auto declProject = declType->mProject;
|
|
bool addProjectName = (declProject != typeInst->mTypeDef->mProject);
|
|
bool addIndex = true;
|
|
|
|
if (typeInst->mTypeDef->IsGlobalsContainer())
|
|
{
|
|
addProjectName = true;
|
|
|
|
if ((methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Cdecl) ||
|
|
(methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Stdcall))
|
|
{
|
|
addProjectName = false;
|
|
addIndex = false;
|
|
}
|
|
}
|
|
|
|
if (addProjectName)
|
|
{
|
|
name += declProject->mName;
|
|
name += "$";
|
|
}
|
|
if (addIndex)
|
|
name += StrFormat("%d$", declType->mPartialIdx);
|
|
}
|
|
|
|
if ((methodInst->mMangleWithIdx) && (!mangledMethodIdx))
|
|
{
|
|
methodName += StrFormat("@%d", methodInst->mMethodDef->mIdx);
|
|
}
|
|
|
|
//
|
|
|
|
if ((prefixLen) && (methodInst->mMethodInstanceGroup->mOwner->mTypeDef->IsGlobalsContainer()) && (methodInst->mMethodDef->mMethodDeclaration == NULL))
|
|
{
|
|
methodName += '@';
|
|
methodName += methodInst->mMethodInstanceGroup->mOwner->mTypeDef->mProject->mName;
|
|
}
|
|
|
|
if (prefixLen)
|
|
AddSizedString(name, methodName);
|
|
else
|
|
name += methodName;
|
|
|
|
if (methodInst->GetNumGenericArguments() != 0)
|
|
{
|
|
auto& methodGenericArguments = methodInst->mMethodInfoEx->mMethodGenericArguments;
|
|
NameSubstitute nameSub(NameSubstitute::Kind_MethodName, methodInst);
|
|
nameSub.mExtendsIdx = (int)mangleContext.mSubstituteList.size() - 1;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name += 'I';
|
|
for (auto genericArg : methodGenericArguments)
|
|
Mangle(mangleContext, name, genericArg);
|
|
name += 'E';
|
|
}
|
|
else if (methodInst->mMethodDef->mGenericParams.size() != 0)
|
|
{
|
|
NameSubstitute nameSub(NameSubstitute::Kind_MethodName, methodInst);
|
|
nameSub.mExtendsIdx = (int)mangleContext.mSubstituteList.size() - 1;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name += 'I';
|
|
for (auto genericArg : methodInst->mMethodDef->mGenericParams)
|
|
name += 'v';
|
|
name += 'E';
|
|
}
|
|
|
|
if (isNameOpen)
|
|
name += 'E';
|
|
|
|
if (methodInst->mMethodDef->mGenericParams.size() != 0)
|
|
Mangle(mangleContext, name, methodInst->mReturnType);
|
|
|
|
mangleContext.mInArgs = true;
|
|
|
|
bool doExplicitThis = (!methodDef->mIsStatic) && (typeInst->IsTypedPrimitive());
|
|
|
|
if (doExplicitThis) // Explicit "_this"
|
|
Mangle(mangleContext, name, typeInst->GetUnderlyingType());
|
|
|
|
for (int paramIdx = 0; paramIdx < (int)methodInst->GetParamCount(); paramIdx++)
|
|
{
|
|
BfType* paramType = methodInst->GetParamType(paramIdx);
|
|
|
|
auto paramKind = methodInst->GetParamKind(paramIdx);
|
|
if (paramKind == BfParamKind_Params)
|
|
name += "U6params";
|
|
else if (paramKind == BfParamKind_DelegateParam)
|
|
name += "U5param";
|
|
Mangle(mangleContext, name, paramType);
|
|
}
|
|
if ((methodInst->GetParamCount() == 0) && (!doExplicitThis))
|
|
name += 'v';
|
|
|
|
return name;
|
|
}
|
|
|
|
String BfGNUMangler::MangleMethodName(BfTypeInstance* type, const StringImpl& methodName)
|
|
{
|
|
MangleContext mangleContext;
|
|
mangleContext.mModule = type->mModule;
|
|
StringT<256> name = "_Z";
|
|
|
|
auto typeInst = type->ToTypeInstance();
|
|
BF_ASSERT(typeInst != NULL);
|
|
|
|
bool isNameOpen;
|
|
MangleTypeInst(mangleContext, name, typeInst, NULL, &isNameOpen);
|
|
AddSizedString(name, methodName);
|
|
if (isNameOpen)
|
|
name += "E";
|
|
name += "v";
|
|
return name;
|
|
}
|
|
|
|
String BfGNUMangler::MangleStaticFieldName(BfTypeInstance* type, const StringImpl& fieldName)
|
|
{
|
|
auto typeInst = type->ToTypeInstance();
|
|
auto typeDef = typeInst->mTypeDef;
|
|
if ((typeDef->IsGlobalsContainer()) && (typeDef->mNamespace.IsEmpty()))
|
|
return fieldName;
|
|
|
|
MangleContext mangleContext;
|
|
mangleContext.mModule = type->mModule;
|
|
StringT<256> name = "_Z";
|
|
bool isNameOpen;
|
|
MangleTypeInst(mangleContext, name, typeInst, NULL, &isNameOpen);
|
|
AddSizedString(name, fieldName);
|
|
if (isNameOpen)
|
|
name += "E";
|
|
return name;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
BfModule* BfMSMangler::MangleContext::GetUnreifiedModule()
|
|
{
|
|
if (mModule == NULL)
|
|
return NULL;
|
|
return mModule->mContext->mUnreifiedModule;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void BfMSMangler::AddGenericArgs(MangleContext& mangleContext, StringImpl& name, const SizedArrayImpl<BfType*>& genericArgs, int numOuterGenericParams)
|
|
{
|
|
if (numOuterGenericParams == (int)genericArgs.size())
|
|
return;
|
|
|
|
auto prevSubList = mangleContext.mSubstituteList;
|
|
auto prevSubTypeList = mangleContext.mSubstituteTypeList;
|
|
mangleContext.mSubstituteList.clear();
|
|
|
|
for (int genericIdx = numOuterGenericParams; genericIdx < (int)genericArgs.size(); genericIdx++)
|
|
Mangle(mangleContext, name, genericArgs[genericIdx]);
|
|
|
|
mangleContext.mSubstituteList = prevSubList;
|
|
mangleContext.mSubstituteTypeList = prevSubTypeList;
|
|
}
|
|
|
|
void BfMSMangler::AddStr(MangleContext& mangleContext, StringImpl& name, const StringImpl& str)
|
|
{
|
|
if ((int)mangleContext.mSubstituteList.size() < 10)
|
|
{
|
|
// Add NULL entry... shouldn't match anything
|
|
mangleContext.mSubstituteList.push_back(NameSubstitute(NameSubstitute::Kind_None, NULL));
|
|
}
|
|
|
|
name += str;
|
|
name += '@';
|
|
}
|
|
|
|
void BfMSMangler::AddSubIdx(StringImpl& name, int strIdx)
|
|
{
|
|
//TODO: BF_ASSERT(strIdx < 10);
|
|
char str[16];
|
|
itoa(strIdx, str, 10);
|
|
name += str;
|
|
}
|
|
|
|
void BfMSMangler::AddTypeStart(MangleContext& mangleContext, StringImpl& name, BfType* type)
|
|
{
|
|
if (mangleContext.mIsSafeMangle)
|
|
{
|
|
name += "V"; // Mangle everything as a struct so we don't need to require the type to be populated
|
|
return;
|
|
}
|
|
|
|
if (!type->IsDeclared())
|
|
{
|
|
if (mangleContext.mModule != NULL)
|
|
{
|
|
auto unreifiedModule = mangleContext.GetUnreifiedModule();
|
|
if (unreifiedModule != NULL)
|
|
unreifiedModule->PopulateType(type, BfPopulateType_Declaration);
|
|
}
|
|
else
|
|
{
|
|
BF_FATAL("No module");
|
|
}
|
|
}
|
|
|
|
if ((type->IsEnum()) && (type->IsTypedPrimitive()))
|
|
{
|
|
auto unreifiedModule = mangleContext.GetUnreifiedModule();
|
|
if (unreifiedModule != NULL)
|
|
unreifiedModule->PopulateType(type, BfPopulateType_Data);
|
|
|
|
BF_ASSERT(type->mSize >= 0);
|
|
|
|
// The enum size is supposed to be encoded, but VC always uses '4'
|
|
//name += "W";
|
|
//name += ('0' + type->mSize);
|
|
name += "W4";
|
|
return;
|
|
}
|
|
|
|
name += type->IsStruct() ? "U" : "V";
|
|
}
|
|
|
|
bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl& name, const NameSubstitute& newNameSub)
|
|
{
|
|
for (int curMatchIdx = 0; curMatchIdx < (int)mangleContext.mSubstituteList.size(); curMatchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[curMatchIdx];
|
|
if ((entry.mKind == newNameSub.mKind) && (entry.mParam == newNameSub.mParam) && (entry.mExtendsTypeId == newNameSub.mExtendsTypeId))
|
|
{
|
|
AddSubIdx(name, curMatchIdx);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (newNameSub.mKind == NameSubstitute::Kind_NamespaceAtom)
|
|
{
|
|
name += newNameSub.mAtom->mString;
|
|
name += '@';
|
|
}
|
|
else if (newNameSub.mKind == NameSubstitute::Kind_TypeInstName)
|
|
{
|
|
if (mangleContext.mWantsGroupStart)
|
|
{
|
|
AddTypeStart(mangleContext, name, newNameSub.mTypeInst);
|
|
mangleContext.mWantsGroupStart = false;
|
|
}
|
|
|
|
if (newNameSub.mTypeInst->IsTuple())
|
|
{
|
|
auto tupleType = (BfTupleType*)newNameSub.mType;
|
|
name += "?$__TUPLE";
|
|
BfTypeVector typeVec;
|
|
for (auto& fieldInst : tupleType->mFieldInstances)
|
|
{
|
|
BfFieldDef* fieldDef = fieldInst.GetFieldDef();
|
|
String fieldName = fieldDef->mName;
|
|
if ((fieldName[0] < '0') || (fieldName[0] > '9'))
|
|
name += StrFormat("_%s", fieldName.c_str());
|
|
typeVec.push_back(fieldInst.mResolvedType);
|
|
}
|
|
name += '@';
|
|
if (!typeVec.empty())
|
|
AddGenericArgs(mangleContext, name, typeVec);
|
|
name += '@';
|
|
}
|
|
else if ((newNameSub.mTypeInst->IsDelegateFromTypeRef()) || (newNameSub.mTypeInst->IsFunctionFromTypeRef()))
|
|
{
|
|
BF_ASSERT(newNameSub.mTypeInst->mTypeDef->mMethods[0]->mName == "Invoke");
|
|
|
|
//
|
|
{
|
|
auto methodDef = newNameSub.mTypeInst->mTypeDef->mMethods[0];
|
|
if (newNameSub.mTypeInst->IsDelegate())
|
|
name += "?$delegate";
|
|
else
|
|
name += "?$function";
|
|
BfTypeVector typeVec;
|
|
typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
|
|
for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
|
|
{
|
|
name += "_";
|
|
name += methodDef->mParams[paramIdx]->mName;
|
|
typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mParams[paramIdx]->mTypeRef)->mType);
|
|
}
|
|
name += '@';
|
|
if (!typeVec.empty())
|
|
AddGenericArgs(mangleContext, name, typeVec);
|
|
name += '@';
|
|
}
|
|
|
|
// auto invokeMethodInst = mangleContext.mModule->GetDelegateInvokeMethod(newNameSub.mTypeInst);
|
|
// if (newNameSub.mTypeInst->IsDelegate())
|
|
// name += "?$delegate";
|
|
// else
|
|
// name += "?$function";
|
|
// BfTypeVector typeVec;
|
|
// typeVec.push_back(invokeMethodInst->mReturnType);
|
|
// for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
|
|
// {
|
|
// name += "_";
|
|
// name += invokeMethodInst->GetParamName(paramIdx);
|
|
// typeVec.push_back(invokeMethodInst->GetParamType(paramIdx));
|
|
// }
|
|
// name += '@';
|
|
// if (!typeVec.empty())
|
|
// AddGenericArgs(mangleContext, name, typeVec);
|
|
// name += '@';
|
|
}
|
|
else if (newNameSub.mTypeInst->IsBoxed())
|
|
{
|
|
auto boxedType = (BfBoxedType*)newNameSub.mTypeInst;
|
|
name += "?$Box@";
|
|
BfTypeVector typeVec;
|
|
typeVec.push_back(boxedType->GetModifiedElementType());
|
|
AddGenericArgs(mangleContext, name, typeVec);
|
|
name += '@';
|
|
}
|
|
else
|
|
{
|
|
auto typeDef = newNameSub.mTypeInst->mTypeDef;
|
|
|
|
BfGenericTypeInstance* genericTypeInst = NULL;
|
|
if (newNameSub.mTypeInst->IsGenericTypeInstance())
|
|
genericTypeInst = (BfGenericTypeInstance*)newNameSub.mTypeInst;
|
|
|
|
int numOuterGenericParams = 0;
|
|
if ((!mangleContext.mIsSafeMangle) && (typeDef->mOuterType != NULL))
|
|
{
|
|
numOuterGenericParams = (int)typeDef->mOuterType->mGenericParamDefs.size();
|
|
}
|
|
|
|
if (genericTypeInst != NULL)
|
|
{
|
|
// If we don't have our own generic params then don't treat us as a generic
|
|
if ((int)typeDef->mGenericParamDefs.size() == numOuterGenericParams)
|
|
genericTypeInst = NULL;
|
|
}
|
|
|
|
if (genericTypeInst != NULL)
|
|
{
|
|
name += "?$";
|
|
mangleContext.mWantsGroupStart = false;
|
|
}
|
|
|
|
// name += *typeDef->mName->mString;
|
|
// if ((typeDef->mIsDelegate) && (newNameSub.mTypeInst->IsClosure()))
|
|
// {
|
|
// auto closureType = (BfClosureType*)newNameSub.mTypeInst;
|
|
// if (!closureType->mCreatedTypeDef)
|
|
// name += closureType->mNameAdd;
|
|
// }
|
|
|
|
if (newNameSub.mTypeInst->IsClosure())
|
|
{
|
|
auto closureType = (BfClosureType*)newNameSub.mTypeInst;
|
|
name += closureType->mSrcDelegate->mTypeDef->mName->mString;
|
|
name += closureType->mNameAdd;
|
|
}
|
|
else
|
|
{
|
|
name += typeDef->mName->mString;
|
|
}
|
|
|
|
name += '@';
|
|
|
|
if (genericTypeInst != NULL)
|
|
{
|
|
AddGenericArgs(mangleContext, name, genericTypeInst->mTypeGenericArguments, numOuterGenericParams);
|
|
name += '@';
|
|
}
|
|
}
|
|
}
|
|
else if (newNameSub.mKind == BfGNUMangler::NameSubstitute::Kind_GenericParam)
|
|
{
|
|
name += "U"; // Struct
|
|
auto genericParamType = (BfGenericParamType*)newNameSub.mType;
|
|
if (genericParamType->mGenericParamKind == BfGenericParamKind_Method)
|
|
name += "_M";
|
|
else
|
|
name += "_T";
|
|
char str[16];
|
|
itoa(genericParamType->mGenericParamIdx, str, 10);
|
|
name += str;
|
|
name += '@';
|
|
name += '@';
|
|
}
|
|
|
|
mangleContext.mSubstituteList.push_back(newNameSub);
|
|
|
|
return false;
|
|
}
|
|
|
|
void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfTypeInstance* typeInstance, bool isAlreadyStarted, bool isOuterType)
|
|
{
|
|
BfGenericTypeInstance* genericTypeInst = NULL;
|
|
if (typeInstance->IsGenericTypeInstance())
|
|
{
|
|
genericTypeInst = (BfGenericTypeInstance*)typeInstance;
|
|
}
|
|
|
|
auto typeDef = typeInstance->mTypeDef;
|
|
bool hasNamespace = typeDef->mNamespace.mSize != 0;
|
|
if (!isAlreadyStarted)
|
|
{
|
|
if ((hasNamespace) || (typeDef->mOuterType != NULL))
|
|
{
|
|
AddTypeStart(mangleContext, name, typeInstance);
|
|
}
|
|
else
|
|
{
|
|
if (typeDef->IsGlobalsContainer())
|
|
return;
|
|
mangleContext.mWantsGroupStart = true;
|
|
}
|
|
}
|
|
|
|
if (!typeDef->IsGlobalsContainer())
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_TypeInstName, typeInstance));
|
|
mangleContext.mWantsGroupStart = false;
|
|
|
|
auto useModule = typeInstance->mModule;
|
|
if (useModule == NULL)
|
|
useModule = mangleContext.mModule;
|
|
|
|
if ((typeDef->mOuterType != NULL) && (!typeInstance->IsBoxed()))
|
|
{
|
|
if (mangleContext.mIsSafeMangle)
|
|
{
|
|
auto outerType = typeDef->mOuterType;
|
|
while (outerType != NULL)
|
|
{
|
|
name += ":";
|
|
name += outerType->mFullName.ToString();
|
|
outerType = outerType->mOuterType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto outerType = useModule->GetOuterType(typeInstance);
|
|
Mangle(mangleContext, name, outerType, true, true);
|
|
}
|
|
}
|
|
|
|
if (!isOuterType)
|
|
{
|
|
if (!typeInstance->IsBoxed())
|
|
{
|
|
for (int namespaceIdx = (int)typeDef->mNamespace.mSize - 1; namespaceIdx >= 0; namespaceIdx--)
|
|
{
|
|
auto namePart = typeDef->mNamespace.mParts[namespaceIdx];
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, namePart));
|
|
}
|
|
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, useModule->mSystem->mBfAtom));
|
|
}
|
|
|
|
name += '@';
|
|
}
|
|
}
|
|
|
|
void BfMSMangler::MangleConst(MangleContext & mangleContext, StringImpl & name, int64 val)
|
|
{
|
|
name += "$0";
|
|
if (val < 0)
|
|
{
|
|
name += "?";
|
|
val = -val;
|
|
}
|
|
if ((val > 0) && (val <= 10))
|
|
{
|
|
name += (char)('0' + val - 1);
|
|
}
|
|
else
|
|
{
|
|
char str[64];
|
|
char* strP = str + 63;
|
|
*strP = 0;
|
|
|
|
while (val > 0)
|
|
{
|
|
*(--strP) = (char)((val % 0x10) + 'A');
|
|
val /= 0x10;
|
|
}
|
|
|
|
name += strP;
|
|
name += '@';
|
|
}
|
|
}
|
|
|
|
void BfMSMangler::AddPrefix(MangleContext& mangleContext, StringImpl& name, int startIdx, const char* prefix)
|
|
{
|
|
int subIdx;
|
|
char startChar = name[startIdx];
|
|
if ((startChar >= '0') && (startChar <= '9'))
|
|
{
|
|
//subIdx = ParseSubIdx(name, startIdx);
|
|
subIdx = startChar - '0';
|
|
for (int matchIdx = subIdx + 1; matchIdx < (int)mangleContext.mSubstituteList.size(); matchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[matchIdx];
|
|
if ((entry.mKind == NameSubstitute::Kind_Prefix) && (entry.mExtendsIdx == subIdx) && (entry.mPrefix == prefix))
|
|
{
|
|
BF_ASSERT(name.EndsWith('_'));
|
|
name.RemoveToEnd(startIdx);
|
|
AddSubIdx(name, matchIdx);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//auto typeCode = GetPrimTypeAt(mangleContext, name, startIdx);
|
|
auto typeCode = BfTypeCode_None;
|
|
if (typeCode != (BfTypeCode)-1)
|
|
{
|
|
for (int matchIdx = 0; matchIdx < (int)mangleContext.mSubstituteList.size(); matchIdx++)
|
|
{
|
|
auto& entry = mangleContext.mSubstituteList[matchIdx];
|
|
if ((entry.mKind == NameSubstitute::Kind_PrimitivePrefix) && (entry.mExtendsTypeCode == typeCode) && (entry.mPrefix == prefix))
|
|
{
|
|
name.RemoveToEnd(startIdx);
|
|
AddSubIdx(name, matchIdx);
|
|
return;
|
|
}
|
|
}
|
|
|
|
NameSubstitute nameSub;
|
|
nameSub.mKind = NameSubstitute::Kind_PrimitivePrefix;
|
|
nameSub.mExtendsTypeCode = typeCode;
|
|
nameSub.mPrefix = prefix;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name.Insert(startIdx, prefix);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Applies to last-added one
|
|
subIdx = (int)mangleContext.mSubstituteList.size() - 1;
|
|
BF_ASSERT(isdigit(startChar) || (startChar == 'N') || (startChar == 'P') || (startChar == 'R'));
|
|
}
|
|
}
|
|
|
|
NameSubstitute nameSub;
|
|
nameSub.mKind = NameSubstitute::Kind_Prefix;
|
|
nameSub.mExtendsIdx = subIdx;
|
|
nameSub.mPrefix = prefix;
|
|
mangleContext.mSubstituteList.push_back(nameSub);
|
|
|
|
name.Insert(startIdx, prefix);
|
|
}
|
|
|
|
void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* type, bool useTypeList)
|
|
{
|
|
bool isLongPrim = false;
|
|
|
|
if (type->IsPrimitiveType())
|
|
{
|
|
auto primType = (BfPrimitiveType*)type;
|
|
|
|
switch (primType->mTypeDef->mTypeCode)
|
|
{
|
|
case BfTypeCode_NullPtr:
|
|
{
|
|
name += "P";
|
|
if (mangleContext.mIs64Bit)
|
|
name += "E";
|
|
name += "AV";
|
|
name += "v";
|
|
}
|
|
return;
|
|
case BfTypeCode_None:
|
|
name += "X"; return;
|
|
case BfTypeCode_Dot:
|
|
name += "Tdot@@"; return;
|
|
case BfTypeCode_Var:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
name += "X";
|
|
else
|
|
name += "Tvar@@";
|
|
return;
|
|
case BfTypeCode_Self:
|
|
if ((mangleContext.mCCompat) || (mangleContext.mInArgs))
|
|
name += "X";
|
|
else
|
|
name += "Tself@@";
|
|
return;
|
|
case BfTypeCode_Int8:
|
|
name += "C"; return;
|
|
case BfTypeCode_UInt8:
|
|
name += "E"; return;
|
|
case BfTypeCode_Int16:
|
|
name += "F"; return;
|
|
case BfTypeCode_UInt16:
|
|
name += "G"; return;
|
|
case BfTypeCode_Int32:
|
|
name += "H"; return;
|
|
case BfTypeCode_UInt32:
|
|
name += "I"; return;
|
|
case BfTypeCode_Char8:
|
|
name += "D"; return;
|
|
case BfTypeCode_Char16:
|
|
name += "_S"; return; //char16_t
|
|
case BfTypeCode_Single:
|
|
name += "M"; return;
|
|
case BfTypeCode_Double:
|
|
name += "N"; return;
|
|
case BfTypeCode_Int64:
|
|
case BfTypeCode_UInt64:
|
|
case BfTypeCode_Boolean:
|
|
case BfTypeCode_Char32:
|
|
isLongPrim = true;
|
|
break;
|
|
case BfTypeCode_IntPtr:
|
|
if ((primType->mSize == 4) && (mangleContext.mCCompat))
|
|
{
|
|
name += "H";
|
|
return;
|
|
}
|
|
isLongPrim = true;
|
|
break;
|
|
case BfTypeCode_UIntPtr:
|
|
if ((primType->mSize == 4) && (mangleContext.mCCompat))
|
|
{
|
|
name += "I";
|
|
return;
|
|
}
|
|
isLongPrim = true;
|
|
break;
|
|
default:
|
|
name += "?"; return;
|
|
}
|
|
}
|
|
|
|
if (useTypeList)
|
|
{
|
|
for (int checkIdx = 0; checkIdx < (int)mangleContext.mSubstituteTypeList.size(); checkIdx++)
|
|
{
|
|
if (mangleContext.mSubstituteTypeList[checkIdx] == type)
|
|
{
|
|
name += ('0' + checkIdx);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isLongPrim)
|
|
{
|
|
auto primType = (BfPrimitiveType*)type;
|
|
switch (primType->mTypeDef->mTypeCode)
|
|
{
|
|
case BfTypeCode_Boolean:
|
|
name += "_N"; break;
|
|
case BfTypeCode_Int64:
|
|
name += "_J"; break;
|
|
case BfTypeCode_UInt64:
|
|
name += "_K"; break;
|
|
case BfTypeCode_UIntPtr:
|
|
if (primType->mSize == 4)
|
|
name += "_I";
|
|
else if (mangleContext.mCCompat)
|
|
name += "_K";
|
|
else
|
|
name += "Tuint@@";
|
|
break;
|
|
case BfTypeCode_IntPtr:
|
|
if (primType->mSize == 4)
|
|
name += "_H";
|
|
else if (mangleContext.mCCompat)
|
|
name += "_J";
|
|
else
|
|
name += "Tint@@";
|
|
break;
|
|
case BfTypeCode_Char32:
|
|
name += "_U"; break;
|
|
}
|
|
}
|
|
else if (type->IsTypeInstance())
|
|
{
|
|
auto typeInstance = (BfTypeInstance*)type;
|
|
auto typeDef = typeInstance->mTypeDef;
|
|
|
|
if (type->IsObjectOrInterface())
|
|
{
|
|
name += "P";
|
|
if (mangleContext.mIs64Bit)
|
|
name += "E";
|
|
name += "A";
|
|
}
|
|
else if (((type->IsGenericTypeInstance()) || (type->IsTuple()) || (type->IsEnum())) && (mangleContext.mInRet))
|
|
name += "?A";
|
|
|
|
Mangle(mangleContext, name, typeInstance, false);
|
|
}
|
|
else if (type->IsGenericParam())
|
|
{
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_GenericParam, type));
|
|
}
|
|
else if (type->IsPointer())
|
|
{
|
|
auto pointerType = (BfPointerType*)type;
|
|
|
|
const char* strAdd = mangleContext.mIs64Bit ? "PEA" : "PA";
|
|
//if (!FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_Prefix, strAdd, pointerType->mTypeId)))
|
|
{
|
|
name += strAdd;
|
|
Mangle(mangleContext, name, pointerType->mElementType);
|
|
}
|
|
}
|
|
else if (type->IsRef())
|
|
{
|
|
auto refType = (BfRefType*)type;
|
|
name += "A";
|
|
if (mangleContext.mIs64Bit)
|
|
name += "E";
|
|
name += "A";
|
|
if (refType->mRefKind == BfRefType::RefKind_Mut)
|
|
name += "mut$";
|
|
else if (refType->mRefKind == BfRefType::RefKind_Out)
|
|
name += "out$";
|
|
Mangle(mangleContext, name, refType->mElementType);
|
|
}
|
|
else if (type->IsRetTypeType())
|
|
{
|
|
auto retType = (BfRetTypeType*)type;
|
|
name += "rettype$";
|
|
Mangle(mangleContext, name, retType->mElementType);
|
|
}
|
|
else if (type->IsConcreteInterfaceType())
|
|
{
|
|
auto concreteType = (BfConcreteInterfaceType*)type;
|
|
name += "concrete$";
|
|
Mangle(mangleContext, name, concreteType->mInterface);
|
|
}
|
|
else if (type->IsSizedArray())
|
|
{
|
|
if (type->IsUnknownSizedArray())
|
|
{
|
|
auto arrType = (BfUnknownSizedArrayType*)type;
|
|
name += StrFormat("arr_$", arrType->mSize);
|
|
Mangle(mangleContext, name, arrType->mElementType);
|
|
name += "$";
|
|
Mangle(mangleContext, name, arrType->mElementCountSource);
|
|
}
|
|
else
|
|
{
|
|
// We can't use MS mangling of "_O" because it isn't size-specific
|
|
auto arrType = (BfSizedArrayType*)type;
|
|
//name += StrFormat("arr_%d$", arrType->mSize);
|
|
//Mangle(mangleContext, name, arrType->mElementType);
|
|
|
|
name += "?$_ARRAY@";
|
|
Mangle(mangleContext, name, arrType->mElementType);
|
|
MangleConst(mangleContext, name, arrType->mSize);
|
|
name += '@';
|
|
}
|
|
}
|
|
else if (type->IsMethodRef())
|
|
{
|
|
auto methodRefType = (BfMethodRefType*)type;
|
|
name += "Tmref_";
|
|
|
|
StringT<128> mangleName;
|
|
BfMethodInstance* methodInstance = methodRefType->mMethodRef;
|
|
if (methodInstance == NULL)
|
|
{
|
|
BF_ASSERT(!methodRefType->mMangledMethodName.IsEmpty());
|
|
mangleName = methodRefType->mMangledMethodName;
|
|
}
|
|
else
|
|
{
|
|
if (methodInstance->mIsAutocompleteMethod)
|
|
name += "AUTOCOMPLETE";
|
|
|
|
auto module = methodInstance->GetOwner()->mModule;
|
|
if (module->mCompiler->mIsResolveOnly)
|
|
{
|
|
// There are cases where we will reprocess a method in ResolveOnly for things like
|
|
// GetSymbolReferences, so we will have duplicate live local methodInstances in those cases
|
|
name += HashEncode64((uint64)methodRefType->mMethodRef);
|
|
}
|
|
else
|
|
{
|
|
Mangle(mangleName, mangleContext.mIs64Bit, methodInstance);
|
|
methodRefType->mMangledMethodName = mangleName;
|
|
}
|
|
}
|
|
|
|
if (!mangleName.IsEmpty())
|
|
{
|
|
Val128 val128 = Hash128(mangleName.c_str(), (int)mangleName.length());
|
|
name += HashEncode128(val128);
|
|
}
|
|
|
|
// if (methodInstance->mIsAutocompleteMethod)
|
|
// name += "AUTOCOMPLETE";
|
|
//
|
|
// String mangleAdd = Mangle(mangleContext.mIs64Bit, methodInstance);
|
|
//
|
|
// auto module = methodInstance->GetOwner()->mModule;
|
|
// if (module->mCompiler->mIsResolveOnly)
|
|
// {
|
|
// // There are cases where we will reprocess a method in ResolveOnly for things like
|
|
// // GetSymbolReferences, so we will have duplicate live local methodInstances in those cases
|
|
// name += HashEncode64((uint64)methodRefType->mMethodRef);
|
|
// }
|
|
// else
|
|
// {
|
|
// Val128 val128 = Hash128(mangleAdd.c_str(), (int)mangleAdd.length());
|
|
// name += HashEncode128(val128);
|
|
// }
|
|
name += "@@";
|
|
}
|
|
else if (type->IsConstExprValue())
|
|
{
|
|
BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type;
|
|
int64 val = constExprValueType->mValue.mInt64;
|
|
if ((!constExprValueType->mType->IsPrimitiveType()) ||
|
|
(((BfPrimitiveType*)constExprValueType->mType)->mTypeDef->mTypeCode != BfTypeCode_IntPtr))
|
|
{
|
|
Mangle(mangleContext, name, constExprValueType->mType);
|
|
name += "$";
|
|
}
|
|
MangleConst(mangleContext, name, val);
|
|
}
|
|
else
|
|
{
|
|
BF_ASSERT("Unhandled");
|
|
}
|
|
|
|
if ((useTypeList) && (!mangleContext.mInRet) && ((int)mangleContext.mSubstituteTypeList.size() < 10))
|
|
mangleContext.mSubstituteTypeList.push_back(type);
|
|
}
|
|
|
|
void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfType* type, BfModule* module)
|
|
{
|
|
if (type->IsTypeAlias())
|
|
{
|
|
auto typeAlias = (BfTypeAliasType*)type;
|
|
name += "__ALIAS_";
|
|
name += typeAlias->mTypeDef->mName->ToString();
|
|
name += '@';
|
|
Mangle(name, is64Bit, typeAlias->mAliasToType, module);
|
|
return;
|
|
}
|
|
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = is64Bit;
|
|
mangleContext.mModule = module;
|
|
auto typeInst = type->ToTypeInstance();
|
|
if ((typeInst != NULL) && (typeInst->mModule != NULL))
|
|
mangleContext.mModule = typeInst->mModule;
|
|
if (typeInst != NULL)
|
|
Mangle(mangleContext, name, typeInst, true);
|
|
else
|
|
Mangle(mangleContext, name, type);
|
|
while ((name.length() > 0) && (name[name.length() - 1] == '@'))
|
|
name.Remove(name.length() - 1);
|
|
}
|
|
|
|
void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* methodInst)
|
|
{
|
|
static int mangleIdx = 0;
|
|
mangleIdx++;
|
|
|
|
if ((methodInst->mMethodDef->mCLink) && (!methodInst->mMangleWithIdx))
|
|
{
|
|
name += methodInst->mMethodDef->mName;
|
|
return;
|
|
}
|
|
|
|
auto methodDef = methodInst->mMethodDef;
|
|
auto typeInst = methodInst->GetOwner();
|
|
auto typeDef = typeInst->mTypeDef;
|
|
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = is64Bit;
|
|
mangleContext.mModule = methodInst->GetOwner()->mModule;
|
|
mangleContext.mCCompat = methodInst->mMethodDef->mIsExtern;
|
|
auto customAttributes = methodInst->GetCustomAttributes();
|
|
if (customAttributes != NULL)
|
|
{
|
|
auto linkNameAttr = customAttributes->Get(typeInst->mModule->mCompiler->mLinkNameAttributeTypeDef);
|
|
if (linkNameAttr != NULL)
|
|
{
|
|
if (linkNameAttr->mCtorArgs.size() == 1)
|
|
{
|
|
if (typeInst->mModule->TryGetConstString(typeInst->mConstHolder, linkNameAttr->mCtorArgs[0], name))
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
name += '?';
|
|
|
|
if (methodInst->GetNumGenericArguments() != 0)
|
|
{
|
|
name += "?$";
|
|
}
|
|
|
|
bool isSpecialFunc = false;
|
|
if (methodInst->mMethodDef->mIsOperator)
|
|
{
|
|
String methodName;
|
|
|
|
auto operatorDef = (BfOperatorDef*)methodInst->mMethodDef;
|
|
if (operatorDef->mOperatorDeclaration->mIsConvOperator)
|
|
{
|
|
name += "?B";
|
|
}
|
|
else
|
|
{
|
|
switch (operatorDef->mOperatorDeclaration->mBinOp)
|
|
{
|
|
case BfBinaryOp_Add:
|
|
name += "?H";
|
|
break;
|
|
case BfBinaryOp_Subtract:
|
|
name += "?G";
|
|
break;
|
|
case BfBinaryOp_Multiply:
|
|
name += "?D";
|
|
break;
|
|
case BfBinaryOp_Divide:
|
|
name += "?K";
|
|
break;
|
|
case BfBinaryOp_Modulus:
|
|
name += "?L";
|
|
break;
|
|
case BfBinaryOp_BitwiseAnd:
|
|
name += "?I";
|
|
break;
|
|
case BfBinaryOp_BitwiseOr:
|
|
name += "?U";
|
|
break;
|
|
case BfBinaryOp_ExclusiveOr:
|
|
name += "?T";
|
|
break;
|
|
case BfBinaryOp_LeftShift:
|
|
name += "?6";
|
|
break;
|
|
case BfBinaryOp_RightShift:
|
|
name += "?5";
|
|
break;
|
|
case BfBinaryOp_Equality:
|
|
name += "?8";
|
|
break;
|
|
case BfBinaryOp_InEquality:
|
|
name += "?9";
|
|
break;
|
|
case BfBinaryOp_GreaterThan:
|
|
name += "?O";
|
|
break;
|
|
case BfBinaryOp_LessThan:
|
|
name += "?M";
|
|
break;
|
|
case BfBinaryOp_GreaterThanOrEqual:
|
|
name += "?P";
|
|
break;
|
|
case BfBinaryOp_LessThanOrEqual:
|
|
name += "?N";
|
|
break;
|
|
case BfBinaryOp_Compare:
|
|
name += "__cmp__";
|
|
break;
|
|
case BfBinaryOp_ConditionalAnd:
|
|
name += "?V";
|
|
break;
|
|
case BfBinaryOp_ConditionalOr:
|
|
name += "?W";
|
|
break;
|
|
case BfBinaryOp_NullCoalesce:
|
|
methodName = "__nc__";
|
|
break;
|
|
case BfBinaryOp_Is:
|
|
methodName = "__is__";
|
|
break;
|
|
case BfBinaryOp_As:
|
|
methodName = "__as__";
|
|
break;
|
|
}
|
|
|
|
switch (operatorDef->mOperatorDeclaration->mUnaryOp)
|
|
{
|
|
case BfUnaryOp_AddressOf:
|
|
name += "?I";
|
|
break;
|
|
case BfUnaryOp_Dereference:
|
|
name += "?D";
|
|
break;
|
|
case BfUnaryOp_Negate:
|
|
name += "?G";
|
|
break;
|
|
case BfUnaryOp_Not:
|
|
name += "?7";
|
|
break;
|
|
case BfUnaryOp_Positive:
|
|
name += "?H";
|
|
break;
|
|
case BfUnaryOp_InvertBits:
|
|
name += "?S";
|
|
break;
|
|
case BfUnaryOp_Increment:
|
|
name += "?E";
|
|
break;
|
|
case BfUnaryOp_Decrement:
|
|
name += "?F";
|
|
break;
|
|
case BfUnaryOp_PostIncrement:
|
|
methodName = "__pi__";
|
|
break;
|
|
case BfUnaryOp_PostDecrement:
|
|
methodName = "__pd__";
|
|
break;
|
|
case BfUnaryOp_Ref:
|
|
methodName = "__ref__";
|
|
break;
|
|
case BfUnaryOp_Out:
|
|
methodName = "__out__";
|
|
break;
|
|
}
|
|
|
|
switch (operatorDef->mOperatorDeclaration->mAssignOp)
|
|
{
|
|
case BfAssignmentOp_Assign:
|
|
methodName += "__a__";
|
|
break;
|
|
case BfAssignmentOp_Add:
|
|
methodName += "__a_add__";
|
|
break;
|
|
case BfAssignmentOp_Subtract:
|
|
methodName += "__a_sub__";
|
|
break;
|
|
case BfAssignmentOp_Multiply:
|
|
methodName += "__a_mul__";
|
|
break;
|
|
case BfAssignmentOp_Divide:
|
|
methodName += "__a_div__";
|
|
break;
|
|
case BfAssignmentOp_Modulus:
|
|
methodName += "__a_mod__";
|
|
break;
|
|
case BfAssignmentOp_ShiftLeft:
|
|
methodName += "__a_shl__";
|
|
break;
|
|
case BfAssignmentOp_ShiftRight:
|
|
methodName += "__a_shr__";
|
|
break;
|
|
case BfAssignmentOp_BitwiseAnd:
|
|
methodName += "__a_bwa__";
|
|
break;
|
|
case BfAssignmentOp_BitwiseOr:
|
|
methodName += "__a_bwo__";
|
|
break;
|
|
case BfAssignmentOp_ExclusiveOr:
|
|
methodName += "__a_xor__";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!methodName.empty())
|
|
{
|
|
AddStr(mangleContext, name, methodName);
|
|
}
|
|
}
|
|
/*else if ((methodDef->mMethodType == BfMethodType_Ctor) && (!methodDef->mIsStatic))
|
|
{
|
|
isSpecialFunc = true;
|
|
name += "?0";
|
|
//AddAtomStr(mangleContext, name, typeDef->mName);
|
|
}
|
|
else if ((methodDef->mMethodType == BfMethodType_Dtor) && (!methodDef->mIsStatic))
|
|
{
|
|
isSpecialFunc = true;
|
|
name += "?1";
|
|
//AddAtomStr(mangleContext, name, typeDef->mName);
|
|
}*/
|
|
else if (methodInst->GetNumGenericArguments() != 0)
|
|
{
|
|
AddStr(mangleContext, name, methodDef->mName);
|
|
AddGenericArgs(mangleContext, name, methodInst->mMethodInfoEx->mMethodGenericArguments);
|
|
name += '@';
|
|
}
|
|
else
|
|
{
|
|
AddStr(mangleContext, name, methodDef->mName);
|
|
}
|
|
|
|
if ((methodInst->mMethodDef->mDeclaringType->mPartialIdx != -1) && (!methodInst->mIsForeignMethodDef))
|
|
{
|
|
auto declType = methodInst->mMethodDef->mDeclaringType;
|
|
BF_ASSERT(methodInst->GetOwner()->mTypeDef->mIsCombinedPartial);
|
|
auto declProject = declType->mProject;
|
|
bool addProjectName = (declProject != typeInst->mTypeDef->mProject);
|
|
bool addIndex = true;
|
|
|
|
if (typeInst->mTypeDef->IsGlobalsContainer())
|
|
{
|
|
addProjectName = true;
|
|
|
|
if ((methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Cdecl) ||
|
|
(methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Stdcall))
|
|
{
|
|
addProjectName = false;
|
|
addIndex = false;
|
|
}
|
|
}
|
|
|
|
if (addProjectName)
|
|
{
|
|
name += declProject->mName;
|
|
name += '$';
|
|
}
|
|
if (addIndex)
|
|
name += StrFormat("%d$", declType->mPartialIdx);
|
|
}
|
|
|
|
if (methodInst->mMangleWithIdx)
|
|
name += StrFormat("i%d$", methodInst->mMethodDef->mIdx);
|
|
if (methodDef->mCheckedKind == BfCheckedKind_Checked)
|
|
name += "CHK$";
|
|
else if (methodDef->mCheckedKind == BfCheckedKind_Unchecked)
|
|
name += "UCHK$";
|
|
|
|
/*if ((methodInst->mMethodInstanceGroup->mOwner->mTypeDef->IsGlobalsContainer()) && (methodInst->mMethodDef->mMethodDeclaration == NULL))
|
|
{
|
|
name += methodInst->mMethodInstanceGroup->mOwner->mTypeDef->mProject->mName;
|
|
name += "$";
|
|
}*/
|
|
|
|
if (methodInst->GetForeignType() != NULL)
|
|
Mangle(mangleContext, name, methodInst->GetForeignType(), true);
|
|
if (methodInst->GetExplicitInterface() != NULL)
|
|
Mangle(mangleContext, name, methodInst->GetExplicitInterface(), true);
|
|
|
|
Mangle(mangleContext, name, methodInst->GetOwner(), true);
|
|
|
|
/*bool isCppDecl = false;
|
|
if (!isCppDecl)
|
|
{
|
|
if (name.EndsWith("@"))
|
|
name.Remove(name.length() - 1);
|
|
FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, typeInst->mModule->mSystem->mBfAtom));
|
|
name += '@';
|
|
}*/
|
|
|
|
//QEA AXXZ
|
|
|
|
char attrib ='A';
|
|
if (methodDef->mProtection == BfProtection_Protected)
|
|
attrib = 'I';
|
|
else if (methodDef->mProtection == BfProtection_Public)
|
|
attrib = 'Q';
|
|
|
|
bool doExplicitThis = (!methodDef->mIsStatic) && (typeInst->IsTypedPrimitive());
|
|
|
|
if ((methodDef->mIsStatic) || (doExplicitThis))
|
|
attrib += 2;
|
|
attrib += (methodDef->mIsVirtual ? 4 : 0);
|
|
name += attrib;
|
|
|
|
auto bfSystem = methodInst->GetOwner()->mModule->mSystem;
|
|
if ((!methodDef->mIsStatic) && (!doExplicitThis))
|
|
{
|
|
/*char cvQualifier = 'A';
|
|
if (mangleContext.mIs64Bit)
|
|
cvQualifier = 'E';
|
|
name += cvQualifier;*/
|
|
if (mangleContext.mIs64Bit)
|
|
name += "E";
|
|
|
|
char qualifier = 'A'; // const / volatile
|
|
name += qualifier;
|
|
}
|
|
|
|
char callingConv = 'A';
|
|
if (methodDef->mCallingConvention == BfCallingConvention_Stdcall)
|
|
callingConv = 'G';
|
|
else if ((!mangleContext.mIs64Bit) && (!methodDef->mIsStatic))
|
|
callingConv = 'E';
|
|
name += callingConv;
|
|
|
|
if (isSpecialFunc)
|
|
name += '@';
|
|
|
|
//
|
|
if (!isSpecialFunc)
|
|
{
|
|
mangleContext.mInRet = true;
|
|
Mangle(mangleContext, name, methodInst->mReturnType);
|
|
mangleContext.mInRet = false;
|
|
}
|
|
if ((methodInst->mParams.size() == 0) && (!doExplicitThis))
|
|
{
|
|
name += 'X';
|
|
}
|
|
else
|
|
{
|
|
// Is this right?
|
|
if (methodInst->GetNumGenericArguments() != 0)
|
|
mangleContext.mSubstituteList.clear();
|
|
|
|
mangleContext.mInArgs = true;
|
|
if (doExplicitThis)
|
|
{
|
|
Mangle(mangleContext, name, typeInst->GetUnderlyingType(), true);
|
|
}
|
|
for (auto& param : methodInst->mParams)
|
|
Mangle(mangleContext, name, param.mResolvedType, true);
|
|
name += '@';
|
|
}
|
|
|
|
name += 'Z';
|
|
|
|
bool wantLog = false;
|
|
if (wantLog)
|
|
{
|
|
BfLog2("Mangling #%d : %s -> %s\n", mangleIdx, mangleContext.mModule->MethodToString(methodInst).c_str(), name.c_str());
|
|
|
|
if (!methodInst->mIsUnspecialized)
|
|
{
|
|
String demangled = BfDemangler::Demangle(name, DbgLanguage_Beef);
|
|
BfLog2(" Demangled %d: %s\n", mangleIdx, demangled.c_str());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfFieldInstance* fieldInstance)
|
|
{
|
|
auto fieldDef = fieldInstance->GetFieldDef();
|
|
if (fieldDef->mFieldDeclaration != NULL)
|
|
{
|
|
auto module = fieldInstance->mOwner->mModule;
|
|
if ((fieldInstance->mCustomAttributes != NULL) && (fieldInstance->mCustomAttributes->Contains(module->mCompiler->mCLinkAttributeTypeDef)))
|
|
{
|
|
name += fieldDef->mName;
|
|
return;
|
|
}
|
|
}
|
|
|
|
BF_ASSERT(fieldDef->mIsStatic);
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = is64Bit;
|
|
mangleContext.mModule = fieldInstance->mOwner->mModule;
|
|
|
|
name += '?';
|
|
AddStr(mangleContext, name, fieldDef->mName);
|
|
Mangle(mangleContext, name, fieldInstance->mOwner, true);
|
|
name += '2'; //TODO: Don't always mark as 'public'
|
|
Mangle(mangleContext, name, fieldInstance->mResolvedType);
|
|
name += ('A' + /*(fieldDef->mIsConst ? 1 : 0) +*/ (fieldDef->mIsVolatile ? 2 : 0));
|
|
}
|
|
|
|
void BfMSMangler::MangleMethodName(StringImpl& name, bool is64Bit, BfTypeInstance* type, const StringImpl& methodName)
|
|
{
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = is64Bit;
|
|
mangleContext.mModule = type->GetModule();
|
|
name += '?';
|
|
AddStr(mangleContext, name, methodName);
|
|
Mangle(mangleContext, name, type);
|
|
name += "@@";
|
|
}
|
|
|
|
void BfMSMangler::MangleStaticFieldName(StringImpl& name, bool is64Bit, BfTypeInstance* owner, const StringImpl& fieldName, BfType* fieldType)
|
|
{
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = is64Bit;
|
|
mangleContext.mModule = owner->GetModule();
|
|
name += '?';
|
|
AddStr(mangleContext, name, fieldName);
|
|
Mangle(mangleContext, name, owner, true);
|
|
//name += "@@";
|
|
name += '2'; // public
|
|
if (fieldType == NULL)
|
|
name += 'H';
|
|
else
|
|
Mangle(mangleContext, name, fieldType);
|
|
name += "A"; // static
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
String BfSafeMangler::Mangle(BfType* type, BfModule* module)
|
|
{
|
|
MangleContext mangleContext;
|
|
mangleContext.mIs64Bit = true;
|
|
mangleContext.mModule = module;
|
|
mangleContext.mIsSafeMangle = true;
|
|
auto typeInst = type->ToTypeInstance();
|
|
String name;
|
|
if (typeInst != NULL)
|
|
BfMSMangler::Mangle(mangleContext, name, typeInst, true);
|
|
else
|
|
BfMSMangler::Mangle(mangleContext, name, type);
|
|
return name;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void BfMangler::Mangle(StringImpl& outStr, MangleKind mangleKind, BfType* type, BfModule* module)
|
|
{
|
|
if (mangleKind == BfMangler::MangleKind_GNU)
|
|
outStr += BfGNUMangler::Mangle(type, module);
|
|
else
|
|
BfMSMangler::Mangle(outStr, mangleKind == BfMangler::MangleKind_Microsoft_64, type, module);
|
|
}
|
|
|
|
void BfMangler::Mangle(StringImpl& outStr, MangleKind mangleKind, BfMethodInstance* methodInst)
|
|
{
|
|
if (mangleKind == BfMangler::MangleKind_GNU)
|
|
outStr += BfGNUMangler::Mangle(methodInst);
|
|
else
|
|
BfMSMangler::Mangle(outStr, mangleKind == BfMangler::MangleKind_Microsoft_64, methodInst);
|
|
}
|
|
|
|
void BfMangler::Mangle(StringImpl& outStr, MangleKind mangleKind, BfFieldInstance* fieldInstance)
|
|
{
|
|
if (mangleKind == BfMangler::MangleKind_GNU)
|
|
outStr += BfGNUMangler::MangleStaticFieldName(fieldInstance->mOwner, fieldInstance->GetFieldDef()->mName);
|
|
else
|
|
BfMSMangler::Mangle(outStr, mangleKind == BfMangler::MangleKind_Microsoft_64, fieldInstance);
|
|
}
|
|
|
|
void BfMangler::MangleMethodName(StringImpl& outStr, MangleKind mangleKind, BfTypeInstance* type, const StringImpl& methodName)
|
|
{
|
|
if (mangleKind == BfMangler::MangleKind_GNU)
|
|
outStr += BfGNUMangler::MangleMethodName(type, methodName);
|
|
else
|
|
BfMSMangler::MangleMethodName(outStr, mangleKind == BfMangler::MangleKind_Microsoft_64, type, methodName);
|
|
}
|
|
|
|
void BfMangler::MangleStaticFieldName(StringImpl& outStr, MangleKind mangleKind, BfTypeInstance* type, const StringImpl& fieldName, BfType* fieldType)
|
|
{
|
|
if (mangleKind == BfMangler::MangleKind_GNU)
|
|
outStr += BfGNUMangler::MangleStaticFieldName(type, fieldName);
|
|
else
|
|
BfMSMangler::MangleStaticFieldName(outStr, mangleKind == BfMangler::MangleKind_Microsoft_64, type, fieldName, fieldType);
|
|
}
|
|
|