2020-01-22 17:58:55 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "RigVMCompiler/RigVMCompiler.h"
# include "RigVMModel/RigVMController.h"
2022-07-05 11:39:15 -04:00
# include "RigVMModel/Nodes/RigVMDispatchNode.h"
2022-11-23 11:09:03 -05:00
# include "RigVMModel/Nodes/RigVMBranchNode.h"
2023-01-03 09:23:55 -05:00
# include "RigVMModel/Nodes/RigVMArrayNode.h"
2020-01-22 17:58:55 -05:00
# include "RigVMCore/RigVMExecuteContext.h"
2022-03-31 14:40:13 -04:00
# include "RigVMCore/RigVMNativized.h"
2020-01-22 17:58:55 -05:00
# include "RigVMDeveloperModule.h"
# include "UObject/PropertyPortFlags.h"
2022-03-16 03:29:38 -04:00
# include "UObject/Interface.h"
2020-01-22 17:58:55 -05:00
# include "Stats/StatsHierarchical.h"
2021-11-18 08:00:07 -05:00
# include "RigVMTypeUtils.h"
2022-11-16 03:33:17 -05:00
# include "RigVMCore/RigVMGraphFunctionDefinition.h"
# include "ProfilingDebugging/ScopedTimers.h"
# include "RigVMModel/RigVMClient.h"
2023-01-03 09:23:55 -05:00
# include "RigVMFunctions/RigVMDispatch_Array.h"
2022-11-10 04:36:01 -05:00
# include "Algo/Count.h"
2022-12-06 09:43:35 -05:00
# include "String/Join.h"
2020-01-22 17:58:55 -05:00
2022-09-24 13:31:25 -04:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(RigVMCompiler)
2020-01-22 17:58:55 -05:00
class FRigVMCompilerImportErrorContext : public FOutputDevice
{
public :
URigVMCompiler * Compiler ;
int32 NumErrors ;
FRigVMCompilerImportErrorContext ( URigVMCompiler * InCompiler )
: FOutputDevice ( )
, Compiler ( InCompiler )
, NumErrors ( 0 )
{
}
virtual void Serialize ( const TCHAR * V , ELogVerbosity : : Type Verbosity , const class FName & Category ) override
{
switch ( Verbosity )
{
case ELogVerbosity : : Error :
case ELogVerbosity : : Fatal :
{
Compiler - > ReportError ( V ) ;
break ;
}
case ELogVerbosity : : Warning :
{
Compiler - > ReportWarning ( V ) ;
break ;
}
default :
{
Compiler - > ReportInfo ( V ) ;
break ;
}
}
NumErrors + + ;
}
} ;
FRigVMCompileSettings : : FRigVMCompileSettings ( )
: SurpressInfoMessages ( true )
, SurpressWarnings ( false )
, SurpressErrors ( false )
, EnablePinWatches ( true )
2021-05-14 02:36:03 -04:00
, IsPreprocessorPhase ( false )
2020-01-22 17:58:55 -05:00
, ASTSettings ( FRigVMParserASTSettings : : Optimized ( ) )
2020-09-24 00:43:27 -04:00
, SetupNodeInstructionIndex ( true )
2020-01-22 17:58:55 -05:00
{
}
2022-11-25 02:59:46 -05:00
FRigVMCompileSettings : : FRigVMCompileSettings ( UScriptStruct * InExecuteContextScriptStruct )
: FRigVMCompileSettings ( )
{
ASTSettings . ExecuteContextStruct = InExecuteContextScriptStruct ;
if ( ASTSettings . ExecuteContextStruct = = nullptr )
{
ASTSettings . ExecuteContextStruct = FRigVMExecuteContext : : StaticStruct ( ) ;
}
}
2021-07-27 14:04:39 -04:00
FRigVMOperand FRigVMCompilerWorkData : : AddProperty (
ERigVMMemoryType InMemoryType ,
const FName & InName ,
const FString & InCPPType ,
UObject * InCPPTypeObject ,
const FString & InDefaultValue )
2020-01-22 17:58:55 -05:00
{
2021-07-27 14:04:39 -04:00
check ( bSetupMemory ) ;
2022-08-11 06:58:29 -04:00
const FRigVMRegistry & Registry = FRigVMRegistry : : Get ( ) ;
FRigVMTemplateArgumentType ArgumentType ( * InCPPType , InCPPTypeObject ) ;
const TRigVMTypeIndex TypeIndex = Registry . GetTypeIndex ( ArgumentType ) ;
if ( TypeIndex ! = INDEX_NONE )
{
// for execute pins we should use the graph's default execute context struct
if ( Registry . IsExecuteType ( TypeIndex ) )
{
ensure ( ! ArgumentType . IsArray ( ) ) ;
ArgumentType = FRigVMTemplateArgumentType ( ExecuteContextStruct ) ;
}
}
2021-07-27 14:04:39 -04:00
2022-08-11 06:58:29 -04:00
FRigVMPropertyDescription Description ( InName , ArgumentType . CPPType . ToString ( ) , ArgumentType . CPPTypeObject , InDefaultValue ) ;
2021-07-27 14:04:39 -04:00
2021-07-28 03:35:30 -04:00
TArray < FRigVMPropertyDescription > & PropertyArray = PropertyDescriptions . FindOrAdd ( InMemoryType ) ;
2021-07-27 14:04:39 -04:00
const int32 PropertyIndex = PropertyArray . Add ( Description ) ;
return FRigVMOperand ( InMemoryType , PropertyIndex ) ;
2020-01-22 17:58:55 -05:00
}
2021-07-27 14:04:39 -04:00
FRigVMOperand FRigVMCompilerWorkData : : FindProperty ( ERigVMMemoryType InMemoryType , const FName & InName )
2020-01-22 17:58:55 -05:00
{
2021-07-28 03:35:30 -04:00
TArray < FRigVMPropertyDescription > * PropertyArray = PropertyDescriptions . Find ( InMemoryType ) ;
2021-07-27 14:04:39 -04:00
if ( PropertyArray )
2020-01-22 17:58:55 -05:00
{
2021-07-27 14:04:39 -04:00
for ( int32 Index = 0 ; Index < PropertyArray - > Num ( ) ; Index + + )
{
if ( PropertyArray - > operator [ ] ( Index ) . Name = = InName )
{
return FRigVMOperand ( InMemoryType , Index ) ;
}
}
2020-01-22 17:58:55 -05:00
}
2021-07-27 14:04:39 -04:00
return FRigVMOperand ( ) ;
2020-01-22 17:58:55 -05:00
}
2021-07-28 03:35:30 -04:00
FRigVMPropertyDescription FRigVMCompilerWorkData : : GetProperty ( const FRigVMOperand & InOperand )
2020-09-24 00:43:27 -04:00
{
2021-07-28 03:35:30 -04:00
TArray < FRigVMPropertyDescription > * PropertyArray = PropertyDescriptions . Find ( InOperand . GetMemoryType ( ) ) ;
2021-07-27 14:04:39 -04:00
if ( PropertyArray )
{
if ( PropertyArray - > IsValidIndex ( InOperand . GetRegisterIndex ( ) ) )
{
return PropertyArray - > operator [ ] ( InOperand . GetRegisterIndex ( ) ) ;
}
}
2021-07-28 03:35:30 -04:00
return FRigVMPropertyDescription ( ) ;
2020-09-24 00:43:27 -04:00
}
2021-08-03 06:19:44 -04:00
int32 FRigVMCompilerWorkData : : FindOrAddPropertyPath ( const FRigVMOperand & InOperand , const FString & InHeadCPPType , const FString & InSegmentPath )
2021-07-27 14:04:39 -04:00
{
2021-07-29 14:29:52 -04:00
if ( InSegmentPath . IsEmpty ( ) )
2021-07-27 14:04:39 -04:00
{
2021-07-29 14:29:52 -04:00
return INDEX_NONE ;
2021-07-28 03:35:30 -04:00
}
TArray < FRigVMPropertyPathDescription > & Descriptions = PropertyPathDescriptions . FindOrAdd ( InOperand . GetMemoryType ( ) ) ;
for ( int32 Index = 0 ; Index < Descriptions . Num ( ) ; Index + + )
{
const FRigVMPropertyPathDescription & Description = Descriptions [ Index ] ;
2021-08-03 06:19:44 -04:00
if ( Description . HeadCPPType = = InHeadCPPType & & Description . SegmentPath = = InSegmentPath )
2021-07-27 14:04:39 -04:00
{
return Index ;
}
}
2021-08-03 06:19:44 -04:00
return Descriptions . Add ( FRigVMPropertyPathDescription ( InOperand . GetRegisterIndex ( ) , InHeadCPPType , InSegmentPath ) ) ;
2021-07-27 14:04:39 -04:00
}
2022-10-20 08:54:59 -04:00
const FProperty * FRigVMCompilerWorkData : : GetPropertyForOperand ( const FRigVMOperand & InOperand ) const
{
if ( ! InOperand . IsValid ( ) )
{
return nullptr ;
}
check ( ! bSetupMemory ) ;
auto GetPropertyFromMemory = [ this ] ( const URigVMMemoryStorage * InMemory , const FRigVMOperand & InOperand )
{
if ( InOperand . GetRegisterOffset ( ) = = INDEX_NONE )
{
return InMemory - > GetProperty ( InOperand . GetRegisterIndex ( ) ) ;
}
if ( ! InMemory - > GetPropertyPaths ( ) . IsValidIndex ( InOperand . GetRegisterOffset ( ) ) )
{
if ( URigVMMemoryStorageGeneratorClass * MemoryClass = Cast < URigVMMemoryStorageGeneratorClass > ( InMemory - > GetClass ( ) ) )
{
MemoryClass - > PropertyPathDescriptions = PropertyPathDescriptions . FindChecked ( InOperand . GetMemoryType ( ) ) ; ;
MemoryClass - > RefreshPropertyPaths ( ) ;
}
}
return InMemory - > GetPropertyPaths ( ) [ InOperand . GetRegisterOffset ( ) ] . GetTailProperty ( ) ;
} ;
const FProperty * Property = nullptr ;
switch ( InOperand . GetMemoryType ( ) )
{
case ERigVMMemoryType : : Literal :
{
Property = GetPropertyFromMemory ( VM - > GetLiteralMemory ( ) , InOperand ) ;
break ;
}
case ERigVMMemoryType : : Work :
{
Property = GetPropertyFromMemory ( VM - > GetWorkMemory ( ) , InOperand ) ;
break ;
}
case ERigVMMemoryType : : Debug :
{
Property = GetPropertyFromMemory ( VM - > GetDebugMemory ( ) , InOperand ) ;
break ;
}
case ERigVMMemoryType : : External :
{
Property = VM - > GetExternalVariables ( ) [ InOperand . GetRegisterIndex ( ) ] . Property ;
if ( InOperand . GetRegisterOffset ( ) ! = INDEX_NONE )
{
if ( ! VM - > ExternalPropertyPaths . IsValidIndex ( InOperand . GetRegisterOffset ( ) ) )
{
VM - > ExternalPropertyPathDescriptions = PropertyPathDescriptions . FindChecked ( InOperand . GetMemoryType ( ) ) ;
VM - > RefreshExternalPropertyPaths ( ) ;
}
Property = VM - > ExternalPropertyPaths [ InOperand . GetRegisterOffset ( ) ] . GetTailProperty ( ) ;
}
break ;
}
case ERigVMMemoryType : : Invalid :
default :
{
break ;
}
}
return Property ;
}
TRigVMTypeIndex FRigVMCompilerWorkData : : GetTypeIndexForOperand ( const FRigVMOperand & InOperand ) const
{
const FProperty * Property = GetPropertyForOperand ( InOperand ) ;
if ( Property = = nullptr )
{
2022-11-02 06:55:06 -04:00
if ( InOperand . GetMemoryType ( ) = = ERigVMMemoryType : : External )
{
const TArray < FRigVMExternalVariable > & ExternalVariables = VM - > GetExternalVariables ( ) ;
if ( ExternalVariables . IsValidIndex ( InOperand . GetRegisterIndex ( ) ) )
{
const FRigVMExternalVariable & Variable = ExternalVariables [ InOperand . GetRegisterIndex ( ) ] ;
FString CPPType ;
UObject * CPPTypeObject ;
RigVMTypeUtils : : CPPTypeFromExternalVariable ( Variable , CPPType , & CPPTypeObject ) ;
return FRigVMRegistry : : Get ( ) . GetTypeIndex ( * CPPType , CPPTypeObject ) ;
}
}
2022-10-20 08:54:59 -04:00
return INDEX_NONE ;
}
FName CPPTypeName ( NAME_None ) ;
UObject * CPPTypeObject = nullptr ;
FRigVMExternalVariable : : GetTypeFromProperty ( Property , CPPTypeName , CPPTypeObject ) ;
return FRigVMRegistry : : Get ( ) . GetTypeIndex ( CPPTypeName , CPPTypeObject ) ;
}
2020-01-22 17:58:55 -05:00
URigVMCompiler : : URigVMCompiler ( )
2022-10-24 08:59:51 -04:00
: CurrentCompilationFunction ( nullptr )
2020-01-22 17:58:55 -05:00
{
}
2022-11-28 02:47:25 -05:00
bool URigVMCompiler : : Compile ( TArray < URigVMGraph * > InGraphs , URigVMController * InController , URigVM * OutVM , const TArray < FRigVMExternalVariable > & InExternalVariables , TMap < FString , FRigVMOperand > * OutOperands , TSharedPtr < FRigVMParserAST > InAST , FRigVMFunctionCompilationData * OutFunctionCompilationData )
2020-01-22 17:58:55 -05:00
{
2022-11-16 03:33:17 -05:00
double CompilationTime = 0 ;
FDurationTimer CompileTimer ( CompilationTime ) ;
2022-05-31 04:27:20 -04:00
if ( InGraphs . IsEmpty ( ) | | InGraphs . Contains ( nullptr ) )
2020-01-22 17:58:55 -05:00
{
ReportError ( TEXT ( " Provided graph is nullptr. " ) ) ;
return false ;
}
2022-05-31 04:27:20 -04:00
2020-01-22 17:58:55 -05:00
if ( OutVM = = nullptr )
{
ReportError ( TEXT ( " Provided vm is nullptr. " ) ) ;
return false ;
}
2022-11-25 02:59:46 -05:00
if ( Settings . GetExecuteContextStruct ( ) = = nullptr )
{
ReportError ( TEXT ( " Compiler settings don't provide the ExecuteContext to use. Cannot compile. " ) ) ;
return false ; ;
}
2022-11-28 02:47:25 -05:00
// also during traverse - find all known execute contexts
// for functions / dispatches / templates.
// we only allow compatible execute context structs within a VM
TArray < UStruct * > ValidExecuteContextStructs = FRigVMTemplate : : GetSuperStructs ( Settings . GetExecuteContextStruct ( ) ) ;
TArray < FString > ValidExecuteContextStructNames ;
Algo : : Transform ( ValidExecuteContextStructs , ValidExecuteContextStructNames , [ ] ( const UStruct * InStruct )
{
return CastChecked < UScriptStruct > ( InStruct ) - > GetStructCPPName ( ) ;
} ) ;
2022-11-25 02:59:46 -05:00
for ( URigVMGraph * Graph : InGraphs )
{
if ( Graph - > GetExecuteContextStruct ( ) )
{
2022-11-28 02:47:25 -05:00
if ( ! ValidExecuteContextStructs . Contains ( Graph - > GetExecuteContextStruct ( ) ) )
2022-11-25 02:59:46 -05:00
{
ReportErrorf (
TEXT ( " Compiler settings' ExecuteContext (%s) is not compatible with '%s' graph's ExecuteContext (%s). Cannot compile. " ) ,
* Settings . GetExecuteContextStruct ( ) - > GetStructCPPName ( ) ,
* Graph - > GetNodePath ( ) ,
* Graph - > GetExecuteContextStruct ( ) - > GetStructCPPName ( )
) ;
return false ; ;
}
}
}
2022-05-31 04:27:20 -04:00
for ( int32 Index = 1 ; Index < InGraphs . Num ( ) ; Index + + )
{
if ( InGraphs [ 0 ] - > GetOuter ( ) ! = InGraphs [ Index ] - > GetOuter ( ) )
{
ReportError ( TEXT ( " Provided graphs don't share a common outer / package. " ) ) ;
return false ;
}
}
2022-03-31 14:40:13 -04:00
if ( OutVM - > GetClass ( ) - > IsChildOf ( URigVMNativized : : StaticClass ( ) ) )
{
ReportError ( TEXT ( " Provided vm is nativized. " ) ) ;
return false ;
}
2020-01-22 17:58:55 -05:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2022-11-25 07:25:38 -05:00
OutVM - > SetContextPublicDataStruct ( Settings . GetExecuteContextStruct ( ) ) ;
2020-01-22 17:58:55 -05:00
OutVM - > Reset ( ) ;
TMap < FString , FRigVMOperand > LocalOperands ;
if ( OutOperands = = nullptr )
{
OutOperands = & LocalOperands ;
}
OutOperands - > Reset ( ) ;
2022-11-02 06:55:06 -04:00
URigVMFunctionLibrary * FunctionLibrary = InGraphs [ 0 ] - > GetDefaultFunctionLibrary ( ) ;
bool bEncounteredGraphError = false ;
2022-11-16 03:33:17 -05:00
TMap < FString , const FRigVMFunctionCompilationData * > CurrentCompiledFunctions ;
// Gather function compilation data
2023-01-11 07:12:21 -05:00
for ( URigVMGraph * Graph : InGraphs )
2022-11-02 06:55:06 -04:00
{
2023-01-11 07:12:21 -05:00
TArray < URigVMNode * > Nodes = Graph - > GetNodes ( ) ;
2022-11-16 03:33:17 -05:00
for ( int32 i = 0 ; i < Nodes . Num ( ) ; + + i )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
if ( URigVMFunctionReferenceNode * ReferenceNode = Cast < URigVMFunctionReferenceNode > ( Nodes [ i ] ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
if ( ! ReferenceNode - > GetReferencedFunctionHeader ( ) . IsValid ( ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
static const FString FunctionCompilationErrorMessage = TEXT ( " Function reference @@ has no function data. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ReferenceNode , FunctionCompilationErrorMessage ) ;
bEncounteredGraphError = true ;
break ;
2022-11-02 06:55:06 -04:00
}
2022-11-16 03:33:17 -05:00
// Try to find the compiled data
FString FunctionHash = ReferenceNode - > GetReferencedFunctionHeader ( ) . GetHash ( ) ;
if ( ! CurrentCompiledFunctions . Contains ( FunctionHash ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
if ( FRigVMGraphFunctionData * FunctionData = ReferenceNode - > GetReferencedFunctionHeader ( ) . GetFunctionData ( ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
// Clear compilation data if compiled with outdated dependency data
if ( FunctionData - > CompilationData . IsValid ( ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
for ( const TPair < FRigVMGraphFunctionIdentifier , uint32 > & Pair : ReferenceNode - > GetReferencedFunctionHeader ( ) . Dependencies )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
if ( IRigVMGraphFunctionHost * HostObj = Cast < IRigVMGraphFunctionHost > ( Pair . Key . HostObject . ResolveObject ( ) ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
if ( FRigVMGraphFunctionData * DependencyData = HostObj - > GetRigVMGraphFunctionStore ( ) - > FindFunction ( Pair . Key ) )
2022-11-02 06:55:06 -04:00
{
2023-03-03 12:54:30 -05:00
if ( DependencyData - > CompilationData . Hash = = 0 | | Pair . Value ! = DependencyData - > CompilationData . Hash )
2022-11-16 03:33:17 -05:00
{
FunctionData - > ClearCompilationData ( ) ;
break ;
}
2022-11-02 06:55:06 -04:00
}
}
2022-11-16 03:33:17 -05:00
}
}
if ( const FRigVMFunctionCompilationData * CompilationData = & FunctionData - > CompilationData )
{
bool bSuccessfullCompilation = false ;
if ( ! CompilationData - > IsValid ( ) )
{
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( FunctionData - > Header . LibraryPointer . LibraryNode . TryLoad ( ) ) )
{
IRigVMClientHost * ClientHost = LibraryNode - > GetImplementingOuter < IRigVMClientHost > ( ) ;
URigVMController * FunctionController = ClientHost - > GetRigVMClient ( ) - > GetController ( LibraryNode - > GetLibrary ( ) ) ;
bSuccessfullCompilation = CompileFunction ( LibraryNode , FunctionController , & FunctionData - > CompilationData ) ;
}
2022-11-02 06:55:06 -04:00
else
{
2022-11-16 03:33:17 -05:00
static const FString FunctionCompilationErrorMessage = TEXT ( " Compilation data for public function @@ has no instructions. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ReferenceNode , FunctionCompilationErrorMessage ) ;
bEncounteredGraphError = true ;
2022-11-02 06:55:06 -04:00
}
}
2022-11-16 03:33:17 -05:00
if ( bSuccessfullCompilation | | CompilationData - > IsValid ( ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
CurrentCompiledFunctions . Add ( FunctionHash , CompilationData ) ;
}
else
{
static const FString FunctionCompilationErrorMessage = TEXT ( " Compilation data for public function @@ has no instructions. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ReferenceNode , FunctionCompilationErrorMessage ) ;
bEncounteredGraphError = true ;
2022-11-02 06:55:06 -04:00
}
}
2022-11-16 03:33:17 -05:00
else
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
static const FString FunctionCompilationErrorMessage = TEXT ( " Could not find compilation data for node @@. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ReferenceNode , FunctionCompilationErrorMessage ) ;
2022-11-02 06:55:06 -04:00
bEncounteredGraphError = true ;
}
}
2022-11-16 03:33:17 -05:00
else
{
static const FString FunctionCompilationErrorMessage = TEXT ( " Could not find graph function data for node @@. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ReferenceNode , FunctionCompilationErrorMessage ) ;
bEncounteredGraphError = true ;
}
2022-11-02 06:55:06 -04:00
}
}
2022-11-16 03:33:17 -05:00
if ( URigVMCollapseNode * CollapseNode = Cast < URigVMCollapseNode > ( Nodes [ i ] ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
Nodes . Append ( CollapseNode - > GetContainedGraph ( ) - > GetNodes ( ) ) ;
2022-11-02 06:55:06 -04:00
}
}
}
2022-11-16 03:33:17 -05:00
if ( bEncounteredGraphError )
{
return false ;
}
CompiledFunctions = CurrentCompiledFunctions ;
2021-04-07 13:09:20 -04:00
# if WITH_EDITOR
// traverse all graphs and try to clear out orphan pins
2021-04-27 03:19:42 -04:00
// also check on function references with unmapped variables
2021-04-07 13:09:20 -04:00
TArray < URigVMGraph * > VisitedGraphs ;
2022-05-31 04:27:20 -04:00
VisitedGraphs . Append ( InGraphs ) ;
2021-04-07 17:24:36 -04:00
2022-11-24 07:22:08 -05:00
const FRigVMRegistry & Registry = FRigVMRegistry : : Get ( ) ;
2021-04-07 13:09:20 -04:00
for ( int32 GraphIndex = 0 ; GraphIndex < VisitedGraphs . Num ( ) ; GraphIndex + + )
{
URigVMGraph * VisitedGraph = VisitedGraphs [ GraphIndex ] ;
2022-01-13 22:49:09 -05:00
{
FRigVMControllerGraphGuard Guard ( InController , VisitedGraph , false ) ;
// make sure variables are up to date before validating other things.
// that is, make sure their cpp type and type object agree with each other
InController - > EnsureLocalVariableValidity ( ) ;
}
2021-04-07 13:09:20 -04:00
for ( URigVMNode * ModelNode : VisitedGraph - > GetNodes ( ) )
{
2021-04-13 12:03:23 -04:00
FRigVMControllerGraphGuard Guard ( InController , VisitedGraph , false ) ;
2022-01-13 22:49:09 -05:00
// make sure pins are up to date before validating other things.
// that is, make sure their cpp type and type object agree with each other
for ( URigVMPin * Pin : ModelNode - > Pins )
{
if ( ! URigVMController : : EnsurePinValidity ( Pin , true ) )
{
return false ;
}
}
2022-11-23 11:09:03 -05:00
if ( ModelNode - > IsA < UDEPRECATED_RigVMBranchNode > ( ) )
{
static const FString LinkedMessage = TEXT ( " Node @@ is a deprecated branch node. Cannot compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , LinkedMessage ) ;
bEncounteredGraphError = true ;
}
2022-11-30 04:26:41 -05:00
if ( ModelNode - > IsA < UDEPRECATED_RigVMIfNode > ( ) )
{
static const FString LinkedMessage = TEXT ( " Node @@ is a deprecated if node. Cannot compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , LinkedMessage ) ;
bEncounteredGraphError = true ;
}
if ( ModelNode - > IsA < UDEPRECATED_RigVMSelectNode > ( ) )
{
static const FString LinkedMessage = TEXT ( " Node @@ is a deprecated select node. Cannot compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , LinkedMessage ) ;
bEncounteredGraphError = true ;
}
2023-01-03 09:23:55 -05:00
if ( ModelNode - > IsA < UDEPRECATED_RigVMArrayNode > ( ) )
{
static const FString LinkedMessage = TEXT ( " Node @@ is a deprecated array node. Cannot compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , LinkedMessage ) ;
bEncounteredGraphError = true ;
}
2022-11-28 06:41:47 -05:00
if ( ! InController - > RemoveUnusedOrphanedPins ( ModelNode ) )
2021-04-07 13:09:20 -04:00
{
static const FString LinkedMessage = TEXT ( " Node @@ uses pins that no longer exist. Please rewire the links and re-compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , LinkedMessage ) ;
2021-09-22 08:06:30 -04:00
bEncounteredGraphError = true ;
2021-04-07 13:09:20 -04:00
}
2021-12-01 06:29:29 -05:00
// avoid function reference related validation for temp assets, a temp asset may get generated during
// certain content validation process. It is usually just a simple file-level copy of the source asset
// so these references are usually not fixed-up properly. Thus, it is meaningless to validate them.
if ( ! ModelNode - > GetPackage ( ) - > GetName ( ) . StartsWith ( TEXT ( " /Temp/ " ) ) )
2021-04-27 03:19:42 -04:00
{
2021-12-01 06:29:29 -05:00
if ( URigVMFunctionReferenceNode * FunctionReferenceNode = Cast < URigVMFunctionReferenceNode > ( ModelNode ) )
2021-04-27 03:19:42 -04:00
{
2021-12-01 06:29:29 -05:00
if ( ! FunctionReferenceNode - > IsFullyRemapped ( ) )
{
static const FString UnmappedMessage = TEXT ( " Node @@ has unmapped variables. Please adjust the node and re-compile. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , UnmappedMessage ) ;
bEncounteredGraphError = true ;
}
2022-11-02 06:55:06 -04:00
2022-11-16 03:33:17 -05:00
FString FunctionHash = FunctionReferenceNode - > GetReferencedFunctionHeader ( ) . GetHash ( ) ;
if ( const FRigVMFunctionCompilationData * * CompilationData = CompiledFunctions . Find ( FunctionHash ) )
2022-11-02 06:55:06 -04:00
{
2022-11-16 03:33:17 -05:00
for ( const TPair < int32 , FName > & Pair : ( * CompilationData ) - > ExternalRegisterIndexToVariable )
2022-11-02 06:55:06 -04:00
{
FName OuterName = FunctionReferenceNode - > GetOuterVariableName ( Pair . Value ) ;
if ( OuterName . IsNone ( ) )
{
OuterName = Pair . Value ;
}
if ( ! InExternalVariables . ContainsByPredicate ( [ OuterName ] ( const FRigVMExternalVariable & ExternalVariable )
{
return ExternalVariable . Name = = OuterName ;
} ) )
{
static const FString UnmappedMessage = TEXT ( " Function referenced in @@ using external variable not found in current rig. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , UnmappedMessage ) ;
bEncounteredGraphError = true ;
}
}
}
else
{
static const FString UnmappedMessage = TEXT ( " Node @@ referencing function, but could not find compilation data. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , UnmappedMessage ) ;
bEncounteredGraphError = true ;
}
2021-04-27 03:19:42 -04:00
}
}
2021-08-31 03:36:39 -04:00
if ( ModelNode - > IsA < URigVMFunctionEntryNode > ( ) | | ModelNode - > IsA < URigVMFunctionReturnNode > ( ) )
{
2021-09-22 08:06:30 -04:00
for ( URigVMPin * ExecutePin : ModelNode - > Pins )
2021-08-31 03:36:39 -04:00
{
2021-09-22 08:06:30 -04:00
if ( ExecutePin - > IsExecuteContext ( ) )
2021-08-31 03:36:39 -04:00
{
2021-09-22 08:06:30 -04:00
if ( ExecutePin - > GetLinks ( ) . Num ( ) = = 0 )
{
static const FString UnlinkedExecuteMessage = TEXT ( " Node @@ has an unconnected Execute pin. \n The function might cause unexpected behavior. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , UnlinkedExecuteMessage ) ;
bEncounteredGraphError = true ;
}
2021-08-31 03:36:39 -04:00
}
}
}
2022-10-24 08:59:51 -04:00
if ( URigVMCollapseNode * CollapseNode = Cast < URigVMCollapseNode > ( ModelNode ) )
2021-04-07 13:09:20 -04:00
{
2022-10-24 08:59:51 -04:00
if ( URigVMGraph * ContainedGraph = CollapseNode - > GetContainedGraph ( ) )
2021-04-07 13:09:20 -04:00
{
VisitedGraphs . AddUnique ( ContainedGraph ) ;
}
}
2021-08-26 06:58:05 -04:00
2021-10-25 20:05:28 -04:00
// for variable let's validate ill formed variable nodes
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( ModelNode ) )
{
static const FString IllFormedVariableNodeMessage = TEXT ( " Variable Node @@ is ill-formed (pin type doesn't match the variable type). \n Consider to recreate the node. " ) ;
const FRigVMGraphVariableDescription VariableDescription = VariableNode - > GetVariableDescription ( ) ;
const TArray < FRigVMGraphVariableDescription > LocalVariables = VisitedGraph - > GetLocalVariables ( true ) ;
bool bFoundVariable = false ;
for ( const FRigVMGraphVariableDescription & LocalVariable : LocalVariables )
{
if ( LocalVariable . Name = = VariableDescription . Name )
{
bFoundVariable = true ;
if ( LocalVariable . CPPType ! = VariableDescription . CPPType | |
LocalVariable . CPPTypeObject ! = VariableDescription . CPPTypeObject )
{
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , IllFormedVariableNodeMessage ) ;
bEncounteredGraphError = true ;
}
}
}
// if the variable is not a local variable, let's test against the external variables.
if ( ! bFoundVariable )
{
const FRigVMExternalVariable ExternalVariable = VariableDescription . ToExternalVariable ( ) ;
for ( const FRigVMExternalVariable & InExternalVariable : InExternalVariables )
{
if ( InExternalVariable . Name = = ExternalVariable . Name )
{
bFoundVariable = true ;
if ( InExternalVariable . TypeName ! = ExternalVariable . TypeName | |
InExternalVariable . TypeObject ! = ExternalVariable . TypeObject | |
InExternalVariable . bIsArray ! = ExternalVariable . bIsArray )
{
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , IllFormedVariableNodeMessage ) ;
bEncounteredGraphError = true ;
}
}
}
}
2022-03-16 03:28:36 -04:00
if ( VariableDescription . CPPTypeObject & & ! RigVMCore : : SupportsUObjects ( ) )
{
2022-04-06 08:26:45 -04:00
if ( VariableDescription . CPPTypeObject - > IsA < UClass > ( ) )
2022-03-16 03:28:36 -04:00
{
2022-04-06 08:26:45 -04:00
static const FString InvalidObjectTypeMessage = TEXT ( " Variable Node @@ uses an unsupported UClass type. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , InvalidObjectTypeMessage ) ;
bEncounteredGraphError = true ;
}
}
if ( VariableDescription . CPPTypeObject & & ! RigVMCore : : SupportsUInterfaces ( ) )
{
if ( VariableDescription . CPPTypeObject - > IsA < UInterface > ( ) )
{
static const FString InvalidObjectTypeMessage = TEXT ( " Variable Node @@ uses an unsupported UInterface type. " ) ;
2022-03-16 03:28:36 -04:00
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , InvalidObjectTypeMessage ) ;
bEncounteredGraphError = true ;
}
}
2021-10-25 20:05:28 -04:00
}
2022-08-22 21:21:49 -04:00
if ( URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( ModelNode ) )
{
if ( ! UnitNode - > HasWildCardPin ( ) )
{
UScriptStruct * ScriptStruct = UnitNode - > GetScriptStruct ( ) ;
if ( ScriptStruct = = nullptr )
{
InController - > FullyResolveTemplateNode ( UnitNode , INDEX_NONE , false ) ;
}
2022-10-03 07:12:07 -04:00
if ( UnitNode - > GetScriptStruct ( ) = = nullptr | | UnitNode - > ResolvedFunctionName . IsEmpty ( ) )
2022-08-22 21:21:49 -04:00
{
static const FString UnresolvedUnitNodeMessage = TEXT ( " Node @@ could not be resolved. " ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , UnresolvedUnitNodeMessage ) ;
bEncounteredGraphError = true ;
}
2022-12-09 09:00:15 -05:00
// Make sure all the pins exist in the node
ScriptStruct = UnitNode - > GetScriptStruct ( ) ;
if ( ScriptStruct )
{
for ( TFieldIterator < FProperty > It ( ScriptStruct , EFieldIterationFlags : : None ) ; It ; + + It )
{
const FRigVMTemplateArgument ExpectedArgument ( * It ) ;
const TRigVMTypeIndex ExpectedTypeIndex = ExpectedArgument . GetSupportedTypeIndices ( ) [ 0 ] ;
if ( URigVMPin * Pin = UnitNode - > FindPin ( ExpectedArgument . Name . ToString ( ) ) )
{
if ( Pin - > GetTypeIndex ( ) ! = ExpectedArgument . GetTypeIndices ( ) [ 0 ] )
{
FString MissingPinMessage = FString : : Printf ( TEXT ( " Could not find pin %s of type %s in Node @@. " ) , * ExpectedArgument . Name . ToString ( ) , * FRigVMRegistry : : Get ( ) . GetType ( ExpectedArgument . TypeIndices [ 0 ] ) . CPPType . ToString ( ) ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , MissingPinMessage ) ;
bEncounteredGraphError = true ;
}
}
else
{
FString MissingPinMessage = FString : : Printf ( TEXT ( " Could not find pin %s of type %s in Node @@. " ) , * ExpectedArgument . Name . ToString ( ) , * FRigVMRegistry : : Get ( ) . GetType ( ExpectedArgument . TypeIndices [ 0 ] ) . CPPType . ToString ( ) ) ;
Settings . ASTSettings . Report ( EMessageSeverity : : Error , ModelNode , MissingPinMessage ) ;
bEncounteredGraphError = true ;
}
}
}
2022-08-22 21:21:49 -04:00
}
}
2022-11-28 02:47:25 -05:00
auto ReportIncompatibleExecuteContextString = [ & ] ( const FString InExecuteContextName )
{
static constexpr TCHAR Format [ ] = TEXT ( " ExecuteContext '%s' on node '%s' is not compatible with '%s' provided by the compiler settings. " ) ;
ReportErrorf (
Format ,
* InExecuteContextName ,
* ModelNode - > GetNodePath ( ) ,
* Settings . GetExecuteContextStruct ( ) - > GetStructCPPName ( ) ) ;
bEncounteredGraphError = true ;
} ;
auto ReportIncompatibleExecuteContext = [ & ] ( const UScriptStruct * InExecuteContext )
{
ReportIncompatibleExecuteContextString ( InExecuteContext - > GetStructCPPName ( ) ) ;
} ;
FString ExecuteContextMetaData ;
if ( const URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( ModelNode ) )
{
if ( UScriptStruct * Struct = UnitNode - > GetScriptStruct ( ) )
{
if ( Struct - > GetStringMetaDataHierarchical ( FRigVMStruct : : ExecuteContextName , & ExecuteContextMetaData ) )
{
if ( ! ValidExecuteContextStructNames . Contains ( ExecuteContextMetaData ) )
{
ReportIncompatibleExecuteContextString ( ExecuteContextMetaData ) ;
}
}
}
}
2022-11-24 07:22:08 -05:00
if ( const URigVMDispatchNode * DispatchNode = Cast < URigVMDispatchNode > ( ModelNode ) )
{
if ( const FRigVMDispatchFactory * Factory = DispatchNode - > GetFactory ( ) )
{
2022-11-28 02:47:25 -05:00
if ( ! ValidExecuteContextStructs . Contains ( Factory - > GetExecuteContextStruct ( ) ) )
{
ReportIncompatibleExecuteContext ( Factory - > GetExecuteContextStruct ( ) ) ;
}
2022-11-24 07:22:08 -05:00
}
}
else if ( const URigVMTemplateNode * TemplateNode = Cast < URigVMTemplateNode > ( ModelNode ) )
{
if ( const FRigVMFunction * ResolvedFunction = TemplateNode - > GetResolvedFunction ( ) )
{
if ( UScriptStruct * RigVMStruct = ResolvedFunction - > Struct )
{
for ( TFieldIterator < FProperty > It ( RigVMStruct , EFieldIterationFlags : : IncludeAll ) ; It ; + + It )
{
const FProperty * Property = * It ;
if ( const FArrayProperty * ArrayProperty = CastField < FArrayProperty > ( Property ) )
{
Property = ArrayProperty - > Inner ;
}
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( Property ) )
{
if ( StructProperty - > Struct - > IsChildOf ( FRigVMExecuteContext : : StaticStruct ( ) ) )
{
2022-11-28 02:47:25 -05:00
if ( ! ValidExecuteContextStructs . Contains ( StructProperty - > Struct ) )
{
ReportIncompatibleExecuteContext ( StructProperty - > Struct ) ;
}
2022-11-24 07:22:08 -05:00
}
}
}
}
}
if ( const FRigVMTemplate * Template = TemplateNode - > GetTemplate ( ) )
{
2022-11-28 10:01:18 -05:00
const FRigVMDispatchContext DispatchContext ;
for ( int32 Index = 0 ; Index < Template - > NumExecuteArguments ( DispatchContext ) ; Index + + )
2022-11-24 07:22:08 -05:00
{
2022-11-28 10:01:18 -05:00
if ( const FRigVMExecuteArgument * Argument = Template - > GetExecuteArgument ( Index , DispatchContext ) )
2022-11-24 07:22:08 -05:00
{
if ( Registry . IsExecuteType ( Argument - > TypeIndex ) )
{
const FRigVMTemplateArgumentType & Type = Registry . GetType ( Argument - > TypeIndex ) ;
if ( UScriptStruct * ExecuteContextStruct = Cast < UScriptStruct > ( Type . CPPTypeObject ) )
{
2022-11-28 02:47:25 -05:00
if ( ! ValidExecuteContextStructs . Contains ( ExecuteContextStruct ) )
{
ReportIncompatibleExecuteContext ( ExecuteContextStruct ) ;
}
2022-11-24 07:22:08 -05:00
}
}
}
}
}
}
2021-08-26 06:58:05 -04:00
for ( URigVMPin * Pin : ModelNode - > Pins )
{
if ( ! URigVMController : : EnsurePinValidity ( Pin , true ) )
{
return false ;
}
}
2021-04-07 13:09:20 -04:00
}
}
2021-04-07 17:24:36 -04:00
2021-09-22 08:06:30 -04:00
if ( bEncounteredGraphError )
2021-04-07 17:24:36 -04:00
{
return false ;
}
2021-04-07 13:09:20 -04:00
# endif
2020-09-24 00:43:27 -04:00
OutVM - > ClearExternalVariables ( ) ;
2021-07-29 14:29:52 -04:00
2020-09-24 00:43:27 -04:00
for ( const FRigVMExternalVariable & ExternalVariable : InExternalVariables )
{
FRigVMOperand Operand = OutVM - > AddExternalVariable ( ExternalVariable ) ;
FString Hash = FString : : Printf ( TEXT ( " Variable::%s " ) , * ExternalVariable . Name . ToString ( ) ) ;
OutOperands - > Add ( Hash , Operand ) ;
}
2022-03-31 14:40:13 -04:00
FRigVMCompilerWorkData WorkData ;
WorkData . AST = InAST ;
if ( ! WorkData . AST . IsValid ( ) )
2020-09-24 00:43:27 -04:00
{
2022-11-28 02:47:25 -05:00
WorkData . AST = MakeShareable ( new FRigVMParserAST ( InGraphs , InController , Settings . ASTSettings , InExternalVariables ) ) ;
2022-05-31 04:27:20 -04:00
for ( URigVMGraph * Graph : InGraphs )
{
Graph - > RuntimeAST = WorkData . AST ;
}
2021-01-12 06:47:41 -04:00
# if UE_BUILD_DEBUG
2020-09-24 00:43:27 -04:00
//UE_LOG(LogRigVMDeveloper, Display, TEXT("%s"), *AST->DumpDot());
2021-01-12 06:47:41 -04:00
# endif
2020-09-24 00:43:27 -04:00
}
2022-03-31 14:40:13 -04:00
ensure ( WorkData . AST . IsValid ( ) ) ;
2020-01-22 17:58:55 -05:00
WorkData . VM = OutVM ;
2022-11-28 02:47:25 -05:00
WorkData . ExecuteContextStruct = Settings . GetExecuteContextStruct ( ) ;
2020-01-22 17:58:55 -05:00
WorkData . PinPathToOperand = OutOperands ;
WorkData . bSetupMemory = true ;
2022-03-31 14:40:13 -04:00
WorkData . ProxySources = & WorkData . AST - > SharedOperandPins ;
2021-11-18 12:28:07 -05:00
// tbd: do we need this only when we have no pins?
//if(!WorkData.WatchedPins.IsEmpty())
{
// create the inverse map for the proxies
WorkData . ProxyTargets . Reserve ( WorkData . ProxySources - > Num ( ) ) ;
for ( const TPair < FRigVMASTProxy , FRigVMASTProxy > & Pair : * WorkData . ProxySources )
{
WorkData . ProxyTargets . FindOrAdd ( Pair . Value ) . Add ( Pair . Key ) ;
}
}
2020-09-24 00:43:27 -04:00
UE_LOG_RIGVMMEMORY ( TEXT ( " RigVMCompiler: Begin '%s'... " ) , * InGraph - > GetPathName ( ) ) ;
2020-01-22 17:58:55 -05:00
2022-10-24 08:59:51 -04:00
// If we are compiling a function, we want the first registers to represent the interface pins (in the order of the pins)
// so they can be replaced when inlining the function
if ( CurrentCompilationFunction )
2021-09-06 04:39:25 -04:00
{
2022-10-24 08:59:51 -04:00
URigVMFunctionEntryNode * EntryNode = CurrentCompilationFunction - > GetEntryNode ( ) ;
URigVMFunctionReturnNode * ReturnNode = CurrentCompilationFunction - > GetReturnNode ( ) ;
for ( URigVMPin * Pin : CurrentCompilationFunction - > GetPins ( ) )
2021-09-06 04:39:25 -04:00
{
2022-10-24 08:59:51 -04:00
URigVMPin * InterfacePin = nullptr ;
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input | |
Pin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
2022-01-13 22:49:09 -05:00
{
2022-11-10 04:36:01 -05:00
if ( EntryNode = = nullptr )
{
ReportError ( TEXT ( " Corrupt library node '%s' - Missing entry node. " ) ) ;
return false ;
}
2022-10-24 08:59:51 -04:00
InterfacePin = EntryNode - > FindPin ( Pin - > GetName ( ) ) ;
2022-01-13 22:49:09 -05:00
}
2022-10-24 08:59:51 -04:00
else
2021-09-07 06:09:01 -04:00
{
2022-11-10 04:36:01 -05:00
if ( ReturnNode = = nullptr )
{
ReportError ( TEXT ( " Corrupt library node '%s' - Missing return node. " ) ) ;
return false ;
}
2022-10-24 08:59:51 -04:00
InterfacePin = ReturnNode - > FindPin ( Pin - > GetName ( ) ) ;
2021-09-07 06:09:01 -04:00
}
2022-11-10 04:36:01 -05:00
if ( InterfacePin = = nullptr )
{
ReportError ( TEXT ( " Corrupt library node '%s' - Pin '%s' is not part of the entry / return node. " ) ) ;
return false ;
}
2022-10-24 08:59:51 -04:00
FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( InterfacePin ) ;
FRigVMVarExprAST * TempVarExpr = WorkData . AST - > MakeExpr < FRigVMVarExprAST > ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
FindOrAddRegister ( TempVarExpr , WorkData , false ) ;
2021-09-06 04:39:25 -04:00
}
}
2021-05-11 17:13:58 -04:00
2021-07-29 14:29:52 -04:00
if ( Settings . EnablePinWatches )
{
for ( int32 GraphIndex = 0 ; GraphIndex < VisitedGraphs . Num ( ) ; GraphIndex + + )
{
URigVMGraph * VisitedGraph = VisitedGraphs [ GraphIndex ] ;
for ( URigVMNode * ModelNode : VisitedGraph - > GetNodes ( ) )
{
for ( URigVMPin * ModelPin : ModelNode - > GetPins ( ) )
{
if ( ModelPin - > RequiresWatch ( true ) )
{
WorkData . WatchedPins . AddUnique ( ModelPin ) ;
}
}
}
}
}
2020-04-07 04:27:49 -04:00
WorkData . ExprComplete . Reset ( ) ;
2022-03-31 14:40:13 -04:00
for ( FRigVMExprAST * RootExpr : * WorkData . AST )
2020-04-07 04:27:49 -04:00
{
TraverseExpression ( RootExpr , WorkData ) ;
}
2021-07-29 14:29:52 -04:00
if ( WorkData . WatchedPins . Num ( ) > 0 )
{
for ( int32 GraphIndex = 0 ; GraphIndex < VisitedGraphs . Num ( ) ; GraphIndex + + )
{
URigVMGraph * VisitedGraph = VisitedGraphs [ GraphIndex ] ;
for ( URigVMNode * ModelNode : VisitedGraph - > GetNodes ( ) )
{
for ( URigVMPin * ModelPin : ModelNode - > GetPins ( ) )
{
if ( ModelPin - > GetDirection ( ) = = ERigVMPinDirection : : Input )
{
if ( ModelPin - > GetSourceLinks ( true ) . Num ( ) = = 0 )
{
continue ;
}
}
FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( ModelPin ) ;
FRigVMVarExprAST TempVarExpr ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
2022-03-31 14:40:13 -04:00
TempVarExpr . ParserPtr = WorkData . AST . Get ( ) ;
2021-07-29 14:29:52 -04:00
FindOrAddRegister ( & TempVarExpr , WorkData , true ) ;
}
}
}
}
2021-07-27 14:04:39 -04:00
// now that we have determined the needed memory, let's
// setup properties as needed as well as property paths
TArray < ERigVMMemoryType > MemoryTypes ;
MemoryTypes . Add ( ERigVMMemoryType : : Work ) ;
MemoryTypes . Add ( ERigVMMemoryType : : Literal ) ;
MemoryTypes . Add ( ERigVMMemoryType : : Debug ) ;
for ( ERigVMMemoryType MemoryType : MemoryTypes )
{
2022-05-31 04:27:20 -04:00
UPackage * Package = InGraphs [ 0 ] - > GetOutermost ( ) ;
2021-08-18 06:18:21 -04:00
2021-07-28 03:35:30 -04:00
TArray < FRigVMPropertyDescription > * Properties = WorkData . PropertyDescriptions . Find ( MemoryType ) ;
2021-07-27 14:04:39 -04:00
if ( Properties = = nullptr )
{
2021-08-18 06:18:21 -04:00
URigVMMemoryStorageGeneratorClass : : RemoveStorageClass ( Package , MemoryType ) ;
2021-07-27 14:04:39 -04:00
continue ;
}
2021-08-03 08:50:47 -04:00
URigVMMemoryStorageGeneratorClass : : CreateStorageClass ( Package , MemoryType , * Properties ) ;
2021-07-27 14:04:39 -04:00
}
2021-08-03 08:50:47 -04:00
WorkData . VM - > ClearMemory ( ) ;
2020-01-22 17:58:55 -05:00
WorkData . bSetupMemory = false ;
WorkData . ExprComplete . Reset ( ) ;
2022-03-31 14:40:13 -04:00
for ( FRigVMExprAST * RootExpr : * WorkData . AST )
2020-01-22 17:58:55 -05:00
{
TraverseExpression ( RootExpr , WorkData ) ;
}
2022-10-24 08:59:51 -04:00
if ( ! CurrentCompilationFunction )
2020-01-22 17:58:55 -05:00
{
2022-10-24 08:59:51 -04:00
if ( WorkData . VM - > GetByteCode ( ) . GetInstructions ( ) . Num ( ) = = 0 )
{
WorkData . VM - > GetByteCode ( ) . AddExitOp ( ) ;
}
WorkData . VM - > GetByteCode ( ) . AlignByteCode ( ) ;
2020-01-22 17:58:55 -05:00
}
2021-05-14 02:36:03 -04:00
// setup debug registers after all other registers have been created
if ( Settings . EnablePinWatches )
2021-04-29 05:02:50 -04:00
{
2021-07-29 14:29:52 -04:00
for ( URigVMPin * WatchedPin : WorkData . WatchedPins )
{
2022-03-31 14:40:13 -04:00
MarkDebugWatch ( true , WatchedPin , WorkData . VM , WorkData . PinPathToOperand , WorkData . AST ) ;
2021-07-29 14:29:52 -04:00
}
2021-04-29 05:02:50 -04:00
}
2021-07-29 14:29:52 -04:00
// now that we have determined the needed memory, let's
// update the property paths once more
for ( ERigVMMemoryType MemoryType : MemoryTypes )
{
const TArray < FRigVMPropertyPathDescription > * Descriptions = WorkData . PropertyPathDescriptions . Find ( MemoryType ) ;
if ( URigVMMemoryStorage * MemoryStorageObject = WorkData . VM - > GetMemoryByType ( MemoryType ) )
{
if ( URigVMMemoryStorageGeneratorClass * Class = Cast < URigVMMemoryStorageGeneratorClass > ( MemoryStorageObject - > GetClass ( ) ) )
{
if ( Descriptions )
{
Class - > PropertyPathDescriptions = * Descriptions ;
}
else
{
Class - > PropertyPathDescriptions . Reset ( ) ;
}
Class - > RefreshPropertyPaths ( ) ;
}
}
}
if ( const TArray < FRigVMPropertyPathDescription > * Descriptions = WorkData . PropertyPathDescriptions . Find ( ERigVMMemoryType : : External ) )
{
WorkData . VM - > ExternalPropertyPathDescriptions = * Descriptions ;
}
2022-10-24 08:59:51 -04:00
// Store function compile data
2022-11-16 03:33:17 -05:00
if ( CurrentCompilationFunction & & OutFunctionCompilationData )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
OutFunctionCompilationData - > ByteCode = WorkData . VM - > ByteCodeStorage ;
OutFunctionCompilationData - > FunctionNames = WorkData . VM - > FunctionNamesStorage ;
OutFunctionCompilationData - > Operands = * OutOperands ;
for ( uint8 MemoryTypeIndex = 0 ; MemoryTypeIndex < ( uint8 ) ERigVMMemoryType : : Invalid ; + + MemoryTypeIndex )
{
TArray < FRigVMFunctionCompilationPropertyDescription > * PropertyDescriptions = nullptr ;
TArray < FRigVMFunctionCompilationPropertyPath > * PropertyPathDescriptions = nullptr ;
ERigVMMemoryType MemoryType = ( ERigVMMemoryType ) MemoryTypeIndex ;
switch ( MemoryType )
{
case ERigVMMemoryType : : Work :
{
PropertyDescriptions = & OutFunctionCompilationData - > WorkPropertyDescriptions ;
PropertyPathDescriptions = & OutFunctionCompilationData - > WorkPropertyPathDescriptions ;
break ;
}
case ERigVMMemoryType : : Literal :
{
PropertyDescriptions = & OutFunctionCompilationData - > LiteralPropertyDescriptions ;
PropertyPathDescriptions = & OutFunctionCompilationData - > LiteralPropertyPathDescriptions ;
break ;
}
case ERigVMMemoryType : : External :
{
PropertyDescriptions = & OutFunctionCompilationData - > ExternalPropertyDescriptions ;
PropertyPathDescriptions = & OutFunctionCompilationData - > ExternalPropertyPathDescriptions ;
break ;
}
case ERigVMMemoryType : : Debug :
{
PropertyDescriptions = & OutFunctionCompilationData - > DebugPropertyDescriptions ;
PropertyPathDescriptions = & OutFunctionCompilationData - > DebugPropertyPathDescriptions ;
break ;
}
default :
{
checkNoEntry ( ) ;
}
}
PropertyDescriptions - > Reset ( ) ;
PropertyPathDescriptions - > Reset ( ) ;
if ( const TArray < FRigVMPropertyDescription > * Descriptions = WorkData . PropertyDescriptions . Find ( MemoryType ) )
{
PropertyDescriptions - > Reserve ( Descriptions - > Num ( ) ) ;
for ( const FRigVMPropertyDescription & Description : ( * Descriptions ) )
{
FRigVMFunctionCompilationPropertyDescription NewDescription ;
NewDescription . Name = Description . Name ;
NewDescription . CPPType = Description . CPPType ;
NewDescription . CPPTypeObject = Description . CPPTypeObject ;
NewDescription . DefaultValue = Description . DefaultValue ;
PropertyDescriptions - > Add ( NewDescription ) ;
}
}
if ( const TArray < FRigVMPropertyPathDescription > * PathDescriptions = WorkData . PropertyPathDescriptions . Find ( MemoryType ) )
{
PropertyPathDescriptions - > Reserve ( PathDescriptions - > Num ( ) ) ;
for ( const FRigVMPropertyPathDescription & Description : ( * PathDescriptions ) )
{
FRigVMFunctionCompilationPropertyPath NewDescription ;
NewDescription . PropertyIndex = Description . PropertyIndex ;
NewDescription . SegmentPath = Description . SegmentPath ;
NewDescription . HeadCPPType = Description . HeadCPPType ;
PropertyPathDescriptions - > Add ( NewDescription ) ;
}
}
}
2022-11-02 06:55:06 -04:00
// Only add used external registers to the function compilation data
2022-11-16 03:33:17 -05:00
FRigVMInstructionArray Instructions = OutFunctionCompilationData - > ByteCode . GetInstructions ( ) ;
2022-11-02 06:55:06 -04:00
TSet < int32 > UsedExternalVariableRegisters ;
for ( const FRigVMInstruction & Instruction : Instructions )
{
2022-11-16 03:33:17 -05:00
const FRigVMOperandArray OperandArray = OutFunctionCompilationData - > ByteCode . GetOperandsForOp ( Instruction ) ;
2022-11-02 06:55:06 -04:00
for ( const FRigVMOperand & Operand : OperandArray )
{
if ( Operand . GetMemoryType ( ) = = ERigVMMemoryType : : External )
{
UsedExternalVariableRegisters . Add ( Operand . GetRegisterIndex ( ) ) ;
}
}
}
2022-10-24 09:35:10 -04:00
for ( const TPair < FString , FRigVMOperand > & Pair : ( * WorkData . PinPathToOperand ) )
2022-10-24 08:59:51 -04:00
{
static const FString VariablePrefix = TEXT ( " Variable:: " ) ;
if ( Pair . Key . StartsWith ( VariablePrefix ) )
{
ensure ( Pair . Value . GetMemoryType ( ) = = ERigVMMemoryType : : External ) ;
2022-11-02 06:55:06 -04:00
if ( UsedExternalVariableRegisters . Contains ( Pair . Value . GetRegisterIndex ( ) ) )
{
FString VariableName = Pair . Key . RightChop ( VariablePrefix . Len ( ) ) ;
2022-11-16 03:33:17 -05:00
OutFunctionCompilationData - > ExternalRegisterIndexToVariable . Add ( Pair . Value . GetRegisterIndex ( ) , * VariableName ) ;
2022-11-02 06:55:06 -04:00
}
2022-10-24 08:59:51 -04:00
}
}
2023-03-03 12:54:30 -05:00
OutFunctionCompilationData - > Hash = GetTypeHash ( OutFunctionCompilationData ) ;
2022-10-24 08:59:51 -04:00
}
2022-11-16 03:33:17 -05:00
if ( ! CurrentCompilationFunction )
{
CompileTimer . Stop ( ) ;
ReportInfof ( TEXT ( " Total Compilation time %f \n " ) , CompilationTime * 1000 ) ;
}
2020-01-22 17:58:55 -05:00
return true ;
}
2022-11-16 03:33:17 -05:00
bool URigVMCompiler : : CompileFunction ( const URigVMLibraryNode * InLibraryNode , URigVMController * InController , FRigVMFunctionCompilationData * OutFunctionCompilationData )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
TGuardValue < const URigVMLibraryNode * > CompilationGuard ( CurrentCompilationFunction , InLibraryNode ) ;
2022-10-24 08:59:51 -04:00
FRigVMControllerGraphGuard ControllerGraphGuard ( InController , InLibraryNode - > GetContainedGraph ( ) , false ) ;
2022-11-16 03:33:17 -05:00
double CompilationTime = 0 ;
FDurationTimer CompileTimer ( CompilationTime ) ;
if ( OutFunctionCompilationData = = nullptr )
{
return false ;
}
2023-03-03 12:54:30 -05:00
OutFunctionCompilationData - > Hash = 0 ;
2022-11-16 03:33:17 -05:00
OutFunctionCompilationData - > ByteCode . Reset ( ) ;
2022-10-24 08:59:51 -04:00
TArray < FRigVMExternalVariable > ExternalVariables ;
if ( InController - > GetExternalVariablesDelegate . IsBound ( ) )
{
ExternalVariables = InController - > GetExternalVariablesDelegate . Execute ( InLibraryNode - > GetContainedGraph ( ) ) ;
}
TMap < FString , FRigVMOperand > Operands ;
2022-11-16 03:33:17 -05:00
2022-10-24 08:59:51 -04:00
URigVM * TempVM = NewObject < URigVM > ( InLibraryNode - > GetContainedGraph ( ) ) ;
2022-11-28 02:47:25 -05:00
const bool bSuccess = Compile ( { InLibraryNode - > GetContainedGraph ( ) } , InController , TempVM , ExternalVariables , & Operands , nullptr , OutFunctionCompilationData ) ;
2022-10-24 20:34:56 -04:00
TempVM - > ClearMemory ( ) ;
2022-10-24 08:59:51 -04:00
TempVM - > Rename ( nullptr , GetTransientPackage ( ) , REN_ForceNoResetLoaders | REN_DoNotDirty | REN_DontCreateRedirectors | REN_NonTransactional ) ;
TempVM - > MarkAsGarbage ( ) ;
2022-11-16 03:33:17 -05:00
CompileTimer . Stop ( ) ;
ReportInfof ( TEXT ( " Compiled Function %s in %fms " ) , * InLibraryNode - > GetName ( ) , CompilationTime * 1000 ) ;
2022-10-24 08:59:51 -04:00
2022-11-16 03:33:17 -05:00
// Update the compilation data of this library, and the hashes of the compilation data of its dependencies used for this compilation
if ( IRigVMClientHost * ClientHost = InLibraryNode - > GetImplementingOuter < IRigVMClientHost > ( ) )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
if ( IRigVMGraphFunctionHost * FunctionHost = ClientHost - > GetRigVMGraphFunctionHost ( ) )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
if ( FRigVMGraphFunctionStore * Store = FunctionHost - > GetRigVMGraphFunctionStore ( ) )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
if ( FRigVMGraphFunctionData * Data = Store - > FindFunction ( InLibraryNode - > GetFunctionIdentifier ( ) ) )
{
for ( TPair < FRigVMGraphFunctionIdentifier , uint32 > & Pair : Data - > Header . Dependencies )
{
2023-01-04 05:53:56 -05:00
if ( IRigVMGraphFunctionHost * ReferencedFunctionHost = Cast < IRigVMGraphFunctionHost > ( Pair . Key . HostObject . ResolveObject ( ) ) )
2022-11-16 03:33:17 -05:00
{
2023-01-04 05:53:56 -05:00
if ( FRigVMGraphFunctionData * ReferencedData = ReferencedFunctionHost - > GetRigVMGraphFunctionStore ( ) - > FindFunction ( Pair . Key ) )
{
Pair . Value = ReferencedData - > CompilationData . Hash ;
}
2022-11-16 03:33:17 -05:00
}
}
2023-03-03 12:54:30 -05:00
ClientHost - > GetRigVMClient ( ) - > UpdateFunctionReferences ( Data - > Header , true , false ) ;
2022-11-16 03:33:17 -05:00
}
Store - > UpdateFunctionCompilationData ( InLibraryNode - > GetFunctionIdentifier ( ) , * OutFunctionCompilationData ) ;
2022-10-24 08:59:51 -04:00
}
}
}
2022-11-16 03:33:17 -05:00
return bSuccess ;
2022-10-24 08:59:51 -04:00
}
2020-01-22 17:58:55 -05:00
void URigVMCompiler : : TraverseExpression ( const FRigVMExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
2020-09-24 00:43:27 -04:00
if ( WorkData . ExprToSkip . Contains ( InExpr ) )
{
return ;
}
2020-01-22 17:58:55 -05:00
if ( WorkData . ExprComplete . Contains ( InExpr ) )
{
return ;
}
WorkData . ExprComplete . Add ( InExpr , true ) ;
switch ( InExpr - > GetType ( ) )
{
case FRigVMExprAST : : EType : : Block :
{
TraverseBlock ( InExpr - > To < FRigVMBlockExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Entry :
{
TraverseEntry ( InExpr - > To < FRigVMEntryExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : CallExtern :
{
2020-09-24 00:43:27 -04:00
const FRigVMCallExternExprAST * CallExternExpr = InExpr - > To < FRigVMCallExternExprAST > ( ) ;
TraverseCallExtern ( CallExternExpr , WorkData ) ;
2020-01-22 17:58:55 -05:00
break ;
}
2022-10-24 08:59:51 -04:00
case FRigVMExprAST : : EType : : InlineFunction :
{
const FRigVMInlineFunctionExprAST * InlineExpr = InExpr - > To < FRigVMInlineFunctionExprAST > ( ) ;
TraverseInlineFunction ( InlineExpr , WorkData ) ;
break ;
}
2020-01-22 17:58:55 -05:00
case FRigVMExprAST : : EType : : NoOp :
{
TraverseNoOp ( InExpr - > To < FRigVMNoOpExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Var :
{
TraverseVar ( InExpr - > To < FRigVMVarExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Literal :
{
TraverseLiteral ( InExpr - > To < FRigVMLiteralExprAST > ( ) , WorkData ) ;
break ;
}
2020-10-26 06:51:31 -04:00
case FRigVMExprAST : : EType : : ExternalVar :
{
TraverseExternalVar ( InExpr - > To < FRigVMExternalVarExprAST > ( ) , WorkData ) ;
break ;
}
2020-01-22 17:58:55 -05:00
case FRigVMExprAST : : EType : : Assign :
{
TraverseAssign ( InExpr - > To < FRigVMAssignExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Copy :
{
TraverseCopy ( InExpr - > To < FRigVMCopyExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : CachedValue :
{
TraverseCachedValue ( InExpr - > To < FRigVMCachedValueExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Exit :
{
TraverseExit ( InExpr - > To < FRigVMExitExprAST > ( ) , WorkData ) ;
break ;
}
2022-06-01 05:56:08 -04:00
case FRigVMExprAST : : EType : : InvokeEntry :
{
TraverseInvokeEntry ( InExpr - > To < FRigVMInvokeEntryExprAST > ( ) , WorkData ) ;
break ;
}
2020-01-22 17:58:55 -05:00
default :
{
ensure ( false ) ;
break ;
}
}
}
void URigVMCompiler : : TraverseChildren ( const FRigVMExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
for ( FRigVMExprAST * ChildExpr : * InExpr )
{
TraverseExpression ( ChildExpr , WorkData ) ;
}
}
void URigVMCompiler : : TraverseBlock ( const FRigVMBlockExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
2020-09-24 00:43:27 -04:00
if ( InExpr - > IsObsolete ( ) )
2020-01-22 17:58:55 -05:00
{
return ;
}
2022-11-16 11:45:34 -05:00
if ( InExpr - > NumChildren ( ) = = 0 )
{
return ;
}
// check if the block is under a lazy pin, in which case we need to set up a branch info
URigVMNode * CallExternNode = nullptr ;
FRigVMBranchInfo BranchInfo ;
if ( ! WorkData . bSetupMemory )
{
if ( const FRigVMExprAST * ParentExpr = InExpr - > GetParent ( ) )
{
if ( const FRigVMExprAST * GrandParentExpr = ParentExpr - > GetParent ( ) )
{
if ( GrandParentExpr - > IsA ( FRigVMExprAST : : CallExtern ) )
{
const URigVMPin * Pin = nullptr ;
if ( ParentExpr - > IsA ( FRigVMExprAST : : Var ) )
{
Pin = ParentExpr - > To < FRigVMVarExprAST > ( ) - > GetPin ( ) ;
}
else if ( ParentExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
Pin = ParentExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) - > GetPin ( ) ;
}
if ( Pin )
{
2022-11-30 04:26:41 -05:00
URigVMPin * RootPin = Pin - > GetRootPin ( ) ;
if ( RootPin - > IsLazy ( ) )
2022-11-16 11:45:34 -05:00
{
2022-11-30 04:26:41 -05:00
CallExternNode = RootPin - > GetNode ( ) ;
2022-11-16 11:45:34 -05:00
2022-11-30 04:26:41 -05:00
if ( RootPin - > IsFixedSizeArray ( ) & & Pin - > GetParentPin ( ) = = RootPin )
{
BranchInfo . Label = FRigVMBranchInfo : : GetFixedArrayLabel ( RootPin - > GetFName ( ) , Pin - > GetFName ( ) ) ;
}
else
{
BranchInfo . Label = RootPin - > GetFName ( ) ;
}
2022-11-16 11:45:34 -05:00
BranchInfo . InstructionIndex = INDEX_NONE ; // we'll fill in the instruction info later
BranchInfo . FirstInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
// find the argument index for the given pin
if ( const URigVMTemplateNode * TemplateNode = Cast < URigVMTemplateNode > ( CallExternNode ) )
{
if ( const FRigVMTemplate * Template = TemplateNode - > GetTemplate ( ) )
{
2022-11-30 04:26:41 -05:00
int32 FlatArgumentIndex = 0 ;
2022-11-16 11:45:34 -05:00
for ( int32 ArgumentIndex = 0 ; ArgumentIndex ! = Template - > NumArguments ( ) ; ArgumentIndex + + )
{
const FRigVMTemplateArgument * Argument = Template - > GetArgument ( ArgumentIndex ) ;
2022-11-30 04:26:41 -05:00
if ( Template - > GetArgument ( ArgumentIndex ) - > GetName ( ) = = RootPin - > GetFName ( ) )
2022-11-16 11:45:34 -05:00
{
2022-11-30 04:26:41 -05:00
BranchInfo . ArgumentIndex = FlatArgumentIndex ;
if ( RootPin - > IsFixedSizeArray ( ) & & Pin - > GetParentPin ( ) = = RootPin )
{
BranchInfo . ArgumentIndex + = Pin - > GetPinIndex ( ) ;
}
2022-11-16 11:45:34 -05:00
break ;
}
2022-11-30 04:26:41 -05:00
if ( const URigVMPin * PinForArgument = RootPin - > GetNode ( ) - > FindPin ( Argument - > Name . ToString ( ) ) )
{
if ( PinForArgument - > IsFixedSizeArray ( ) )
{
FlatArgumentIndex + = RootPin - > GetSubPins ( ) . Num ( ) ;
continue ;
}
}
FlatArgumentIndex + + ;
2022-11-16 11:45:34 -05:00
}
}
// we also need to deal with unit nodes separately here. if a unit node does
// not offer a valid backing template - we need to visit its properties. since
// templates don't contain executecontext type arguments anymore - we need
// to step over them as well here.
else if ( const URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( CallExternNode ) )
{
2022-11-18 09:02:06 -05:00
if ( const FRigVMFunction * Function = UnitNode - > GetResolvedFunction ( ) )
2022-11-16 11:45:34 -05:00
{
2022-11-18 09:02:06 -05:00
for ( int32 ArgumentIndex = 0 ; ArgumentIndex ! = Function - > Arguments . Num ( ) ; ArgumentIndex + + )
2022-11-16 11:45:34 -05:00
{
2022-11-18 09:02:06 -05:00
const FRigVMFunctionArgument & Argument = Function - > Arguments [ ArgumentIndex ] ;
2022-11-30 04:26:41 -05:00
if ( Argument . Name = = RootPin - > GetFName ( ) )
2022-11-18 09:02:06 -05:00
{
BranchInfo . ArgumentIndex = ArgumentIndex ;
break ;
}
2022-11-16 11:45:34 -05:00
}
}
}
}
check ( BranchInfo . ArgumentIndex ! = INDEX_NONE ) ;
}
}
}
}
}
}
2020-01-22 17:58:55 -05:00
TraverseChildren ( InExpr , WorkData ) ;
2022-11-16 11:45:34 -05:00
if ( ! BranchInfo . Label . IsNone ( ) )
{
BranchInfo . LastInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
WorkData . BranchInfos . FindOrAdd ( CallExternNode ) . Add ( BranchInfo ) ;
}
2020-01-22 17:58:55 -05:00
}
void URigVMCompiler : : TraverseEntry ( const FRigVMEntryExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
2022-11-01 11:47:34 -04:00
if ( URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( InExpr - > GetNode ( ) ) )
2021-09-08 07:57:30 -04:00
{
2022-11-01 11:47:34 -04:00
if ( ! ValidateNode ( UnitNode ) )
2020-01-22 17:58:55 -05:00
{
2022-11-01 11:47:34 -04:00
return ;
2020-01-22 17:58:55 -05:00
}
2022-11-01 11:47:34 -04:00
if ( WorkData . bSetupMemory )
{
TSharedPtr < FStructOnScope > DefaultStruct = UnitNode - > ConstructStructInstance ( ) ;
TraverseChildren ( InExpr , WorkData ) ;
}
else
{
TArray < FRigVMOperand > Operands ;
for ( FRigVMExprAST * ChildExpr : * InExpr )
{
if ( ChildExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
2022-11-10 04:36:01 -05:00
const FRigVMVarExprAST * SourceVarExpr = GetSourceVarExpr ( ChildExpr ) ;
if ( ! SourceVarExpr - > IsExecuteContext ( ) )
{
Operands . Add ( WorkData . ExprToOperand . FindChecked ( SourceVarExpr ) ) ;
}
2022-11-01 11:47:34 -04:00
}
else
{
break ;
}
}
// setup the instruction
int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( UnitNode - > GetScriptStruct ( ) , UnitNode - > GetMethodName ( ) ) ;
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , Operands ) ;
2020-09-24 00:43:27 -04:00
2022-11-01 11:47:34 -04:00
int32 EntryInstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
FName Entryname = UnitNode - > GetEventName ( ) ;
2020-09-24 00:43:27 -04:00
2022-11-01 11:47:34 -04:00
if ( WorkData . VM - > GetByteCode ( ) . FindEntryIndex ( Entryname ) = = INDEX_NONE )
{
FRigVMByteCodeEntry Entry ;
Entry . Name = Entryname ;
Entry . InstructionIndex = EntryInstructionIndex ;
WorkData . VM - > GetByteCode ( ) . Entries . Add ( Entry ) ;
}
if ( Settings . SetupNodeInstructionIndex )
{
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( EntryInstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
2020-09-24 00:43:27 -04:00
}
2020-01-22 17:58:55 -05:00
}
2022-11-01 11:47:34 -04:00
else if ( CurrentCompilationFunction & & InExpr - > NumParents ( ) = = 0 )
{
// Initialize local variables
if ( WorkData . bSetupMemory )
{
TArray < FRigVMGraphVariableDescription > LocalVariables = CurrentCompilationFunction - > GetContainedGraph ( ) - > GetLocalVariables ( ) ;
for ( const FRigVMGraphVariableDescription & Variable : LocalVariables )
{
FString Path = FString : : Printf ( TEXT ( " LocalVariableDefault::%s|%s::Const " ) , * CurrentCompilationFunction - > GetContainedGraph ( ) - > GetGraphName ( ) , * Variable . Name . ToString ( ) ) ;
FRigVMOperand Operand = WorkData . AddProperty ( ERigVMMemoryType : : Literal , * Path , Variable . CPPType , Variable . CPPTypeObject , Variable . DefaultValue ) ;
WorkData . PinPathToOperand - > Add ( Path , Operand ) ;
}
}
else
{
TArray < FRigVMGraphVariableDescription > LocalVariables = CurrentCompilationFunction - > GetContainedGraph ( ) - > GetLocalVariables ( ) ;
for ( const FRigVMGraphVariableDescription & Variable : LocalVariables )
{
FString TargetPath = FString : : Printf ( TEXT ( " LocalVariable::%s|%s " ) , * CurrentCompilationFunction - > GetContainedGraph ( ) - > GetGraphName ( ) , * Variable . Name . ToString ( ) ) ;
FString SourcePath = FString : : Printf ( TEXT ( " LocalVariableDefault::%s|%s::Const " ) , * CurrentCompilationFunction - > GetContainedGraph ( ) - > GetGraphName ( ) , * Variable . Name . ToString ( ) ) ;
FRigVMOperand * TargetPtr = WorkData . PinPathToOperand - > Find ( TargetPath ) ;
FRigVMOperand * SourcePtr = WorkData . PinPathToOperand - > Find ( SourcePath ) ;
if ( SourcePtr & & TargetPtr )
{
const FRigVMOperand & Source = * SourcePtr ;
const FRigVMOperand & Target = * TargetPtr ;
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( WorkData . VM - > GetCopyOpForOperands ( Source , Target ) ) ;
}
}
}
}
TraverseChildren ( InExpr , WorkData ) ;
2020-01-22 17:58:55 -05:00
}
2020-09-24 00:43:27 -04:00
int32 URigVMCompiler : : TraverseCallExtern ( const FRigVMCallExternExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
2020-01-22 17:58:55 -05:00
{
2022-07-05 11:39:15 -04:00
URigVMNode * Node = InExpr - > GetNode ( ) ;
URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( Node ) ;
URigVMDispatchNode * DispatchNode = Cast < URigVMDispatchNode > ( Node ) ;
if ( ! ValidateNode ( UnitNode , false ) & & ! ValidateNode ( DispatchNode , false ) )
2021-09-08 07:57:30 -04:00
{
return INDEX_NONE ;
}
2020-01-22 17:58:55 -05:00
2022-08-11 06:58:29 -04:00
auto CheckExecuteStruct = [ this , & WorkData ] ( URigVMNode * Subject , const UScriptStruct * ExecuteStruct ) - > bool
{
if ( ExecuteStruct - > IsChildOf ( FRigVMExecuteContext : : StaticStruct ( ) ) )
{
// top level expected execute struct is provided by the graph
const UScriptStruct * SpecializedExecuteStruct = WorkData . ExecuteContextStruct ;
if ( ! SpecializedExecuteStruct - > IsChildOf ( ExecuteStruct ) )
{
static constexpr TCHAR UnknownExecuteContextMessage [ ] = TEXT ( " Node @@ uses an unexpected execute type '%s'. This graph uses '%s'. " ) ;
Settings . Report ( EMessageSeverity : : Error , Subject , FString : : Printf (
UnknownExecuteContextMessage , * ExecuteStruct - > GetStructCPPName ( ) , * SpecializedExecuteStruct - > GetStructCPPName ( ) ) ) ;
return false ;
}
}
return true ;
} ;
2022-07-05 11:39:15 -04:00
if ( UnitNode )
2022-03-31 14:40:13 -04:00
{
2022-08-11 06:58:29 -04:00
const UScriptStruct * ScriptStruct = UnitNode - > GetScriptStruct ( ) ;
if ( ScriptStruct = = nullptr )
2022-07-05 11:39:15 -04:00
{
2022-08-22 21:21:49 -04:00
static const FString UnresolvedMessage = TEXT ( " Node @@ is unresolved. " ) ;
Settings . Report ( EMessageSeverity : : Error , UnitNode , UnresolvedMessage ) ;
2022-07-05 11:39:15 -04:00
return INDEX_NONE ;
}
2022-08-11 06:58:29 -04:00
// check execute pins for compatibility
for ( TFieldIterator < FProperty > It ( ScriptStruct ) ; It ; + + It )
{
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( * It ) )
{
if ( ! CheckExecuteStruct ( UnitNode , StructProperty - > Struct ) )
{
return INDEX_NONE ;
}
}
}
2022-07-05 11:39:15 -04:00
}
if ( DispatchNode )
{
if ( DispatchNode - > GetFactory ( ) = = nullptr )
{
2022-08-22 21:21:49 -04:00
static const FString UnresolvedDispatchMessage = TEXT ( " Dispatch node @@ has no factory. " ) ;
Settings . Report ( EMessageSeverity : : Error , DispatchNode , UnresolvedDispatchMessage ) ;
2022-07-05 11:39:15 -04:00
return INDEX_NONE ;
}
2022-08-11 06:58:29 -04:00
// check execute pins for compatibility
if ( ! CheckExecuteStruct ( DispatchNode , DispatchNode - > GetFactory ( ) - > GetExecuteContextStruct ( ) ) )
{
return INDEX_NONE ;
}
2022-03-31 14:40:13 -04:00
}
2022-11-18 06:25:07 -05:00
int32 CallExternInstructionIndex = INDEX_NONE ;
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2020-09-24 00:43:27 -04:00
2020-01-22 17:58:55 -05:00
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
}
else
{
TArray < FRigVMOperand > Operands ;
2022-06-10 03:42:15 -04:00
// iterate over the child expressions in the order of the arguments on the function
2022-07-05 11:39:15 -04:00
const FRigVMFunction * Function = nullptr ;
if ( UnitNode )
{
Function = FRigVMRegistry : : Get ( ) . FindFunction ( UnitNode - > GetScriptStruct ( ) , * UnitNode - > GetMethodName ( ) . ToString ( ) ) ;
}
else if ( DispatchNode )
{
Function = DispatchNode - > GetResolvedFunction ( ) ;
}
2022-06-10 03:42:15 -04:00
check ( Function ) ;
2022-11-18 06:25:07 -05:00
FRigVMOperand CountOperand ;
FRigVMOperand IndexOperand ;
FRigVMOperand BlockToRunOperand ;
2022-06-10 03:42:15 -04:00
for ( const FRigVMFunctionArgument & Argument : Function - > GetArguments ( ) )
2020-01-22 17:58:55 -05:00
{
2022-11-28 10:01:18 -05:00
auto ProcessArgument = [
& WorkData ,
Argument ,
& Operands ,
& BlockToRunOperand ,
& CountOperand ,
& IndexOperand
] ( const FRigVMExprAST * InExpr )
2022-06-10 03:42:15 -04:00
{
2022-11-28 10:01:18 -05:00
if ( InExpr - > GetType ( ) = = FRigVMExprAST : : EType : : CachedValue )
{
Operands . Add ( WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ) ) ) ;
}
else if ( InExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
Operands . Add ( WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > To < FRigVMVarExprAST > ( ) ) ) ) ;
}
else
{
return ;
}
if ( Argument . Name = = FRigVMStruct : : ControlFlowBlockToRunName )
{
BlockToRunOperand = Operands . Last ( ) ;
}
else if ( Argument . Name = = FRigVMStruct : : ControlFlowCountName )
{
CountOperand = Operands . Last ( ) ;
}
else if ( Argument . Name = = FRigVMStruct : : ControlFlowIndexName )
{
IndexOperand = Operands . Last ( ) ;
}
} ;
if ( URigVMPin * Pin = InExpr - > GetNode ( ) - > FindPin ( Argument . Name ) )
{
if ( Pin - > IsFixedSizeArray ( ) )
{
for ( URigVMPin * SubPin : Pin - > GetSubPins ( ) )
{
2022-11-30 04:26:41 -05:00
const FString PinName = FRigVMBranchInfo : : GetFixedArrayLabel ( Pin - > GetName ( ) , SubPin - > GetName ( ) ) ;
2022-11-28 10:01:18 -05:00
const FRigVMExprAST * SubPinExpr = InExpr - > FindExprWithPinName ( * PinName ) ;
check ( SubPinExpr ) ;
ProcessArgument ( SubPinExpr ) ;
}
continue ;
}
2022-06-10 03:42:15 -04:00
}
2022-11-28 10:01:18 -05:00
const FRigVMExprAST * ChildExpr = InExpr - > FindExprWithPinName ( Argument . Name ) ;
check ( ChildExpr ) ;
ProcessArgument ( ChildExpr ) ;
2022-11-18 06:25:07 -05:00
}
// make sure to skip the output blocks while we are traversing this call extern
TArray < const FRigVMExprAST * > ExpressionsToSkip ;
TArray < int32 > BranchIndices ;
if ( Node - > IsControlFlowNode ( ) )
{
const TArray < FName > & BlockNames = Node - > GetControlFlowBlocks ( ) ;
BranchIndices . Reserve ( BlockNames . Num ( ) ) ;
for ( const FName & BlockName : BlockNames )
{
const FRigVMVarExprAST * BlockExpr = InExpr - > FindVarWithPinName ( BlockName ) ;
check ( BlockExpr ) ;
WorkData . ExprToSkip . AddUnique ( BlockExpr ) ;
BranchIndices . Add ( WorkData . VM - > GetByteCode ( ) . AddBranchInfo ( FRigVMBranchInfo ( ) ) ) ;
}
2020-01-22 17:58:55 -05:00
}
2022-11-16 11:45:34 -05:00
// traverse all non-lazy children
TArray < const FRigVMExprAST * > LazyChildExprs ;
for ( const FRigVMExprAST * ChildExpr : * InExpr )
{
// if there's a direct child block under this - the pin may be lazy
if ( ChildExpr - > IsA ( FRigVMExprAST : : Var ) | | ChildExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
if ( const FRigVMExprAST * BlockExpr = ChildExpr - > GetFirstChildOfType ( FRigVMExprAST : : Block ) )
{
if ( BlockExpr - > GetParent ( ) = = ChildExpr )
{
URigVMPin * Pin = nullptr ;
if ( ChildExpr - > IsA ( FRigVMExprAST : : Var ) )
{
Pin = ChildExpr - > To < FRigVMVarExprAST > ( ) - > GetPin ( ) ;
}
else
{
Pin = ChildExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) - > GetPin ( ) ;
}
check ( Pin ) ;
if ( Pin - > IsLazy ( ) )
{
LazyChildExprs . Add ( ChildExpr ) ;
continue ;
}
}
}
}
TraverseExpression ( ChildExpr , WorkData ) ;
}
if ( ! LazyChildExprs . IsEmpty ( ) )
{
// set up an operator to skip the lazy branches
const uint64 JumpToCallExternByte = WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpForward , INDEX_NONE ) ;
const int32 JumpToCallExternInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
// traverse the lazy children
for ( const FRigVMExprAST * ChildExpr : LazyChildExprs )
{
TraverseExpression ( ChildExpr , WorkData ) ;
}
// update the operator with the target instruction
const int32 InstructionsToJump = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToCallExternInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpOp > ( JumpToCallExternByte ) . InstructionIndex = InstructionsToJump ;
}
2020-01-22 17:58:55 -05:00
2022-11-18 06:25:07 -05:00
if ( Node - > IsControlFlowNode ( ) )
{
check ( BlockToRunOperand . IsValid ( ) ) ;
WorkData . VM - > GetByteCode ( ) . AddZeroOp ( BlockToRunOperand ) ;
}
2020-01-22 17:58:55 -05:00
// setup the instruction
2022-07-05 11:39:15 -04:00
const int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( Function - > GetName ( ) ) ;
check ( FunctionIndex ! = INDEX_NONE ) ;
2020-09-24 00:43:27 -04:00
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , Operands ) ;
2022-11-18 06:25:07 -05:00
CallExternInstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-10-12 21:21:22 -04:00
2022-11-16 11:45:34 -05:00
// setup the branch infos for this call extern instruction
if ( const TArray < FRigVMBranchInfo > * BranchInfosPtr = WorkData . BranchInfos . Find ( Node ) )
{
const TArray < FRigVMBranchInfo > & BranchInfos = * BranchInfosPtr ;
for ( FRigVMBranchInfo BranchInfo : BranchInfos )
{
2022-11-18 06:25:07 -05:00
BranchInfo . InstructionIndex = CallExternInstructionIndex ;
( void ) WorkData . VM - > GetByteCode ( ) . AddBranchInfo ( BranchInfo ) ;
2022-11-16 11:45:34 -05:00
}
}
2021-10-12 21:21:22 -04:00
# if WITH_EDITORONLY_DATA
TArray < FRigVMOperand > InputsOperands , OutputOperands ;
2022-07-05 11:39:15 -04:00
for ( const URigVMPin * InputPin : Node - > GetPins ( ) )
2021-10-12 21:21:22 -04:00
{
if ( InputPin - > IsExecuteContext ( ) )
{
continue ;
}
2022-11-10 04:36:01 -05:00
int32 OperandIndex = Function - > Arguments . IndexOfByPredicate ( [ InputPin ] ( const FRigVMFunctionArgument & FunctionArgument ) - > bool
{
return FunctionArgument . Name = = InputPin - > GetName ( ) ;
} ) ;
if ( ! Operands . IsValidIndex ( OperandIndex ) )
{
continue ;
}
const FRigVMOperand & Operand = Operands [ OperandIndex ] ;
2021-10-12 21:21:22 -04:00
if ( InputPin - > GetDirection ( ) = = ERigVMPinDirection : : Output | | InputPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
OutputOperands . Add ( Operand ) ;
}
if ( InputPin - > GetDirection ( ) ! = ERigVMPinDirection : : Input & & InputPin - > GetDirection ( ) ! = ERigVMPinDirection : : IO )
{
continue ;
}
InputsOperands . Add ( Operand ) ;
}
WorkData . VM - > GetByteCode ( ) . SetOperandsForInstruction (
2022-11-18 06:25:07 -05:00
CallExternInstructionIndex ,
2021-10-12 21:21:22 -04:00
FRigVMOperandArray ( InputsOperands . GetData ( ) , InputsOperands . Num ( ) ) ,
FRigVMOperandArray ( OutputOperands . GetData ( ) , OutputOperands . Num ( ) ) ) ;
# endif
2020-09-24 00:43:27 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2022-11-18 06:25:07 -05:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( CallExternInstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
if ( Node - > IsControlFlowNode ( ) )
{
// add an operator to jump to the right branch
const int32 JumpToBranchInstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
// use the index of the first branch info relating to this control flow node.
// branches are stored on the bytecode in order for each control flow node - so the
// VM needs to know which branch to start to look at then evaluating the JumpToBranchOp.
// Branches are stored in order - similar to this example representing two JumpBranchOps
// with BranchIndices [0, 1] and [2, 3]
// [
// 0 = {ExecuteContext, InstructionIndex 2, First 3, Last 5},
// 1 = {Completed, InstructionIndex 2, First 6, Last 12},
// 2 = {ExecuteContext, InstructionIndex 17, First 18, Last 21},
// 3 = {Completed, InstructionIndex 17, First 22, Last 28},
// ]
// The first index of the branch in the overall list of branches is stored in the operator (BranchIndices[0])
WorkData . VM - > GetByteCode ( ) . AddJumpToBranchOp ( BlockToRunOperand , BranchIndices [ 0 ] ) ;
2023-01-09 04:47:30 -05:00
// create a copy here for ensure memory validity
TArray < FName > BlockNames = Node - > GetControlFlowBlocks ( ) ;
2022-11-18 06:25:07 -05:00
// traverse all of the blocks now
for ( int32 BlockIndex = 0 ; BlockIndex < BlockNames . Num ( ) ; BlockIndex + + )
{
2023-01-09 04:47:30 -05:00
const FName BlockName = BlockNames [ BlockIndex ] ;
2022-12-05 06:45:16 -05:00
int32 BranchIndex = BranchIndices [ BlockIndex ] ;
{
FRigVMBranchInfo & BranchInfo = WorkData . VM - > GetByteCode ( ) . BranchInfos [ BranchIndex ] ;
BranchInfo . Label = BlockName ;
BranchInfo . InstructionIndex = JumpToBranchInstructionIndex ;
BranchInfo . FirstInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
// BranchInfo can be invalidated by ByteCode array reallocs in the code below, so do not keep a reference to it
}
2022-11-18 06:25:07 -05:00
// check if the block requires slicing or not.
// (do we want the private state of the nodes to be unique per run of the block)
if ( Node - > IsControlFlowBlockSliced ( BlockName ) )
{
check ( BlockName ! = FRigVMStruct : : ControlFlowCompletedName ) ;
check ( CountOperand . IsValid ( ) ) ;
check ( IndexOperand . IsValid ( ) ) ;
WorkData . VM - > GetByteCode ( ) . AddBeginBlockOp ( CountOperand , IndexOperand ) ;
}
// traverse the body of the block
const FRigVMVarExprAST * BlockExpr = InExpr - > FindVarWithPinName ( BlockName ) ;
check ( BlockExpr ) ;
WorkData . ExprToSkip . Remove ( BlockExpr ) ;
TraverseExpression ( BlockExpr , WorkData ) ;
// end the block if necessary
if ( Node - > IsControlFlowBlockSliced ( BlockName ) )
{
WorkData . VM - > GetByteCode ( ) . AddEndBlockOp ( ) ;
}
// if this is not the completed block - we need to jump back to the control flow instruction
if ( BlockName ! = FRigVMStruct : : ControlFlowCompletedName )
{
const int32 JumpToCallExternInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpBackward , JumpToCallExternInstruction - CallExternInstructionIndex ) ;
}
2022-12-05 06:45:16 -05:00
WorkData . VM - > GetByteCode ( ) . BranchInfos [ BranchIndex ] . LastInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2022-11-18 06:25:07 -05:00
}
2020-09-24 00:43:27 -04:00
}
2020-01-22 17:58:55 -05:00
}
2020-09-24 00:43:27 -04:00
2022-11-18 06:25:07 -05:00
return CallExternInstructionIndex ;
2020-09-24 00:43:27 -04:00
}
2022-10-24 08:59:51 -04:00
int32 URigVMCompiler : : TraverseInlineFunction ( const FRigVMInlineFunctionExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
URigVMNode * Node = InExpr - > GetNode ( ) ;
URigVMFunctionReferenceNode * FunctionReferenceNode = Cast < URigVMFunctionReferenceNode > ( Node ) ;
if ( ! ValidateNode ( FunctionReferenceNode , false ) )
{
return INDEX_NONE ;
}
int32 InstructionIndexStart = INDEX_NONE ;
int32 InstructionIndexEnd = INDEX_NONE ;
2022-11-21 07:52:44 -05:00
int32 BranchIndexStart = INDEX_NONE ;
2022-11-16 03:33:17 -05:00
FString FunctionHash = FunctionReferenceNode - > GetReferencedFunctionHeader ( ) . GetHash ( ) ;
if ( ! CompiledFunctions . Contains ( FunctionHash ) )
2022-10-24 08:59:51 -04:00
{
return INDEX_NONE ;
}
2022-11-16 03:33:17 -05:00
const FRigVMFunctionCompilationData * FunctionCompilationData = CompiledFunctions . FindChecked ( FunctionHash ) ;
const FRigVMByteCode & FunctionByteCode = FunctionCompilationData - > ByteCode ;
2022-10-24 08:59:51 -04:00
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
// Add internal operands (not the ones represented by interface pins)
2022-11-16 03:33:17 -05:00
for ( uint8 MemoryIndex = 0 ; MemoryIndex < ( uint8 ) ERigVMMemoryType : : Invalid ; + + MemoryIndex )
2022-10-24 08:59:51 -04:00
{
2022-11-16 03:33:17 -05:00
ERigVMMemoryType MemoryType = ( ERigVMMemoryType ) MemoryIndex ;
TArray < FRigVMFunctionCompilationPropertyDescription > Properties ;
switch ( MemoryType )
2022-11-10 04:36:01 -05:00
{
2022-11-16 03:33:17 -05:00
case ERigVMMemoryType : : Work :
{
Properties = FunctionCompilationData - > WorkPropertyDescriptions ;
break ;
}
case ERigVMMemoryType : : Literal :
{
Properties = FunctionCompilationData - > LiteralPropertyDescriptions ;
break ;
}
case ERigVMMemoryType : : External :
{
Properties = FunctionCompilationData - > ExternalPropertyDescriptions ;
break ;
}
case ERigVMMemoryType : : Debug :
{
Properties = FunctionCompilationData - > DebugPropertyDescriptions ;
break ;
}
}
int32 NumProperties = 0 ;
if ( MemoryType = = ERigVMMemoryType : : Work )
{
for ( const FRigVMGraphFunctionArgument & Argument : FunctionReferenceNode - > GetReferencedFunctionHeader ( ) . Arguments )
{
if ( Argument . CPPTypeObject . IsValid ( ) )
{
if ( const UScriptStruct * ScriptStruct = Cast < UScriptStruct > ( Argument . CPPTypeObject . Get ( ) ) )
{
if ( ScriptStruct - > IsChildOf ( FRigVMExecuteContext : : StaticStruct ( ) ) )
{
continue ;
}
}
}
if ( ! Properties . IsValidIndex ( NumProperties ) )
{
continue ;
}
if ( ! Properties [ NumProperties ] . Name . ToString ( ) . Contains ( Argument . Name . ToString ( ) ) )
{
continue ;
}
NumProperties + + ;
}
}
int32 StartIndex = MemoryType = = ERigVMMemoryType : : Work ? NumProperties : 0 ;
2022-10-24 08:59:51 -04:00
for ( int32 PropertyIndex = StartIndex ; PropertyIndex < Properties . Num ( ) ; + + PropertyIndex )
{
2022-11-16 03:33:17 -05:00
const FRigVMFunctionCompilationPropertyDescription & Description = Properties [ PropertyIndex ] ;
2022-10-24 08:59:51 -04:00
FString NewName = Description . Name . ToString ( ) ;
static const FString FunctionLibraryPrefix = TEXT ( " FunctionLibrary " ) ;
2022-11-16 03:33:17 -05:00
if ( NewName . StartsWith ( FunctionLibraryPrefix ) )
{
NewName = FString : : Printf ( TEXT ( " %s%s " ) , * FunctionReferenceNode - > GetNodePath ( ) , * NewName . RightChop ( FunctionLibraryPrefix . Len ( ) ) ) ;
}
FRigVMOperand Operand = WorkData . AddProperty ( MemoryType , * NewName , Description . CPPType , Description . CPPTypeObject . Get ( ) , Description . DefaultValue ) ;
2022-10-24 08:59:51 -04:00
FRigVMCompilerWorkData : : FFunctionRegisterData Data = { FunctionReferenceNode , MemoryType , PropertyIndex } ;
WorkData . FunctionRegisterToOperand . Add ( Data , Operand ) ;
// @todo Try to reuse literal operands
}
}
}
else
{
TArray < FRigVMOperand > Operands ;
for ( const URigVMPin * Pin : FunctionReferenceNode - > GetPins ( ) )
{
const FRigVMExprAST * ChildExpr = InExpr - > FindExprWithPinName ( Pin - > GetFName ( ) ) ;
checkf ( ChildExpr , TEXT ( " Found unexpected opaque argument for %s while inlining function %s in package %s " ) , * InExpr - > Name . ToString ( ) , * FunctionReferenceNode - > GetPathName ( ) , * GetPackage ( ) - > GetPathName ( ) ) ;
if ( ChildExpr - > GetType ( ) = = FRigVMExprAST : : EType : : CachedValue )
{
2022-11-10 04:36:01 -05:00
const FRigVMVarExprAST * SourceVarExpr = GetSourceVarExpr ( ChildExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ) ;
if ( ! SourceVarExpr - > IsExecuteContext ( ) )
{
Operands . Add ( WorkData . ExprToOperand . FindChecked ( SourceVarExpr ) ) ;
}
2022-10-24 08:59:51 -04:00
}
else if ( ChildExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
2022-11-10 04:36:01 -05:00
const FRigVMVarExprAST * SourceVarExpr = GetSourceVarExpr ( ChildExpr - > To < FRigVMVarExprAST > ( ) ) ;
if ( ! SourceVarExpr - > IsExecuteContext ( ) )
{
Operands . Add ( WorkData . ExprToOperand . FindChecked ( SourceVarExpr ) ) ;
}
2022-10-24 08:59:51 -04:00
}
else
{
break ;
}
}
TraverseChildren ( InExpr , WorkData ) ;
// Inline the bytecode from the function
FRigVMByteCode & ByteCode = WorkData . VM - > GetByteCode ( ) ;
InstructionIndexStart = ByteCode . GetNumInstructions ( ) ;
FRigVMInstructionArray OldInstructions = ByteCode . GetInstructions ( ) ;
ByteCode . InlineFunction ( & FunctionByteCode , Operands ) ;
InstructionIndexEnd = ByteCode . GetNumInstructions ( ) - 1 ;
FRigVMCallstack FuncRefCallstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2022-11-21 07:52:44 -05:00
for ( const FRigVMBranchInfo & BranchInfo : FunctionByteCode . BranchInfos )
{
const int32 BranchInfoIndex = ByteCode . AddBranchInfo ( BranchInfo ) ;
if ( BranchIndexStart = = INDEX_NONE )
{
BranchIndexStart = BranchInfoIndex ;
}
ByteCode . BranchInfos [ BranchInfoIndex ] . InstructionIndex + = InstructionIndexStart ;
ByteCode . BranchInfos [ BranchInfoIndex ] . FirstInstruction + = ( uint16 ) InstructionIndexStart ;
ByteCode . BranchInfos [ BranchInfoIndex ] . LastInstruction + = ( uint16 ) InstructionIndexStart ;
}
2022-10-24 08:59:51 -04:00
// For each instruction, substitute the operand for the one used in the current bytecode
const FRigVMInstructionArray FunctionInstructions = FunctionByteCode . GetInstructions ( ) ;
FRigVMInstructionArray Instructions = ByteCode . GetInstructions ( ) ;
for ( int32 i = InstructionIndexStart ; i < = InstructionIndexEnd ; + + i )
{
const FRigVMInstruction & Instruction = Instructions [ i ] ;
const FRigVMOperandArray OperandArray = ByteCode . GetOperandsForOp ( Instruction ) ;
uint64 OperandsIndex = ByteCode . GetFirstOperandByteIndex ( Instruction ) ;
for ( int32 j = 0 ; j < OperandArray . Num ( ) ; + + j )
{
FRigVMOperand * Operand = ( FRigVMOperand * ) ( ByteCode . ByteCode . GetData ( ) + OperandsIndex + j * sizeof ( FRigVMOperand ) ) ;
ERigVMMemoryType OriginalMemoryType = Operand - > GetMemoryType ( ) ;
// Remap the variable: find the operand index of the outer variable
if ( Operand - > GetMemoryType ( ) = = ERigVMMemoryType : : External )
{
2022-11-16 03:33:17 -05:00
const FName & InnerVariableName = FunctionCompilationData - > ExternalRegisterIndexToVariable [ Operand - > GetRegisterIndex ( ) ] ;
2022-10-24 10:43:43 -04:00
FName OuterVariableName = InnerVariableName ;
if ( const FName * VariableRemapped = FunctionReferenceNode - > GetVariableMap ( ) . Find ( InnerVariableName ) )
{
OuterVariableName = * VariableRemapped ;
}
else
{
ensureMsgf ( ! FunctionReferenceNode - > RequiresVariableRemapping ( ) , TEXT ( " Could not find variable %s in function reference %s variable map, in package %s \n " ) , * InnerVariableName . ToString ( ) , * FunctionReferenceNode - > GetNodePath ( ) , * GetPackage ( ) - > GetPathName ( ) ) ;
}
2022-10-24 08:59:51 -04:00
const FRigVMOperand & OuterOperand = WorkData . PinPathToOperand - > FindChecked ( FString : : Printf ( TEXT ( " Variable::%s " ) , * OuterVariableName . ToString ( ) ) ) ;
Operand - > RegisterIndex = OuterOperand . RegisterIndex ;
}
// Operand is an interface pin: replace the index and memory type
else if ( Operand - > GetMemoryType ( ) = = ERigVMMemoryType : : Work & &
2022-11-10 04:36:01 -05:00
Operands . IsValidIndex ( Operand - > RegisterIndex ) )
2022-10-24 08:59:51 -04:00
{
Operand - > MemoryType = Operands [ Operand - > GetRegisterIndex ( ) ] . MemoryType ;
Operand - > RegisterIndex = Operands [ Operand - > GetRegisterIndex ( ) ] . RegisterIndex ;
}
else
{
// Operand is internal
// Replace with added Operand
FRigVMCompilerWorkData : : FFunctionRegisterData Data = { FunctionReferenceNode , Operand - > GetMemoryType ( ) , Operand - > GetRegisterIndex ( ) } ;
FRigVMOperand NewOperand = WorkData . FunctionRegisterToOperand . FindChecked ( Data ) ;
Operand - > MemoryType = NewOperand . MemoryType ;
Operand - > RegisterIndex = NewOperand . RegisterIndex ;
}
// For all operands, check to see if we need to add a property path
if ( Operand - > GetRegisterOffset ( ) ! = INDEX_NONE )
{
2022-11-16 03:33:17 -05:00
FRigVMFunctionCompilationPropertyPath Description ;
switch ( OriginalMemoryType )
{
case ERigVMMemoryType : : Work :
{
Description = FunctionCompilationData - > WorkPropertyPathDescriptions [ Operand - > GetRegisterOffset ( ) ] ;
break ;
}
case ERigVMMemoryType : : Literal :
{
Description = FunctionCompilationData - > LiteralPropertyPathDescriptions [ Operand - > GetRegisterOffset ( ) ] ;
break ;
}
case ERigVMMemoryType : : External :
{
Description = FunctionCompilationData - > ExternalPropertyPathDescriptions [ Operand - > GetRegisterOffset ( ) ] ;
break ;
}
case ERigVMMemoryType : : Debug :
{
Description = FunctionCompilationData - > DebugPropertyPathDescriptions [ Operand - > GetRegisterOffset ( ) ] ;
break ;
}
}
2022-10-24 08:59:51 -04:00
Operand - > RegisterOffset = WorkData . FindOrAddPropertyPath ( * Operand , Description . HeadCPPType , Description . SegmentPath ) ;
}
}
if ( Instruction . OpCode > = ERigVMOpCode : : Execute_0_Operands & & Instruction . OpCode < = ERigVMOpCode : : Execute_64_Operands )
{
FRigVMExecuteOp & Op = ByteCode . GetOpAt < FRigVMExecuteOp > ( Instruction ) ;
2022-11-16 03:33:17 -05:00
const int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( FunctionCompilationData - > FunctionNames [ Op . FunctionIndex ] . ToString ( ) ) ;
2022-10-24 08:59:51 -04:00
Op . FunctionIndex = FunctionIndex ;
}
2022-11-21 07:52:44 -05:00
if ( Instruction . OpCode = = ERigVMOpCode : : JumpToBranch )
{
FRigVMJumpToBranchOp & Op = ByteCode . GetOpAt < FRigVMJumpToBranchOp > ( Instruction ) ;
Op . FirstBranchInfoIndex = Op . FirstBranchInfoIndex + BranchIndexStart ;
}
2022-10-24 08:59:51 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
if ( const TArray < UObject * > * Callstack = FunctionByteCode . GetCallstackForInstruction ( i - InstructionIndexStart ) )
{
if ( Callstack - > Num ( ) > 1 )
{
FRigVMCallstack InstructionCallstack = FuncRefCallstack ;
InstructionCallstack . Stack . Append ( & ( * Callstack ) [ 1 ] , Callstack - > Num ( ) - 1 ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( i , InstructionCallstack . GetCallPath ( ) , InstructionCallstack . GetStack ( ) ) ;
}
}
}
}
# if WITH_EDITORONLY_DATA
TArray < FRigVMOperand > InputsOperands , OutputOperands ;
2022-11-10 04:36:01 -05:00
int32 ArgumentIndex = 0 ;
2022-10-24 08:59:51 -04:00
for ( const URigVMPin * InputPin : Node - > GetPins ( ) )
{
if ( InputPin - > IsExecuteContext ( ) )
{
continue ;
}
2022-11-10 04:36:01 -05:00
const FRigVMOperand & Operand = Operands [ ArgumentIndex + + ] ;
2022-10-24 08:59:51 -04:00
if ( InputPin - > GetDirection ( ) = = ERigVMPinDirection : : Output | | InputPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
OutputOperands . Add ( Operand ) ;
}
if ( InputPin - > GetDirection ( ) ! = ERigVMPinDirection : : Input & & InputPin - > GetDirection ( ) ! = ERigVMPinDirection : : IO )
{
continue ;
}
InputsOperands . Add ( Operand ) ;
}
WorkData . VM - > GetByteCode ( ) . SetOperandsForInstruction (
InstructionIndexStart ,
FRigVMOperandArray ( InputsOperands . GetData ( ) , InputsOperands . Num ( ) ) ,
FRigVMOperandArray ( OutputOperands . GetData ( ) , OutputOperands . Num ( ) ) ) ;
# endif
}
return InstructionIndexEnd ;
}
2020-01-22 17:58:55 -05:00
void URigVMCompiler : : TraverseNoOp ( const FRigVMNoOpExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseChildren ( InExpr , WorkData ) ;
}
void URigVMCompiler : : TraverseVar ( const FRigVMVarExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseChildren ( InExpr , WorkData ) ;
if ( WorkData . bSetupMemory )
{
FindOrAddRegister ( InExpr , WorkData ) ;
}
}
void URigVMCompiler : : TraverseLiteral ( const FRigVMVarExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseVar ( InExpr , WorkData ) ;
}
2020-10-26 06:51:31 -04:00
void URigVMCompiler : : TraverseExternalVar ( const FRigVMExternalVarExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseVar ( InExpr , WorkData ) ;
}
2020-01-22 17:58:55 -05:00
void URigVMCompiler : : TraverseAssign ( const FRigVMAssignExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseChildren ( InExpr , WorkData ) ;
ensure ( InExpr - > NumChildren ( ) > 0 ) ;
const FRigVMVarExprAST * SourceExpr = nullptr ;
const FRigVMExprAST * ChildExpr = InExpr - > ChildAt ( 0 ) ;
if ( ChildExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
SourceExpr = ChildExpr - > To < FRigVMVarExprAST > ( ) ;
}
else if ( ChildExpr - > GetType ( ) = = FRigVMExprAST : : EType : : CachedValue )
{
SourceExpr = ChildExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
else if ( ChildExpr - > GetType ( ) = = FRigVMExprAST : : EType : : NoOp )
{
ensure ( ChildExpr - > NumChildren ( ) > 0 ) ;
for ( FRigVMExprAST * GrandChild : * ChildExpr )
{
if ( GrandChild - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
const FRigVMVarExprAST * VarExpr = GrandChild - > To < FRigVMVarExprAST > ( ) ;
2020-09-24 00:43:27 -04:00
if ( VarExpr - > GetPin ( ) - > GetName ( ) = = TEXT ( " Value " ) | |
VarExpr - > GetPin ( ) - > GetName ( ) = = TEXT ( " EnumIndex " ) )
2020-01-22 17:58:55 -05:00
{
SourceExpr = VarExpr ;
break ;
}
}
}
check ( SourceExpr ) ;
}
else
{
checkNoEntry ( ) ;
}
2021-08-18 06:18:21 -04:00
FRigVMOperand Source = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( SourceExpr ) ) ;
2020-01-22 17:58:55 -05:00
2021-07-27 14:04:39 -04:00
if ( ! WorkData . bSetupMemory )
2020-01-22 17:58:55 -05:00
{
2020-09-24 00:43:27 -04:00
const FRigVMVarExprAST * TargetExpr = InExpr - > GetFirstParentOfType ( FRigVMVarExprAST : : EType : : Var ) - > To < FRigVMVarExprAST > ( ) ;
2021-08-18 06:18:21 -04:00
TargetExpr = GetSourceVarExpr ( TargetExpr ) ;
2022-10-21 22:29:04 -04:00
FRigVMOperand Target = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( TargetExpr ) ) ;
2021-08-18 06:18:21 -04:00
if ( Target = = Source )
{
return ;
}
2022-03-31 14:40:13 -04:00
2020-01-22 17:58:55 -05:00
// if this is a copy - we should check if operands need offsets
if ( InExpr - > GetType ( ) = = FRigVMExprAST : : EType : : Copy )
{
struct Local
{
2022-03-31 14:40:13 -04:00
static void SetupRegisterOffset ( URigVM * VM , const FRigVMASTLinkDescription & InLink , URigVMPin * Pin ,
FRigVMOperand & Operand , const FRigVMVarExprAST * VarExpr , bool bSource , FRigVMCompilerWorkData & WorkData )
2020-01-22 17:58:55 -05:00
{
2022-03-31 14:40:13 -04:00
const bool bHasTargetSegmentPath = ! bSource & & ! InLink . SegmentPath . IsEmpty ( ) ;
2020-01-22 17:58:55 -05:00
URigVMPin * RootPin = Pin - > GetRootPin ( ) ;
2022-03-31 14:40:13 -04:00
if ( Pin = = RootPin & & ! bHasTargetSegmentPath )
2020-01-22 17:58:55 -05:00
{
return ;
}
2022-03-31 14:40:13 -04:00
FString SegmentPath = Pin - > GetSegmentPath ( false ) ;
if ( bHasTargetSegmentPath )
2020-09-24 00:43:27 -04:00
{
2022-03-31 14:40:13 -04:00
if ( SegmentPath . IsEmpty ( ) )
2020-09-24 00:43:27 -04:00
{
2022-03-31 14:40:13 -04:00
SegmentPath = InLink . SegmentPath ;
2022-03-31 14:39:59 -04:00
}
else
2022-03-31 14:40:13 -04:00
{
SegmentPath = URigVMPin : : JoinPinPath ( SegmentPath , InLink . SegmentPath ) ;
2022-03-31 14:39:59 -04:00
}
}
2022-11-28 10:01:18 -05:00
// for fixed array pins we create a register for each array element
2022-03-31 14:40:13 -04:00
// thus we do not need to setup a registeroffset for the array element.
2022-11-28 10:01:18 -05:00
if ( RootPin - > IsFixedSizeArray ( ) )
2022-03-31 14:40:13 -04:00
{
2022-11-28 10:01:18 -05:00
if ( Pin - > GetParentPin ( ) = = RootPin )
2022-03-31 14:40:13 -04:00
{
2022-11-28 10:01:18 -05:00
return ;
}
2022-03-31 14:40:13 -04:00
2022-11-28 10:01:18 -05:00
// if the pin is a sub pin of a case of a fixed array
// we'll need to re-adjust the root pin to the case pin (for example: Values.0)
TArray < FString > SegmentPathPaths ;
if ( ensure ( URigVMPin : : SplitPinPath ( SegmentPath , SegmentPathPaths ) ) )
{
RootPin = RootPin - > FindSubPin ( SegmentPathPaths [ 0 ] ) ;
2022-03-31 14:40:13 -04:00
2022-11-28 10:01:18 -05:00
SegmentPathPaths . RemoveAt ( 0 ) ;
ensure ( SegmentPathPaths . Num ( ) > 0 ) ;
SegmentPath = URigVMPin : : JoinPinPath ( SegmentPathPaths ) ;
}
else
{
return ;
2022-03-31 14:40:13 -04:00
}
}
2022-03-31 14:39:59 -04:00
2021-07-29 14:29:52 -04:00
const int32 PropertyPathIndex = WorkData . FindOrAddPropertyPath ( Operand , RootPin - > GetCPPType ( ) , SegmentPath ) ;
2021-07-27 14:04:39 -04:00
Operand = FRigVMOperand ( Operand . GetMemoryType ( ) , Operand . GetRegisterIndex ( ) , PropertyPathIndex ) ;
2020-01-22 17:58:55 -05:00
}
} ;
2022-03-31 14:40:13 -04:00
const FRigVMASTLinkDescription & Link = InExpr - > GetLink ( ) ;
Local : : SetupRegisterOffset ( WorkData . VM , Link , InExpr - > GetSourcePin ( ) , Source , SourceExpr , true , WorkData ) ;
Local : : SetupRegisterOffset ( WorkData . VM , Link , InExpr - > GetTargetPin ( ) , Target , TargetExpr , false , WorkData ) ;
2020-01-22 17:58:55 -05:00
}
2021-08-18 06:18:21 -04:00
FRigVMCopyOp CopyOp = WorkData . VM - > GetCopyOpForOperands ( Source , Target ) ;
if ( CopyOp . IsValid ( ) )
2020-09-24 00:43:27 -04:00
{
2022-03-31 14:40:13 -04:00
AddCopyOperator ( CopyOp , InExpr , SourceExpr , TargetExpr , WorkData ) ;
2020-09-24 00:43:27 -04:00
}
2020-01-22 17:58:55 -05:00
}
}
void URigVMCompiler : : TraverseCopy ( const FRigVMCopyExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseAssign ( InExpr - > To < FRigVMAssignExprAST > ( ) , WorkData ) ;
}
void URigVMCompiler : : TraverseCachedValue ( const FRigVMCachedValueExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
TraverseChildren ( InExpr , WorkData ) ;
}
void URigVMCompiler : : TraverseExit ( const FRigVMExitExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
ensure ( InExpr - > NumChildren ( ) = = 0 ) ;
if ( ! WorkData . bSetupMemory )
{
2020-09-24 00:43:27 -04:00
WorkData . VM - > GetByteCode ( ) . AddExitOp ( ) ;
}
}
2022-06-01 05:56:08 -04:00
void URigVMCompiler : : TraverseInvokeEntry ( const FRigVMInvokeEntryExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
URigVMInvokeEntryNode * InvokeEntryNode = Cast < URigVMInvokeEntryNode > ( InExpr - > GetNode ( ) ) ;
if ( ! ValidateNode ( InvokeEntryNode ) )
{
return ;
}
if ( WorkData . bSetupMemory )
{
return ;
}
else
{
2022-06-01 11:28:01 -04:00
const int32 InstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
2022-06-01 05:56:08 -04:00
WorkData . VM - > GetByteCode ( ) . AddInvokeEntryOp ( InvokeEntryNode - > GetEntryName ( ) ) ;
2022-06-01 11:28:01 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetSibling ( InvokeEntryNode ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
2022-06-01 05:56:08 -04:00
}
}
2022-03-31 14:40:13 -04:00
void URigVMCompiler : : AddCopyOperator ( const FRigVMCopyOp & InOp , const FRigVMAssignExprAST * InAssignExpr ,
2022-06-01 05:56:08 -04:00
const FRigVMVarExprAST * InSourceExpr , const FRigVMVarExprAST * InTargetExpr , FRigVMCompilerWorkData & WorkData ,
bool bDelayCopyOperations )
2022-03-31 14:40:13 -04:00
{
if ( bDelayCopyOperations )
{
// if this is a full literal copy, let's delay it.
// to maintain the execution order we want nodes which compose a value
// to delay their reset to the default value, which happens prior to
// computing dependencies.
// so for example an external variable of FVector may need to be reset
// to a literal value prior to the rest of the composition, for example
// if there's a float link only on the Y component. the execution order
// desired is this:
//
// * Run all dependent branches
// * Copy the literal value into the variable
// * Copy the parts into the variable (like the Y component).
//
// By delaying the copy operator until right before the very first composition
// copy operator we ensure the desired execution order
if ( InOp . Target . GetRegisterOffset ( ) = = INDEX_NONE & &
InOp . Source . GetMemoryType ( ) = = ERigVMMemoryType : : Literal & &
InOp . Source . GetRegisterOffset ( ) = = INDEX_NONE )
{
if ( URigVMPin * Pin = InTargetExpr - > GetPin ( ) )
{
if ( URigVMPin * RootPin = Pin - > GetRootPin ( ) )
{
const FRigVMASTProxy RootPinProxy = InTargetExpr - > GetProxy ( ) . GetSibling ( RootPin ) ;
// if the root pin has only links on its subpins
if ( WorkData . AST - > GetSourceLinkIndices ( RootPinProxy , false ) . Num ( ) = = 0 )
{
if ( WorkData . AST - > GetSourceLinkIndices ( RootPinProxy , true ) . Num ( ) > 0 )
{
FRigVMCompilerWorkData : : FCopyOpInfo DeferredCopyOp ;
DeferredCopyOp . Op = InOp ;
DeferredCopyOp . AssignExpr = InAssignExpr ;
DeferredCopyOp . SourceExpr = InSourceExpr ;
DeferredCopyOp . TargetExpr = InTargetExpr ;
const FRigVMOperand Key ( InOp . Target . GetMemoryType ( ) , InOp . Target . GetRegisterIndex ( ) ) ;
WorkData . DeferredCopyOps . FindOrAdd ( Key ) = DeferredCopyOp ;
return ;
}
}
}
}
}
bDelayCopyOperations = false ;
}
2022-11-18 06:25:07 -05:00
// look up a potentially delayed copy operation which needs to happen
2022-03-31 14:40:13 -04:00
// just prior to this one and inject it as well.
if ( ! bDelayCopyOperations )
{
const FRigVMOperand DeferredKey ( InOp . Target . GetMemoryType ( ) , InOp . Target . GetRegisterIndex ( ) ) ;
const FRigVMCompilerWorkData : : FCopyOpInfo * DeferredCopyOpPtr = WorkData . DeferredCopyOps . Find ( DeferredKey ) ;
if ( DeferredCopyOpPtr ! = nullptr )
{
FRigVMCompilerWorkData : : FCopyOpInfo CopyOpInfo = * DeferredCopyOpPtr ;
WorkData . DeferredCopyOps . Remove ( DeferredKey ) ;
AddCopyOperator ( CopyOpInfo , WorkData , false ) ;
}
}
2022-07-01 09:58:51 -04:00
bool bAddCopyOp = true ;
2022-10-20 08:54:59 -04:00
// check if we need to inject a cast instead of a copy operator
const TRigVMTypeIndex SourceTypeIndex = WorkData . GetTypeIndexForOperand ( InOp . Source ) ;
const TRigVMTypeIndex TargetTypeIndex = WorkData . GetTypeIndexForOperand ( InOp . Target ) ;
if ( SourceTypeIndex ! = TargetTypeIndex )
2022-07-01 09:58:51 -04:00
{
2022-10-20 08:54:59 -04:00
// if the type system can't auto cast these types (like float vs double)
if ( ! FRigVMRegistry : : Get ( ) . CanMatchTypes ( SourceTypeIndex , TargetTypeIndex , true ) )
2022-07-01 09:58:51 -04:00
{
2022-10-20 08:54:59 -04:00
const FRigVMFunction * CastFunction = RigVMTypeUtils : : GetCastForTypeIndices ( SourceTypeIndex , TargetTypeIndex ) ;
if ( CastFunction = = nullptr )
{
const FRigVMRegistry & Registry = FRigVMRegistry : : Get ( ) ;
2022-11-07 04:27:49 -05:00
static constexpr TCHAR MissingCastMessage [ ] = TEXT ( " Cast (%s to %s) for Node @@ not found. " ) ;
2022-10-20 08:54:59 -04:00
const FString & SourceCPPType = Registry . GetType ( SourceTypeIndex ) . CPPType . ToString ( ) ;
const FString & TargetCPPType = Registry . GetType ( TargetTypeIndex ) . CPPType . ToString ( ) ;
Settings . Report ( EMessageSeverity : : Error , InAssignExpr - > GetTargetPin ( ) - > GetNode ( ) ,
FString : : Printf ( MissingCastMessage , * SourceCPPType , * TargetCPPType ) ) ;
return ;
}
check ( CastFunction - > Arguments . Num ( ) > = 2 ) ;
const FRigVMOperand Source = InOp . Source ;
const FRigVMOperand Target = InOp . Target ;
const int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( CastFunction - > Name ) ;
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , { Source , Target } ) ;
bAddCopyOp = false ;
}
}
// if we are copying into an array variable
if ( bAddCopyOp )
{
if ( const URigVMPin * Pin = InTargetExpr - > GetPin ( ) )
{
if ( Pin - > IsArray ( ) & & Pin - > GetNode ( ) - > IsA < URigVMVariableNode > ( ) )
{
if ( InOp . Source . GetRegisterOffset ( ) = = INDEX_NONE & &
InOp . Target . GetRegisterOffset ( ) = = INDEX_NONE )
2023-01-03 09:23:55 -05:00
{
static const FString ArrayCloneName =
FRigVMRegistry : : Get ( ) . FindOrAddSingletonDispatchFunction < FRigVMDispatch_ArrayClone > ( ) ;
const int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( ArrayCloneName ) ;
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , { InOp . Source , InOp . Target } ) ;
2022-10-20 08:54:59 -04:00
bAddCopyOp = false ;
}
2022-07-01 12:05:47 -04:00
}
2022-07-01 09:58:51 -04:00
}
}
2022-03-31 14:40:13 -04:00
2022-07-01 09:58:51 -04:00
if ( bAddCopyOp )
{
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( InOp ) ;
}
2022-03-31 14:40:13 -04:00
int32 InstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
{
2022-11-24 05:01:22 -05:00
bool bSetSubject = false ;
2022-03-31 14:40:13 -04:00
if ( URigVMPin * SourcePin = InAssignExpr - > GetSourcePin ( ) )
{
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( SourcePin - > GetNode ( ) ) )
{
const FRigVMCallstack Callstack = InSourceExpr - > GetProxy ( ) . GetSibling ( VariableNode ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2022-11-24 05:01:22 -05:00
bSetSubject = true ;
2022-03-31 14:40:13 -04:00
}
}
2022-11-24 05:01:22 -05:00
if ( ! bSetSubject )
2022-03-31 14:40:13 -04:00
{
2022-11-24 05:01:22 -05:00
if ( URigVMPin * TargetPin = InAssignExpr - > GetTargetPin ( ) )
2022-03-31 14:40:13 -04:00
{
2022-11-24 05:01:22 -05:00
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( TargetPin - > GetNode ( ) ) )
{
const FRigVMCallstack Callstack = InTargetExpr - > GetProxy ( ) . GetSibling ( VariableNode ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
bSetSubject = true ;
}
else
{
const FRigVMCallstack Callstack = InTargetExpr - > GetProxy ( ) . GetSibling ( TargetPin - > GetNode ( ) ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
bSetSubject = true ;
}
2022-03-31 14:40:13 -04:00
}
}
}
}
void URigVMCompiler : : AddCopyOperator (
const FRigVMCompilerWorkData : : FCopyOpInfo & CopyOpInfo ,
FRigVMCompilerWorkData & WorkData ,
bool bDelayCopyOperations )
{
AddCopyOperator ( CopyOpInfo . Op , CopyOpInfo . AssignExpr , CopyOpInfo . SourceExpr , CopyOpInfo . TargetExpr , WorkData , bDelayCopyOperations ) ;
}
2022-11-16 03:33:17 -05:00
FString URigVMCompiler : : GetPinHashImpl ( const URigVMPin * InPin , const FRigVMVarExprAST * InVarExpr , bool bIsDebugValue , const URigVMLibraryNode * FunctionCompiling , const FRigVMASTProxy & InPinProxy )
2020-01-22 17:58:55 -05:00
{
2020-09-24 00:43:27 -04:00
FString Prefix = bIsDebugValue ? TEXT ( " DebugWatch: " ) : TEXT ( " " ) ;
2020-01-22 17:58:55 -05:00
FString Suffix ;
if ( InPin - > IsExecuteContext ( ) )
{
return TEXT ( " ExecuteContext! " ) ;
}
2020-09-24 00:43:27 -04:00
URigVMNode * Node = InPin - > GetNode ( ) ;
bool bIsExecutePin = false ;
bool bIsLiteral = false ;
bool bIsVariable = false ;
2022-10-24 08:59:51 -04:00
bool bIsFunctionInterfacePin = false ;
2020-09-24 00:43:27 -04:00
2020-01-22 17:58:55 -05:00
if ( InVarExpr ! = nullptr & & ! bIsDebugValue )
{
2021-08-18 06:18:21 -04:00
if ( InVarExpr - > IsA ( FRigVMExprAST : : ExternalVar ) )
2020-10-26 06:51:31 -04:00
{
2021-01-19 04:57:43 -04:00
URigVMPin : : FPinOverride PinOverride ( InVarExpr - > GetProxy ( ) , InVarExpr - > GetParser ( ) - > GetPinOverrides ( ) ) ;
FString VariablePath = InPin - > GetBoundVariablePath ( PinOverride ) ;
2020-10-26 06:51:31 -04:00
return FString : : Printf ( TEXT ( " %sVariable::%s%s " ) , * Prefix , * VariablePath , * Suffix ) ;
}
2021-08-18 06:18:21 -04:00
// for IO array pins we'll walk left and use that pin hash instead
if ( const FRigVMVarExprAST * SourceVarExpr = GetSourceVarExpr ( InVarExpr ) )
{
if ( SourceVarExpr ! = InVarExpr )
{
2022-10-24 08:59:51 -04:00
return GetPinHash ( SourceVarExpr - > GetPin ( ) , SourceVarExpr , bIsDebugValue , FunctionCompiling ) ;
2021-08-18 06:18:21 -04:00
}
}
2020-09-24 00:43:27 -04:00
bIsExecutePin = InPin - > IsExecuteContext ( ) ;
bIsLiteral = InVarExpr - > GetType ( ) = = FRigVMExprAST : : EType : : Literal ;
2020-10-26 06:51:31 -04:00
bIsVariable = Cast < URigVMVariableNode > ( Node ) ! = nullptr | | InVarExpr - > IsA ( FRigVMExprAST : : ExternalVar ) ;
2022-10-24 08:59:51 -04:00
bIsFunctionInterfacePin = ( Cast < URigVMFunctionEntryNode > ( Node ) | | Cast < URigVMFunctionReturnNode > ( Node ) ) & &
Node - > GetTypedOuter < URigVMLibraryNode > ( ) = = FunctionCompiling ;
2020-01-22 17:58:55 -05:00
// determine if this is an initialization for an IO pin
2022-03-31 14:40:13 -04:00
if ( ! bIsLiteral & &
! bIsVariable & &
2022-10-24 08:59:51 -04:00
! bIsFunctionInterfacePin & &
2020-09-24 00:43:27 -04:00
! bIsExecutePin & & ( InPin - > GetDirection ( ) = = ERigVMPinDirection : : IO | |
2020-01-22 17:58:55 -05:00
( InPin - > GetDirection ( ) = = ERigVMPinDirection : : Input & & InPin - > GetSourceLinks ( ) . Num ( ) = = 0 ) ) )
{
Suffix = TEXT ( " ::IO " ) ;
}
2020-12-03 12:09:21 -04:00
else if ( bIsLiteral )
{
Suffix = TEXT ( " ::Const " ) ;
}
2020-01-22 17:58:55 -05:00
}
2021-05-14 02:36:03 -04:00
bool bUseFullNodePath = true ;
2022-03-31 14:40:13 -04:00
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( Node ) )
2020-01-22 17:58:55 -05:00
{
2021-05-11 17:13:58 -04:00
if ( InPin - > GetName ( ) = = TEXT ( " Value " ) & & ! bIsDebugValue )
2020-01-22 17:58:55 -05:00
{
2021-04-27 03:19:42 -04:00
FName VariableName = VariableNode - > GetVariableName ( ) ;
2021-06-02 06:17:52 -04:00
if ( VariableNode - > IsLocalVariable ( ) )
2021-05-11 17:13:58 -04:00
{
2021-06-02 06:17:52 -04:00
if ( bIsLiteral )
2021-05-11 17:13:58 -04:00
{
2022-03-31 14:40:13 -04:00
if ( InVarExpr & & InVarExpr - > NumParents ( ) = = 0 & & InVarExpr - > NumChildren ( ) = = 0 )
2021-06-07 06:49:07 -04:00
{
2022-08-19 19:38:13 -04:00
// Default literal values will be reused for all instance of local variables
2021-06-07 06:49:07 -04:00
return FString : : Printf ( TEXT ( " %sLocalVariableDefault::%s|%s%s " ) , * Prefix , * Node - > GetGraph ( ) - > GetGraphName ( ) , * VariableName . ToString ( ) , * Suffix ) ;
}
2022-03-31 14:40:13 -04:00
else if ( InVarExpr )
{
2022-10-24 08:59:51 -04:00
const FString PinPath = InVarExpr - > GetProxy ( ) . GetCallstack ( ) . GetCallPath ( true ) ;
return FString : : Printf ( TEXT ( " %sLocalVariable::%s%s " ) , * Prefix , * PinPath , * Suffix ) ;
2022-03-31 14:40:13 -04:00
}
2021-06-07 06:49:07 -04:00
else
{
return FString : : Printf ( TEXT ( " %sLocalVariable::%s|%s%s " ) , * Prefix , * Node - > GetGraph ( ) - > GetGraphName ( ) , * VariableName . ToString ( ) , * Suffix ) ;
}
2021-06-02 06:17:52 -04:00
}
else
{
if ( InVarExpr )
2021-04-27 03:19:42 -04:00
{
2021-06-02 06:17:52 -04:00
FRigVMASTProxy ParentProxy = InVarExpr - > GetProxy ( ) ;
while ( ParentProxy . GetCallstack ( ) . Num ( ) > 1 )
2021-04-27 03:19:42 -04:00
{
2021-06-02 06:17:52 -04:00
ParentProxy = ParentProxy . GetParent ( ) ;
if ( URigVMLibraryNode * LibraryNode = ParentProxy . GetSubject < URigVMLibraryNode > ( ) )
2021-05-11 17:13:58 -04:00
{
2022-05-31 04:27:20 -04:00
break ;
2021-05-11 17:13:58 -04:00
}
2021-04-27 03:19:42 -04:00
}
2021-06-02 06:17:52 -04:00
2022-05-31 04:27:20 -04:00
// Local variables for root / non-root graphs are in the format "LocalVariable::PathToGraph|VariableName"
2022-10-24 08:59:51 -04:00
return FString : : Printf ( TEXT ( " %sLocalVariable::%s|%s%s " ) , * Prefix , * Node - > GetGraph ( ) - > GetGraphName ( ) , * VariableName . ToString ( ) , * Suffix ) ;
2021-04-27 03:19:42 -04:00
}
}
}
2022-03-31 14:40:13 -04:00
else if ( VariableNode - > IsInputArgument ( ) )
{
FString FullPath ;
if ( InPinProxy . IsValid ( ) )
{
FullPath = InPinProxy . GetCallstack ( ) . GetCallPath ( true ) ;
}
else if ( InVarExpr )
{
const FRigVMASTProxy NodeProxy = InVarExpr - > GetProxy ( ) . GetSibling ( Node ) ;
FullPath = InPinProxy . GetCallstack ( ) . GetCallPath ( true ) ;
}
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * FullPath , * Suffix ) ;
}
2021-05-11 17:13:58 -04:00
if ( ! bIsLiteral )
{
// determine if this variable needs to be remapped
if ( InVarExpr )
{
FRigVMASTProxy ParentProxy = InVarExpr - > GetProxy ( ) ;
while ( ParentProxy . GetCallstack ( ) . Num ( ) > 1 )
{
ParentProxy = ParentProxy . GetParent ( ) ;
if ( URigVMFunctionReferenceNode * FunctionReferenceNode = ParentProxy . GetSubject < URigVMFunctionReferenceNode > ( ) )
{
const FName RemappedVariableName = FunctionReferenceNode - > GetOuterVariableName ( VariableName ) ;
if ( ! RemappedVariableName . IsNone ( ) )
{
VariableName = RemappedVariableName ;
}
}
}
}
2021-04-27 03:19:42 -04:00
2021-05-11 17:13:58 -04:00
return FString : : Printf ( TEXT ( " %sVariable::%s%s " ) , * Prefix , * VariableName . ToString ( ) , * Suffix ) ;
}
}
2020-01-22 17:58:55 -05:00
}
2021-01-12 06:47:41 -04:00
else
{
2021-07-29 14:29:52 -04:00
if ( InVarExpr & & ! bIsDebugValue )
2021-01-12 06:47:41 -04:00
{
2021-05-14 02:36:03 -04:00
const FRigVMASTProxy NodeProxy = InVarExpr - > GetProxy ( ) . GetSibling ( Node ) ;
2021-01-12 06:47:41 -04:00
if ( const FRigVMExprAST * NodeExpr = InVarExpr - > GetParser ( ) - > GetExprForSubject ( NodeProxy ) )
{
// rely on the proxy callstack to differentiate registers
2021-05-14 02:36:03 -04:00
const FString CallStackPath = NodeProxy . GetCallstack ( ) . GetCallPath ( false /* include last */ ) ;
2022-07-20 12:20:55 -04:00
if ( ! CallStackPath . IsEmpty ( ) & & ! InPinProxy . IsValid ( ) )
2021-01-12 06:47:41 -04:00
{
Prefix + = CallStackPath + TEXT ( " | " ) ;
2021-05-14 02:36:03 -04:00
bUseFullNodePath = false ;
2021-01-12 06:47:41 -04:00
}
}
2022-03-31 14:40:13 -04:00
else if ( Node - > IsA < URigVMFunctionEntryNode > ( ) | | Node - > IsA < URigVMFunctionReturnNode > ( ) )
{
const FString FullPath = InPinProxy . GetCallstack ( ) . GetCallPath ( true ) ;
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * FullPath , * Suffix ) ;
}
2021-01-12 06:47:41 -04:00
}
}
2022-03-31 14:40:13 -04:00
if ( InPinProxy . IsValid ( ) )
{
const FString FullPath = InPinProxy . GetCallstack ( ) . GetCallPath ( true ) ;
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * FullPath , * Suffix ) ;
}
if ( InVarExpr )
{
if ( bUseFullNodePath )
{
FString FullPath = InVarExpr - > GetProxy ( ) . GetCallstack ( ) . GetCallPath ( true ) ;
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * FullPath , * Suffix ) ;
}
else
{
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * InPin - > GetPinPath ( ) , * Suffix ) ;
}
}
FString PinPath = InPin - > GetPinPath ( bUseFullNodePath ) ;
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * PinPath , * Suffix ) ;
2020-01-22 17:58:55 -05:00
}
2022-11-16 03:33:17 -05:00
FString URigVMCompiler : : GetPinHash ( const URigVMPin * InPin , const FRigVMVarExprAST * InVarExpr , bool bIsDebugValue , const URigVMLibraryNode * FunctionCompiling , const FRigVMASTProxy & InPinProxy )
2022-04-05 06:57:59 -04:00
{
2022-10-24 08:59:51 -04:00
const FString Hash = GetPinHashImpl ( InPin , InVarExpr , bIsDebugValue , FunctionCompiling , InPinProxy ) ;
if ( ! bIsDebugValue & & FunctionCompiling = = nullptr )
2022-07-20 12:20:55 -04:00
{
ensureMsgf ( ! Hash . Contains ( TEXT ( " FunctionLibrary:: " ) ) , TEXT ( " A library path should never be part of a pin hash %s. " ) , * Hash ) ;
}
2022-04-05 06:57:59 -04:00
return Hash ;
}
2021-08-18 06:18:21 -04:00
const FRigVMVarExprAST * URigVMCompiler : : GetSourceVarExpr ( const FRigVMExprAST * InExpr )
{
if ( InExpr )
{
if ( InExpr - > IsA ( FRigVMExprAST : : EType : : CachedValue ) )
{
return GetSourceVarExpr ( InExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ) ;
}
if ( InExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
const FRigVMVarExprAST * VarExpr = InExpr - > To < FRigVMVarExprAST > ( ) ;
if ( VarExpr - > GetPin ( ) - > IsReferenceCountedContainer ( ) & &
( ( VarExpr - > GetPin ( ) - > GetDirection ( ) = = ERigVMPinDirection : : Input ) | | ( VarExpr - > GetPin ( ) - > GetDirection ( ) = = ERigVMPinDirection : : IO ) ) )
{
// if this is a variable setter we cannot follow the source var
if ( VarExpr - > GetPin ( ) - > GetDirection ( ) = = ERigVMPinDirection : : Input )
{
if ( VarExpr - > GetPin ( ) - > GetNode ( ) - > IsA < URigVMVariableNode > ( ) )
{
return VarExpr ;
}
}
if ( const FRigVMExprAST * AssignExpr = VarExpr - > GetFirstChildOfType ( FRigVMExprAST : : EType : : Assign ) )
{
// don't follow a copy assignment
if ( AssignExpr - > IsA ( FRigVMExprAST : : EType : : Copy ) )
{
return VarExpr ;
}
if ( const FRigVMExprAST * CachedValueExpr = VarExpr - > GetFirstChildOfType ( FRigVMExprAST : : EType : : CachedValue ) )
{
return GetSourceVarExpr ( CachedValueExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ) ;
}
else if ( const FRigVMExprAST * ChildExpr = VarExpr - > GetFirstChildOfType ( FRigVMExprAST : : EType : : Var ) )
{
return GetSourceVarExpr ( ChildExpr - > To < FRigVMVarExprAST > ( ) ) ;
}
}
}
return VarExpr ;
}
}
return nullptr ;
}
2021-07-29 14:29:52 -04:00
void URigVMCompiler : : MarkDebugWatch ( bool bRequired , URigVMPin * InPin , URigVM * OutVM ,
TMap < FString , FRigVMOperand > * OutOperands , TSharedPtr < FRigVMParserAST > InRuntimeAST )
{
check ( InPin ) ;
check ( OutVM ) ;
check ( OutOperands ) ;
check ( InRuntimeAST . IsValid ( ) ) ;
URigVMPin * Pin = InPin - > GetRootPin ( ) ;
URigVMPin * SourcePin = Pin ;
if ( Settings . ASTSettings . bFoldAssignments )
{
while ( SourcePin - > GetSourceLinks ( ) . Num ( ) > 0 )
{
SourcePin = SourcePin - > GetSourceLinks ( ) [ 0 ] - > GetSourcePin ( ) ;
}
}
TArray < const FRigVMExprAST * > Expressions = InRuntimeAST - > GetExpressionsForSubject ( SourcePin ) ;
TArray < FRigVMOperand > VisitedKeys ;
2022-07-20 12:20:55 -04:00
for ( int32 ExpressionIndex = 0 ; ExpressionIndex < Expressions . Num ( ) ; ExpressionIndex + + )
2021-07-29 14:29:52 -04:00
{
2022-07-20 12:20:55 -04:00
const FRigVMExprAST * Expression = Expressions [ ExpressionIndex ] ;
2021-07-29 14:29:52 -04:00
check ( Expression - > IsA ( FRigVMExprAST : : EType : : Var ) ) ;
const FRigVMVarExprAST * VarExpression = Expression - > To < FRigVMVarExprAST > ( ) ;
if ( VarExpression - > GetPin ( ) = = Pin )
{
// literals don't need to be stored on the debug memory
if ( VarExpression - > IsA ( FRigVMExprAST : : Literal ) )
{
2022-07-20 12:20:55 -04:00
// check if there's also an IO expression for this pin
for ( int32 ParentIndex = 0 ; ParentIndex < VarExpression - > NumParents ( ) ; ParentIndex + + )
{
const FRigVMExprAST * ParentExpression = VarExpression - > ParentAt ( ParentIndex ) ;
if ( ParentExpression - > IsA ( FRigVMExprAST : : EType : : Assign ) )
{
if ( const FRigVMExprAST * GrandParentExpression = ParentExpression - > GetParent ( ) )
{
if ( GrandParentExpression - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
if ( GrandParentExpression - > To < FRigVMVarExprAST > ( ) - > GetPin ( ) = = Pin )
{
Expressions . Add ( GrandParentExpression ) ;
}
}
}
}
}
2021-07-29 14:29:52 -04:00
continue ;
}
}
2022-07-20 12:20:55 -04:00
2022-10-24 08:59:51 -04:00
FString PinHash = GetPinHash ( Pin , VarExpression , false , CurrentCompilationFunction ) ;
2022-07-20 12:20:55 -04:00
if ( ! OutOperands - > Contains ( PinHash ) )
{
2022-10-24 08:59:51 -04:00
PinHash = GetPinHash ( SourcePin , VarExpression , false , CurrentCompilationFunction ) ;
2022-07-20 12:20:55 -04:00
}
2021-07-29 14:29:52 -04:00
if ( const FRigVMOperand * Operand = OutOperands - > Find ( PinHash ) )
{
const FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( Pin ) ;
FRigVMVarExprAST TempVarExpr ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
TempVarExpr . ParserPtr = InRuntimeAST . Get ( ) ;
2022-10-24 08:59:51 -04:00
const FString DebugPinHash = GetPinHash ( Pin , & TempVarExpr , true , CurrentCompilationFunction ) ;
2021-07-29 14:29:52 -04:00
const FRigVMOperand * DebugOperand = OutOperands - > Find ( DebugPinHash ) ;
if ( DebugOperand )
{
if ( DebugOperand - > IsValid ( ) )
{
FRigVMOperand KeyOperand ( Operand - > GetMemoryType ( ) , Operand - > GetRegisterIndex ( ) ) ; // no register offset
if ( bRequired )
{
if ( ! VisitedKeys . Contains ( KeyOperand ) )
{
OutVM - > OperandToDebugRegisters . FindOrAdd ( KeyOperand ) . AddUnique ( * DebugOperand ) ;
VisitedKeys . Add ( KeyOperand ) ;
}
}
else
{
TArray < FRigVMOperand > * MappedOperands = OutVM - > OperandToDebugRegisters . Find ( KeyOperand ) ;
if ( MappedOperands )
{
MappedOperands - > Remove ( * DebugOperand ) ;
if ( MappedOperands - > IsEmpty ( ) )
{
OutVM - > OperandToDebugRegisters . Remove ( KeyOperand ) ;
}
}
}
}
}
}
}
}
2020-01-22 17:58:55 -05:00
UScriptStruct * URigVMCompiler : : GetScriptStructForCPPType ( const FString & InCPPType )
{
if ( InCPPType = = TEXT ( " FRotator " ) )
{
return TBaseStructure < FRotator > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FQuat " ) )
{
return TBaseStructure < FQuat > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FTransform " ) )
{
return TBaseStructure < FTransform > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FLinearColor " ) )
{
return TBaseStructure < FLinearColor > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FColor " ) )
{
return TBaseStructure < FColor > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FPlane " ) )
{
return TBaseStructure < FPlane > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FVector " ) )
{
return TBaseStructure < FVector > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FVector2D " ) )
{
return TBaseStructure < FVector2D > : : Get ( ) ;
}
if ( InCPPType = = TEXT ( " FVector4 " ) )
{
return TBaseStructure < FVector4 > : : Get ( ) ;
}
return nullptr ;
}
TArray < URigVMPin * > URigVMCompiler : : GetLinkedPins ( URigVMPin * InPin , bool bInputs , bool bOutputs , bool bRecursive )
{
TArray < URigVMPin * > LinkedPins ;
for ( URigVMLink * Link : InPin - > GetLinks ( ) )
{
if ( bInputs & & Link - > GetTargetPin ( ) = = InPin )
{
LinkedPins . Add ( Link - > GetSourcePin ( ) ) ;
}
else if ( bOutputs & & Link - > GetSourcePin ( ) = = InPin )
{
LinkedPins . Add ( Link - > GetTargetPin ( ) ) ;
}
}
if ( bRecursive )
{
for ( URigVMPin * SubPin : InPin - > GetSubPins ( ) )
{
LinkedPins . Append ( GetLinkedPins ( SubPin , bInputs , bOutputs , bRecursive ) ) ;
}
}
return LinkedPins ;
}
uint16 URigVMCompiler : : GetElementSizeFromCPPType ( const FString & InCPPType , UScriptStruct * InScriptStruct )
{
if ( InScriptStruct = = nullptr )
{
InScriptStruct = GetScriptStructForCPPType ( InCPPType ) ;
}
if ( InScriptStruct ! = nullptr )
{
return InScriptStruct - > GetStructureSize ( ) ;
}
if ( InCPPType = = TEXT ( " bool " ) )
{
return sizeof ( bool ) ;
}
else if ( InCPPType = = TEXT ( " int32 " ) )
{
return sizeof ( int32 ) ;
}
if ( InCPPType = = TEXT ( " float " ) )
{
return sizeof ( float ) ;
}
2021-06-22 14:11:52 -04:00
if ( InCPPType = = TEXT ( " double " ) )
{
return sizeof ( double ) ;
}
2020-01-22 17:58:55 -05:00
if ( InCPPType = = TEXT ( " FName " ) )
{
return sizeof ( FName ) ;
}
if ( InCPPType = = TEXT ( " FString " ) )
{
return sizeof ( FString ) ;
}
ensure ( false ) ;
return 0 ;
}
FRigVMOperand URigVMCompiler : : FindOrAddRegister ( const FRigVMVarExprAST * InVarExpr , FRigVMCompilerWorkData & WorkData , bool bIsDebugValue )
{
2021-08-18 06:18:21 -04:00
if ( ! bIsDebugValue )
{
InVarExpr = GetSourceVarExpr ( InVarExpr ) ;
}
2020-01-22 17:58:55 -05:00
if ( ! bIsDebugValue )
{
FRigVMOperand const * ExistingOperand = WorkData . ExprToOperand . Find ( InVarExpr ) ;
if ( ExistingOperand )
{
return * ExistingOperand ;
}
}
2021-01-19 04:57:43 -04:00
const URigVMPin : : FPinOverrideMap & PinOverrides = InVarExpr - > GetParser ( ) - > GetPinOverrides ( ) ;
URigVMPin : : FPinOverride PinOverride ( InVarExpr - > GetProxy ( ) , PinOverrides ) ;
2020-01-22 17:58:55 -05:00
URigVMPin * Pin = InVarExpr - > GetPin ( ) ;
2021-07-29 14:29:52 -04:00
2022-11-10 04:36:01 -05:00
if ( Pin - > IsExecuteContext ( ) )
2021-07-29 14:29:52 -04:00
{
return FRigVMOperand ( ) ;
}
2021-07-27 14:04:39 -04:00
FString CPPType = Pin - > GetCPPType ( ) ;
FString BaseCPPType = Pin - > IsArray ( ) ? Pin - > GetArrayElementCppType ( ) : CPPType ;
2022-10-24 08:59:51 -04:00
FString Hash = GetPinHash ( Pin , InVarExpr , bIsDebugValue , CurrentCompilationFunction ) ;
2020-01-22 17:58:55 -05:00
FRigVMOperand Operand ;
FString RegisterKey = Hash ;
bool bIsExecutePin = Pin - > IsExecuteContext ( ) ;
2020-11-18 07:48:31 -04:00
bool bIsLiteral = InVarExpr - > GetType ( ) = = FRigVMExprAST : : EType : : Literal & & ! bIsDebugValue ;
2021-04-29 09:47:07 -04:00
bool bIsVariable = Pin - > IsRootPin ( ) & & ( Pin - > GetName ( ) = = URigVMVariableNode : : ValueName ) & &
InVarExpr - > GetPin ( ) - > GetNode ( ) - > IsA < URigVMVariableNode > ( ) ;
2021-05-11 17:13:58 -04:00
// external variables don't require to add any register.
2021-04-29 09:47:07 -04:00
if ( bIsVariable & & ! bIsDebugValue )
{
for ( int32 ExternalVariableIndex = 0 ; ExternalVariableIndex < WorkData . VM - > GetExternalVariables ( ) . Num ( ) ; ExternalVariableIndex + + )
{
const FName & ExternalVariableName = WorkData . VM - > GetExternalVariables ( ) [ ExternalVariableIndex ] . Name ;
const FString ExternalVariableHash = FString : : Printf ( TEXT ( " Variable::%s " ) , * ExternalVariableName . ToString ( ) ) ;
if ( ExternalVariableHash = = Hash )
{
Operand = FRigVMOperand ( ERigVMMemoryType : : External , ExternalVariableIndex , INDEX_NONE ) ;
WorkData . ExprToOperand . Add ( InVarExpr , Operand ) ;
WorkData . PinPathToOperand - > FindOrAdd ( Hash ) = Operand ;
return Operand ;
}
}
}
2020-01-22 17:58:55 -05:00
2021-07-27 14:04:39 -04:00
const ERigVMMemoryType MemoryType =
bIsLiteral ? ERigVMMemoryType : : Literal :
( bIsDebugValue ? ERigVMMemoryType : : Debug : ERigVMMemoryType : : Work ) ;
2022-09-05 07:45:28 -04:00
TArray < FString > HashesWithSharedOperand ;
2022-10-27 14:59:45 -04:00
FRigVMOperand const * ExistingOperandPtr = WorkData . PinPathToOperand - > Find ( Hash ) ;
if ( ! ExistingOperandPtr )
2022-09-05 07:45:28 -04:00
{
if ( Settings . ASTSettings . bFoldAssignments )
{
// Get all possible pins that lead to the same operand
const FRigVMCompilerWorkData : : FRigVMASTProxyArray PinProxies = FindProxiesWithSharedOperand ( InVarExpr , WorkData ) ;
ensure ( ! PinProxies . IsEmpty ( ) ) ;
// Look for an existing operand from a different pin with shared operand
for ( const FRigVMASTProxy & Proxy : PinProxies )
{
if ( const URigVMPin * VirtualPin = Cast < URigVMPin > ( Proxy . GetSubject ( ) ) )
{
2022-10-24 08:59:51 -04:00
const FString VirtualPinHash = GetPinHash ( VirtualPin , InVarExpr , bIsDebugValue , CurrentCompilationFunction , Proxy ) ;
2022-09-05 07:45:28 -04:00
HashesWithSharedOperand . Add ( VirtualPinHash ) ;
if ( Pin ! = VirtualPin )
{
2022-10-27 14:59:45 -04:00
ExistingOperandPtr = WorkData . PinPathToOperand - > Find ( VirtualPinHash ) ;
if ( ExistingOperandPtr )
2022-09-05 07:45:28 -04:00
{
break ;
}
}
}
}
}
}
2022-10-27 14:59:45 -04:00
if ( ExistingOperandPtr )
2020-01-22 17:58:55 -05:00
{
2022-10-27 14:59:45 -04:00
// Dereference the operand pointer here since modifying the PinPathToOperand map will invalidate the pointer.
FRigVMOperand ExistingOperand = * ExistingOperandPtr ;
2022-10-24 20:34:56 -04:00
// Add any missing hash that shares this existing operand
for ( const FString & VirtualPinHash : HashesWithSharedOperand )
2020-01-22 17:58:55 -05:00
{
2022-10-27 14:59:45 -04:00
WorkData . PinPathToOperand - > Add ( VirtualPinHash , ExistingOperand ) ;
2020-01-22 17:58:55 -05:00
}
2022-10-24 20:34:56 -04:00
if ( ! bIsDebugValue )
{
check ( ! WorkData . ExprToOperand . Contains ( InVarExpr ) ) ;
2022-10-27 14:59:45 -04:00
WorkData . ExprToOperand . Add ( InVarExpr , ExistingOperand ) ;
2022-10-24 20:34:56 -04:00
}
2022-10-27 14:59:45 -04:00
return ExistingOperand ;
2020-01-22 17:58:55 -05:00
}
// create remaining operands / registers
if ( ! Operand . IsValid ( ) )
{
FName RegisterName = * RegisterKey ;
2021-07-27 14:04:39 -04:00
FString JoinedDefaultValue ;
2020-01-22 17:58:55 -05:00
TArray < FString > DefaultValues ;
if ( Pin - > IsArray ( ) )
{
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Hidden )
{
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = Pin - > GetDefaultValue ( PinOverride ) ;
DefaultValues = URigVMPin : : SplitDefaultValue ( JoinedDefaultValue ) ;
2020-01-22 17:58:55 -05:00
}
else
{
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = Pin - > GetDefaultValue ( PinOverride ) ;
if ( ! JoinedDefaultValue . IsEmpty ( ) )
{
if ( JoinedDefaultValue [ 0 ] = = TCHAR ( ' ( ' ) )
{
DefaultValues = URigVMPin : : SplitDefaultValue ( JoinedDefaultValue ) ;
}
else
{
DefaultValues . Add ( JoinedDefaultValue ) ;
}
}
2020-01-22 17:58:55 -05:00
}
while ( DefaultValues . Num ( ) < Pin - > GetSubPins ( ) . Num ( ) )
{
DefaultValues . Add ( FString ( ) ) ;
}
}
2020-09-24 00:43:27 -04:00
else if ( URigVMEnumNode * EnumNode = Cast < URigVMEnumNode > ( Pin - > GetNode ( ) ) )
{
2021-01-19 04:57:43 -04:00
FString EnumValueStr = EnumNode - > GetDefaultValue ( PinOverride ) ;
2020-09-24 00:43:27 -04:00
if ( UEnum * Enum = EnumNode - > GetEnum ( ) )
{
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = FString : : FromInt ( ( int32 ) Enum - > GetValueByNameString ( EnumValueStr ) ) ;
DefaultValues . Add ( JoinedDefaultValue ) ;
2020-09-24 00:43:27 -04:00
}
else
{
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = FString : : FromInt ( 0 ) ;
DefaultValues . Add ( JoinedDefaultValue ) ;
2020-09-24 00:43:27 -04:00
}
}
2020-01-22 17:58:55 -05:00
else
{
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = Pin - > GetDefaultValue ( PinOverride ) ;
DefaultValues . Add ( JoinedDefaultValue ) ;
2020-01-22 17:58:55 -05:00
}
UScriptStruct * ScriptStruct = Pin - > GetScriptStruct ( ) ;
if ( ScriptStruct = = nullptr )
{
ScriptStruct = GetScriptStructForCPPType ( BaseCPPType ) ;
}
if ( ! Operand . IsValid ( ) )
{
2021-05-18 10:22:22 -04:00
const int32 NumSlices = 1 ;
2021-04-29 05:02:50 -04:00
int32 Register = INDEX_NONE ;
// debug watch register might already exists - look for them by name
2021-07-27 14:04:39 -04:00
if ( bIsDebugValue )
{
Operand = WorkData . FindProperty ( MemoryType , RegisterName ) ;
if ( Operand . IsValid ( ) )
{
2021-07-28 03:35:30 -04:00
FRigVMPropertyDescription Property = WorkData . GetProperty ( Operand ) ;
2021-07-27 14:04:39 -04:00
if ( Property . IsValid ( ) )
{
2022-10-27 14:59:45 -04:00
if ( ExistingOperandPtr = = nullptr )
2021-07-27 14:04:39 -04:00
{
WorkData . PinPathToOperand - > Add ( Hash , Operand ) ;
}
return Operand ;
}
}
}
}
2021-07-29 14:29:52 -04:00
if ( bIsDebugValue )
{
// debug values are always stored as arrays
2022-03-31 14:40:13 -04:00
CPPType = RigVMTypeUtils : : ArrayTypeFromBaseType ( CPPType ) ;
2021-08-06 19:39:37 -04:00
JoinedDefaultValue = URigVMPin : : GetDefaultValueForArray ( { JoinedDefaultValue } ) ;
2021-07-29 14:29:52 -04:00
}
2022-07-05 11:39:15 -04:00
else if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Hidden )
2021-07-30 15:49:56 -04:00
{
2022-07-05 11:39:15 -04:00
bool bValidHiddenPin = false ;
if ( Pin - > GetNode ( ) - > IsA < URigVMUnitNode > ( ) )
{
UScriptStruct * UnitStruct = Cast < URigVMUnitNode > ( Pin - > GetNode ( ) ) - > GetScriptStruct ( ) ;
const FProperty * Property = UnitStruct - > FindPropertyByName ( Pin - > GetFName ( ) ) ;
check ( Property ) ;
2021-07-30 15:49:56 -04:00
2022-12-06 09:43:35 -05:00
JoinedDefaultValue . Reset ( ) ;
FStructOnScope StructOnScope ( UnitStruct ) ;
const FRigVMStruct * StructMemory = ( const FRigVMStruct * ) StructOnScope . GetStructMemory ( ) ;
const uint8 * PropertyMemory = Property - > ContainerPtrToValuePtr < uint8 > ( StructMemory ) ;
Property - > ExportText_Direct (
JoinedDefaultValue ,
PropertyMemory ,
PropertyMemory ,
nullptr ,
PPF_None ,
nullptr ) ;
2022-07-05 11:39:15 -04:00
if ( ! Property - > HasMetaData ( FRigVMStruct : : SingletonMetaName ) )
{
bValidHiddenPin = true ;
}
}
2022-11-30 10:26:42 -05:00
else if ( URigVMDispatchNode * DispatchNode = Cast < URigVMDispatchNode > ( Pin - > GetNode ( ) ) )
2022-07-05 11:39:15 -04:00
{
bValidHiddenPin = true ;
2022-11-30 10:26:42 -05:00
if ( const FRigVMDispatchFactory * Factory = DispatchNode - > GetFactory ( ) )
{
bValidHiddenPin = ! Factory - > HasArgumentMetaData ( Pin - > GetFName ( ) , FRigVMStruct : : SingletonMetaName ) ;
2022-12-06 09:43:35 -05:00
JoinedDefaultValue = Factory - > GetArgumentDefaultValue ( Pin - > GetFName ( ) , Pin - > GetTypeIndex ( ) ) ;
2022-11-30 10:26:42 -05:00
}
2022-07-05 11:39:15 -04:00
}
if ( bValidHiddenPin )
2021-07-30 15:49:56 -04:00
{
2022-03-31 14:40:13 -04:00
CPPType = RigVMTypeUtils : : ArrayTypeFromBaseType ( CPPType ) ;
2021-08-06 19:39:37 -04:00
JoinedDefaultValue = URigVMPin : : GetDefaultValueForArray ( { JoinedDefaultValue } ) ;
2021-07-30 15:49:56 -04:00
}
}
2021-08-07 15:31:27 -04:00
2021-07-27 14:04:39 -04:00
Operand = WorkData . AddProperty ( MemoryType , RegisterName , CPPType , Pin - > GetCPPTypeObject ( ) , JoinedDefaultValue ) ;
2020-01-22 17:58:55 -05:00
}
ensure ( Operand . IsValid ( ) ) ;
2021-03-19 12:43:05 -04:00
// Get all possible pins that lead to the same operand
2021-09-27 11:48:28 -04:00
if ( Settings . ASTSettings . bFoldAssignments )
2021-03-31 13:16:23 -04:00
{
2021-11-18 12:28:07 -05:00
// tbd: this functionality is only needed when there is a watch anywhere?
//if(!WorkData.WatchedPins.IsEmpty())
2021-03-31 13:16:23 -04:00
{
2022-09-05 07:45:28 -04:00
for ( const FString & VirtualPinHash : HashesWithSharedOperand )
2021-09-27 11:48:28 -04:00
{
2022-09-05 07:45:28 -04:00
WorkData . PinPathToOperand - > Add ( VirtualPinHash , Operand ) ;
2021-11-18 12:28:07 -05:00
}
2021-03-31 13:16:23 -04:00
}
}
else
2021-03-30 10:21:09 -04:00
{
2022-10-27 14:59:45 -04:00
if ( ExistingOperandPtr = = nullptr )
2021-04-29 05:02:50 -04:00
{
WorkData . PinPathToOperand - > Add ( Hash , Operand ) ;
}
2021-03-19 12:43:05 -04:00
}
2021-04-01 09:40:45 -04:00
if ( ! bIsDebugValue )
{
check ( ! WorkData . ExprToOperand . Contains ( InVarExpr ) ) ;
WorkData . ExprToOperand . Add ( InVarExpr , Operand ) ;
}
2020-01-22 17:58:55 -05:00
return Operand ;
}
2021-11-18 12:28:07 -05:00
const FRigVMCompilerWorkData : : FRigVMASTProxyArray & URigVMCompiler : : FindProxiesWithSharedOperand ( const FRigVMVarExprAST * InVarExpr , FRigVMCompilerWorkData & WorkData )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
const FRigVMASTProxy & InProxy = InVarExpr - > GetProxy ( ) ;
if ( const FRigVMCompilerWorkData : : FRigVMASTProxyArray * ExistingArray = WorkData . CachedProxiesWithSharedOperand . Find ( InProxy ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
return * ExistingArray ;
}
FRigVMCompilerWorkData : : FRigVMASTProxyArray PinProxies , PinProxiesToProcess ;
const FRigVMCompilerWorkData : : FRigVMASTProxySourceMap & ProxySources = * WorkData . ProxySources ;
const FRigVMCompilerWorkData : : FRigVMASTProxyTargetsMap & ProxyTargets = WorkData . ProxyTargets ;
2021-09-27 11:48:28 -04:00
2021-11-18 12:28:07 -05:00
PinProxiesToProcess . Add ( InProxy ) ;
2022-03-31 14:40:13 -04:00
const FString CPPType = InProxy . GetSubjectChecked < URigVMPin > ( ) - > GetCPPType ( ) ;
2023-03-02 06:20:07 -05:00
bool bContainsInterfacePin = false ;
2021-11-18 12:28:07 -05:00
for ( int32 ProxyIndex = 0 ; ProxyIndex < PinProxiesToProcess . Num ( ) ; ProxyIndex + + )
{
2023-01-06 10:38:37 -05:00
if ( PinProxiesToProcess [ ProxyIndex ] . IsValid ( ) )
2021-09-27 11:48:28 -04:00
{
2023-01-06 10:38:37 -05:00
if ( URigVMPin * Pin = Cast < URigVMPin > ( PinProxiesToProcess [ ProxyIndex ] . GetSubject ( ) ) )
2021-09-27 11:48:28 -04:00
{
2022-03-31 14:40:13 -04:00
if ( Pin - > GetNode ( ) - > IsA < URigVMVariableNode > ( ) )
2021-09-27 11:48:28 -04:00
{
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input )
{
continue ;
}
}
2022-03-31 14:40:13 -04:00
// due to LWC we may have two pins that don't
// actually share the same CPP type (float vs double)
if ( Pin - > GetCPPType ( ) ! = CPPType )
{
continue ;
}
2023-03-02 06:20:07 -05:00
// when compiling a function, avoid folding pins from entry and return nodes
if ( CurrentCompilationFunction )
{
if ( URigVMNode * Node = Pin - > GetNode ( ) )
{
if ( Node - > IsA < URigVMFunctionEntryNode > ( ) | | Node - > IsA < URigVMFunctionReturnNode > ( ) )
{
if ( bContainsInterfacePin )
{
continue ;
}
bContainsInterfacePin = true ;
}
}
}
2021-09-27 11:48:28 -04:00
}
2023-01-06 10:38:37 -05:00
PinProxies . Add ( PinProxiesToProcess [ ProxyIndex ] ) ;
2021-09-27 11:48:28 -04:00
}
2023-01-06 10:38:37 -05:00
if ( const FRigVMASTProxy * SourceProxy = ProxySources . Find ( PinProxiesToProcess [ ProxyIndex ] ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
if ( SourceProxy - > IsValid ( ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
if ( ! PinProxies . Contains ( * SourceProxy ) & & ! PinProxiesToProcess . Contains ( * SourceProxy ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
PinProxiesToProcess . Add ( * SourceProxy ) ;
}
}
}
2023-01-06 10:38:37 -05:00
if ( const FRigVMCompilerWorkData : : FRigVMASTProxyArray * TargetProxies = WorkData . ProxyTargets . Find ( PinProxiesToProcess [ ProxyIndex ] ) )
2021-11-18 12:28:07 -05:00
{
for ( const FRigVMASTProxy & TargetProxy : * TargetProxies )
{
if ( TargetProxy . IsValid ( ) )
{
if ( ! PinProxies . Contains ( TargetProxy ) & & ! PinProxiesToProcess . Contains ( TargetProxy ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
PinProxiesToProcess . Add ( TargetProxy ) ;
2021-09-27 11:48:28 -04:00
}
}
}
}
}
2021-10-11 05:25:39 -04:00
if ( PinProxies . IsEmpty ( ) )
{
PinProxies . Add ( InVarExpr - > GetProxy ( ) ) ;
}
2021-11-18 12:28:07 -05:00
// store the cache for all other proxies within this group
for ( const FRigVMASTProxy & CurrentProxy : PinProxies )
{
if ( CurrentProxy ! = InProxy )
{
WorkData . CachedProxiesWithSharedOperand . Add ( CurrentProxy , PinProxies ) ;
}
}
// finally store and return the cache the the input proxy
return WorkData . CachedProxiesWithSharedOperand . Add ( InProxy , PinProxies ) ;
2021-09-27 11:48:28 -04:00
}
2022-07-05 11:39:15 -04:00
bool URigVMCompiler : : ValidateNode ( URigVMNode * InNode , bool bCheck )
2021-09-08 07:57:30 -04:00
{
2022-07-05 11:39:15 -04:00
if ( bCheck )
2021-09-08 07:57:30 -04:00
{
2022-07-05 11:39:15 -04:00
check ( InNode )
2021-09-08 07:57:30 -04:00
}
2022-07-05 11:39:15 -04:00
if ( InNode )
{
if ( InNode - > HasWildCardPin ( ) )
{
static const FString UnknownTypeMessage = TEXT ( " Node @@ has unresolved pins of wildcard type. " ) ;
Settings . Report ( EMessageSeverity : : Error , InNode , UnknownTypeMessage ) ;
return false ;
}
return true ;
}
return false ;
2021-09-08 07:57:30 -04:00
}
2020-01-22 17:58:55 -05:00
void URigVMCompiler : : ReportInfo ( const FString & InMessage )
{
2021-01-19 07:26:41 -04:00
if ( Settings . SurpressInfoMessages )
2020-01-22 17:58:55 -05:00
{
2021-01-19 07:26:41 -04:00
return ;
2020-01-22 17:58:55 -05:00
}
2021-01-19 07:26:41 -04:00
Settings . Report ( EMessageSeverity : : Info , nullptr , InMessage ) ;
2020-01-22 17:58:55 -05:00
}
void URigVMCompiler : : ReportWarning ( const FString & InMessage )
{
2021-01-19 07:26:41 -04:00
Settings . Report ( EMessageSeverity : : Warning , nullptr , InMessage ) ;
2020-01-22 17:58:55 -05:00
}
void URigVMCompiler : : ReportError ( const FString & InMessage )
{
2021-01-19 07:26:41 -04:00
Settings . Report ( EMessageSeverity : : Error , nullptr , InMessage ) ;
2020-01-22 17:58:55 -05:00
}
2022-09-24 13:31:25 -04:00