#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"); } 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_VECTOR_UCHAR: AppendGListName(&name_mangle_list, "XUc"); return; case STRUCT_VECTOR_SCHAR: AppendGListName(&name_mangle_list, "Xc"); return; case STRUCT_VECTOR_BCHAR: AppendGListName(&name_mangle_list, "XC"); return; case STRUCT_VECTOR_USHORT: AppendGListName(&name_mangle_list, "XUs"); return; case STRUCT_VECTOR_SSHORT: AppendGListName(&name_mangle_list, "Xs"); return; case STRUCT_VECTOR_BSHORT: AppendGListName(&name_mangle_list, "XS"); return; case STRUCT_VECTOR_UINT: AppendGListName(&name_mangle_list, "XUi"); return; case STRUCT_VECTOR_SINT: AppendGListName(&name_mangle_list, "Xi"); return; case STRUCT_VECTOR_BINT: AppendGListName(&name_mangle_list, "XI"); return; case STRUCT_VECTOR_FLOAT: AppendGListName(&name_mangle_list, "Xf"); return; case STRUCT_VECTOR_PIXEL: 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; } }