static void appendToGlobalArray(const char *Array, Module &M, Function *F, int Priority) { IRBuilder<> IRB(M.getContext()); FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); // Get the current set of static global constructors and add the new ctor // to the list. SmallVector<Constant *, 16> CurrentCtors; StructType *EltTy; if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) { // If there is a global_ctors array, use the existing struct type, which can // have 2 or 3 fields. ArrayType *ATy = cast<ArrayType>(GVCtor->getType()->getElementType()); EltTy = cast<StructType>(ATy->getElementType()); if (Constant *Init = GVCtor->getInitializer()) { unsigned n = Init->getNumOperands(); CurrentCtors.reserve(n + 1); for (unsigned i = 0; i != n; ++i) CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); } GVCtor->eraseFromParent(); } else { // Use a simple two-field struct if there isn't one already. EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), nullptr); } // Build a 2 or 3 field global_ctor entry. We don't take a comdat key. Constant *CSVals[3]; CSVals[0] = IRB.getInt32(Priority); CSVals[1] = F; // FIXME: Drop support for the two element form in LLVM 4.0. if (EltTy->getNumElements() >= 3) CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy()); Constant *RuntimeCtorInit = ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements())); CurrentCtors.push_back(RuntimeCtorInit); // Create a new initializer. ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); Constant *NewInit = ConstantArray::get(AT, CurrentCtors); // Create the new global variable and replace all uses of // the old global variable with the new one. (void)new GlobalVariable(M, NewInit->getType(), false, GlobalValue::AppendingLinkage, NewInit, Array); }
ConstantInt* Variables::getAlignmentInBits(Type *type) { ConstantInt *alignment = NULL; ArrayType *arrayType = dyn_cast<ArrayType>(type); switch (arrayType->getElementType()->getTypeID()) { case Type::FloatTyID: alignment = getInt64(32); break; case Type::DoubleTyID: alignment = getInt64(64); break; default: errs() << "WARNING: Unhandled type @ getAlignmentInBits\n"; exit(1); } return alignment; }
void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) const { if (_arrayType.getLocation() == ArrayType::Location::Storage) { if (_arrayType.isByteArray()) m_context << u256(31) << eth::Instruction::ADD << u256(32) << eth::Instruction::SWAP1 << eth::Instruction::DIV; else if (_arrayType.getBaseType()->getStorageSize() <= 1) { unsigned baseBytes = _arrayType.getBaseType()->getStorageBytes(); if (baseBytes == 0) m_context << eth::Instruction::POP << u256(1); else if (baseBytes <= 16) { unsigned itemsPerSlot = 32 / baseBytes; m_context << u256(itemsPerSlot - 1) << eth::Instruction::ADD << u256(itemsPerSlot) << eth::Instruction::SWAP1 << eth::Instruction::DIV; } } else m_context << _arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL; } else { if (!_arrayType.isByteArray()) m_context << _arrayType.getBaseType()->getCalldataEncodedSize() << eth::Instruction::MUL; else if (_pad) m_context << u256(31) << eth::Instruction::ADD << u256(32) << eth::Instruction::DUP1 << eth::Instruction::SWAP2 << eth::Instruction::DIV << eth::Instruction::MUL; } }
Type* IndexExpression::GetType() { Type *containerType = Container->GetType(); if (typeid(*containerType) == typeid(ArrayType)) { ArrayType *arrayType = dynamic_cast<ArrayType *>(containerType); return arrayType->GetElementType(); } else if (typeid(*containerType) == typeid(PointerType)) { PointerType *pointerType = dynamic_cast<PointerType *>(containerType); return pointerType->GetUnderlyingType(); } else { abort(); } }
int ArrayConv::ToV8Array(JNIEnv *jniEnv, jobject jVal, int expectedType, Handle<Object> *val) { int result = conv->UnwrapObject(jniEnv, jVal, val); if(result == ErrorNotfound) { int componentType = getComponentType(expectedType); ArrayType *arr; result = GetRefsForComponentType(jniEnv, componentType, &arr); if(result == OK) { Handle<Object> vInst; result = arr->PlatformNew(jniEnv, &vInst); if(result == OK) { result = conv->BindToJavaObject(jniEnv, jVal, vInst, arr->sHiddenKey); if(result == OK) *val = vInst; } } } return result; }
/** Rearrange an array such that ‘arr[j]’ becomes ‘i’ if ‘arr[i]’ is ‘j’ | Set 1 * * @reference https://www.geeksforgeeks.org/rearrange-array-arrj-becomes-arri-j/ * * Given an array of size n where all elements are distinct and in range from 0 to n-1, * change contents of arr[] so that arr[i] = j is changed to arr[j] = i. */ auto RearrangeArraySimple(const ArrayType &elements) { auto output = elements; for (ArrayType::size_type i = 0; i < elements.size(); ++i) { const auto j = elements[i]; output[j] = i; } return output; }
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value> h5_read(h5::group gr, std::string name, ArrayType& a) { static_assert(!std::is_const<ArrayType>::value, "Cannot read in const object"); auto gr2 = gr.open_group(name); // TODO checking scheme... // load the shape auto sha2 = a.shape(); array<int, 1> sha; h5_read(gr2, "shape", sha); if (first_dim(sha) != sha2.size()) TRIQS_RUNTIME_ERROR << " array<array<...>> load : rank mismatch. Expected " << sha2.size()<< " Got " << first_dim(sha); for (int u = 0; u < sha2.size(); ++u) sha2[u] = sha(u); if (a.shape() != sha2) a.resize(sha2); #ifndef __cpp_generic_lambdas foreach(a, h5_impl::_load_lambda<ArrayType>{a, gr2}); #else foreach(a, [&](auto... is) { h5_read(gr2, h5_impl::_h5_name(is...), a(is...)); }); #endif }
void delete_line(ArrayType & stencil, long line_nb) { for (long ci = 0; ci < stencil.size_2(); ++ci) { stencil(line_nb, ci) = 0.0; if (line_nb == long(ci)) stencil(line_nb, ci) = 1.0; } }
DataType* ExportPass::CloneDataType(DataType* t) { assert(t != NULL) ; PointerType* pointerClone = dynamic_cast<PointerType*>(t) ; ReferenceType* referenceClone = dynamic_cast<ReferenceType*>(t) ; ArrayType* arrayClone = dynamic_cast<ArrayType*>(t) ; if (pointerClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(pointerClone->get_reference_type()) ; assert(refType != NULL) ; DataType* cloneType = CloneDataType(refType->get_base_type()) ; assert(cloneType != NULL) ; return create_pointer_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, cloneType)) ; } if (referenceClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(referenceClone->get_reference_type()) ; assert(refType != NULL) ; DataType* clonedType = CloneDataType(refType->get_base_type()) ; return create_reference_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, clonedType)) ; } if (arrayClone != NULL) { QualifiedType* elementType = arrayClone->get_element_type() ; DataType* internalType = CloneDataType(elementType->get_base_type()) ; QualifiedType* finalQual = create_qualified_type(theEnv, internalType) ; return create_pointer_type(theEnv, IInteger(32), 0, finalQual) ; } return dynamic_cast<DataType*>(t->deep_clone()) ; }
status_t ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader, ValueLocation*& _location) { // get the parent (== array) location ValueLocation* parentLocation = fParent->Location(); if (parentLocation == NULL) return B_BAD_VALUE; // create an array index path ArrayType* arrayType = fParent->GetArrayType(); int32 dimensionCount = arrayType->CountDimensions(); // add dummy indices first -- we'll replace them on our way back through // our ancestors ArrayIndexPath indexPath; for (int32 i = 0; i < dimensionCount; i++) { if (!indexPath.AddIndex(0)) return B_NO_MEMORY; } AbstractArrayValueNodeChild* child = this; for (int32 i = dimensionCount - 1; i >= 0; i--) { indexPath.SetIndexAt(i, child->ElementIndex()); child = dynamic_cast<AbstractArrayValueNodeChild*>( child->ArrayParent()->NodeChild()); } // resolve the element location ValueLocation* location; status_t error = arrayType->ResolveElementLocation(indexPath, *parentLocation, location); if (error != B_OK) { TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): " "ResolveElementLocation() failed: %s\n", strerror(error)); return error; } _location = location; return B_OK; }
void Stream::WriteMembers(const uint8* object, ClassType* pType) { for (uint i = 0; i < pType->m_pScope->m_orderedDecls.size(); i++) { Declarator* decl = pType->m_pScope->m_orderedDecls[i]; if (!decl->get_IsStatic() && !decl->get_IsTypedef()) { Type* pType = decl->m_pType->GetStripped(); Type_type kind = pType->get_Kind(); if (kind == type_array) { ArrayType* array = static_cast<ArrayType*>(pType); size_t count = array->get_ElemCount(); for (size_t i = 0; i < count; ++i) { WriteMember(object + decl->m_offset + i*array->get_ElemType()->get_sizeof(), array->get_ElemType()); } } else if (kind != type_function) { WriteMember(object + decl->m_offset, pType); /* switch (kind) { case type_int: case type_long: case type_unsigned_int: case type_unsigned_long: case type_float: case type_double: case type_long_long: } */ } } } }
MultiDimArrayType* OneDimArrayConverter::array_type2multi_array_type(ArrayType* at){ suif_vector<ArrayType*> array_types; suif_map<ArrayType*, MultiDimArrayType*>::iterator type_iter = type_map->find(to<ArrayType>(at)); if (type_iter == type_map->end()) { suif_vector<Expression*> lower_bounds; suif_vector<Expression*> upper_bounds; suif_vector<ArrayType*> array_types; Type *type = at->get_element_type()->get_base_type(); array_types.push_back(at); // sub-types for this array type all_array_types->push_back(at); // all array types while (is_kind_of<ArrayType>(type)) { // unwrap array access ArrayType *atyp = to<ArrayType>(type); array_types.push_back(atyp); type = atyp->get_element_type()->get_base_type(); } // save lower and upper bounds for (int i = array_types.size()-1;i >=0;i--) { ArrayType *atyp = array_types[i]; lower_bounds.push_back(deep_suif_clone(atyp->get_lower_bound())); upper_bounds.push_back(deep_suif_clone(atyp->get_upper_bound())); } IInteger bit_size = to<DataType>(type)->get_bit_size(); IInteger bit_alignment = to<DataType>(type)->get_bit_alignment(); MultiDimArrayType* multi_type = tb->get_multi_dim_array_type( bit_size, bit_alignment.c_int(), tb->get_qualified_type(type), lower_bounds, upper_bounds); // save the translation in the map type_map->enter_value(at, multi_type); return multi_type; }else return (*type_iter).second; }
std::pair<int, int> FindSubarrayWithGivenSum(const ArrayType &integers, const ArrayType::value_type SUM) { assert(not integers.empty()); auto start = integers.cbegin(); auto current_sum = *start; for (auto i = start + 1; i != integers.cend(); ++i) { while (current_sum > SUM and start < i - 1) { current_sum -= *start++; } if (current_sum == SUM) { return std::make_pair(start - integers.cbegin(), i - integers.cbegin() - 1); } current_sum += *i; } return NOT_FOUND; }
ConstantInt* Variables::getSizeInBits(Type *type) { ConstantInt *size = NULL; ArrayType *arrayType = dyn_cast<ArrayType>(type); switch (arrayType->getElementType()->getTypeID()) { case Type::FloatTyID: { int isize = arrayType->getNumElements() * 32; size = getInt64(isize); break; } case Type::DoubleTyID: { int isize = arrayType->getNumElements() * 64; size = getInt64(isize); break; } default: errs() << "WARNING: Unhandled type @ getSizeInBits\n"; exit(1); } return size; }
void ArrayUtils::retrieveLength(ArrayType const& _arrayType) const { if (!_arrayType.isDynamicallySized()) m_context << _arrayType.getLength(); else { m_context << eth::Instruction::DUP1; switch (_arrayType.getLocation()) { case ArrayType::Location::CallData: // length is stored on the stack break; case ArrayType::Location::Memory: m_context << eth::Instruction::MLOAD; break; case ArrayType::Location::Storage: m_context << eth::Instruction::SLOAD; break; } } }
auto RearrangeArrayInPlace(ArrayType elements) { for (ArrayType::size_type i = 0; i < elements.size(); ++i) { elements[elements[i] % elements.size()] += i * elements.size(); } std::transform(elements.cbegin(), elements.cend(), elements.begin(), [&elements](const ArrayType::value_type v) { return v / elements.size(); }); return elements; }
void generateRepresentation(ConvertOrientations* filter, typename DataArray<T>::Pointer inputOrientations, typename DataArray<T>::Pointer outputOrientations) { typedef typename DataArray<T>::Pointer ArrayType; typedef OrientationConverter<T> OCType; QVector<typename OCType::Pointer> converters(7); converters[0] = EulerConverter<T>::New(); converters[1] = OrientationMatrixConverter<T>::New(); converters[2] = QuaternionConverter<T>::New(); converters[3] = AxisAngleConverter<T>::New(); converters[4] = RodriguesConverter<T>::New(); converters[5] = HomochoricConverter<T>::New(); converters[6] = CubochoricConverter<T>::New(); QVector<typename OCType::OrientationType> ocTypes = OCType::GetOrientationTypes(); converters[filter->getInputType()]->setInputData(inputOrientations); converters[filter->getInputType()]->convertRepresentationTo(ocTypes[filter->getOutputType()]); ArrayType output = converters[filter->getInputType()]->getOutputData(); if(NULL == output.get()) { QString ss = QObject::tr("There was an error converting the input data using convertor %1").arg(converters[filter->getInputType()]->getNameOfClass()); filter->setErrorCondition(-1004); filter->notifyErrorMessage(filter->getHumanLabel(), ss, filter->getErrorCondition()); return; } if(!output->copyIntoArray(outputOrientations) ) { QString ss = QObject::tr("There was an error copying the final results into the output array."); filter->setErrorCondition(-1003); filter->notifyErrorMessage(filter->getHumanLabel(), ss, filter->getErrorCondition()); } }
uint64_t TargetData::getTypeSizeInBits(Type *Ty) const { assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); switch (Ty->getTypeID()) { case Type::LabelTyID: case Type::PointerTyID: return getPointerSizeInBits(); case Type::ArrayTyID: { ArrayType *ATy = cast<ArrayType>(Ty); return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements(); } case Type::StructTyID: // Get the layout annotation... which is lazily created on demand. return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); case Type::IntegerTyID: return cast<IntegerType>(Ty)->getBitWidth(); case Type::VoidTyID: return 8; case Type::HalfTyID: return 16; case Type::FloatTyID: return 32; case Type::DoubleTyID: case Type::X86_MMXTyID: return 64; case Type::PPC_FP128TyID: case Type::FP128TyID: return 128; // In memory objects this is always aligned to a higher boundary, but // only 80 bits contain information. case Type::X86_FP80TyID: return 80; case Type::VectorTyID: return cast<VectorType>(Ty)->getBitWidth(); default: llvm_unreachable("TargetData::getTypeSizeInBits(): Unsupported type"); } }
bool DevirtModule::tryFindVirtualCallTargets( std::vector<VirtualCallTarget> &TargetsForSlot, const std::set<BitSetInfo> &BitSetInfos, uint64_t ByteOffset) { for (const BitSetInfo &BS : BitSetInfos) { if (!BS.Bits->GV->isConstant()) return false; auto Init = dyn_cast<ConstantArray>(BS.Bits->GV->getInitializer()); if (!Init) return false; ArrayType *VTableTy = Init->getType(); uint64_t ElemSize = M.getDataLayout().getTypeAllocSize(VTableTy->getElementType()); uint64_t GlobalSlotOffset = BS.Offset + ByteOffset; if (GlobalSlotOffset % ElemSize != 0) return false; unsigned Op = GlobalSlotOffset / ElemSize; if (Op >= Init->getNumOperands()) return false; auto Fn = dyn_cast<Function>(Init->getOperand(Op)->stripPointerCasts()); if (!Fn) return false; // We can disregard __cxa_pure_virtual as a possible call target, as // calls to pure virtuals are UB. if (Fn->getName() == "__cxa_pure_virtual") continue; TargetsForSlot.push_back({Fn, &BS}); } // Give up if we couldn't find any targets. return !TargetsForSlot.empty(); }
bool ConstantArrayPropagationPass::ValidSymbol(VariableSymbol* var) { assert(var != NULL) ; // The variable should be an array type and have the const qualifier. if (dynamic_cast<ArrayType*>(var->get_type()->get_base_type()) == NULL) { return false ; } QualifiedType* qualType = var->get_type() ; while (dynamic_cast<ArrayType*>(qualType->get_base_type()) != NULL) { ArrayType* array = dynamic_cast<ArrayType*>(qualType->get_base_type()) ; qualType = array->get_element_type() ; } assert(qualType != NULL) ; for (int i = 0 ; i < qualType->get_qualification_count(); ++i) { if (qualType->get_qualification(i) == LString("const")) { return true ; } } return false ; }
ArrayStoreAll::ArrayStoreAll(const ArrayType& type, const Expr& expr) : d_type(), d_expr() { // this check is stronger than the assertion check in the expr manager that // ArrayTypes are actually array types // because this check is done in production builds too PrettyCheckArgument( type.isArray(), type, "array store-all constants can only be created for array types, not `%s'", type.toString().c_str()); PrettyCheckArgument( expr.getType().isComparableTo(type.getConstituentType()), expr, "expr type `%s' does not match constituent type of array type `%s'", expr.getType().toString().c_str(), type.toString().c_str()); PrettyCheckArgument(expr.isConst(), expr, "ArrayStoreAll requires a constant expression"); // Delay allocation until the checks above have been performed. If these fail, // the memory for d_type and d_expr should not leak. The alternative is catch, // delete and re-throw. d_type.reset(new ArrayType(type)); d_expr.reset(new Expr(expr)); }
bool Type::Compare(Type *left, Type *right) { if (left == right) return true; if (left->kind_ != right->kind_) return false; switch (left->kind_) { case Kind::Primitive: return left->primitive() == right->primitive(); case Kind::Array: { ArrayType *aleft = left->toArray(); ArrayType *aright = right->toArray(); return aleft->equalTo(aright); } case Kind::Function: // :TODO: return false; case Kind::Enum: case Kind::Typedef: return false; case Kind::Void: return true; default: assert(false); return false; } }
void ArrayUtils::resizeDynamicArray(const ArrayType& _type) const { solAssert(_type.getLocation() == ArrayType::Location::Storage, ""); solAssert(_type.isDynamicallySized(), ""); if (!_type.isByteArray() && _type.getBaseType()->getStorageBytes() < 32) solAssert(_type.getBaseType()->isValueType(), "Invalid storage size for non-value type."); unsigned stackHeightStart = m_context.getStackHeight(); eth::AssemblyItem resizeEnd = m_context.newTag(); // stack: ref new_length // fetch old length m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD; // stack: ref new_length old_length // store new length m_context << eth::Instruction::DUP2 << eth::Instruction::DUP4 << eth::Instruction::SSTORE; // skip if size is not reduced m_context << eth::Instruction::DUP2 << eth::Instruction::DUP2 << eth::Instruction::ISZERO << eth::Instruction::GT; m_context.appendConditionalJumpTo(resizeEnd); // size reduced, clear the end of the array // stack: ref new_length old_length convertLengthToSize(_type); m_context << eth::Instruction::DUP2; convertLengthToSize(_type); // stack: ref new_length old_size new_size // compute data positions m_context << eth::Instruction::DUP4; CompilerUtils(m_context).computeHashStatic(); // stack: ref new_length old_size new_size data_pos m_context << eth::Instruction::SWAP2 << eth::Instruction::DUP3 << eth::Instruction::ADD; // stack: ref new_length data_pos new_size delete_end m_context << eth::Instruction::SWAP2 << eth::Instruction::ADD; // stack: ref new_length delete_end delete_start if (_type.isByteArray() || _type.getBaseType()->getStorageBytes() < 32) clearStorageLoop(IntegerType(256)); else clearStorageLoop(*_type.getBaseType()); m_context << resizeEnd; // cleanup m_context << eth::Instruction::POP << eth::Instruction::POP << eth::Instruction::POP; solAssert(m_context.getStackHeight() == stackHeightStart - 2, ""); }
QualifiedType* TransformUnrolledArraysPass::OneLessDimension(QualifiedType* original, int dimensionality) { ArrayType* topLevelType = dynamic_cast<ArrayType*>(original->get_base_type()) ; assert(topLevelType != NULL) ; if (dynamic_cast<ArrayType*>(topLevelType->get_element_type()->get_base_type()) != NULL) { ArrayType* nextLevel = dynamic_cast<ArrayType*>(topLevelType->get_element_type()->get_base_type()) ; return nextLevel->get_element_type() ; } else { return topLevelType->get_element_type() ; } }
/// cmpType - compares two types, /// defines total ordering among the types set. /// See method declaration comments for more details. int FunctionComparator::cmpType(Type *TyL, Type *TyR) const { PointerType *PTyL = dyn_cast<PointerType>(TyL); PointerType *PTyR = dyn_cast<PointerType>(TyR); if (DL) { if (PTyL && PTyL->getAddressSpace() == 0) TyL = DL->getIntPtrType(TyL); if (PTyR && PTyR->getAddressSpace() == 0) TyR = DL->getIntPtrType(TyR); } if (TyL == TyR) return 0; if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID())) return Res; switch (TyL->getTypeID()) { default: llvm_unreachable("Unknown type!"); // Fall through in Release mode. case Type::IntegerTyID: case Type::VectorTyID: // TyL == TyR would have returned true earlier. return cmpNumbers((uint64_t)TyL, (uint64_t)TyR); case Type::VoidTyID: case Type::FloatTyID: case Type::DoubleTyID: case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: case Type::LabelTyID: case Type::MetadataTyID: return 0; case Type::PointerTyID: { assert(PTyL && PTyR && "Both types must be pointers here."); return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace()); } case Type::StructTyID: { StructType *STyL = cast<StructType>(TyL); StructType *STyR = cast<StructType>(TyR); if (STyL->getNumElements() != STyR->getNumElements()) return cmpNumbers(STyL->getNumElements(), STyR->getNumElements()); if (STyL->isPacked() != STyR->isPacked()) return cmpNumbers(STyL->isPacked(), STyR->isPacked()); for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) { if (int Res = cmpType(STyL->getElementType(i), STyR->getElementType(i))) return Res; } return 0; } case Type::FunctionTyID: { FunctionType *FTyL = cast<FunctionType>(TyL); FunctionType *FTyR = cast<FunctionType>(TyR); if (FTyL->getNumParams() != FTyR->getNumParams()) return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams()); if (FTyL->isVarArg() != FTyR->isVarArg()) return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg()); if (int Res = cmpType(FTyL->getReturnType(), FTyR->getReturnType())) return Res; for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) { if (int Res = cmpType(FTyL->getParamType(i), FTyR->getParamType(i))) return Res; } return 0; } case Type::ArrayTyID: { ArrayType *ATyL = cast<ArrayType>(TyL); ArrayType *ATyR = cast<ArrayType>(TyR); if (ATyL->getNumElements() != ATyR->getNumElements()) return cmpNumbers(ATyL->getNumElements(), ATyR->getNumElements()); return cmpType(ATyL->getElementType(), ATyR->getElementType()); } } }
array_view<typename ArrayType::value_type, ArrayType::rank-1> sum0 (ArrayType const & A) { array<typename ArrayType::value_type, ArrayType::rank-1> res = A(0,ellipsis()); for (size_t u =1; u< A.shape()[0]; ++u) res += A(u,ellipsis()); return res; }
static bool tryPromoteAllocaToVector(AllocaInst *Alloca) { ArrayType *AllocaTy = dyn_cast<ArrayType>(Alloca->getAllocatedType()); DEBUG(dbgs() << "Alloca candidate for vectorization\n"); // FIXME: There is no reason why we can't support larger arrays, we // are just being conservative for now. if (!AllocaTy || AllocaTy->getElementType()->isVectorTy() || AllocaTy->getNumElements() > 4) { DEBUG(dbgs() << " Cannot convert type to vector\n"); return false; } std::map<GetElementPtrInst*, Value*> GEPVectorIdx; std::vector<Value*> WorkList; for (User *AllocaUser : Alloca->users()) { GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(AllocaUser); if (!GEP) { if (!canVectorizeInst(cast<Instruction>(AllocaUser), Alloca)) return false; WorkList.push_back(AllocaUser); continue; } Value *Index = GEPToVectorIndex(GEP); // If we can't compute a vector index from this GEP, then we can't // promote this alloca to vector. if (!Index) { DEBUG(dbgs() << " Cannot compute vector index for GEP " << *GEP << '\n'); return false; } GEPVectorIdx[GEP] = Index; for (User *GEPUser : AllocaUser->users()) { if (!canVectorizeInst(cast<Instruction>(GEPUser), AllocaUser)) return false; WorkList.push_back(GEPUser); } } VectorType *VectorTy = arrayTypeToVecType(AllocaTy); DEBUG(dbgs() << " Converting alloca to vector " << *AllocaTy << " -> " << *VectorTy << '\n'); for (Value *V : WorkList) { Instruction *Inst = cast<Instruction>(V); IRBuilder<> Builder(Inst); switch (Inst->getOpcode()) { case Instruction::Load: { Value *Ptr = Inst->getOperand(0); Value *Index = calculateVectorIndex(Ptr, GEPVectorIdx); Value *BitCast = Builder.CreateBitCast(Alloca, VectorTy->getPointerTo(0)); Value *VecValue = Builder.CreateLoad(BitCast); Value *ExtractElement = Builder.CreateExtractElement(VecValue, Index); Inst->replaceAllUsesWith(ExtractElement); Inst->eraseFromParent(); break; } case Instruction::Store: { Value *Ptr = Inst->getOperand(1); Value *Index = calculateVectorIndex(Ptr, GEPVectorIdx); Value *BitCast = Builder.CreateBitCast(Alloca, VectorTy->getPointerTo(0)); Value *VecValue = Builder.CreateLoad(BitCast); Value *NewVecValue = Builder.CreateInsertElement(VecValue, Inst->getOperand(0), Index); Builder.CreateStore(NewVecValue, BitCast); Inst->eraseFromParent(); break; } case Instruction::BitCast: case Instruction::AddrSpaceCast: break; default: Inst->dump(); llvm_unreachable("Inconsistency in instructions promotable to vector"); } } return true; }
StorageArrayLength::StorageArrayLength(CompilerContext& _compilerContext, const ArrayType& _arrayType): LValue(_compilerContext, _arrayType.memberType("length").get()), m_arrayType(_arrayType) { solAssert(m_arrayType.isDynamicallySized(), ""); }
/** * @brief Construct an ArrayComparisonFunctor for an array. * * @param array Array to compare values against * @param strict Flag to use strict type comparison */ ArrayComparisonFunctor(const ArrayType &array, bool strict) : itr(array.begin()), end(array.end()), strict(strict) { }
static Constant *julia_const_to_llvm(const void *ptr, jl_datatype_t *bt) { // assumes `jl_isbits(bt)`. // `ptr` can point to a inline field, do not read the tag from it. // make sure to return exactly the type specified by // julia_type_to_llvm as this will be assumed by the callee. if (bt == jl_bool_type) return ConstantInt::get(T_int8, (*(const uint8_t*)ptr) ? 1 : 0); if (jl_is_vecelement_type((jl_value_t*)bt)) bt = (jl_datatype_t*)jl_tparam0(bt); Type *lt = julia_struct_to_llvm((jl_value_t*)bt, NULL, NULL); if (type_is_ghost(lt)) return UndefValue::get(NoopType); if (jl_is_primitivetype(bt)) { if (lt->isFloatTy()) { uint32_t data32 = *(const uint32_t*)ptr; return ConstantFP::get(jl_LLVMContext, APFloat(lt->getFltSemantics(), APInt(32, data32))); } if (lt->isDoubleTy()) { uint64_t data64 = *(const uint64_t*)ptr; return ConstantFP::get(jl_LLVMContext, APFloat(lt->getFltSemantics(), APInt(64, data64))); } int nb = jl_datatype_size(bt); APInt val(8 * nb, 0); void *bits = const_cast<uint64_t*>(val.getRawData()); assert(sys::IsLittleEndianHost); memcpy(bits, ptr, nb); if (lt->isFloatingPointTy()) { return ConstantFP::get(jl_LLVMContext, APFloat(lt->getFltSemantics(), val)); } assert(cast<IntegerType>(lt)->getBitWidth() == 8u * nb); return ConstantInt::get(lt, val); } CompositeType *lct = cast<CompositeType>(lt); size_t nf = jl_datatype_nfields(bt); std::vector<Constant*> fields(nf); for (size_t i = 0; i < nf; i++) { size_t offs = jl_field_offset(bt, i); assert(!jl_field_isptr(bt, i)); jl_value_t *ft = jl_field_type(bt, i); Type *lft = lct->getTypeAtIndex(i); const uint8_t *ov = (const uint8_t*)ptr + offs; Constant *val; if (jl_is_uniontype(ft)) { // compute the same type layout as julia_struct_to_llvm size_t fsz = jl_field_size(bt, i); size_t al = jl_field_align(bt, i); uint8_t sel = ((const uint8_t*)ptr)[offs + fsz - 1]; jl_value_t *active_ty = jl_nth_union_component(ft, sel); size_t active_sz = jl_datatype_size(active_ty); ArrayType *aty = cast<ArrayType>(cast<StructType>(lft)->getTypeAtIndex(0u)); assert(aty->getElementType() == IntegerType::get(jl_LLVMContext, 8 * al) && aty->getNumElements() == (fsz - 1) / al); std::vector<Constant*> ArrayElements(0); for (unsigned j = 0; j < aty->getNumElements(); j++) { APInt Elem(8 * al, 0); void *bits = const_cast<uint64_t*>(Elem.getRawData()); if (active_sz > al) { memcpy(bits, ov, al); active_sz -= al; } else if (active_sz > 0) { memcpy(bits, ov, active_sz); active_sz = 0; } ov += al; ArrayElements.push_back(ConstantInt::get(aty->getElementType(), Elem)); } std::vector<Constant*> Elements(0); Elements.push_back(ConstantArray::get(aty, ArrayElements)); unsigned remainder = (fsz - 1) % al; while (remainder--) { uint8_t byte; if (active_sz > 0) { byte = *ov; active_sz -= 1; } else { byte = 0; } ov += 1; APInt Elem(8, byte); Elements.push_back(ConstantInt::get(T_int8, Elem)); } Elements.push_back(ConstantInt::get(T_int8, sel)); val = ConstantStruct::get(cast<StructType>(lft), Elements); } else { val = julia_const_to_llvm(ov, (jl_datatype_t*)ft); } fields[i] = val; } if (lct->isVectorTy()) return ConstantVector::get(fields); if (StructType *st = dyn_cast<StructType>(lct)) return ConstantStruct::get(st, fields); ArrayType *at = cast<ArrayType>(lct); return ConstantArray::get(at, fields); }