void visit(Dsymbol *s) { #if 0 printf("Dsymbol::mangle() '%s'", s->toChars()); if (s->parent) printf(" parent = %s %s", s->parent->kind(), s->parent->toChars()); printf("\n"); #endif char *id = s->ident ? s->ident->toChars() : s->toChars(); OutBuffer buf; if (s->parent) { FuncDeclaration *f = s->parent->isFuncDeclaration(); if (f) mangleExact(f); else s->parent->accept(this); if (result[0] == '_' && result[1] == 'D') result += 2; buf.writestring(result); } buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id); result = id; }
void visit(OverDeclaration *od) { if (od->overnext) { visit((Dsymbol *)od); return; } if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration()) { if (!od->hasOverloads || fd->isUnique()) { mangleExact(fd); return; } } if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration()) { if (!od->hasOverloads || td->overnext == NULL) { td->accept(this); return; } } visit((Dsymbol *)od); }
/****************************************************************************** * Normally FuncDeclaration and FuncAliasDeclaration have overloads. * If and only if there is no overloads, mangle() could return * exact mangled name. * * module test; * void foo(long) {} // _D4test3fooFlZv * void foo(string) {} // _D4test3fooFAyaZv * * // from FuncDeclaration::mangle(). * pragma(msg, foo.mangleof); // prints unexact mangled name "4test3foo" * // by calling Dsymbol::mangle() * * // from FuncAliasDeclaration::mangle() * pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof); // "_D4test3fooFlZv" * pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof); // "_D4test3fooFAyaZv" * * If a function has no overloads, .mangleof property still returns exact mangled name. * * void bar() {} * pragma(msg, bar.mangleof); // still prints "_D4test3barFZv" * // by calling FuncDeclaration::mangleExact(). */ void visit(FuncDeclaration *fd) { if (fd->isUnique()) mangleExact(fd); else visit((Dsymbol *)fd); }
void visit(TemplateInstance *ti) { OutBuffer buf; #if 0 printf("TemplateInstance::mangle() %p %s", ti, ti->toChars()); if (ti->parent) printf(" parent = %s %s", ti->parent->kind(), ti->parent->toChars()); printf("\n"); #endif ti->getIdent(); const char *id = ti->ident ? ti->ident->toChars() : ti->toChars(); if (!ti->tempdecl) ti->error("is not defined"); else { Dsymbol *par = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent; if (par) { FuncDeclaration *f = par->isFuncDeclaration(); if (f) mangleExact(f); else par->accept(this); if (result[0] == '_' && result[1] == 'D') result += 2; buf.writestring(result); } } buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id); result = id; }
/** * Replaces <<func>> with the name of the currently codegen'd function. * * This kludge is required to handle labels correctly, as the instruction * strings for jumps, … are generated during semantic3, but attribute inference * might change the function type (and hence the mangled name) right at the end * of semantic3. */ static void replace_func_name(IRState *p, std::string &insnt) { static const std::string needle("<<func>>"); const char *mangle = mangleExact(p->func()->decl); size_t pos; while (std::string::npos != (pos = insnt.find(needle))) { // This will only happen for few instructions, and only once for those. insnt.replace(pos, needle.size(), mangle); } }
std::string getIRMangledName(FuncDeclaration *fdecl, LINK link) { std::string mangledName = mangleExact(fdecl); // Hash the name if necessary if (((link == LINKd) || (link == LINKdefault)) && (global.params.hashThreshold != 0) && (mangledName.length() > global.params.hashThreshold)) { auto hashedName = hashSymbolName(mangledName, fdecl); mangledName = "_D" + hashedName + "Z"; } // TODO: Cache the result? return getIRMangledFuncName(std::move(mangledName), link); }
// ditto void visit(FuncAliasDeclaration *fd) { FuncDeclaration *f = fd->toAliasFunc(); FuncAliasDeclaration *fa = f->isFuncAliasDeclaration(); if (!fd->hasOverloads && !fa) { mangleExact(f); return; } if (fa) { fa->accept(this); return; } visit((Dsymbol *)fd); }
void visit(FuncDeclaration *fd) { if (!fd->csym) { const char *id = mangleExact(fd); //printf("FuncDeclaration::toSymbol(%s %s)\n", fd->kind(), fd->toChars()); //printf("\tid = '%s'\n", id); //printf("\ttype = %s\n", fd->type->toChars()); Symbol *s = symbol_calloc(id); slist_add(s); s->prettyIdent = fd->toPrettyChars(); s->Sclass = SCglobal; symbol_func(s); func_t *f = s->Sfunc; if (fd->isVirtual() && fd->vtblIndex != -1) f->Fflags |= Fvirtual; else if (fd->isMember2() && fd->isStatic()) f->Fflags |= Fstatic; f->Fstartline.Slinnum = fd->loc.linnum; f->Fstartline.Scharnum = fd->loc.charnum; f->Fstartline.Sfilename = (char *)fd->loc.filename; if (fd->endloc.linnum) { f->Fendline.Slinnum = fd->endloc.linnum; f->Fendline.Scharnum = fd->endloc.charnum; f->Fendline.Sfilename = (char *)fd->endloc.filename; } else { f->Fendline.Slinnum = fd->loc.linnum; f->Fendline.Scharnum = fd->loc.charnum; f->Fendline.Sfilename = (char *)fd->loc.filename; } TYPE *t = Type_toCtype(fd->type); mangle_t msave = t->Tmangle; if (fd->isMain()) { t->Tty = TYnfunc; t->Tmangle = mTYman_c; } else { switch (fd->linkage) { case LINKwindows: t->Tmangle = mTYman_std; break; case LINKpascal: t->Tty = TYnpfunc; t->Tmangle = mTYman_pas; break; case LINKc: t->Tmangle = mTYman_c; break; case LINKd: t->Tmangle = mTYman_d; break; case LINKcpp: s->Sflags |= SFLpublic; if (fd->isThis() && !global.params.is64bit && global.params.isWindows) { if (((TypeFunction *)fd->type)->varargs == 1) { t->Tty = TYnfunc; } else { t->Tty = TYmfunc; } } t->Tmangle = mTYman_d; break; default: printf("linkage = %d\n", fd->linkage); assert(0); } } if (msave) assert(msave == t->Tmangle); //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle); t->Tcount++; s->Stype = t; //s->Sfielddef = this; fd->csym = s; } result = fd->csym; }
/******************************************* * Convert intrinsic function to operator. * Returns that operator, -1 if not an intrinsic function. */ int intrinsic_op(FuncDeclaration *fd) { fd = fd->toAliasFunc(); const char *name = mangleExact(fd); //printf("intrinsic_op(%s)\n", name); static const char *std_namearray[] = { /* The names are mangled differently because of the pure and * nothrow attributes. */ "4math3cosFNaNbNiNfeZe", "4math3sinFNaNbNiNfeZe", "4math4fabsFNaNbNiNfeZe", "4math4rintFNaNbNiNfeZe", "4math4sqrtFNaNbNiNfdZd", "4math4sqrtFNaNbNiNfeZe", "4math4sqrtFNaNbNiNffZf", "4math4yl2xFNaNbNiNfeeZe", "4math5ldexpFNaNbNiNfeiZe", "4math6rndtolFNaNbNiNfeZl", "4math6yl2xp1FNaNbNiNfeeZe", }; static const char *std_namearray64[] = { /* The names are mangled differently because of the pure and * nothrow attributes. */ "4math3cosFNaNbNiNfeZe", "4math3sinFNaNbNiNfeZe", "4math4fabsFNaNbNiNfeZe", "4math4rintFNaNbNiNfeZe", "4math4sqrtFNaNbNiNfdZd", "4math4sqrtFNaNbNiNfeZe", "4math4sqrtFNaNbNiNffZf", "4math4yl2xFNaNbNiNfeeZe", "4math5ldexpFNaNbNiNfeiZe", "4math6rndtolFNaNbNiNfeZl", "4math6yl2xp1FNaNbNiNfeeZe", }; static unsigned char std_ioptab[] = { OPcos, OPsin, OPabs, OPrint, OPsqrt, OPsqrt, OPsqrt, OPyl2x, OPscale, OPrndtol, OPyl2xp1, }; static const char *core_namearray[] = { "4math3cosFNaNbNiNfeZe", "4math3sinFNaNbNiNfeZe", "4math4fabsFNaNbNiNfeZe", "4math4rintFNaNbNiNfeZe", "4math4sqrtFNaNbNiNfdZd", "4math4sqrtFNaNbNiNfeZe", "4math4sqrtFNaNbNiNffZf", "4math4yl2xFNaNbNiNfeeZe", "4math5ldexpFNaNbNiNfeiZe", "4math6rndtolFNaNbNiNfeZl", "4math6yl2xp1FNaNbNiNfeeZe", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v", "4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v", "5bitop12volatileLoadFNbNiNfPhZh", "5bitop12volatileLoadFNbNiNfPkZk", "5bitop12volatileLoadFNbNiNfPmZm", "5bitop12volatileLoadFNbNiNfPtZt", "5bitop13volatileStoreFNbNiNfPhhZv", "5bitop13volatileStoreFNbNiNfPkkZv", "5bitop13volatileStoreFNbNiNfPmmZv", "5bitop13volatileStoreFNbNiNfPttZv", "5bitop3bsfFNaNbNiNfkZi", "5bitop3bsrFNaNbNiNfkZi", "5bitop3btcFNaNbNiPkkZi", "5bitop3btrFNaNbNiPkkZi", "5bitop3btsFNaNbNiPkkZi", "5bitop3inpFNbNikZh", "5bitop4inplFNbNikZk", "5bitop4inpwFNbNikZt", "5bitop4outpFNbNikhZh", "5bitop5bswapFNaNbNiNfkZk", "5bitop5outplFNbNikkZk", "5bitop5outpwFNbNiktZt", "5bitop7_popcntFNaNbNiNfkZi", "5bitop7_popcntFNaNbNiNfmxx", // don't find 64 bit version in 32 bit code "5bitop7_popcntFNaNbNiNftZt", }; static const char *core_namearray64[] = { "4math3cosFNaNbNiNfeZe", "4math3sinFNaNbNiNfeZe", "4math4fabsFNaNbNiNfeZe", "4math4rintFNaNbNiNfeZe", "4math4sqrtFNaNbNiNfdZd", "4math4sqrtFNaNbNiNfeZe", "4math4sqrtFNaNbNiNffZf", "4math4yl2xFNaNbNiNfeeZe", "4math5ldexpFNaNbNiNfeiZe", "4math6rndtolFNaNbNiNfeZl", "4math6yl2xp1FNaNbNiNfeeZe", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v", "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v", "4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v", "4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v", "5bitop12volatileLoadFNbNiNfPhZh", "5bitop12volatileLoadFNbNiNfPkZk", "5bitop12volatileLoadFNbNiNfPmZm", "5bitop12volatileLoadFNbNiNfPtZt", "5bitop13volatileStoreFNbNiNfPhhZv", "5bitop13volatileStoreFNbNiNfPkkZv", "5bitop13volatileStoreFNbNiNfPmmZv", "5bitop13volatileStoreFNbNiNfPttZv", "5bitop3bsfFNaNbNiNfmZi", "5bitop3bsrFNaNbNiNfmZi", "5bitop3btcFNaNbNiPmmZi", "5bitop3btrFNaNbNiPmmZi", "5bitop3btsFNaNbNiPmmZi", "5bitop3inpFNbNikZh", "5bitop4inplFNbNikZk", "5bitop4inpwFNbNikZt", "5bitop4outpFNbNikhZh", "5bitop5bswapFNaNbNiNfkZk", "5bitop5outplFNbNikkZk", "5bitop5outpwFNbNiktZt", "5bitop7_popcntFNaNbNiNfkZi", "5bitop7_popcntFNaNbNiNfmZi", "5bitop7_popcntFNaNbNiNftZt", }; static unsigned char core_ioptab[] = { OPcos, OPsin, OPabs, OPrint, OPsqrt, OPsqrt, OPsqrt, OPyl2x, OPscale, OPrndtol, OPyl2xp1, OPvector, OPvector, OPvector, OPvector, OPvector, OPvector, OPvector, OPvector, OPvector, OPind, OPind, OPind, OPind, OPeq, OPeq, OPeq, OPeq, OPbsf, OPbsr, OPbtc, OPbtr, OPbts, OPinp, OPinp, OPinp, OPoutp, OPbswap, OPoutp, OPoutp, OPpopcnt, OPpopcnt, OPpopcnt, }; #ifdef DEBUG assert(sizeof(std_namearray) == sizeof(std_namearray64)); assert(sizeof(std_namearray) / sizeof(char *) == sizeof(std_ioptab)); for (size_t i = 0; i < sizeof(std_namearray) / sizeof(char *) - 1; i++) { if (strcmp(std_namearray[i], std_namearray[i + 1]) >= 0) { printf("std_namearray[%ld] = '%s'\n", (long)i, std_namearray[i]); assert(0); } } assert(sizeof(std_namearray64) / sizeof(char *) == sizeof(std_ioptab)); for (size_t i = 0; i < sizeof(std_namearray64) / sizeof(char *) - 1; i++) { if (strcmp(std_namearray64[i], std_namearray64[i + 1]) >= 0) { printf("std_namearray64[%ld] = '%s'\n", (long)i, std_namearray64[i]); assert(0); } } assert(sizeof(core_namearray) == sizeof(core_namearray64)); assert(sizeof(core_namearray) / sizeof(char *) == sizeof(core_ioptab)); for (size_t i = 0; i < sizeof(core_namearray) / sizeof(char *) - 1; i++) { //printf("test1 %s %s %d\n", core_namearray[i], core_namearray[i + 1], strcmp(core_namearray[i], core_namearray[i + 1])); if (strcmp(core_namearray[i], core_namearray[i + 1]) >= 0) { printf("core_namearray[%ld] = '%s'\n", (long)i, core_namearray[i]); assert(0); } } assert(sizeof(core_namearray64) / sizeof(char *) == sizeof(core_ioptab)); for (size_t i = 0; i < sizeof(core_namearray64) / sizeof(char *) - 1; i++) { if (strcmp(core_namearray64[i], core_namearray64[i + 1]) >= 0) { printf("core_namearray64[%ld] = '%s'\n", (long)i, core_namearray64[i]); assert(0); } } #endif size_t length = strlen(name); if (length > 10 && (name[7] == 'm' || name[7] == 'i') && !memcmp(name, "_D3std", 6)) { int i = binary(name + 6, I64 ? std_namearray64 : std_namearray, sizeof(std_namearray) / sizeof(char *)); return (i == -1) ? i : std_ioptab[i]; } if (length > 12 && (name[8] == 'm' || name[8] == 'b' || name[8] == 's') && !memcmp(name, "_D4core", 7)) { int i = binary(name + 7, I64 ? core_namearray64 : core_namearray, sizeof(core_namearray) / sizeof(char *)); if (i != -1) return core_ioptab[i]; if (global.params.is64bit && fd->toParent()->isTemplateInstance() && !strcmp(mangle(fd->getModule()), "4core4stdc6stdarg") && fd->ident == Id::va_start) { return OPva_start; } return -1; } return -1; }
Symbol *FuncDeclaration::toSymbol() { if (!csym) { Symbol *s; TYPE *t; const char *id; #if 0 id = ident->toChars(); #else id = mangleExact(); #endif //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars()); //printf("\tid = '%s'\n", id); //printf("\ttype = %s\n", type->toChars()); s = symbol_calloc(id); slist_add(s); { s->prettyIdent = toPrettyChars(); s->Sclass = SCglobal; symbol_func(s); func_t *f = s->Sfunc; if (isVirtual() && vtblIndex != -1) f->Fflags |= Fvirtual; else if (isMember2() && isStatic()) f->Fflags |= Fstatic; f->Fstartline.Slinnum = loc.linnum; f->Fstartline.Sfilename = (char *)loc.filename; if (endloc.linnum) { f->Fendline.Slinnum = endloc.linnum; f->Fendline.Sfilename = (char *)endloc.filename; } else { f->Fendline.Slinnum = loc.linnum; f->Fendline.Sfilename = (char *)loc.filename; } t = type->toCtype(); } mangle_t msave = t->Tmangle; if (isMain()) { t->Tty = TYnfunc; t->Tmangle = mTYman_c; } else { switch (linkage) { case LINKwindows: t->Tmangle = mTYman_std; break; case LINKpascal: t->Tty = TYnpfunc; t->Tmangle = mTYman_pas; break; case LINKc: t->Tmangle = mTYman_c; break; case LINKd: t->Tmangle = mTYman_d; break; case LINKcpp: { t->Tmangle = mTYman_cpp; if (isThis() && !global.params.is64bit && global.params.isWindows) { if (((TypeFunction *)type)->varargs == 1) t->Tty = TYnfunc; else t->Tty = TYmfunc; } s->Sflags |= SFLpublic; Dsymbol *parent = toParent(); ClassDeclaration *cd = parent->isClassDeclaration(); if (cd) { ::type *tc = cd->type->toCtype(); s->Sscope = tc->Tnext->Ttag; } StructDeclaration *sd = parent->isStructDeclaration(); if (sd) { ::type *ts = sd->type->toCtype(); s->Sscope = ts->Ttag; } if (isCtorDeclaration()) s->Sfunc->Fflags |= Fctor; if (isDtorDeclaration()) s->Sfunc->Fflags |= Fdtor; break; } default: printf("linkage = %d\n", linkage); assert(0); } } if (msave) assert(msave == t->Tmangle); //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle); t->Tcount++; s->Stype = t; //s->Sfielddef = this; csym = s; } return csym; }
void DtoDeclareFunction(FuncDeclaration* fdecl) { DtoResolveFunction(fdecl); if (fdecl->ir.isDeclared()) return; fdecl->ir.setDeclared(); IF_LOG Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars()); LOG_SCOPE; if (fdecl->isUnitTestDeclaration() && !global.params.useUnitTests) { Logger::println("unit tests not enabled"); return; } //printf("declare function: %s\n", fdecl->toPrettyChars()); // intrinsic sanity check if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { error(fdecl->loc, "intrinsics cannot have function bodies"); fatal(); } // get TypeFunction* Type* t = fdecl->type->toBasetype(); TypeFunction* f = static_cast<TypeFunction*>(t); // create IrFunction IrFunction *irFunc = getIrFunc(fdecl, true); LLFunction* vafunc = 0; if (DtoIsVaIntrinsic(fdecl)) vafunc = DtoDeclareVaFunction(fdecl); // calling convention LINK link = f->linkage; if (vafunc || fdecl->llvmInternal == LLVMintrinsic // DMD treats _Dmain as having C calling convention and this has been // hardcoded into druntime, even if the frontend type has D linkage. // See Bugzilla issue 9028. || fdecl->isMain() ) { link = LINKc; } // mangled name std::string mangledName(mangleExact(fdecl)); mangledName = gABI->mangleForLLVM(mangledName, link); // construct function LLFunctionType* functype = DtoFunctionType(fdecl); LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName); if (!func) { if(fdecl->llvmInternal == LLVMinline_ir) { func = DtoInlineIRFunction(fdecl); } else { // All function declarations are "external" - any other linkage type // is set when actually defining the function. func = LLFunction::Create(functype, llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module); } } else if (func->getFunctionType() != functype) { error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", mangleExact(fdecl)); fatal(); } func->setCallingConv(gABI->callingConv(link)); IF_LOG Logger::cout() << "func = " << *func << std::endl; // add func to IRFunc irFunc->func = func; // parameter attributes if (!DtoIsIntrinsic(fdecl)) { set_param_attrs(f, func, fdecl); if (global.params.disableRedZone) { func->addFnAttr(LDC_ATTRIBUTE(NoRedZone)); } } // main if (fdecl->isMain()) { // Detect multiple main functions, which is disallowed. DMD checks this // in the glue code, so we need to do it here as well. if (gIR->mainFunc) { error(fdecl->loc, "only one main function allowed"); } gIR->mainFunc = func; } if (fdecl->neverInline) { irFunc->setNeverInline(); } if (fdecl->llvmInternal == LLVMglobal_crt_ctor || fdecl->llvmInternal == LLVMglobal_crt_dtor) { AppendFunctionToLLVMGlobalCtorsDtors(func, fdecl->priority, fdecl->llvmInternal == LLVMglobal_crt_ctor); } IrFuncTy &irFty = irFunc->irFty; // if (!declareOnly) { // name parameters llvm::Function::arg_iterator iarg = func->arg_begin(); if (irFty.arg_sret) { iarg->setName(".sret_arg"); irFunc->retArg = iarg; ++iarg; } if (irFty.arg_this) { iarg->setName(".this_arg"); irFunc->thisArg = iarg; VarDeclaration* v = fdecl->vthis; if (v) { // We already build the this argument here if we will need it // later for codegen'ing the function, just as normal // parameters below, because it can be referred to in nested // context types. Will be given storage in DtoDefineFunction. assert(!isIrParameterCreated(v)); IrParameter *irParam = getIrParameter(v, true); irParam->value = iarg; irParam->arg = irFty.arg_this; irParam->isVthis = true; } ++iarg; } else if (irFty.arg_nest) { iarg->setName(".nest_arg"); irFunc->nestArg = iarg; assert(irFunc->nestArg); ++iarg; } if (irFty.arg_arguments) { iarg->setName("._arguments"); irFunc->_arguments = iarg; ++iarg; } // we never reference parameters of function prototypes unsigned int k = 0; for (; iarg != func->arg_end(); ++iarg) { if (fdecl->parameters && fdecl->parameters->dim > k) { int paramIndex = irFty.reverseParams ? fdecl->parameters->dim-k-1 : k; Dsymbol* argsym = static_cast<Dsymbol*>(fdecl->parameters->data[paramIndex]); VarDeclaration* argvd = argsym->isVarDeclaration(); assert(argvd); assert(!isIrLocalCreated(argvd)); std::string str(argvd->ident->toChars()); str.append("_arg"); iarg->setName(str); IrParameter *irParam = getIrParameter(argvd, true); irParam->value = iarg; irParam->arg = irFty.args[paramIndex]; k++; } else { iarg->setName("unnamed"); } } } }
LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl) { const char* mangled_name = mangleExact(fdecl); TemplateInstance* tinst = fdecl->parent->isTemplateInstance(); assert(tinst); Objects& objs = tinst->tdtypes; assert(objs.dim == 3); Expression* a0 = isExpression(objs[0]); assert(a0); StringExp* strexp = a0->toStringExp(); assert(strexp); assert(strexp->sz == 1); std::string code(static_cast<char*>(strexp->string), strexp->len); Type* ret = isType(objs[1]); assert(ret); Tuple* a2 = isTuple(objs[2]); assert(a2); Objects& arg_types = a2->objects; std::string str; llvm::raw_string_ostream stream(str); stream << "define " << *DtoType(ret) << " @" << mangled_name << "("; for(size_t i = 0; ;) { Type* ty = isType(arg_types[i]); //assert(ty); if(!ty) { error(tinst->loc, "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types"); fatal(); } stream << *DtoType(ty); i++; if(i >= arg_types.dim) break; stream << ", "; } if(ret->ty == Tvoid) code.append("\nret void"); stream << ")\n{\n" << code << "\n}"; llvm::SMDiagnostic err; #if LDC_LLVM_VER >= 306 std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString( stream.str().c_str(), err, gIR->context()); #elif LDC_LLVM_VER >= 303 llvm::Module* m = llvm::ParseAssemblyString( stream.str().c_str(), NULL, err, gIR->context()); #else llvm::ParseAssemblyString( stream.str().c_str(), gIR->module, err, gIR->context()); #endif std::string errstr = err.getMessage(); if(errstr != "") error(tinst->loc, "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s", #if LDC_LLVM_VER >= 303 err.getLineContents().str().c_str(), #else err.getLineContents().c_str(), #endif (std::string(err.getColumnNo(), ' ') + '^').c_str(), errstr.c_str(), stream.str().c_str()); #if LDC_LLVM_VER >= 306 llvm::Linker(gIR->module).linkInModule(m.get()); #else #if LDC_LLVM_VER >= 303 std::string errstr2 = ""; #if LDC_LLVM_VER >= 306 llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2); #else llvm::Linker(gIR->module).linkInModule(m, &errstr2); #endif if(errstr2 != "") error(tinst->loc, "Error when linking in llvm inline ir: %s", errstr2.c_str()); #endif #endif LLFunction* fun = gIR->module->getFunction(mangled_name); fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline)); return fun; }