LLConstant* DtoConstFP(Type* t, longdouble value) { LLType* llty = DtoType(t); assert(llty->isFloatingPointTy()); if(llty == LLType::getFloatTy(gIR->context()) || llty == LLType::getDoubleTy(gIR->context())) return LLConstantFP::get(llty, value); else if(llty == LLType::getX86_FP80Ty(gIR->context())) { uint64_t bits[] = { 0, 0 }; bits[0] = *reinterpret_cast<uint64_t*>(&value); bits[1] = *reinterpret_cast<uint16_t*>(reinterpret_cast<uint64_t*>(&value) + 1); #if LDC_LLVM_VER >= 303 return LLConstantFP::get(gIR->context(), APFloat(APFloat::x87DoubleExtended, APInt(80, 2, bits))); #else return LLConstantFP::get(gIR->context(), APFloat(APInt(80, 2, bits))); #endif } else if(llty == LLType::getPPC_FP128Ty(gIR->context())) { uint64_t bits[] = {0, 0}; bits[0] = *reinterpret_cast<uint64_t*>(&value); bits[1] = *reinterpret_cast<uint16_t*>(reinterpret_cast<uint64_t*>(&value) + 1); #if LDC_LLVM_VER >= 303 return LLConstantFP::get(gIR->context(), APFloat(APFloat::PPCDoubleDouble, APInt(128, 2, bits))); #else return LLConstantFP::get(gIR->context(), APFloat(APInt(128, 2, bits))); #endif } llvm_unreachable("Unknown floating point type encountered"); }
LLValue* DtoPointedType(LLValue* ptr, LLValue* val) { LLType* ptrTy = ptr->getType()->getContainedType(0); LLType* valTy = val->getType(); // ptr points to val's type if (ptrTy == valTy) { return val; } // ptr is integer pointer else if (ptrTy->isIntegerTy()) { // val is integer assert(valTy->isIntegerTy()); LLIntegerType* pt = llvm::cast<LLIntegerType>(ptrTy); LLIntegerType* vt = llvm::cast<LLIntegerType>(valTy); if (pt->getBitWidth() < vt->getBitWidth()) { return new llvm::TruncInst(val, pt, "tmp", gIR->scopebb()); } else assert(0); } // something else unsupported else { if (Logger::enabled()) Logger::cout() << *ptrTy << '|' << *valTy << '\n'; assert(0); } return 0; }
LLConstant *DtoConstFP(Type *t, const real_t value) { LLType *llty = DtoType(t); assert(llty->isFloatingPointTy()); // 1) represent host real_t as llvm::APFloat const auto &targetSemantics = llty->getFltSemantics(); APFloat v(targetSemantics, APFloat::uninitialized); CTFloat::toAPFloat(value, v); // 2) convert to target format if (&v.getSemantics() != &targetSemantics) { bool ignored; v.convert(targetSemantics, APFloat::rmNearestTiesToEven, &ignored); } return LLConstantFP::get(gIR->context(), v); }
LLConstant *DtoConstFP(Type *t, longdouble value) { LLType *llty = DtoType(t); assert(llty->isFloatingPointTy()); if (llty == LLType::getFloatTy(gIR->context()) || llty == LLType::getDoubleTy(gIR->context())) { return LLConstantFP::get(llty, value); } if (llty == LLType::getX86_FP80Ty(gIR->context())) { uint64_t bits[] = {0, 0}; bits[0] = *reinterpret_cast<uint64_t *>(&value); bits[1] = *reinterpret_cast<uint16_t *>(reinterpret_cast<uint64_t *>(&value) + 1); return LLConstantFP::get(gIR->context(), APFloat(APFloat::x87DoubleExtended, APInt(80, 2, bits))); } if (llty == LLType::getFP128Ty(gIR->context())) { union { longdouble ld; uint64_t bits[2]; } t; t.ld = value; return LLConstantFP::get(gIR->context(), APFloat(APFloat::IEEEquad, APInt(128, 2, t.bits))); } if (llty == LLType::getPPC_FP128Ty(gIR->context())) { uint64_t bits[] = {0, 0}; bits[0] = *reinterpret_cast<uint64_t *>(&value); bits[1] = *reinterpret_cast<uint16_t *>(reinterpret_cast<uint64_t *>(&value) + 1); return LLConstantFP::get( gIR->context(), APFloat(APFloat::PPCDoubleDouble, APInt(128, 2, bits))); } llvm_unreachable("Unknown floating point type encountered"); }
LLConstant * IrStruct::getVtblInit() { if (constVtbl) return constVtbl; IF_LOG Logger::println("Building vtbl initializer"); LOG_SCOPE; ClassDeclaration* cd = aggrdecl->isClassDeclaration(); assert(cd && "not class"); std::vector<llvm::Constant*> constants; constants.reserve(cd->vtbl.dim); // start with the classinfo llvm::Constant* c = getClassInfoSymbol(); c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type)); constants.push_back(c); // add virtual function pointers size_t n = cd->vtbl.dim; for (size_t i = 1; i < n; i++) { Dsymbol* dsym = static_cast<Dsymbol*>(cd->vtbl.data[i]); assert(dsym && "null vtbl member"); FuncDeclaration* fd = dsym->isFuncDeclaration(); assert(fd && "vtbl entry not a function"); if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody)) { c = getNullValue(DtoType(fd->type->pointerTo())); } else { fd->codegen(Type::sir); assert(fd->ir.irFunc && "invalid vtbl function"); c = fd->ir.irFunc->func; #if DMDV2 if (cd->isFuncHidden(fd)) { /* fd is hidden from the view of this class. * If fd overlaps with any function in the vtbl[], then * issue 'hidden' error. */ for (size_t j = 1; j < n; j++) { if (j == i) continue; FuncDeclaration *fd2 = static_cast<Dsymbol *>(cd->vtbl.data[j])->isFuncDeclaration(); if (!fd2->ident->equals(fd->ident)) continue; if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd)) { if (global.params.warnings) { TypeFunction *tf = static_cast<TypeFunction *>(fd->type); if (tf->ty == Tfunction) error("%s%s is hidden by %s\n", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars()); else error("%s is hidden by %s\n", fd->toPrettyChars(), toChars()); } c = DtoBitCast(LLVM_D_GetRuntimeFunction(gIR->module, "_d_hidden_func"), c->getType()); break; } } } #endif } constants.push_back(c); } // build the constant struct LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl(); constVtbl = LLConstantStruct::get(isaStruct(vtblTy), constants); #if 0 IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl; IF_LOG Logger::cout() << "vtbl type: " << *stripModifiers(type)->irtype->isClass()->getVtbl() << std::endl; #endif #if 0 size_t nc = constants.size(); for (size_t i = 0; i < nc; ++i) { if (constVtbl->getOperand(i)->getType() != vtblTy->getContainedType(i)) { Logger::cout() << "type mismatch for entry # " << i << " in vtbl initializer" << std::endl; constVtbl->getOperand(i)->dump(); vtblTy->getContainedType(i)->dump(); } } #endif assert(constVtbl->getType() == stripModifiers(type)->irtype->isClass()->getVtbl() && "vtbl initializer type mismatch"); return constVtbl; }
static void DtoCreateNestedContextType(FuncDeclaration* fd) { Logger::println("DtoCreateNestedContextType for %s", fd->toChars()); LOG_SCOPE #if DMDV2 DtoDeclareFunction(fd); #endif if (fd->ir.irFunc->nestedContextCreated) return; fd->ir.irFunc->nestedContextCreated = true; #if DMDV2 if (fd->nestedVars.empty()) { // fill nestedVars size_t nnest = fd->closureVars.dim; for (size_t i = 0; i < nnest; ++i) { VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i]; fd->nestedVars.insert(vd); } } #endif if (nestedCtx == NCHybrid) { // construct nested variables array if (!fd->nestedVars.empty()) { Logger::println("has nested frame"); // start with adding all enclosing parent frames until a static parent is reached LLStructType* innerFrameType = NULL; unsigned depth = -1; if (!fd->isStatic()) { if (FuncDeclaration* parfd = getParentFunc(fd, true)) { // Make sure parfd->ir.irFunc has already been set. DtoDeclareFunction(parfd); innerFrameType = parfd->ir.irFunc->frameType; if (innerFrameType) depth = parfd->ir.irFunc->depth; } } fd->ir.irFunc->depth = ++depth; Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n'; typedef std::vector<LLType*> TypeVec; TypeVec types; if (depth != 0) { assert(innerFrameType); // Add frame pointer types for all but last frame if (depth > 1) { for (unsigned i = 0; i < (depth - 1); ++i) { types.push_back(innerFrameType->getElementType(i)); } } // Add frame pointer type for last frame types.push_back(LLPointerType::getUnqual(innerFrameType)); } if (Logger::enabled()) { Logger::println("Frame types: "); LOG_SCOPE; for (TypeVec::iterator i = types.begin(); i != types.end(); ++i) Logger::cout() << **i << '\n'; } // Add the direct nested variables of this function, and update their indices to match. // TODO: optimize ordering for minimal space usage? for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { VarDeclaration* vd = *i; if (!vd->ir.irLocal) vd->ir.irLocal = new IrLocal(vd); vd->ir.irLocal->nestedIndex = types.size(); vd->ir.irLocal->nestedDepth = depth; if (vd->isParameter()) { // Parameters will have storage associated with them (to handle byref etc.), // so handle those cases specially by storing a pointer instead of a value. IrParameter * irparam = vd->ir.irParam; LLValue* value = irparam->value; assert(value); LLType* type = value->getType(); bool refout = vd->storage_class & (STCref | STCout); bool lazy = vd->storage_class & STClazy; bool byref = irparam->arg->byref; #if STRUCTTHISREF bool isVthisPtr = irparam->isVthis && !byref; #else bool isVthisPtr = irparam->isVthis; #endif if ((!refout && (!byref || lazy)) || isVthisPtr) { // This will be copied to the nesting frame. if (lazy) type = type->getContainedType(0); else type = DtoType(vd->type); vd->ir.irParam->byref = false; } else { vd->ir.irParam->byref = true; } types.push_back(type); } else if (vd->isRef() || vd->isOut()) { // Foreach variables can also be by reference, for instance. types.push_back(DtoType(vd->type->pointerTo())); vd->ir.irLocal->byref = true; } else { types.push_back(DtoType(vd->type)); vd->ir.irLocal->byref = false; } if (Logger::enabled()) { Logger::println("Nested var: %s", vd->toChars()); Logger::cout() << "of type: " << *types.back() << '\n'; } } LLStructType* frameType = LLStructType::create(gIR->context(), types, std::string("nest.") + fd->toChars()); Logger::cout() << "frameType = " << *frameType << '\n'; // Store type in IrFunction fd->ir.irFunc->frameType = frameType; } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) { // Propagate context arg properties if the context arg is passed on unmodified. DtoCreateNestedContextType(parFunc); fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType; fd->ir.irFunc->depth = parFunc->ir.irFunc->depth; } } else { assert(0 && "Not implemented yet"); } }