void CGRecordLowering::insertPadding() { std::vector<std::pair<CharUnits, CharUnits> > Padding; CharUnits Size = CharUnits::Zero(); for (std::vector<MemberInfo>::const_iterator Member = Members.begin(), MemberEnd = Members.end(); Member != MemberEnd; ++Member) { if (!Member->Data) continue; CharUnits Offset = Member->Offset; assert(Offset >= Size); // Insert padding if we need to. if (Offset != Size.alignTo(Packed ? CharUnits::One() : getAlignment(Member->Data))) Padding.push_back(std::make_pair(Size, Offset - Size)); Size = Offset + getSize(Member->Data); } if (Padding.empty()) return; // Add the padding to the Members list and sort it. for (std::vector<std::pair<CharUnits, CharUnits> >::const_iterator Pad = Padding.begin(), PadEnd = Padding.end(); Pad != PadEnd; ++Pad) Members.push_back(StorageInfo(Pad->first, getByteArrayType(Pad->second))); std::stable_sort(Members.begin(), Members.end()); }
void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, FunctionArgList &Args) { // Emit a call to cudaSetupArgument for each arg in Args. llvm::FunctionCallee cudaSetupArgFn = getSetupArgumentFn(); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); CharUnits Offset = CharUnits::Zero(); for (const VarDecl *A : Args) { CharUnits TyWidth, TyAlign; std::tie(TyWidth, TyAlign) = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TyAlign); llvm::Value *Args[] = { CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), VoidPtrTy), llvm::ConstantInt::get(SizeTy, TyWidth.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; llvm::CallBase *CB = CGF.EmitRuntimeCallOrInvoke(cudaSetupArgFn, Args); llvm::Constant *Zero = llvm::ConstantInt::get(IntTy, 0); llvm::Value *CBZero = CGF.Builder.CreateICmpEQ(CB, Zero); llvm::BasicBlock *NextBlock = CGF.createBasicBlock("setup.next"); CGF.Builder.CreateCondBr(CBZero, NextBlock, EndBlock); CGF.EmitBlock(NextBlock); Offset += TyWidth; } // Emit the call to cudaLaunch llvm::FunctionCallee cudaLaunchFn = getLaunchFn(); llvm::Value *Arg = CGF.Builder.CreatePointerCast(CGF.CurFn, CharPtrTy); CGF.EmitRuntimeCallOrInvoke(cudaLaunchFn, Arg); CGF.EmitBranch(EndBlock); CGF.EmitBlock(EndBlock); }
ConstantAggregateBuilderBase::PlaceholderPosition ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) { // Bring the offset up to the last field. CharUnits offset = getNextOffsetFromGlobal(); // Create the placeholder. auto position = addPlaceholder(); // Advance the offset past that field. auto &layout = Builder.CGM.getDataLayout(); if (!Packed) offset = offset.alignTo(CharUnits::fromQuantity( layout.getABITypeAlignment(type))); offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type)); CachedOffsetEnd = Builder.Buffer.size(); CachedOffsetFromGlobal = offset; return position; }
CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{ size_t cacheEnd = CachedOffsetEnd; assert(cacheEnd <= end); // Fast path: if the cache is valid, just use it. if (cacheEnd == end) { return CachedOffsetFromGlobal; } // If the cached range ends before the index at which the current // aggregate starts, recurse for the parent. CharUnits offset; if (cacheEnd < Begin) { assert(cacheEnd == 0); assert(Parent && "Begin != 0 for root builder"); cacheEnd = Begin; offset = Parent->getOffsetFromGlobalTo(Begin); } else { offset = CachedOffsetFromGlobal; } // Perform simple layout on the elements in cacheEnd..<end. if (cacheEnd != end) { auto &layout = Builder.CGM.getDataLayout(); do { llvm::Constant *element = Builder.Buffer[cacheEnd]; assert(element != nullptr && "cannot compute offset when a placeholder is present"); llvm::Type *elementType = element->getType(); if (!Packed) offset = offset.alignTo(CharUnits::fromQuantity( layout.getABITypeAlignment(elementType))); offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType)); } while (++cacheEnd != end); } // Cache and return. CachedOffsetEnd = cacheEnd; CachedOffsetFromGlobal = offset; return offset; }