LLValue* DtoBinFloatsEquals(Loc loc, DValue* lhs, DValue* rhs, TOK op) { LLValue* res = 0; #if DMDV2 if (op == TOKequal) { res = gIR->ir->CreateFCmpOEQ(lhs->getRVal(), rhs->getRVal(), "tmp"); } else if (op == TOKnotequal) { res = gIR->ir->CreateFCmpUNE(lhs->getRVal(), rhs->getRVal(), "tmp"); } else { llvm::ICmpInst::Predicate cmpop; if (op == TOKidentity) cmpop = llvm::ICmpInst::ICMP_EQ; else cmpop = llvm::ICmpInst::ICMP_NE; LLValue* sz = DtoConstSize_t(getTypeStoreSize(DtoType(lhs->getType()))); LLValue* val = DtoMemCmp(makeLValue(loc, lhs), makeLValue(loc, rhs), sz); res = gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp"); } #else LLValue* lv = lhs->getRVal(); LLValue* rv = rhs->getRVal(); res = (op == TOKidentity || op == TOKequal) ? gIR->ir->CreateFCmpOEQ(lv, rv, "tmp") : gIR->ir->CreateFCmpUNE(lv, rv, "tmp"); #endif assert(res); return res; }
DValue* DtoArgument(Parameter* fnarg, Expression* argexp) { IF_LOG Logger::println("DtoArgument"); LOG_SCOPE; DValue* arg = toElem(argexp); // ref/out arg if (fnarg && (fnarg->storageClass & (STCref | STCout))) { Loc loc; arg = new DImValue(argexp->type, makeLValue(loc, arg)); } // lazy arg else if (fnarg && (fnarg->storageClass & STClazy)) { assert(argexp->type->toBasetype()->ty == Tdelegate); assert(!arg->isLVal()); return arg; } // byval arg, but expr has no storage yet else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull())) { LLValue* alloc = DtoAlloca(argexp->type, ".tmp_arg"); DVarValue* vv = new DVarValue(argexp->type, alloc); DtoAssign(argexp->loc, vv, arg); arg = vv; } return arg; }
DValue *DtoAARemove(Loc& loc, DValue* aa, DValue* key) { // D1: // call: // extern(C) void _aaDel(AA aa, TypeInfo keyti, void* pkey) // D2: // call: // extern(C) bool _aaDelX(AA aa, TypeInfo keyti, void* pkey) // first get the runtime function #if DMDV2 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDelX"); #else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDel"); #endif LLFunctionType* funcTy = func->getFunctionType(); if (Logger::enabled()) Logger::cout() << "_aaDel = " << *func << '\n'; // aa param LLValue* aaval = aa->getRVal(); if (Logger::enabled()) { Logger::cout() << "aaval: " << *aaval << '\n'; Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; } aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // keyti param #if DMDV2 LLValue* keyti = to_keyti(aa); #else LLValue* keyti = to_keyti(key); #endif keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param LLValue* pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(2)); // build arg vector LLSmallVector<LLValue*, 3> args; args.push_back(aaval); args.push_back(keyti); args.push_back(pkey); // call runtime LLCallSite call = gIR->CreateCallOrInvoke(func, args); #if DMDV2 return new DImValue(Type::tbool, call.getInstruction()); #else return NULL; #endif }
LLValue *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) { LLValue *res = nullptr; if (op == TOKequal || op == TOKnotequal) { LLValue *l = DtoRVal(lhs); LLValue *r = DtoRVal(rhs); res = (op == TOKequal ? gIR->ir->CreateFCmpOEQ(l, r) : gIR->ir->CreateFCmpUNE(l, r)); if (lhs->type->toBasetype()->ty == Tvector) { res = mergeVectorEquals(res, op); } } else { const auto cmpop = op == TOKidentity ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; LLValue *sz = DtoConstSize_t(getTypeStoreSize(DtoType(lhs->type))); LLValue *val = DtoMemCmp(makeLValue(loc, lhs), makeLValue(loc, rhs), sz); res = gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false)); } assert(res); return res; }
DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key) { // D1: // call: // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) // D2: // call: // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) // first get the runtime function #if DMDV2 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaInX"); #else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaIn"); #endif LLFunctionType* funcTy = func->getFunctionType(); if (Logger::enabled()) Logger::cout() << "_aaIn = " << *func << '\n'; // aa param LLValue* aaval = aa->getRVal(); if (Logger::enabled()) { Logger::cout() << "aaval: " << *aaval << '\n'; Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; } aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // keyti param #if DMDV2 LLValue* keyti = to_keyti(aa); #else LLValue* keyti = to_keyti(key); #endif keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param LLValue* pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, getVoidPtrType()); // call runtime LLValue* ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.in").getInstruction(); // cast return value LLType* targettype = DtoType(type); if (ret->getType() != targettype) ret = DtoBitCast(ret, targettype); return new DImValue(type, ret); }
DValue *DtoAARemove(Loc &loc, DValue *aa, DValue *key) { // D1: // call: // extern(C) void _aaDel(AA aa, TypeInfo keyti, void* pkey) // D2: // call: // extern(C) bool _aaDelX(AA aa, TypeInfo keyti, void* pkey) // first get the runtime function llvm::Function *func = getRuntimeFunction(loc, gIR->module, "_aaDelX"); LLFunctionType *funcTy = func->getFunctionType(); IF_LOG Logger::cout() << "_aaDel = " << *func << '\n'; // aa param LLValue *aaval = aa->getRVal(); IF_LOG { Logger::cout() << "aaval: " << *aaval << '\n'; Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; } aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // keyti param LLValue *keyti = to_keyti(aa); keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param LLValue *pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(2)); // call runtime LLCallSite call = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey); return new DImValue(Type::tbool, call.getInstruction()); }
DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) { // D1: // call: // extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) // or // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) // D2: // call: // extern(C) void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) // or // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) // first get the runtime function llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGetX":"_aaInX"); LLFunctionType* funcTy = func->getFunctionType(); // aa param LLValue* aaval = lvalue ? aa->getLVal() : aa->getRVal(); aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // keyti param LLValue* keyti = to_keyti(aa); keyti = DtoBitCast(keyti, funcTy->getParamType(1)); // pkey param LLValue* pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2)); // call runtime LLValue* ret; if (lvalue) { // valuesize param LLValue* valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type))); ret = gIR->CreateCallOrInvoke4(func, aaval, keyti, valsize, pkey, "aa.index").getInstruction(); } else { ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.index").getInstruction(); } // cast return value LLType* targettype = getPtrToType(DtoType(type)); if (ret->getType() != targettype) ret = DtoBitCast(ret, targettype); // Only check bounds for rvalues ('aa[key]'). // Lvalue use ('aa[key] = value') auto-adds an element. if (!lvalue && global.params.useArrayBounds) { llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend); llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend); LLValue* nullaa = LLConstant::getNullValue(ret->getType()); LLValue* cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck"); gIR->ir->CreateCondBr(cond, okbb, failbb); // set up failbb to call the array bounds error runtime function gIR->scope() = IRScope(failbb, okbb); std::vector<LLValue*> args; // module param LLValue *moduleInfoSymbol = gIR->func()->decl->getModule()->moduleInfoSymbol(); LLType *moduleInfoType = DtoType(Module::moduleinfo->type); args.push_back(DtoBitCast(moduleInfoSymbol, getPtrToType(moduleInfoType))); // line param LLConstant* c = DtoConstUint(loc.linnum); args.push_back(c); // call llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); gIR->CreateCallOrInvoke(errorfn, args); // the function does not return gIR->ir->CreateUnreachable(); // if ok, proceed in okbb gIR->scope() = IRScope(okbb, oldend); } return new DVarValue(type, ret); }
DValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key, bool lvalue) { // D2: // call: // extern(C) void* _aaGetY(AA* aa, TypeInfo aati, size_t valuesize, void* // pkey) // or // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) // first get the runtime function llvm::Function *func = getRuntimeFunction( loc, gIR->module, lvalue ? "_aaGetY" : "_aaInX"); LLFunctionType *funcTy = func->getFunctionType(); // aa param LLValue *aaval = lvalue ? aa->getLVal() : aa->getRVal(); aaval = DtoBitCast(aaval, funcTy->getParamType(0)); // pkey param LLValue *pkey = makeLValue(loc, key); pkey = DtoBitCast(pkey, funcTy->getParamType(lvalue ? 3 : 2)); // call runtime LLValue *ret; if (lvalue) { LLValue *rawAATI = DtoTypeInfoOf(aa->type->unSharedOf()->mutableOf(), false); LLValue *castedAATI = DtoBitCast(rawAATI, funcTy->getParamType(1)); LLValue *valsize = DtoConstSize_t(getTypePaddedSize(DtoType(type))); ret = gIR->CreateCallOrInvoke(func, aaval, castedAATI, valsize, pkey, "aa.index") .getInstruction(); } else { LLValue *keyti = DtoBitCast(to_keyti(aa), funcTy->getParamType(1)); ret = gIR->CreateCallOrInvoke(func, aaval, keyti, pkey, "aa.index") .getInstruction(); } // cast return value LLType *targettype = DtoPtrToType(type); if (ret->getType() != targettype) { ret = DtoBitCast(ret, targettype); } // Only check bounds for rvalues ('aa[key]'). // Lvalue use ('aa[key] = value') auto-adds an element. if (!lvalue && gIR->emitArrayBoundsChecks()) { llvm::BasicBlock *failbb = llvm::BasicBlock::Create( gIR->context(), "aaboundscheckfail", gIR->topfunc()); llvm::BasicBlock *okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc()); LLValue *nullaa = LLConstant::getNullValue(ret->getType()); LLValue *cond = gIR->ir->CreateICmpNE(nullaa, ret, "aaboundscheck"); gIR->ir->CreateCondBr(cond, okbb, failbb); // set up failbb to call the array bounds error runtime function gIR->scope() = IRScope(failbb); llvm::Function *errorfn = getRuntimeFunction(loc, gIR->module, "_d_arraybounds"); gIR->CreateCallOrInvoke( errorfn, DtoModuleFileName(gIR->func()->decl->getModule(), loc), DtoConstUint(loc.linnum)); // the function does not return gIR->ir->CreateUnreachable(); // if ok, proceed in okbb gIR->scope() = IRScope(okbb); } return new DVarValue(type, ret); }