//------------------------------------------------------------ bool DualTypeEqual::AreIntrinsicClustersCompatible(TypeRef typeRefX, TypeRef typeRefY) const { SubString typeXName, typeYName; Boolean isTypeXIntrinsicClusterType = typeRefX->IsIntrinsicClusterDataType(&typeXName); Boolean isTypeYIntrinsicClusterType = typeRefY->IsIntrinsicClusterDataType(&typeYName); return typeXName.Compare(&typeYName); }
void VariantType::SetVariantToDataTypeError(TypeRef inputType, TypeRef targetType, TypeRef outputType, void* outputData, ErrorCluster* errPtr) { if (inputType && inputType->IsCluster() && targetType->IsArray()) { errPtr->SetErrorAndAppendCallChain(true, kUnsupportedOnTarget, "Variant To Data"); } else { errPtr->SetErrorAndAppendCallChain(true, kVariantIncompatibleType, "Variant To Data"); } if (outputType && outputData) { outputType->InitData(outputData); } }
//------------------------------------------------------------ VIREO_FUNCTION_SIGNATURE3(ArrayFill, TypedArrayCoreRef, Int32, void) { TypedArrayCore* array = _Param(0); TypeRef eltType = array->ElementType(); Int32 length = _Param(1); if (array->Resize1D(length)) { eltType->MultiCopyData(_ParamPointer(2), array->RawBegin(), length); } return _NextInstruction(); }
//------------------------------------------------------------ //! Get a reference to the type pointer and data for a sub element VIREO_EXPORT EggShellResult EggShell_FindSubValue(TypeManagerRef tm, const TypeRef typeRef, void * pData, const char* eltName, TypeRef* typeRefLocation, void** dataRefLocation) { if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; TypeManagerScope scope(tm); SubString path(eltName); *typeRefLocation = typeRef->GetSubElementAddressFromPath(&path, pData, dataRefLocation, true); if (*typeRefLocation == nullptr) return kEggShellResult_ObjectNotFoundAtPath; return kEggShellResult_Success; }
VariantTypeRef VariantType::CreateNewVariantFromStaticTypeAndData(const StaticTypeAndData& input) { TypeRef inputType = input._paramType; TypeManagerRef tm = THREAD_TADM(); auto inputData = input._pData; if (inputType->IsVariant()) { VariantTypeRef variant = *reinterpret_cast<VariantTypeRef *>(input._pData); inputType = variant->_underlyingTypeRef; inputData = variant->Begin(kPARead); } VariantTypeRef newVariant = VariantType::New(tm, inputType); newVariant->CopyData(inputData, newVariant->Begin(kPAWrite)); return newVariant; }
//------------------------------------------------------------ bool DualTypeEqual::Apply(TypeRef typeRefX, void* pDataX, TypeRef typeRefY, void* pDataY) const { EncodingEnum encodingX = typeRefX->BitEncoding(); bool success = false; switch (encodingX) { case kEncoding_Boolean: success = ApplyBooleans(typeRefX, pDataX, typeRefY, pDataY); break; case kEncoding_UInt: success = ApplyUInts(typeRefX, pDataX, typeRefY, pDataY); break; case kEncoding_S2CInt: success = ApplyS2CInts(typeRefX, pDataX, typeRefY, pDataY); break; case kEncoding_IEEE754Binary: success = ApplyIEEE754Binaries(typeRefX, pDataX, typeRefY, pDataY); break; case kEncoding_Enum: success = ApplyUInts(typeRefX, pDataX, typeRefY, pDataY); break; default: break; } return success; }
//------------------------------------------------------------ //! Read a symbol's value as a string. Value will be formatted according to designated format. VIREO_EXPORT EggShellResult EggShell_ReadValueString(TypeManagerRef tm, const TypeRef typeRef, void* pData, const char* format, UInt8** valueString) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; static StringRef returnBuffer = nullptr; if (returnBuffer == nullptr) { // Allocate a string the first time it is used. // After that it will be resized as needed. STACK_VAR(String, tempReturn); returnBuffer = tempReturn.DetachValue(); } else { returnBuffer->Resize1D(0); } if (returnBuffer) { SubString formatss(format); TDViaFormatter formatter(returnBuffer, true, 0, &formatss, kJSONEncodingEggShell); formatter.FormatData(typeRef, pData); // Add an explicit null terminator so it looks like a C string. returnBuffer->Append((Utf8Char)'\0'); *valueString = returnBuffer->Begin(); return kEggShellResult_Success; } return kEggShellResult_UnableToCreateReturnBuffer; }
//------------------------------------------------------------ VIREO_FUNCTION_SIGNATURE3(ArrayIndexElt, TypedArrayCoreRef, Int32, void) { TypedArrayCoreRef array = _Param(0); Int32 length = array->Length(); TypeRef elementType = array->ElementType(); Int32 index = _Param(1); if (_ParamPointer(2)) { if (index < 0 || index >= length) { elementType->InitData(_ParamPointer(2)); } else { elementType->CopyData(array->BeginAt(index), _ParamPointer(2)); } } return _NextInstruction(); }
FunctionRef FunctionRef::create( TypeRef returnType, Visibility visibility, const QByteArray &name, const QVector<TypeRef> &argTypes, const QVector<QByteArray> &argNames, bool firstArgIsReturnValuePointer, ModuleRef & parent, llvm::LLVMContext* ctx ) { llvm::Type *lt = returnType.rawPtr(); std::vector<llvm::Type*> largTypes(argTypes.size()); for (int i=0; i<argTypes.size(); ++i) { llvm::Type *at = (llvm::Type*) argTypes[i].rawPtr(); largTypes[i] = at; } llvm::FunctionType * lft = largTypes.empty() ? llvm::FunctionType::get(lt, false) : llvm::FunctionType::get(lt, largTypes, false) ; llvm::GlobalValue::LinkageTypes link = VS_Extern==visibility ? llvm::GlobalValue::ExternalLinkage : llvm::GlobalValue::PrivateLinkage ; std::string lname(name.constData(), name.size()); llvm::Module *lm = (llvm::Module*) parent.rawPtr(); llvm::Function *lf = llvm::Function::Create( lft, link, lname, lm ); lf->addFnAttr(llvm::Attribute::NoUnwind); lf->addFnAttr(llvm::Attribute::UWTable); typedef llvm::Function::ArgumentListType::iterator AIt; int argNumber = 0; for (AIt it=lf->getArgumentList().begin(); argNumber<argNames.size() ; ++argNumber, ++it) { const std::string argName(argNames[argNumber].constData()); it->setName(argName); } if (firstArgIsReturnValuePointer) { llvm::Argument & firstArg = lf->getArgumentList().front(); llvm::AttrBuilder abuilder; abuilder.addAttribute(llvm::Attribute::StructRet); abuilder.addAttribute(llvm::Attribute::NoAlias); firstArg.addAttr(llvm::AttributeSet::get(*ctx, 0, abuilder)); firstArg.addAttr(llvm::AttributeSet::get(*ctx, 1, abuilder)); } FunctionRef result; result.d = (lf); return result; }
/// Try to optimize the regular Convolution into a target-specific convolution /// with a different filter memory layout. This optimization adds a new kind of /// cpu-specific convolution that operates on filter weight data in a /// non-standard format. The default format is DKKC, where D is the output /// depth of the filter and C is the input channel, and K is the kernel size. /// This optimization changes the data layout to [D/8, K, K, C, 8]. We /// pre-swizzle the data in the weights to make the access pattern more /// efficient. static Node *optimizeCPUConv(ConvolutionNode *CN, Function *F) { auto depth = CN->getFilter().dims()[0]; auto *M = F->getParent(); // The depth dimension must be a multiple of 64 to perform the // transformation. This transformation is currently only profitable on // low-channel convolutions. if (depth < 64 || (depth % 64) != 0) { return nullptr; } Variable *filter = dyn_cast<Variable>(CN->getFilter()); if (!filter || filter->getNumUsers() != 1 || !filter->isPrivate()) { // Can't mutate the filter. return nullptr; } // We only support Floats for now. if (filter->getElementType() != ElemKind::FloatTy) { return nullptr; } // Create a new variable filter with the layout [D/8, K, K, C, 8]; TypeRef filterTy = filter->getType(); auto dims = filterTy->dims(); assert(dims.size() == 4 && "Invalid filter size"); auto *filter8 = M->createVariable( filterTy->getElementType(), {dims[0] / 8, dims[1], dims[2], dims[3], 8}, filter->getName(), VisibilityKind::Private, Variable::TrainKind::None); auto F8H = filter8->getHandle(); auto FH = filter->getHandle(); // Transpose the weights into the format [D/8, K, K, C, 8], where the depth // dimension is consecutive in memory. for (size_t c0 = 0; c0 < dims[0]; c0++) for (size_t c1 = 0; c1 < dims[1]; c1++) for (size_t c2 = 0; c2 < dims[2]; c2++) for (size_t c3 = 0; c3 < dims[3]; c3++) { F8H.at({c0 / 8, c1, c2, c3, c0 % 8}) = FH.at({c0, c1, c2, c3}); } return F->addNode(new CPUConvDKKC8Node( CN->getName(), CN->getType(), CN->getInput(), filter8, CN->getBias(), CN->getKernel(), CN->getStride(), CN->getPad())); }
VIREO_FUNCTION_SIGNATURE4(AnalogWaveformBuild, AnalogWaveform, Timestamp, Double, TypedArrayCoreRef) { _Param(0)._t0 = _ParamPointer(1) ? _Param(1) : Timestamp(0, 0); _Param(0)._dt = _ParamPointer(2) ? _Param(2) : 1.0; TypedArrayCoreRef* argY_source = _ParamPointer(3); TypedArrayCoreRef* waveY_dest = &_Param(0)._Y; if (argY_source) { if (!(*argY_source)->ElementType()->IsA((*waveY_dest)->ElementType())) { THREAD_EXEC()->LogEvent(EventLog::kHardDataError, "AnalogWaveformBuild() Type of argument-3 does not match type of output waveform"); return THREAD_EXEC()->Stop(); } TypeRef type = (*argY_source)->Type(); type->CopyData(argY_source, waveY_dest); } return _NextInstruction(); }
//------------------------------------------------------------ VIREO_FUNCTION_SIGNATURE4(ArrayReplaceElt, TypedArrayCoreRef, TypedArrayCoreRef, Int32, void) { TypedArrayCoreRef arrayOut = _Param(0); TypedArrayCoreRef arrayIn = _Param(1); TypeRef elementType = arrayOut->ElementType(); Int32 index = _Param(2); Int32 length = arrayIn->Length(); if(arrayOut != arrayIn){ arrayOut->Type()->CopyData(_ParamPointer(1), _ParamPointer(0)); } if (index >= 0 && index < length) { void* pDest = arrayOut->BeginAt(index); elementType->CopyData(_ParamPointer(3), pDest); } return _NextInstruction(); }
//------------------------------------------------------------ //! Deallocates data and frees up memory in dataRef described by typeRef VIREO_EXPORT EggShellResult EggShell_DeallocateData(TypeManagerRef tm, const TypeRef typeRef, void* dataRef) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) { return kEggShellResult_InvalidTypeRef; } if (dataRef == nullptr) { return kEggShellResult_InvalidDataPointer; } NIError error = typeRef->ClearData(dataRef); THREAD_TADM()->Free(dataRef); if (error != kNIError_Success) { return kEggShellResult_UnableToDeallocateData; } return kEggShellResult_Success; }
//------------------------------------------------------------ //! Write a numeric value to a symbol. Value will be coerced as needed. VIREO_EXPORT EggShellResult EggShell_WriteDouble(TypeManagerRef tm, const TypeRef typeRef, void* pData, Double value) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; NIError error = WriteDoubleToMemory(typeRef, pData, value); if (error) return kEggShellResult_UnexpectedObjectType; return kEggShellResult_Success; }
//------------------------------------------------------------ //! Allocates enough memory to fit a new object of TypeRef VIREO_EXPORT EggShellResult EggShell_AllocateData(TypeManagerRef tm, const TypeRef typeRef, void** dataRefLocation) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) { return kEggShellResult_InvalidTypeRef; } if (dataRefLocation == nullptr) { return kEggShellResult_InvalidDataPointer; } *dataRefLocation = nullptr; Int32 topSize = typeRef->TopAQSize(); void* pData = THREAD_TADM()->Malloc(topSize); NIError error = typeRef->InitData(pData); if (error != kNIError_Success) { return kEggShellResult_UnableToAllocateData; } *dataRefLocation = pData; return kEggShellResult_Success; }
//------------------------------------------------------------ //! Resizes a variable size Array symbol to have new dimension lengths specified by newLengths, it also initializes cells for non-flat data. VIREO_EXPORT EggShellResult EggShell_ResizeArray(TypeManagerRef tm, const TypeRef typeRef, const void* pData, Int32 rank, Int32 dimensionLengths[]) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; if (!typeRef->IsArray()) return kEggShellResult_UnexpectedObjectType; if (typeRef->Rank() != rank) return kEggShellResult_MismatchedArrayRank; TypedArrayCoreRef arrayObject = *(static_cast<const TypedArrayCoreRef*>(pData)); VIREO_ASSERT(TypedArrayCore::ValidateHandle(arrayObject)); if (!arrayObject->ResizeDimensions(rank, dimensionLengths, true, false)) { return kEggShellResult_UnableToCreateReturnBuffer; } return kEggShellResult_Success; }
bool TypeHierarchy::reachable(const TypeRef & t1,const TypeRef & t2) { if(t1 == t2) return true; Graph::iterator i = graph.find(&t1); if(i == graph.end()) { return false; }; Graph::const_iterator j = graph.find(&t2); if(j == graph.end() && t2.expected()) { return false; }; t2.addContents(this); j = graph.find(&t2); if(i->second.find(j->first) != i->second.end()) return true; Nodes ns; return closure(graph,i,ns,i,j->first); };
//------------------------------------------------------------ //! Read a numeric value from a symbol. Value will be coerced as needed. VIREO_EXPORT EggShellResult EggShell_ReadDouble(TypeManagerRef tm, const TypeRef typeRef, const void* pData, Double* result) { TypeManagerScope scope(tm); if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; if (result == nullptr) return kEggShellResult_InvalidResultPointer; NIError error = kNIError_Success; *result = ReadDoubleFromMemory(typeRef, pData, &error); if (error) return kEggShellResult_UnexpectedObjectType; return kEggShellResult_Success; }
void TypeHierarchy::add(const PTypeRef & t1,const TypeRef & t2) { Graph::const_iterator i = graph.find(&t1); Graph::const_iterator j = graph.find(&t2); if(j == graph.end()) { TypeRef * c = t2.clone(); graph[c] = set<const TypeRef*>(); j = graph.find(&t2); }; if(i == graph.end()) { TypeRef * c = t1.clone(); graph[c] = set<const TypeRef*>(); }; graph[&t1].insert(j->first); };
//------------------------------------------------------------ // Write a string value to a symbol. Value will be parsed according to format designated. VIREO_EXPORT EggShellResult EggShell_WriteValueString(TypeManagerRef tm, const TypeRef typeRef, void* pData, const char* format, const char* value) { TypeManagerScope scope(tm); SubString valueString(value); if (typeRef == nullptr || !typeRef->IsValid()) return kEggShellResult_InvalidTypeRef; EventLog log(EventLog::DevNull); SubString formatss(format); TDViaParser parser(tm, &valueString, &log, 1, &formatss, true, true, true); Int32 error = parser.ParseData(typeRef, pData); if (error) { return kEggShellResult_UnableToParseData; } return kEggShellResult_Success; }
//------------------------------------------------------------ VIREO_EXPORT StringRef TypeRef_ElementName(TypeManagerRef tm, TypeRef typeRef) { TypeManagerScope scope(tm); SubString name = typeRef->ElementName(); static StringRef returnBuffer = nullptr; if (returnBuffer == nullptr) { // Allocate a string the first time it is used. // After that it will be resized as needed. STACK_VAR(String, tempReturn); returnBuffer = tempReturn.DetachValue(); } else { returnBuffer->Resize1D(name.Length()); } if (returnBuffer) { returnBuffer->CopyFromSubString(&name); return returnBuffer; } return nullptr; }
//------------------------------------------------------------ VIREO_EXPORT TypeRef TypeRef_Next(TypeRef typeRef) { return typeRef->Next(); }
//------------------------------------------------------------ VIREO_EXPORT Int32 TypeRef_SubElementCount(TypeRef typeRef) { return typeRef->SubElementCount(); }
// Convert variant to data of given type. Error if the data types don't match VIREO_FUNCTION_SIGNATURET(VariantToData, VariantToDataParamBlock) { ErrorCluster *errPtr = _ParamPointer(ErrorClust); if (!errPtr || !errPtr->status) { TypeRef inputType = _ParamImmediate(InputData._paramType); void* inputData = _ParamImmediate(InputData)._pData; TypeRef targetType = _ParamPointer(TargetType); TypeRef outputType = _ParamImmediate(OutputData._paramType); void* outputData = _ParamImmediate(OutputData)._pData; if (targetType->IsStaticTypeWildcard() || (!outputType->IsStaticTypeAndDataWildcard() && !outputType->IsA(targetType, true))) { // In VIA, TargetType is a required argument. Generated VIA from G must guarantee this. // If TargetType is optional, just throw internal error and exit. // OutputData is optional. However, if supplied, outputType MUST be same as targetType. Generated VIA from G must guarantee this. // If violated, just throw internal error and exit. // We should not throw valid LV errors. if (errPtr) errPtr->SetErrorAndAppendCallChain(true, kUnspecifiedError, "Variant To Data"); return _NextInstruction(); } if (inputType->IsVariant()) { VariantTypeRef variant = *reinterpret_cast<VariantTypeRef *>_ParamImmediate(InputData._pData); if (VariantType::IsNullVariant(variant)) { if (errPtr) errPtr->SetErrorAndAppendCallChain(true, kVariantIncompatibleType, "Variant To Data"); } else { TypeRef underlyingType = variant->_underlyingTypeRef; if (targetType->IsVariant()) { if (outputData) *static_cast<VariantTypeRef *>(outputData) = VariantType::CreateNewVariantFromType(underlyingType); } else if (underlyingType->IsA(targetType, true)) { if (outputData) targetType->CopyData(underlyingType->Begin(kPARead), outputData); } else if (errPtr) { VariantType::SetVariantToDataTypeError(underlyingType, targetType, outputType, outputData, errPtr); } } } else {
//------------------------------------------------------------ VIREO_EXPORT UsageTypeEnum TypeRef_ElementUsageType(TypeRef typeRef) { return typeRef->ElementUsageType(); }
//------------------------------------------------------------ VIREO_EXPORT TypeRef TypeRef_GetSubElementByPath(TypeRef typeRef, char* buffer, Int32 *offset) { SubString string(buffer); return typeRef->GetSubElementOffsetFromPath(&string, offset); }
//------------------------------------------------------------ VIREO_EXPORT TypeRef TypeRef_GetSubElementByName(TypeRef typeRef, char* buffer) { SubString string(buffer); return typeRef->GetSubElementByName(&string); }
//------------------------------------------------------------ VIREO_EXPORT TypeRef TypeRef_GetSubElementByIndex(TypeRef typeRef, Int32 index) { return typeRef->GetSubElement(index); }
llvm::ArrayRef<size_t> Node::dims(unsigned resNo) const { TypeRef TR = getType(resNo); return TR->dims(); }
ElemKind Node::getElementType(unsigned resNo) const { TypeRef TR = getType(resNo); return TR->getElementType(); }