/// Move the given iterators to the next leaf type in depth first traversal. /// /// Performs a depth-first traversal of the type as specified by its arguments, /// stopping at the next leaf node (which may be a legitimate scalar type or an /// empty struct or array). /// /// @param SubTypes List of the partial components making up the type from /// outermost to innermost non-empty aggregate. The element currently /// represented is SubTypes.back()->getTypeAtIndex(Path.back() - 1). /// /// @param Path Set of extractvalue indices leading from the outermost type /// (SubTypes[0]) to the leaf node currently represented. /// /// @returns true if a new type was found, false otherwise. Calling this /// function again on a finished iterator will repeatedly return /// false. SubTypes.back()->getTypeAtIndex(Path.back()) is either an empty /// aggregate or a non-aggregate static bool advanceToNextLeafType(SmallVectorImpl<CompositeType *> &SubTypes, SmallVectorImpl<unsigned> &Path) { // First march back up the tree until we can successfully increment one of the // coordinates in Path. while (!Path.empty() && !indexReallyValid(SubTypes.back(), Path.back() + 1)) { Path.pop_back(); SubTypes.pop_back(); } // If we reached the top, then the iterator is done. if (Path.empty()) return false; // We know there's *some* valid leaf now, so march back down the tree picking // out the left-most element at each node. ++Path.back(); Type *DeeperType = SubTypes.back()->getTypeAtIndex(Path.back()); while (DeeperType->isAggregateType()) { CompositeType *CT = cast<CompositeType>(DeeperType); if (!indexReallyValid(CT, 0)) return true; SubTypes.push_back(CT); Path.push_back(0); DeeperType = CT->getTypeAtIndex(0U); } return true; }
GetElementPtrInst* TargetInfo::getRegister(llvm::Value *registerStruct, const char *name) const { name = largestOverlappingRegister(name); const TargetRegisterInfo* selected = nullptr; for (const auto& info : targetRegisterInfo()) { if (info.name.c_str() == name) { selected = &info; break; } } if (selected == nullptr) { return nullptr; } SmallVector<Value*, 4> indices; LLVMContext& ctx = registerStruct->getContext(); IntegerType* int32 = Type::getInt32Ty(ctx); IntegerType* int64 = Type::getInt64Ty(ctx); CompositeType* currentType = cast<CompositeType>(registerStruct->getType()); for (unsigned offset : selected->gepOffsets) { IntegerType* constantType = isa<StructType>(currentType) ? int32 : int64; indices.push_back(ConstantInt::get(constantType, offset)); currentType = dyn_cast<CompositeType>(currentType->getTypeAtIndex(offset)); } return GetElementPtrInst::CreateInBounds(registerStruct, indices); }
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); }
LLVMTypeRef LLVMGetTypeAtIndex(LLVMTypeRef Ty, LLVMValueRef Idx) { CompositeType* Comp = cast<CompositeType>(unwrap(Ty)); const Value* V = unwrap(Idx); return wrap(Comp->getTypeAtIndex(V)); }