llvm::GlobalVariable* createGlobal(llvm::Module *module, const Var& var, llvm::GlobalValue::LinkageTypes linkage, unsigned addrspace) { bool isExtern = (linkage == llvm::GlobalValue::ExternalLinkage); Type type = var.getType(); // Make sure extern structs are packed, so that we can correctly set them llvm::Type* externType = (type.isSet()) ? llvmType(*type.toSet(), addrspace, isExtern) : llvmType(type, addrspace); llvm::Constant* initializer = defaultInitializer(externType); llvm::GlobalVariable* globalPtr = new llvm::GlobalVariable(*module, externType, false, linkage, initializer, var.getName(), nullptr, llvm::GlobalVariable::NotThreadLocal, addrspace, isExtern); globalPtr->setAlignment(8); return globalPtr; }
llvm::Value* TypeDataDef::coerceFrom(FuncBuilder& builder, TypeData& other, llvm::Value* value) { if(other.kind == TyVar) return builder.ir.CreateBitCast(value, llvmType(builder.modBuilder)); return TypeData::coerceFrom(builder, other, value); }
const llvm::StructLayout *recordTypeLayout(RecordType *t) { if (t->layout == NULL) { const llvm::StructType *st = llvm::cast<llvm::StructType>(llvmType(t)); t->layout = llvmTargetData->getStructLayout(st); } return t->layout; }
static void initTypeInfo(Type *t) { if (!t->typeInfoInitialized) { t->typeInfoInitialized = true; const llvm::Type *llt = llvmType(t); t->typeSize = llvmTargetData->getTypeAllocSize(llt); t->typeAlignment = llvmTargetData->getABITypeAlignment(llt); } }
llvm::Function* createPrototype(const std::string &name, const vector<Var> &arguments, const vector<Var> &results, llvm::Module *module, bool externalLinkage, bool doesNotThrow, bool scalarsByValue, unsigned addrspace) { vector<string> llvmArgNames; vector<llvm::Type*> llvmArgTypes; // We don't need two llvm arguments for aliased simit argument/results std::set<std::string> argNames; for (auto &arg : arguments) { argNames.insert(arg.getName()); llvmArgNames.push_back(arg.getName()); // Our convention is that scalars are passed to functions by value, // while everything else is passed through a pointer llvm::Type *type = (isScalar(arg.getType()) && scalarsByValue) ? llvmType(arg.getType().toTensor()->getComponentType()) : llvmType(arg.getType(), addrspace); llvmArgTypes.push_back(type); } for (auto &res : results) { if (argNames.find(res.getName()) != argNames.end()) { continue; } llvmArgNames.push_back(res.getName()); llvmArgTypes.push_back(llvmType(res.getType(), addrspace)); } assert(llvmArgNames.size() == llvmArgTypes.size()); return createPrototypeLLVM(name, llvmArgNames, llvmArgTypes, module, externalLinkage, doesNotThrow); }
Value ArrayValueType::constructArray(Builder *builder, const QList<Value> &dims) { assert(dims.size() == mDimensions); if (!mConstructFunction) { llvm::Type *intT = builder->irBuilder().getIntPtrTy(&mRuntime->dataLayout()); std::vector<llvm::Type*> paramTypes; for (int i = 0; i != mDimensions; i++) { paramTypes.push_back(intT); } llvm::FunctionType *ft = llvm::FunctionType::get(llvmType(), paramTypes, false); mConstructFunction = llvm::Function::Create(ft, llvm::Function::InternalLinkage, ("constructor_" + name()).toStdString(), mRuntime->module()); llvm::BasicBlock *bb = llvm::BasicBlock::Create(builder->context(), "bb", mConstructFunction); llvm::IRBuilder<> irBuilder(bb); llvm::AllocaInst *pArr = irBuilder.CreateAlloca(intT, irBuilder.getInt32(mDimensions)); llvm::Function::arg_iterator arg_i = mConstructFunction->arg_begin(); for (int i = 0; i != mDimensions; i++) { llvm::Value *dPtr = irBuilder.CreateGEP(pArr, irBuilder.getInt32(i)); irBuilder.CreateStore(arg_i, dPtr); arg_i++; } llvm::Value *genericArray = irBuilder.CreateCall3( mRuntime->genericArrayValueType()->constructFunction(), llvm::ConstantInt::get(intT, mDimensions), pArr, llvm::ConstantInt::get(intT, mBaseValueType->size())); irBuilder.CreateRet(irBuilder.CreateBitCast(genericArray, llvmType())); } std::vector<llvm::Value*> params; for (const Value &v : dims) { params.push_back(builder->intPtrTypeValue(v)); } return Value(this, builder->irBuilder().CreateCall(mConstructFunction, params)); }
static const llvm::Type *makeLLVMType(TypePtr t) { switch (t->typeKind) { case BOOL_TYPE : return llvmIntType(8); case INTEGER_TYPE : { IntegerType *x = (IntegerType *)t.ptr(); return llvmIntType(x->bits); } case FLOAT_TYPE : { FloatType *x = (FloatType *)t.ptr(); return llvmFloatType(x->bits); } case POINTER_TYPE : { PointerType *x = (PointerType *)t.ptr(); return llvmPointerType(x->pointeeType); } case CODE_POINTER_TYPE : { CodePointerType *x = (CodePointerType *)t.ptr(); vector<const llvm::Type *> llArgTypes; for (unsigned i = 0; i < x->argTypes.size(); ++i) llArgTypes.push_back(llvmPointerType(x->argTypes[i])); for (unsigned i = 0; i < x->returnTypes.size(); ++i) { TypePtr t = x->returnTypes[i]; if (x->returnIsRef[i]) llArgTypes.push_back(llvmPointerType(pointerType(t))); else llArgTypes.push_back(llvmPointerType(t)); } llvm::FunctionType *llFuncType = llvm::FunctionType::get(llvmIntType(32), llArgTypes, false); return llvm::PointerType::getUnqual(llFuncType); } case CCODE_POINTER_TYPE : { CCodePointerType *x = (CCodePointerType *)t.ptr(); vector<const llvm::Type *> llArgTypes; for (unsigned i = 0; i < x->argTypes.size(); ++i) llArgTypes.push_back(llvmType(x->argTypes[i])); const llvm::Type *llReturnType = x->returnType.ptr() ? llvmType(x->returnType) : llvmVoidType(); llvm::FunctionType *llFuncType = llvm::FunctionType::get(llReturnType, llArgTypes, x->hasVarArgs); return llvm::PointerType::getUnqual(llFuncType); } case ARRAY_TYPE : { ArrayType *x = (ArrayType *)t.ptr(); return llvmArrayType(x->elementType, x->size); } case VEC_TYPE : { VecType *x = (VecType *)t.ptr(); return llvm::VectorType::get(llvmType(x->elementType), x->size); } case TUPLE_TYPE : { TupleType *x = (TupleType *)t.ptr(); vector<const llvm::Type *> llTypes; vector<TypePtr>::iterator i, end; for (i = x->elementTypes.begin(), end = x->elementTypes.end(); i != end; ++i) llTypes.push_back(llvmType(*i)); if (x->elementTypes.empty()) llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case UNION_TYPE : { UnionType *x = (UnionType *)t.ptr(); const llvm::Type *maxAlignType = NULL; size_t maxAlign = 0; size_t maxAlignSize = 0; size_t maxSize = 0; for (unsigned i = 0; i < x->memberTypes.size(); ++i) { const llvm::Type *llt = makeLLVMApproximateType(x->memberTypes[i]); size_t align = llvmTargetData->getABITypeAlignment(llt); size_t size = llvmTargetData->getTypeAllocSize(llt); if (align > maxAlign) { maxAlign = align; maxAlignType = llt; maxAlignSize = size; } if (size > maxSize) maxSize = size; } if (!maxAlignType) { maxAlignType = llvmIntType(8); maxAlign = 1; } vector<const llvm::Type *> llTypes; llTypes.push_back(maxAlignType); if (maxSize > maxAlignSize) { const llvm::Type *padding = llvm::ArrayType::get(llvmIntType(8), maxSize-maxAlignSize); llTypes.push_back(padding); } return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case RECORD_TYPE : { RecordType *x = (RecordType *)t.ptr(); const vector<TypePtr> &fieldTypes = recordFieldTypes(x); vector<const llvm::Type *> llTypes; vector<TypePtr>::const_iterator i, end; for (i = fieldTypes.begin(), end = fieldTypes.end(); i != end; ++i) llTypes.push_back(llvmType(*i)); if (fieldTypes.empty()) llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case VARIANT_TYPE : { VariantType *x = (VariantType *)t.ptr(); return llvmType(variantReprType(x)); } case STATIC_TYPE : { vector<const llvm::Type *> llTypes; llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case ENUM_TYPE : { return llvmType(cIntType); } default : assert(false); return NULL; } }
const llvm::Type *llvmArrayType(TypePtr type, int size) { return llvmArrayType(llvmType(type), size); }
const llvm::Type *llvmPointerType(TypePtr t) { return llvmPointerType(llvmType(t)); }
llvm::Constant *llvmPtr(const TensorType &type, const void *data, unsigned addrspace) { return llvmPtr(llvmType(type, addrspace), data); }