MWCC/compiler_and_linker/unsorted/CMangler.c

714 lines
25 KiB
C

#include "compiler/CMangler.h"
#include "compiler/CError.h"
#include "compiler/CInt64.h"
#include "compiler/CFunc.h"
#include "compiler/CParser.h"
#include "compiler/CTemplateTools.h"
#include "compiler/CompilerTools.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/templates.h"
#include "compiler/types.h"
#include "cos.h"
HashNameNode *constructor_name_node;
HashNameNode *destructor_name_node;
HashNameNode *asop_name_node;
// forward decls
static void CMangler_MangleClassName(TypeClass *tclass);
static void CMangler_MangleTypeAppend(Type *type, UInt32 qual);
static void CMangler_MangleArgs(FuncArg *args);
void CMangler_Setup(void) {
constructor_name_node = GetHashNameNodeExport("__ct");
destructor_name_node = GetHashNameNodeExport("__dt");
asop_name_node = GetHashNameNodeExport("__as");
}
HashNameNode *CMangler_BasicDtorName(void) {
return GetHashNameNodeExport("__dtb");
}
HashNameNode *CMangler_VBaseDtorName(void) {
return GetHashNameNodeExport("__dtv");
}
HashNameNode *CMangler_ArrayDtorName(void) {
return GetHashNameNodeExport("__dta");
}
HashNameNode *CMangler_SDeleteDtorName(void) {
return GetHashNameNodeExport("__dts");
}
HashNameNode *CMangler_DeleteDtorName(void) {
return GetHashNameNodeExport("__dt");
}
char *CMangler_GetOperator(HashNameNode *name) {
char *str;
if (name == asop_name_node)
return "operator=";
str = name->name;
if (!strcmp(str, "__nw")) return "operator new";
if (!strcmp(str, "__dl")) return "operator delete";
if (!strcmp(str, "__nwa")) return "operator new[]";
if (!strcmp(str, "__dla")) return "operator delete[]";
if (!strcmp(str, "__pl")) return "operator+";
if (!strcmp(str, "__mi")) return "operator-";
if (!strcmp(str, "__ml")) return "operator*";
if (!strcmp(str, "__dv")) return "operator/";
if (!strcmp(str, "__md")) return "operator%";
if (!strcmp(str, "__er")) return "operator^";
if (!strcmp(str, "__ad")) return "operator&";
if (!strcmp(str, "__or")) return "operator|";
if (!strcmp(str, "__co")) return "operator~";
if (!strcmp(str, "__nt")) return "operator!";
if (!strcmp(str, "__lt")) return "operator<";
if (!strcmp(str, "__gt")) return "operator>";
if (!strcmp(str, "__apl")) return "operator+=";
if (!strcmp(str, "__ami")) return "operator-=";
if (!strcmp(str, "__amu")) return "operator*=";
if (!strcmp(str, "__adv")) return "operator/=";
if (!strcmp(str, "__amd")) return "operator%=";
if (!strcmp(str, "__aer")) return "operator^=";
if (!strcmp(str, "__aad")) return "operator&=";
if (!strcmp(str, "__aor")) return "operator|=";
if (!strcmp(str, "__ls")) return "operator<<";
if (!strcmp(str, "__rs")) return "operator>>";
if (!strcmp(str, "__als")) return "operator<<=";
if (!strcmp(str, "__ars")) return "operator>>=";
if (!strcmp(str, "__eq")) return "operator==";
if (!strcmp(str, "__ne")) return "operator!=";
if (!strcmp(str, "__le")) return "operator<=";
if (!strcmp(str, "__ge")) return "operator>=";
if (!strcmp(str, "__aa")) return "operator&&";
if (!strcmp(str, "__oo")) return "operator||";
if (!strcmp(str, "__pp")) return "operator++";
if (!strcmp(str, "__mm")) return "operator--";
if (!strcmp(str, "__cm")) return "operator,";
if (!strcmp(str, "__rm")) return "operator->*";
if (!strcmp(str, "__rf")) return "operator*";
if (!strcmp(str, "__cl")) return "operator()";
if (!strcmp(str, "__vc")) return "operator[]";
return NULL;
}
HashNameNode *CMangler_OperatorName(short token) {
switch (token) {
case TK_NEW: return GetHashNameNodeExport("__nw");
case TK_DELETE: return GetHashNameNodeExport("__dl");
case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa");
case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla");
case '+': return GetHashNameNodeExport("__pl");
case '-': return GetHashNameNodeExport("__mi");
case '*': return GetHashNameNodeExport("__ml");
case '/': return GetHashNameNodeExport("__dv");
case '%': return GetHashNameNodeExport("__md");
case '^': return GetHashNameNodeExport("__er");
case '&': return GetHashNameNodeExport("__ad");
case '|': return GetHashNameNodeExport("__or");
case '~': return GetHashNameNodeExport("__co");
case '!': return GetHashNameNodeExport("__nt");
case '=': return asop_name_node;
case '<': return GetHashNameNodeExport("__lt");
case '>': return GetHashNameNodeExport("__gt");
case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl");
case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami");
case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu");
case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv");
case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd");
case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer");
case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad");
case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor");
case TK_SHL: return GetHashNameNodeExport("__ls");
case TK_SHR: return GetHashNameNodeExport("__rs");
case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als");
case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars");
case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq");
case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne");
case TK_LESS_EQUAL: return GetHashNameNodeExport("__le");
case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge");
case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa");
case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo");
case TK_INCREMENT: return GetHashNameNodeExport("__pp");
case TK_DECREMENT: return GetHashNameNodeExport("__mm");
case ',': return GetHashNameNodeExport("__cm");
case TK_ARROW_STAR: return GetHashNameNodeExport("__rm");
case TK_ARROW: return GetHashNameNodeExport("__rf");
case '(': return GetHashNameNodeExport("__cl");
case '[': return GetHashNameNodeExport("__vc");
default: return NULL;
}
}
HashNameNode *CMangler_VTableName(TypeClass *theclass) {
HashNameNode *name;
name_mangle_list.size = 0;
AppendGListName(&name_mangle_list, "__vt__");
CMangler_MangleClassName(theclass);
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) {
HashNameNode *name;
name_mangle_list.size = 0;
AppendGListName(&name_mangle_list, "__RTTI__");
CMangler_MangleTypeAppend(type, qual);
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
HashNameNode *CMangler_ThunkName(Object *vfunc, SInt32 this_delta, SInt32 return_delta, SInt32 ctoroffset) {
HashNameNode *linkname;
HashNameNode *name;
char buf[64];
linkname = CMangler_GetLinkName(vfunc);
name_mangle_list.size = 0;
if (return_delta == 0) {
if (ctoroffset < 0)
sprintf(buf, "_@%" PRId32 "@", -this_delta);
else
sprintf(buf, "_@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset);
} else {
sprintf(buf, "_@%" PRId32 "@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset, return_delta);
}
AppendGListName(&name_mangle_list, buf);
AppendGListID(&name_mangle_list, linkname->name + 1);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
static void CMangler_CheckTemplateArguments(TemplArg *arg) {
ENode *expr;
while (arg) {
if (arg->pid.type == TPT_NONTYPE) {
expr = arg->data.paramdecl.expr;
CError_ASSERT(360, expr);
if (expr->rtype->type != TYPETEMPLDEPEXPR) {
switch (expr->type) {
case EINTCONST:
break;
case EOBJREF:
CMangler_GetLinkName(expr->data.objref);
break;
default:
CError_FATAL(383);
}
}
}
arg = arg->next;
}
}
static void CMangler_AppendTemplateArgumentList(TemplArg *arg) {
ENode *expr;
char buf[32];
AppendGListByte(&name_mangle_list, '<');
while (arg) {
if (arg->pid.type == TPT_NONTYPE) {
expr = arg->data.paramdecl.expr;
CError_ASSERT(409, expr);
if (expr->rtype->type != TYPETEMPLDEPEXPR) {
switch (expr->type) {
case EINTCONST:
CInt64_PrintDec(buf, expr->data.intval);
AppendGListName(&name_mangle_list, buf);
break;
case EOBJREF:
AppendGListByte(&name_mangle_list, '&');
AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name);
break;
default:
CError_FATAL(452);
}
} else {
AppendGListByte(&name_mangle_list, 'T');
}
} else if (arg->pid.type == TPT_TYPE) {
CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual);
} else {
CError_ASSERT(467, arg->pid.type == TPT_TEMPLATE);
CMangler_MangleTypeAppend(arg->data.ttargtype, 0);
}
if (arg->next)
AppendGListByte(&name_mangle_list, ',');
arg = arg->next;
}
AppendGListByte(&name_mangle_list, '>');
}
HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) {
HashNameNode *name;
CMangler_CheckTemplateArguments(args);
name_mangle_list.size = 0;
AppendGListName(&name_mangle_list, basename->name);
CMangler_AppendTemplateArgumentList(args);
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
static void CMangler_MangleTypeName(char *str) {
char buf[16];
sprintf(buf, "%d", strlen(str));
AppendGListName(&name_mangle_list, buf);
AppendGListName(&name_mangle_list, str);
}
static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) {
char *stack[10];
int stackp;
stack[0] = str;
stackp = 1;
while (nspace) {
if (nspace->name) {
stack[stackp++] = nspace->name->name;
if (stackp >= 9)
break;
}
nspace = nspace->parent;
}
if (stackp > 1) {
AppendGListByte(&name_mangle_list, 'Q');
AppendGListByte(&name_mangle_list, '0' + stackp);
}
while (--stackp >= 0)
CMangler_MangleTypeName(stack[stackp]);
}
static void CMangler_MangleClassName(TypeClass *tclass) {
if (!tclass->classname)
CMangler_MangleNameSpaceName(tclass->nspace->parent, "class");
else
CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name);
}
static void CMangler_MangleQualifier(UInt32 qual) {
if (qual & Q_CONST)
AppendGListByte(&name_mangle_list, 'C');
if (qual & Q_VOLATILE)
AppendGListByte(&name_mangle_list, 'V');
}
static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) {
char buf[16];
switch (type->type) {
case TYPEVOID:
CMangler_MangleQualifier(qual);
AppendGListByte(&name_mangle_list, 'v');
break;
case TYPEINT:
case TYPEFLOAT:
CMangler_MangleQualifier(qual);
switch (TYPE_INTEGRAL(type)->integral) {
case IT_BOOL:
AppendGListByte(&name_mangle_list, 'b');
return;
case IT_CHAR:
AppendGListByte(&name_mangle_list, 'c');
return;
case IT_WCHAR_T:
AppendGListByte(&name_mangle_list, 'w');
return;
case IT_UCHAR:
AppendGListName(&name_mangle_list, "Uc");
return;
case IT_SCHAR:
AppendGListName(&name_mangle_list, "Sc");
return;
case IT_SHORT:
AppendGListByte(&name_mangle_list, 's');
return;
case IT_USHORT:
AppendGListName(&name_mangle_list, "Us");
return;
case IT_INT:
AppendGListByte(&name_mangle_list, 'i');
return;
case IT_UINT:
AppendGListName(&name_mangle_list, "Ui");
return;
case IT_LONG:
AppendGListByte(&name_mangle_list, 'l');
return;
case IT_ULONG:
AppendGListName(&name_mangle_list, "Ul");
return;
case IT_LONGLONG:
AppendGListByte(&name_mangle_list, 'x');
return;
case IT_ULONGLONG:
AppendGListName(&name_mangle_list, "Ux");
return;
case IT_FLOAT:
AppendGListByte(&name_mangle_list, 'f');
return;
case IT_SHORTDOUBLE:
AppendGListByte(&name_mangle_list, 'D');
return;
case IT_DOUBLE:
AppendGListByte(&name_mangle_list, 'd');
return;
case IT_LONGDOUBLE:
AppendGListByte(&name_mangle_list, 'r');
return;
default:
CError_FATAL(619);
}
case TYPEENUM:
CMangler_MangleQualifier(qual);
if (!TYPE_ENUM(type)->enumname)
CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum");
else
CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name);
break;
case TYPEPOINTER:
CMangler_MangleQualifier(TYPE_POINTER(type)->qual);
if (TYPE_POINTER(type)->qual & Q_REFERENCE)
AppendGListByte(&name_mangle_list, 'R');
else
AppendGListByte(&name_mangle_list, 'P');
CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
break;
case TYPEMEMBERPOINTER:
if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) {
AppendGListName(&name_mangle_list, "3<T>");
} else {
CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual);
AppendGListByte(&name_mangle_list, 'M');
CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2));
CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual);
}
break;
case TYPEARRAY:
AppendGListByte(&name_mangle_list, 'A');
if (TYPE_POINTER(type)->target->size) {
sprintf(buf, "%" PRId32 "", type->size / TYPE_POINTER(type)->target->size);
AppendGListName(&name_mangle_list, buf);
} else {
AppendGListByte(&name_mangle_list, '0');
}
AppendGListByte(&name_mangle_list, '_');
CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual);
break;
case TYPEFUNC:
CMangler_MangleQualifier(qual);
AppendGListByte(&name_mangle_list, 'F');
CMangler_MangleArgs(TYPE_FUNC(type)->args);
AppendGListByte(&name_mangle_list, '_');
CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual);
break;
case TYPESTRUCT:
CMangler_MangleQualifier(qual);
switch (TYPE_STRUCT(type)->stype) {
case STRUCT_TYPE_4:
AppendGListName(&name_mangle_list, "XUc");
return;
case STRUCT_TYPE_5:
AppendGListName(&name_mangle_list, "Xc");
return;
case STRUCT_TYPE_6:
AppendGListName(&name_mangle_list, "XC");
return;
case STRUCT_TYPE_7:
AppendGListName(&name_mangle_list, "XUs");
return;
case STRUCT_TYPE_8:
AppendGListName(&name_mangle_list, "Xs");
return;
case STRUCT_TYPE_9:
AppendGListName(&name_mangle_list, "XS");
return;
case STRUCT_TYPE_A:
AppendGListName(&name_mangle_list, "XUi");
return;
case STRUCT_TYPE_B:
AppendGListName(&name_mangle_list, "Xi");
return;
case STRUCT_TYPE_C:
AppendGListName(&name_mangle_list, "XI");
return;
case STRUCT_TYPE_D:
AppendGListName(&name_mangle_list, "Xf");
return;
case STRUCT_TYPE_E:
AppendGListName(&name_mangle_list, "Xp");
return;
}
if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) {
CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name);
return;
}
switch (TYPE_STRUCT(type)->stype) {
case STRUCT_TYPE_STRUCT:
AppendGListName(&name_mangle_list, "struct");
break;
case STRUCT_TYPE_UNION:
AppendGListName(&name_mangle_list, "union");
break;
case STRUCT_TYPE_CLASS:
AppendGListName(&name_mangle_list, "class");
break;
default:
CError_FATAL(701);
}
break;
case TYPECLASS:
CMangler_MangleQualifier(qual);
CMangler_MangleClassName(TYPE_CLASS(type));
break;
case TYPETEMPLATE:
AppendGListName(&name_mangle_list, "1T");
break;
default:
CError_FATAL(716);
}
}
void CMangler_MangleType(Type *type, UInt32 qual) {
name_mangle_list.size = 0;
CMangler_MangleTypeAppend(type, qual);
}
static void CMangler_MangleArgs(FuncArg *args) {
TypePointer ptr;
if (args) {
if (args->type) {
while (args) {
if (args != &elipsis && args != &oldstyle) {
if (args->type->type == TYPEPOINTER) {
ptr = *TYPE_POINTER(args->type);
ptr.qual &= ~(Q_CONST | Q_VOLATILE);
CMangler_MangleTypeAppend(TYPE(&ptr), args->qual);
} else {
CMangler_MangleTypeAppend(args->type, 0);
}
} else {
AppendGListByte(&name_mangle_list, 'e');
}
args = args->next;
}
} else {
AppendGListByte(&name_mangle_list, 'e');
}
} else {
AppendGListByte(&name_mangle_list, 'v');
}
}
static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) {
TypeFunc *tfunc = TYPE_FUNC(obj->type);
FuncArg *arg = tfunc->args;
AppendGListName(&name_mangle_list, obj->name->name);
if (obj->u.func.inst) {
if (tfunc->flags & FUNC_FLAGS_40)
CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
CMangler_AppendTemplateArgumentList(obj->u.func.inst->args);
}
AppendGListName(&name_mangle_list, "__");
while (nspace && nspace->name == NULL)
nspace = nspace->parent;
if (nspace) {
CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
if (nspace->theclass) {
if (obj->name == destructor_name_node) {
AppendGListName(&name_mangle_list, "Fv");
return;
}
if (arg) {
if (obj->name == constructor_name_node) {
arg = arg->next;
if (arg && (nspace->theclass->flags & CLASS_FLAGS_20))
arg = arg->next;
} else {
if ((tfunc->flags & FUNC_FLAGS_METHOD) && !TYPE_METHOD(tfunc)->x26) {
CMangler_MangleQualifier(arg->qual);
arg = arg->next;
}
}
}
}
}
AppendGListByte(&name_mangle_list, 'F');
CMangler_MangleArgs(arg);
if (obj->u.func.inst && copts.new_mangler) {
AppendGListByte(&name_mangle_list, '_');
CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual);
}
}
HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) {
HashNameNode *name;
if (CTemplTool_IsTemplateArgumentDependentType(type))
return GetHashNameNodeExport("__op");
name_mangle_list.size = 0;
AppendGListName(&name_mangle_list, "__op");
CMangler_MangleTypeAppend(type, qual);
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
static HashNameNode *CMangler_MangleNameToUpper(char *str) {
HashNameNode *name;
name_mangle_list.size = 0;
while (*str) {
AppendGListByte(&name_mangle_list, toupper(*(str++)));
}
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
static HashNameNode *CMangler_FunctionLinkName(Object *obj) {
HashNameNode *name;
NameSpace *nspace;
if (obj->u.func.inst)
CMangler_CheckTemplateArguments(obj->u.func.inst->args);
for (nspace = obj->nspace; nspace; nspace = nspace->parent) {
if (nspace->name)
break;
}
name_mangle_list.size = 0;
if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) {
AppendGListData(&name_mangle_list, "_", 1);
AppendGListID(&name_mangle_list, obj->name->name);
} else if ((obj->qual & Q_80000) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) {
AppendGListData(&name_mangle_list, "_", 1);
CMangler_MangleFunction(obj, nspace);
AppendGListByte(&name_mangle_list, 0);
} else {
AppendGListData(&name_mangle_list, "_", 1);
AppendGListID(&name_mangle_list, obj->name->name);
}
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
HashNameNode *CMangler_GetCovariantFunctionName(Object *dobj, TypeClass *theclass) {
HashNameNode *name;
name = CMangler_GetLinkName(dobj);
name_mangle_list.size = 0;
AppendGListName(&name_mangle_list, name->name);
AppendGListName(&name_mangle_list, "@@");
CMangler_MangleTypeAppend(TYPE(theclass), 0);
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
static HashNameNode *CMangler_DataLinkName(Object *obj) {
NameSpace *nspace;
HashNameNode *name;
nspace = obj->nspace;
while (nspace && nspace->name == NULL)
nspace = nspace->parent;
name_mangle_list.size = 0;
AppendGListData(&name_mangle_list, "_", 1);
AppendGListName(&name_mangle_list, obj->name->name);
while (nspace && nspace->name == NULL)
nspace = nspace->parent;
if (nspace && (obj->qual & Q_80000)) {
AppendGListName(&name_mangle_list, "__");
CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name);
}
AppendGListByte(&name_mangle_list, 0);
COS_LockHandle(name_mangle_list.data);
name = GetHashNameNodeExport(*name_mangle_list.data);
COS_UnlockHandle(name_mangle_list.data);
return name;
}
HashNameNode *CMangler_GetLinkName(Object *obj) {
while (obj->datatype == DALIAS)
obj = obj->u.alias.object;
switch (obj->datatype) {
case DFUNC:
case DVFUNC:
if (!obj->u.func.linkname)
obj->u.func.linkname = CMangler_FunctionLinkName(obj);
return obj->u.func.linkname;
case DDATA:
if (!obj->u.data.linkname)
obj->u.data.linkname = CMangler_DataLinkName(obj);
return obj->u.data.linkname;
case DINLINEFUNC:
return CMangler_FunctionLinkName(obj);
case DLOCAL:
case DABSOLUTE:
case DLABEL:
return obj->name;
case DNONLAZYPTR:
if (!obj->u.toc.linkname)
obj->u.toc.linkname = CMangler_DataLinkName(obj);
return obj->u.toc.linkname;
default:
CError_FATAL(1110);
return NULL;
}
}