llvm::Value * Target::SizeOf(LLVM_TYPE_CONST llvm::Type *type, llvm::BasicBlock *insertAtEnd) { if (isa == Target::GENERIC && lGenericTypeLayoutIndeterminate(type)) { llvm::Value *index[1] = { LLVMInt32(1) }; LLVM_TYPE_CONST llvm::PointerType *ptrType = llvm::PointerType::get(type, 0); llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType); #if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) llvm::ArrayRef<llvm::Value *> arrayRef(&index[0], &index[1]); llvm::Instruction *gep = llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "sizeof_gep", insertAtEnd); #else llvm::Instruction *gep = llvm::GetElementPtrInst::Create(voidPtr, &index[0], &index[1], "sizeof_gep", insertAtEnd); #endif if (is32Bit || g->opt.force32BitAddressing) return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, "sizeof_int", insertAtEnd); else return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, "sizeof_int", insertAtEnd); } const llvm::TargetData *td = GetTargetMachine()->getTargetData(); Assert(td != NULL); uint64_t byteSize = td->getTypeSizeInBits(type) / 8; if (is32Bit || g->opt.force32BitAddressing) return LLVMInt32((int32_t)byteSize); else return LLVMInt64(byteSize); }
bool TypeInfo::objectHasCustomMove(const AST::TypeInstance& typeInstance) const { if (typeInstance.isClassDecl()) { // Assume a custom move function exists. return true; } if (typeInstance.isPrimitive()) { const auto& primitive = module_.getPrimitive(typeInstance); return primitive.hasCustomMove(*this, arrayRef(typeInstance.selfTemplateArgs())); } if (typeInstance.isVariant()) { for (const auto variantType: typeInstance.variantTypes()) { if (hasCustomMove(variantType)) { return true; } } return false; } else { if (typeInstance.isClassDef() && objectHasCustomMoveMethod(typeInstance)) { return true; } for (const auto var: typeInstance.variables()) { if (hasCustomMove(var->type())) { return true; } } return false; } }
bool Write(uint8_t const * data, uint32_t count) { JNIEnv * env = jni::GetEnv(); jni::TScopedLocalByteArrayRef arrayRef(env, env->NewByteArray(count)); //this call copies native buffer to java byte array env->SetByteArrayRegion(arrayRef.get(), 0, count, reinterpret_cast<const jbyte *>(data)); static jmethodID const writeMethod = jni::GetMethodID(env, m_self, "write", "([BI)Z"); jboolean result = env->CallBooleanMethod(m_self, writeMethod, arrayRef.get(), static_cast<jint>(count)); if (jni::HandleJavaException(env)) return false; return result; }
llvm::Value* genPrimitiveSizeOf(Function& function, const AST::Type* const type) { auto& module = function.module(); IREmitter irEmitter(function); const auto& primitive = module.getPrimitive(*(type->getObjectType())); return primitive.emitMethod(irEmitter, METHOD_SIZEOF, arrayRef(type->templateArguments()), /*functionTemplateArguments=*/llvm::ArrayRef<AST::Value>(), /*args=*/{}, /*resultPtr=*/nullptr); }
bool TypeInfo::hasCustomDestructor(const AST::Type* const type) const { if (type->isObject()) { if (type->isPrimitive()) { const auto& primitive = module_.getPrimitive(*(type->getObjectType())); return primitive.hasCustomDestructor(*this, arrayRef(type->templateArguments())); } else { return objectHasCustomDestructor(*(type->getObjectType())); } } else { return type->isTemplateVar(); } }
bool TypeInfo::hasCustomMove(const AST::Type* const type) const { if (type->isObject()) { if (type->isPrimitive()) { const auto& primitive = module_.getPrimitive(*(type->getObjectType())); return primitive.hasCustomMove(*this, arrayRef(type->templateArguments())); } else { return objectHasCustomMove(*(type->getObjectType())) // We have a custom move operation if there's a liveness indicator, // since we need to set the source value to be dead. || objectHasLivenessIndicator(*(type->getObjectType())); } } else { return type->isTemplateVar(); } }
bool TypeInfo::isSizeAlwaysKnown(const AST::Type* const type) const { switch (type->kind()) { case AST::Type::OBJECT: if (type->isPrimitive()) { const auto& primitive = module_.getPrimitive(*(type->getObjectType())); return primitive.isSizeAlwaysKnown(*this, arrayRef(type->templateArguments())); } else { return isObjectSizeAlwaysKnown(*(type->getObjectType())); } case AST::Type::TEMPLATEVAR: return false; case AST::Type::ALIAS: return isSizeAlwaysKnown(type->resolveAliases()); default: llvm_unreachable("Unknown AST type kind enum."); } }
llvm::Value * Target::StructOffset(LLVM_TYPE_CONST llvm::Type *type, int element, llvm::BasicBlock *insertAtEnd) { if (isa == Target::GENERIC && lGenericTypeLayoutIndeterminate(type) == true) { llvm::Value *indices[2] = { LLVMInt32(0), LLVMInt32(element) }; LLVM_TYPE_CONST llvm::PointerType *ptrType = llvm::PointerType::get(type, 0); llvm::Value *voidPtr = llvm::ConstantPointerNull::get(ptrType); #if defined(LLVM_3_0) || defined(LLVM_3_0svn) || defined(LLVM_3_1svn) llvm::ArrayRef<llvm::Value *> arrayRef(&indices[0], &indices[2]); llvm::Instruction *gep = llvm::GetElementPtrInst::Create(voidPtr, arrayRef, "offset_gep", insertAtEnd); #else llvm::Instruction *gep = llvm::GetElementPtrInst::Create(voidPtr, &indices[0], &indices[2], "offset_gep", insertAtEnd); #endif if (is32Bit || g->opt.force32BitAddressing) return new llvm::PtrToIntInst(gep, LLVMTypes::Int32Type, "offset_int", insertAtEnd); else return new llvm::PtrToIntInst(gep, LLVMTypes::Int64Type, "offset_int", insertAtEnd); } const llvm::TargetData *td = GetTargetMachine()->getTargetData(); Assert(td != NULL); LLVM_TYPE_CONST llvm::StructType *structType = llvm::dyn_cast<LLVM_TYPE_CONST llvm::StructType>(type); Assert(structType != NULL); const llvm::StructLayout *sl = td->getStructLayout(structType); Assert(sl != NULL); uint64_t offset = sl->getElementOffset(element); if (is32Bit || g->opt.force32BitAddressing) return LLVMInt32((int32_t)offset); else return LLVMInt64(offset); }
llvm::Value* genTrivialPrimitiveFunctionCall(Function& function, const MethodInfo& methodInfo, PendingResultArray args, llvm::Value* const hintResultValue) { auto& module = function.module(); const auto type = methodInfo.parentType; const auto methodName = methodInfo.name; const auto functionType = methodInfo.functionType; const auto& templateArgs = methodInfo.templateArgs; ConstantGenerator constGen(module); TypeGenerator typeGen(module); switch (type->primitiveID()) { case PrimitiveVoid: return genVoidPrimitiveMethodCall(function, type, methodName, functionType, std::move(args)); case PrimitiveCompareResult: return genCompareResultPrimitiveMethodCall(function, type, methodName, functionType, std::move(args)); case PrimitiveNull: return genNullPrimitiveMethodCall(function, type, methodName, arrayRef(templateArgs), std::move(args), hintResultValue); case PrimitiveBool: return genBoolPrimitiveMethodCall(function, type, methodName, functionType, arrayRef(templateArgs), std::move(args), hintResultValue); case PrimitiveValueLval: return genValueLvalPrimitiveMethodCall(function, type, methodName, functionType, std::move(args), hintResultValue); case PrimitiveFinalLval: return genFinalLvalPrimitiveMethodCall(function, type, methodName, functionType, std::move(args), hintResultValue); case PrimitivePtrLval: return genPtrLvalPrimitiveMethodCall(function, type, methodName, functionType, std::move(args), hintResultValue); case PrimitivePtr: return genPtrPrimitiveMethodCall(function, type, methodName, functionType, std::move(args)); case PrimitiveFunctionPtr: case PrimitiveMethodFunctionPtr: case PrimitiveTemplatedFunctionPtr: case PrimitiveTemplatedMethodFunctionPtr: case PrimitiveVarArgFunctionPtr: case PrimitiveMethod: case PrimitiveTemplatedMethod: case PrimitiveInterfaceMethod: case PrimitiveStaticInterfaceMethod: return genFunctionPtrPrimitiveMethodCall(function, type, methodName, functionType, std::move(args), hintResultValue); case PrimitiveInt8: case PrimitiveInt16: case PrimitiveInt32: case PrimitiveInt64: case PrimitiveByte: case PrimitiveShort: case PrimitiveInt: case PrimitiveLong: case PrimitiveLongLong: case PrimitiveSSize: case PrimitivePtrDiff: return genSignedIntegerPrimitiveMethodCall(function, type, methodName, functionType, arrayRef(templateArgs), std::move(args), hintResultValue); case PrimitiveUInt8: case PrimitiveUInt16: case PrimitiveUInt32: case PrimitiveUInt64: case PrimitiveUByte: case PrimitiveUShort: case PrimitiveUInt: case PrimitiveULong: case PrimitiveULongLong: case PrimitiveSize: return genUnsignedIntegerPrimitiveMethodCall(function, type, methodName, functionType, arrayRef(templateArgs), std::move(args), hintResultValue); case PrimitiveFloat: case PrimitiveDouble: case PrimitiveLongDouble: return genFloatPrimitiveMethodCall(function, type, methodName, functionType, arrayRef(templateArgs), std::move(args), hintResultValue); case PrimitiveTypename: return genTypenamePrimitiveMethodCall(function, type, methodName, functionType, std::move(args)); case PrimitiveRef: return genRefPrimitiveMethodCall(function, type, methodName, functionType, std::move(args), hintResultValue); } const auto& typeName = type->getObjectType()->name().last(); printf("%s\n", typeName.c_str()); llvm_unreachable("Unknown trivial primitive function."); }