2020-01-22 17:58:55 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "RigVMCompiler/RigVMCompiler.h"
# include "RigVMModel/RigVMController.h"
# include "RigVMCore/RigVMExecuteContext.h"
# include "RigVMDeveloperModule.h"
# include "UObject/PropertyPortFlags.h"
# include "Stats/StatsHierarchical.h"
2021-11-18 08:00:07 -05:00
# include "RigVMTypeUtils.h"
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
{
}
2021-07-27 14:04:39 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
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 ) ;
2021-07-28 03:35:30 -04:00
FRigVMPropertyDescription Description ( InName , InCPPType , InCPPTypeObject , 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
}
# endif
2020-01-22 17:58:55 -05:00
URigVMCompiler : : URigVMCompiler ( )
{
}
2020-09-24 00:43:27 -04:00
bool URigVMCompiler : : Compile ( URigVMGraph * InGraph , URigVMController * InController , URigVM * OutVM , const TArray < FRigVMExternalVariable > & InExternalVariables , const TArray < FRigVMUserDataArray > & InRigVMUserData , TMap < FString , FRigVMOperand > * OutOperands , TSharedPtr < FRigVMParserAST > InAST )
2020-01-22 17:58:55 -05:00
{
if ( InGraph = = nullptr )
{
ReportError ( TEXT ( " Provided graph is nullptr. " ) ) ;
return false ;
}
if ( OutVM = = nullptr )
{
ReportError ( TEXT ( " Provided vm is nullptr. " ) ) ;
return false ;
}
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2020-09-24 00:43:27 -04:00
TArray < FRigVMUserDataArray > UserData = InRigVMUserData ;
if ( UserData . Num ( ) = = 0 )
{
UserData . Add ( FRigVMUserDataArray ( ) ) ;
}
2020-01-22 17:58:55 -05:00
OutVM - > Reset ( ) ;
TMap < FString , FRigVMOperand > LocalOperands ;
if ( OutOperands = = nullptr )
{
OutOperands = & LocalOperands ;
}
OutOperands - > Reset ( ) ;
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 ;
VisitedGraphs . Add ( InGraph ) ;
2021-04-07 17:24:36 -04:00
2021-09-22 08:06:30 -04:00
bool bEncounteredGraphError = false ;
2021-04-07 13:09:20 -04:00
for ( int32 GraphIndex = 0 ; GraphIndex < VisitedGraphs . Num ( ) ; GraphIndex + + )
{
URigVMGraph * VisitedGraph = VisitedGraphs [ GraphIndex ] ;
for ( URigVMNode * ModelNode : VisitedGraph - > GetNodes ( ) )
{
2021-04-13 12:03:23 -04:00
FRigVMControllerGraphGuard Guard ( InController , VisitedGraph , false ) ;
2021-04-07 13:09:20 -04:00
if ( ! InController - > RemoveUnusedOrphanedPins ( ModelNode , true ) )
{
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 ;
}
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
}
}
}
2021-04-07 13:09:20 -04:00
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( ModelNode ) )
{
if ( URigVMGraph * ContainedGraph = LibraryNode - > GetContainedGraph ( ) )
{
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 ;
}
}
}
}
}
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 )
{
2021-07-29 14:29:52 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
check ( ExternalVariable . Property ) ;
# endif
2020-09-24 00:43:27 -04:00
FRigVMOperand Operand = OutVM - > AddExternalVariable ( ExternalVariable ) ;
FString Hash = FString : : Printf ( TEXT ( " Variable::%s " ) , * ExternalVariable . Name . ToString ( ) ) ;
OutOperands - > Add ( Hash , Operand ) ;
}
TSharedPtr < FRigVMParserAST > AST = InAST ;
if ( ! AST . IsValid ( ) )
{
AST = MakeShareable ( new FRigVMParserAST ( InGraph , InController , Settings . ASTSettings , InExternalVariables , UserData ) ) ;
InGraph - > RuntimeAST = 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
}
2020-01-22 17:58:55 -05:00
ensure ( AST . IsValid ( ) ) ;
FRigVMCompilerWorkData WorkData ;
WorkData . VM = OutVM ;
WorkData . PinPathToOperand = OutOperands ;
2020-09-24 00:43:27 -04:00
WorkData . RigVMUserData = UserData [ 0 ] ;
2020-01-22 17:58:55 -05:00
WorkData . bSetupMemory = true ;
2021-11-18 12:28:07 -05:00
WorkData . ProxySources = & AST - > SharedOperandPins ;
// 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
2021-09-06 04:39:25 -04:00
# if WITH_EDITOR
// If in editor, make sure we visit all the graphs to initialize local variables
// in case the user wants to edit default values
URigVMFunctionLibrary * FunctionLibrary = InGraph - > GetDefaultFunctionLibrary ( ) ;
2021-09-07 06:09:01 -04:00
if ( FunctionLibrary )
2021-09-06 04:39:25 -04:00
{
2021-09-07 06:09:01 -04:00
for ( URigVMLibraryNode * LibraryNode : FunctionLibrary - > GetFunctions ( ) )
2021-09-06 04:39:25 -04:00
{
2021-09-07 06:09:01 -04:00
for ( FRigVMGraphVariableDescription & Variable : LibraryNode - > GetContainedGraph ( ) - > LocalVariables )
{
FString Path = FString : : Printf ( TEXT ( " LocalVariableDefault::%s|%s::Const " ) , * LibraryNode - > GetFName ( ) . ToString ( ) , * Variable . Name . ToString ( ) ) ;
FRigVMOperand Operand = WorkData . AddProperty ( ERigVMMemoryType : : Literal , * Path , Variable . CPPType , Variable . CPPTypeObject , Variable . DefaultValue ) ;
WorkData . PinPathToOperand - > Add ( Path , Operand ) ;
2021-09-14 10:59:08 -04:00
for ( const FRigVMExternalVariable & ExternalVariable : InExternalVariables )
{
if ( ExternalVariable . Name = = Variable . Name )
{
ReportWarningf ( TEXT ( " Blueprint variable %s is being shadowed by a local variable in function %s " ) , * ExternalVariable . Name . ToString ( ) , * LibraryNode - > GetName ( ) ) ;
}
}
2021-09-07 06:09:01 -04:00
}
2021-09-06 04:39:25 -04:00
}
}
# endif
2021-05-11 17:13:58 -04:00
// Look for all local variables to create the register with the default value in the literal memory
int32 IndexLocalVariable = 0 ;
for ( URigVMGraph * VisitedGraph : VisitedGraphs )
{
for ( const FRigVMGraphVariableDescription & LocalVariable : VisitedGraph - > LocalVariables )
{
2021-11-15 05:32:56 -05:00
auto AddDefaultValueOperand = [ & ] ( URigVMPin * Pin )
{
FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( Pin ) ;
FRigVMVarExprAST * TempVarExpr = AST - > MakeExpr < FRigVMVarExprAST > ( FRigVMExprAST : : EType : : Literal , PinProxy ) ;
FRigVMOperand Operand = FindOrAddRegister ( TempVarExpr , WorkData , false ) ;
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
WorkData . VM - > GetLiteralMemory ( ) . SetRegisterValueFromString ( Operand , LocalVariable . CPPType , LocalVariable . CPPTypeObject , { LocalVariable . DefaultValue } ) ;
# else
check ( Operand . GetMemoryType ( ) = = ERigVMMemoryType : : Literal ) ;
TArray < FRigVMPropertyDescription > & LiteralProperties = WorkData . PropertyDescriptions . FindChecked ( Operand . GetMemoryType ( ) ) ;
LiteralProperties [ Operand . GetRegisterIndex ( ) ] . DefaultValue = LocalVariable . DefaultValue ;
# endif
} ;
// To create the default value in the literal memory, we need to find a pin in a variable node (or bounded to a local variable) that
2021-05-11 17:13:58 -04:00
// uses this local variable
for ( URigVMNode * Node : VisitedGraph - > GetNodes ( ) )
{
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( Node ) )
{
if ( URigVMPin * Pin = VariableNode - > FindPin ( URigVMVariableNode : : VariableName ) )
{
if ( Pin - > GetDefaultValue ( ) = = LocalVariable . Name . ToString ( ) )
{
URigVMPin * ValuePin = VariableNode - > FindPin ( URigVMVariableNode : : ValueName ) ;
2021-11-15 05:32:56 -05:00
AddDefaultValueOperand ( ValuePin ) ;
2021-05-11 17:13:58 -04:00
break ;
}
}
}
}
}
}
2021-07-29 14:29:52 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
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 ) ;
}
}
}
}
}
# endif
2020-01-22 17:58:55 -05:00
// define all parameters independent from sorted nodes
2020-04-07 04:27:49 -04:00
for ( const FRigVMExprAST * Expr : AST - > Expressions )
2020-01-22 17:58:55 -05:00
{
2020-11-18 07:48:31 -04:00
if ( Expr - > IsA ( FRigVMExprAST : : EType : : Literal ) )
{
continue ;
}
2020-04-07 04:27:49 -04:00
if ( Expr - > IsA ( FRigVMExprAST : : EType : : Var ) )
2020-01-22 17:58:55 -05:00
{
2020-04-07 04:27:49 -04:00
const FRigVMVarExprAST * VarExpr = Expr - > To < FRigVMVarExprAST > ( ) ;
2020-01-22 17:58:55 -05:00
{
2020-04-07 04:27:49 -04:00
if ( Cast < URigVMParameterNode > ( VarExpr - > GetPin ( ) - > GetNode ( ) ) )
2020-01-22 17:58:55 -05:00
{
if ( VarExpr - > GetPin ( ) - > GetName ( ) = = TEXT ( " Value " ) )
{
FindOrAddRegister ( VarExpr , WorkData , false /* watchvalue */ ) ;
}
}
}
}
}
2020-04-07 04:27:49 -04:00
WorkData . ExprComplete . Reset ( ) ;
for ( FRigVMExprAST * RootExpr : * AST )
{
TraverseExpression ( RootExpr , WorkData ) ;
}
2020-01-22 17:58:55 -05:00
// If a parameter node has no corresponding AST node, because it's not on the execution path,
// then add a dummy parameter with no register index, so that we can properly add the pins on the
// ControlRig node later and not lose any existing external connections.
for ( URigVMNode * Node : InGraph - > GetNodes ( ) )
{
if ( URigVMParameterNode * ParameterNode = Cast < URigVMParameterNode > ( Node ) )
{
2021-01-12 06:47:41 -04:00
FRigVMASTProxy ParameterNodeProxy = FRigVMASTProxy : : MakeFromUObject ( ParameterNode ) ;
const FRigVMExprAST * ParameterExpr = AST - > GetExprForSubject ( ParameterNodeProxy ) ;
2020-01-22 17:58:55 -05:00
if ( ! ParameterExpr | | ParameterExpr - > IsA ( FRigVMExprAST : : NoOp ) )
{
FName Name = ParameterNode - > GetParameterName ( ) ;
if ( ! WorkData . VM - > ParametersNameMap . Contains ( Name ) )
{
ERigVMParameterType ParameterType = ParameterNode - > IsInput ( ) ? ERigVMParameterType : : Input : ERigVMParameterType : : Output ;
FRigVMParameter Parameter ( ParameterType , Name , INDEX_NONE , ParameterNode - > GetCPPType ( ) , nullptr ) ;
WorkData . VM - > ParametersNameMap . Add ( Parameter . Name , WorkData . VM - > Parameters . Add ( Parameter ) ) ;
}
}
}
}
2021-07-27 14:04:39 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
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 ) ;
TempVarExpr . ParserPtr = AST . Get ( ) ;
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 )
{
2021-08-18 06:18:21 -04:00
UPackage * Package = InGraph - > GetOutermost ( ) ;
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 ( ) ;
2021-07-27 14:04:39 -04:00
# endif
2020-01-22 17:58:55 -05:00
WorkData . bSetupMemory = false ;
WorkData . ExprComplete . Reset ( ) ;
for ( FRigVMExprAST * RootExpr : * AST )
{
TraverseExpression ( RootExpr , WorkData ) ;
}
2020-09-24 00:43:27 -04:00
if ( WorkData . VM - > GetByteCode ( ) . GetInstructions ( ) . Num ( ) = = 0 )
2020-01-22 17:58:55 -05:00
{
2020-09-24 00:43:27 -04:00
WorkData . VM - > GetByteCode ( ) . AddExitOp ( ) ;
2020-01-22 17:58:55 -05:00
}
2020-10-15 13:40:12 -04:00
WorkData . VM - > GetByteCode ( ) . AlignByteCode ( ) ;
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
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2021-05-14 02:36:03 -04:00
for ( int32 GraphIndex = 0 ; GraphIndex < VisitedGraphs . Num ( ) ; GraphIndex + + )
2021-04-29 05:02:50 -04:00
{
2021-05-14 02:36:03 -04:00
URigVMGraph * VisitedGraph = VisitedGraphs [ GraphIndex ] ;
for ( URigVMNode * ModelNode : VisitedGraph - > GetNodes ( ) )
2021-04-29 05:02:50 -04:00
{
2021-05-14 02:36:03 -04:00
for ( URigVMPin * ModelPin : ModelNode - > GetPins ( ) )
2021-04-29 05:02:50 -04:00
{
2021-05-14 02:36:03 -04:00
if ( ModelPin - > RequiresWatch ( true ) )
{
CreateDebugRegister ( ModelPin , WorkData . VM , WorkData . PinPathToOperand , AST ) ;
}
2021-04-29 05:02:50 -04:00
}
}
}
2021-07-29 14:29:52 -04:00
# else
for ( URigVMPin * WatchedPin : WorkData . WatchedPins )
{
MarkDebugWatch ( true , WatchedPin , WorkData . VM , WorkData . PinPathToOperand , AST ) ;
}
# endif
2021-04-29 05:02:50 -04:00
}
2021-07-29 14:29:52 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
// 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 ;
}
# endif
2020-09-24 00:43:27 -04:00
2020-01-22 17:58:55 -05:00
return true ;
}
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 ) ;
2021-05-11 17:13:58 -04:00
InitializeLocalVariables ( InExpr , WorkData ) ;
2020-01-22 17:58:55 -05:00
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 > ( ) ;
2020-12-02 10:59:58 -04:00
if ( URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( CallExternExpr - > GetNode ( ) ) )
2020-09-24 00:43:27 -04:00
{
2020-12-02 10:59:58 -04:00
if ( UnitNode - > IsLoopNode ( ) )
2020-09-24 00:43:27 -04:00
{
TraverseForLoop ( CallExternExpr , WorkData ) ;
break ;
}
}
TraverseCallExtern ( CallExternExpr , WorkData ) ;
2020-01-22 17:58:55 -05:00
break ;
}
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 ;
}
2020-09-24 00:43:27 -04:00
case FRigVMExprAST : : EType : : Branch :
{
TraverseBranch ( InExpr - > To < FRigVMBranchExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : If :
{
TraverseIf ( InExpr - > To < FRigVMIfExprAST > ( ) , WorkData ) ;
break ;
}
case FRigVMExprAST : : EType : : Select :
{
TraverseSelect ( InExpr - > To < FRigVMSelectExprAST > ( ) , WorkData ) ;
break ;
}
2021-08-18 06:18:21 -04:00
case FRigVMExprAST : : EType : : Array :
{
TraverseArray ( InExpr - > To < FRigVMArrayExprAST > ( ) , 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 ;
}
TraverseChildren ( InExpr , WorkData ) ;
}
void URigVMCompiler : : TraverseEntry ( const FRigVMEntryExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
2020-12-02 10:59:58 -04:00
URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( UnitNode ) )
{
return ;
}
2020-01-22 17:58:55 -05:00
if ( WorkData . bSetupMemory )
{
2020-12-02 10:59:58 -04:00
TSharedPtr < FStructOnScope > DefaultStruct = UnitNode - > ConstructStructInstance ( ) ;
2020-01-22 17:58:55 -05:00
WorkData . DefaultStructs . Add ( DefaultStruct ) ;
TraverseChildren ( InExpr , WorkData ) ;
WorkData . DefaultStructs . Pop ( ) ;
}
else
{
// todo: define the entry in the VM
TArray < FRigVMOperand > Operands ;
for ( FRigVMExprAST * ChildExpr : * InExpr )
{
if ( ChildExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
2021-08-18 06:18:21 -04:00
Operands . Add ( WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ChildExpr ) ) ) ;
2020-01-22 17:58:55 -05:00
}
else
{
break ;
}
}
// setup the instruction
2020-12-02 10:59:58 -04:00
int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( UnitNode - > GetScriptStruct ( ) , UnitNode - > GetMethodName ( ) ) ;
2020-09-24 00:43:27 -04:00
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , Operands ) ;
int32 EntryInstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2020-12-02 10:59:58 -04:00
FName Entryname = UnitNode - > GetEventName ( ) ;
2020-09-24 00:43:27 -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 )
{
2021-05-11 17:13:58 -04:00
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
TraverseChildren ( InExpr , WorkData ) ;
}
}
2020-09-24 00:43:27 -04:00
int32 URigVMCompiler : : TraverseCallExtern ( const FRigVMCallExternExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
2020-01-22 17:58:55 -05:00
{
2020-12-02 10:59:58 -04:00
URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( UnitNode ) )
{
return INDEX_NONE ;
}
2020-01-22 17:58:55 -05:00
2020-09-24 00:43:27 -04:00
int32 InstructionIndex = INDEX_NONE ;
2020-01-22 17:58:55 -05:00
if ( WorkData . bSetupMemory )
{
2020-12-02 10:59:58 -04:00
TSharedPtr < FStructOnScope > DefaultStruct = UnitNode - > ConstructStructInstance ( ) ;
2020-01-22 17:58:55 -05:00
WorkData . DefaultStructs . Add ( DefaultStruct ) ;
TraverseChildren ( InExpr , WorkData ) ;
WorkData . DefaultStructs . Pop ( ) ;
}
else
{
TArray < FRigVMOperand > Operands ;
for ( FRigVMExprAST * ChildExpr : * InExpr )
{
if ( ChildExpr - > GetType ( ) = = FRigVMExprAST : : EType : : CachedValue )
{
2021-08-18 06:18:21 -04:00
Operands . Add ( WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ChildExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ) ) ) ;
2020-01-22 17:58:55 -05:00
}
else if ( ChildExpr - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
2021-08-18 06:18:21 -04:00
Operands . Add ( WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ChildExpr - > To < FRigVMVarExprAST > ( ) ) ) ) ;
2020-01-22 17:58:55 -05:00
}
else
{
break ;
}
}
TraverseChildren ( InExpr , WorkData ) ;
// setup the instruction
2020-12-02 10:59:58 -04:00
int32 FunctionIndex = WorkData . VM - > AddRigVMFunction ( UnitNode - > GetScriptStruct ( ) , UnitNode - > GetMethodName ( ) ) ;
2020-09-24 00:43:27 -04:00
WorkData . VM - > GetByteCode ( ) . AddExecuteOp ( FunctionIndex , Operands ) ;
InstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-10-12 21:21:22 -04:00
# if WITH_EDITORONLY_DATA
TArray < FRigVMOperand > InputsOperands , OutputOperands ;
for ( const URigVMPin * InputPin : UnitNode - > GetPins ( ) )
{
if ( InputPin - > IsExecuteContext ( ) )
{
continue ;
}
const FRigVMOperand & Operand = Operands [ InputPin - > GetPinIndex ( ) ] ;
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 (
InstructionIndex ,
FRigVMOperandArray ( InputsOperands . GetData ( ) , InputsOperands . Num ( ) ) ,
FRigVMOperandArray ( OutputOperands . GetData ( ) , OutputOperands . Num ( ) ) ) ;
# endif
2020-09-24 00:43:27 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2020-09-24 00:43:27 -04:00
}
2020-01-22 17:58:55 -05:00
}
2020-09-24 00:43:27 -04:00
return InstructionIndex ;
}
void URigVMCompiler : : TraverseForLoop ( const FRigVMCallExternExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
if ( WorkData . bSetupMemory )
{
TraverseCallExtern ( InExpr , WorkData ) ;
return ;
}
2020-12-02 10:59:58 -04:00
URigVMUnitNode * UnitNode = Cast < URigVMUnitNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( UnitNode ) )
{
return ;
}
2021-05-11 17:13:58 -04:00
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2020-09-24 00:43:27 -04:00
const FRigVMVarExprAST * CompletedExpr = InExpr - > FindVarWithPinName ( FRigVMStruct : : ForLoopCompletedPinName ) ;
check ( CompletedExpr ) ;
const FRigVMVarExprAST * ExecuteExpr = InExpr - > FindVarWithPinName ( FRigVMStruct : : ExecuteContextName ) ;
check ( ExecuteExpr ) ;
WorkData . ExprToSkip . AddUnique ( CompletedExpr ) ;
WorkData . ExprToSkip . AddUnique ( ExecuteExpr ) ;
// set the index to 0
const FRigVMVarExprAST * IndexExpr = InExpr - > FindVarWithPinName ( FRigVMStruct : : ForLoopIndexPinName ) ;
check ( IndexExpr ) ;
FRigVMOperand IndexOperand = WorkData . ExprToOperand . FindChecked ( IndexExpr ) ;
WorkData . VM - > GetByteCode ( ) . AddZeroOp ( IndexOperand ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// call the for loop compute
int32 ForLoopInstructionIndex = TraverseCallExtern ( InExpr , WorkData ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( ForLoopInstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// set up the jump forward (jump out of the loop)
const FRigVMVarExprAST * ContinueLoopExpr = InExpr - > FindVarWithPinName ( FRigVMStruct : : ForLoopContinuePinName ) ;
check ( ContinueLoopExpr ) ;
FRigVMOperand ContinueLoopOperand = WorkData . ExprToOperand . FindChecked ( ContinueLoopExpr ) ;
uint64 JumpToEndByte = WorkData . VM - > GetByteCode ( ) . AddJumpIfOp ( ERigVMOpCode : : JumpForwardIf , 0 , ContinueLoopOperand , false ) ;
int32 JumpToEndInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// begin the loop's block
const FRigVMVarExprAST * CountExpr = InExpr - > FindVarWithPinName ( FRigVMStruct : : ForLoopCountPinName ) ;
check ( CountExpr ) ;
FRigVMOperand CountOperand = WorkData . ExprToOperand . FindChecked ( CountExpr ) ;
WorkData . VM - > GetByteCode ( ) . AddBeginBlockOp ( CountOperand , IndexOperand ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// traverse the body of the loop
WorkData . ExprToSkip . Remove ( ExecuteExpr ) ;
TraverseExpression ( ExecuteExpr , WorkData ) ;
// end the loop's block
WorkData . VM - > GetByteCode ( ) . AddEndBlockOp ( ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// increment the index
WorkData . VM - > GetByteCode ( ) . AddIncrementOp ( IndexOperand ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// jump to the beginning of the loop
int32 JumpToStartInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpBackward , JumpToStartInstruction - ForLoopInstructionIndex ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// update the jump operator with the right address
int32 InstructionsToEnd = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToEndInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpIfOp > ( JumpToEndByte ) . InstructionIndex = InstructionsToEnd ;
// now traverse everything else connected to the completed pin
WorkData . ExprToSkip . Remove ( CompletedExpr ) ;
TraverseExpression ( CompletedExpr , WorkData ) ;
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 ) ;
2020-01-22 17:58:55 -05:00
FRigVMOperand Target = WorkData . ExprToOperand . FindChecked ( TargetExpr ) ;
2021-08-18 06:18:21 -04:00
if ( Target = = Source )
{
return ;
}
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
{
2021-07-27 14:04:39 -04:00
static void SetupRegisterOffset ( URigVM * VM , URigVMPin * Pin , FRigVMOperand & Operand , const FRigVMVarExprAST * VarExpr , bool bSource , FRigVMCompilerWorkData & WorkData )
2020-01-22 17:58:55 -05:00
{
URigVMPin * RootPin = Pin - > GetRootPin ( ) ;
if ( Pin = = RootPin )
{
return ;
}
2020-09-24 00:43:27 -04:00
if ( URigVMSelectNode * SelectNode = Cast < URigVMSelectNode > ( RootPin - > GetNode ( ) ) )
{
if ( Pin - > GetParentPin ( ) = = RootPin & & RootPin - > GetName ( ) = = URigVMSelectNode : : ValueName )
{
return ;
}
}
2020-01-22 17:58:55 -05:00
FString SegmentPath = Pin - > GetSegmentPath ( ) ;
2021-07-29 14:29:52 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-01-22 17:58:55 -05:00
int32 ArrayIndex = INDEX_NONE ;
if ( RootPin - > IsArray ( ) )
{
FString SegmentArrayIndex = SegmentPath ;
int32 DotIndex = INDEX_NONE ;
if ( SegmentPath . FindChar ( ' . ' , DotIndex ) )
{
SegmentArrayIndex = SegmentPath . Left ( DotIndex ) ;
SegmentPath = SegmentPath . Mid ( DotIndex + 1 ) ;
}
else
2021-07-29 14:29:52 -04:00
{
2020-01-22 17:58:55 -05:00
SegmentPath = FString ( ) ;
}
ArrayIndex = FCString : : Atoi ( * SegmentArrayIndex ) ;
}
2021-07-29 14:29:52 -04:00
2020-09-24 00:43:27 -04:00
if ( Operand . GetMemoryType ( ) = = ERigVMMemoryType : : External )
{
const FRigVMExternalVariable & ExternalVariable = VM - > GetExternalVariables ( ) [ Operand . GetRegisterIndex ( ) ] ;
UScriptStruct * ScriptStruct = CastChecked < UScriptStruct > ( ExternalVariable . TypeObject ) ;
2021-05-27 13:40:37 -04:00
int32 RegisterOffset = VM - > GetWorkMemory ( ) . GetOrAddRegisterOffset ( INDEX_NONE , ScriptStruct , SegmentPath , ArrayIndex = = INDEX_NONE ? 0 : ArrayIndex , ExternalVariable . Size ) ;
2020-09-24 00:43:27 -04:00
Operand = FRigVMOperand ( ERigVMMemoryType : : External , Operand . GetRegisterIndex ( ) , RegisterOffset ) ;
}
else
{
2021-04-29 05:02:50 -04:00
FRigVMMemoryContainer & Memory = Operand . GetMemoryType ( ) = = ERigVMMemoryType : : Literal ? VM - > GetLiteralMemory ( ) :
( Operand . GetMemoryType ( ) = = ERigVMMemoryType : : Work ? VM - > GetWorkMemory ( ) : VM - > GetDebugMemory ( ) ) ;
2020-09-24 00:43:27 -04:00
Operand = Memory . GetOperand ( Operand . GetRegisterIndex ( ) , SegmentPath , ArrayIndex ) ;
}
2021-07-27 14:04:39 -04:00
# else
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 ) ;
# endif
2020-01-22 17:58:55 -05:00
}
} ;
2021-07-27 14:04:39 -04:00
Local : : SetupRegisterOffset ( WorkData . VM , InExpr - > GetSourcePin ( ) , Source , SourceExpr , true , WorkData ) ;
Local : : SetupRegisterOffset ( WorkData . VM , 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
{
2021-08-18 06:18:21 -04:00
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( CopyOp ) ;
int32 InstructionIndex = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
2020-09-24 00:43:27 -04:00
{
2021-10-11 05:23:58 -04:00
if ( URigVMPin * SourcePin = InExpr - > GetSourcePin ( ) )
2020-09-24 00:43:27 -04:00
{
2021-10-11 05:23:58 -04:00
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( SourcePin - > GetNode ( ) ) )
2020-09-24 00:43:27 -04:00
{
2021-10-11 05:23:58 -04:00
const FRigVMCallstack Callstack = SourceExpr - > GetProxy ( ) . GetSibling ( VariableNode ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2020-09-24 00:43:27 -04:00
}
}
2021-10-11 05:23:58 -04:00
if ( URigVMPin * TargetPin = InExpr - > GetTargetPin ( ) )
2020-09-24 00:43:27 -04:00
{
2021-10-11 05:23:58 -04:00
if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( TargetPin - > GetNode ( ) ) )
2020-09-24 00:43:27 -04:00
{
2021-10-11 05:23:58 -04:00
const FRigVMCallstack Callstack = TargetExpr - > GetProxy ( ) . GetSibling ( VariableNode ) . GetCallstack ( ) ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
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 ( ) ;
}
}
void URigVMCompiler : : TraverseBranch ( const FRigVMBranchExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
ensure ( InExpr - > NumChildren ( ) = = 4 ) ;
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
return ;
}
URigVMBranchNode * BranchNode = Cast < URigVMBranchNode > ( InExpr - > GetNode ( ) ) ;
2021-05-11 17:13:58 -04:00
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2020-09-24 00:43:27 -04:00
const FRigVMVarExprAST * ExecuteContextExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 0 ) ;
const FRigVMVarExprAST * ConditionExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 1 ) ;
const FRigVMVarExprAST * TrueExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 2 ) ;
const FRigVMVarExprAST * FalseExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 3 ) ;
// traverse the condition first
TraverseExpression ( ConditionExpr , WorkData ) ;
if ( ConditionExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
ConditionExpr = ConditionExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
FRigVMOperand & ConditionOperand = WorkData . ExprToOperand . FindChecked ( ConditionExpr ) ;
// setup the first jump
uint64 JumpToFalseByte = WorkData . VM - > GetByteCode ( ) . AddJumpIfOp ( ERigVMOpCode : : JumpForwardIf , 1 , ConditionOperand , false ) ;
int32 JumpToFalseInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2020-09-24 00:43:27 -04:00
}
// traverse the true case
TraverseExpression ( TrueExpr , WorkData ) ;
uint64 JumpToEndByte = WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpForward , 1 ) ;
int32 JumpToEndInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// correct the jump to false instruction index
int32 NumInstructionsInTrueCase = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToFalseInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpIfOp > ( JumpToFalseByte ) . InstructionIndex = NumInstructionsInTrueCase ;
// traverse the false case
TraverseExpression ( FalseExpr , WorkData ) ;
// correct the jump to end instruction index
int32 NumInstructionsInFalseCase = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToEndInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpOp > ( JumpToEndByte ) . InstructionIndex = NumInstructionsInFalseCase ;
}
void URigVMCompiler : : TraverseIf ( const FRigVMIfExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
ensure ( InExpr - > NumChildren ( ) = = 4 ) ;
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
return ;
}
URigVMIfNode * IfNode = Cast < URigVMIfNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( IfNode ) )
{
return ;
}
2021-05-11 17:13:58 -04:00
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2020-09-24 00:43:27 -04:00
const FRigVMVarExprAST * ConditionExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 0 ) ;
const FRigVMVarExprAST * TrueExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 1 ) ;
const FRigVMVarExprAST * FalseExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 2 ) ;
const FRigVMVarExprAST * ResultExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 3 ) ;
// traverse the condition first
TraverseExpression ( ConditionExpr , WorkData ) ;
if ( ConditionExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
ConditionExpr = ConditionExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
FRigVMOperand & ConditionOperand = WorkData . ExprToOperand . FindChecked ( ConditionExpr ) ;
FRigVMOperand & ResultOperand = WorkData . ExprToOperand . FindChecked ( ResultExpr ) ;
// setup the first jump
uint64 JumpToFalseByte = WorkData . VM - > GetByteCode ( ) . AddJumpIfOp ( ERigVMOpCode : : JumpForwardIf , 1 , ConditionOperand , false ) ;
int32 JumpToFalseInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2020-09-24 00:43:27 -04:00
}
// traverse the true case
TraverseExpression ( TrueExpr , WorkData ) ;
if ( TrueExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
TrueExpr = TrueExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
FRigVMOperand & TrueOperand = WorkData . ExprToOperand . FindChecked ( TrueExpr ) ;
2021-05-17 12:35:41 -04:00
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( WorkData . VM - > GetCopyOpForOperands ( TrueOperand , ResultOperand ) ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
uint64 JumpToEndByte = WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpForward , 1 ) ;
int32 JumpToEndInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// correct the jump to false instruction index
int32 NumInstructionsInTrueCase = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToFalseInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpIfOp > ( JumpToFalseByte ) . InstructionIndex = NumInstructionsInTrueCase ;
// traverse the false case
TraverseExpression ( FalseExpr , WorkData ) ;
if ( FalseExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
FalseExpr = FalseExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
FRigVMOperand & FalseOperand = WorkData . ExprToOperand . FindChecked ( FalseExpr ) ;
2021-05-17 12:35:41 -04:00
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( WorkData . VM - > GetCopyOpForOperands ( FalseOperand , ResultOperand ) ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
// correct the jump to end instruction index
int32 NumInstructionsInFalseCase = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToEndInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpOp > ( JumpToEndByte ) . InstructionIndex = NumInstructionsInFalseCase ;
}
void URigVMCompiler : : TraverseSelect ( const FRigVMSelectExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
URigVMSelectNode * SelectNode = Cast < URigVMSelectNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( SelectNode ) )
{
return ;
}
2021-05-11 17:13:58 -04:00
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
2021-03-19 06:35:50 -04:00
2020-09-24 00:43:27 -04:00
int32 NumCases = SelectNode - > FindPin ( URigVMSelectNode : : ValueName ) - > GetArraySize ( ) ;
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
// setup literals for each index (we don't need zero)
for ( int32 CaseIndex = 1 ; CaseIndex < NumCases ; CaseIndex + + )
{
if ( ! WorkData . IntegerLiterals . Contains ( CaseIndex ) )
{
FName LiteralName = * FString : : FromInt ( CaseIndex ) ;
2021-07-27 14:04:39 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-09-24 00:43:27 -04:00
int32 Register = WorkData . VM - > GetLiteralMemory ( ) . Add < int32 > ( LiteralName , CaseIndex ) ;
2020-12-04 11:37:54 -04:00
# if WITH_EDITORONLY_DATA
WorkData . VM - > GetLiteralMemory ( ) . Registers [ Register ] . BaseCPPType = TEXT ( " int32 " ) ;
WorkData . VM - > GetLiteralMemory ( ) . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
# endif
2020-09-24 00:43:27 -04:00
FRigVMOperand Operand = WorkData . VM - > GetLiteralMemory ( ) . GetOperand ( Register ) ;
2021-07-27 14:04:39 -04:00
# else
const FString DefaultValue = FString : : FromInt ( CaseIndex ) ;
FRigVMOperand Operand = WorkData . AddProperty (
ERigVMMemoryType : : Literal ,
LiteralName ,
TEXT ( " int32 " ) ,
nullptr ,
DefaultValue ) ;
# endif
2020-09-24 00:43:27 -04:00
WorkData . IntegerLiterals . Add ( CaseIndex , Operand ) ;
}
}
2020-12-04 11:37:54 -04:00
if ( ! WorkData . ComparisonOperand . IsValid ( ) )
2020-09-24 00:43:27 -04:00
{
2021-07-27 14:04:39 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-12-04 11:37:54 -04:00
int32 Register = WorkData . VM - > GetWorkMemory ( ) . Add < bool > ( FName ( TEXT ( " IntEquals " ) ) , false ) ;
# if WITH_EDITORONLY_DATA
WorkData . VM - > GetWorkMemory ( ) . Registers [ Register ] . BaseCPPType = TEXT ( " bool " ) ;
WorkData . VM - > GetWorkMemory ( ) . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
# endif
WorkData . ComparisonOperand = WorkData . VM - > GetWorkMemory ( ) . GetOperand ( Register ) ;
2021-07-27 14:04:39 -04:00
# else
WorkData . ComparisonOperand = WorkData . AddProperty (
ERigVMMemoryType : : Work ,
FName ( TEXT ( " IntEquals " ) ) ,
TEXT ( " bool " ) ,
nullptr ,
TEXT ( " false " ) ) ;
# endif
2020-09-24 00:43:27 -04:00
}
return ;
}
const FRigVMVarExprAST * IndexExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( 0 ) ;
TArray < const FRigVMVarExprAST * > CaseExpressions ;
for ( int32 CaseIndex = 0 ; CaseIndex < NumCases ; CaseIndex + + )
{
CaseExpressions . Add ( InExpr - > ChildAt < FRigVMVarExprAST > ( CaseIndex + 1 ) ) ;
}
const FRigVMVarExprAST * ResultExpr = InExpr - > ChildAt < FRigVMVarExprAST > ( InExpr - > NumChildren ( ) - 1 ) ;
// traverse the condition first
TraverseExpression ( IndexExpr , WorkData ) ;
// this can happen if the optimizer doesn't remove it
if ( CaseExpressions . Num ( ) = = 0 )
{
return ;
}
if ( IndexExpr - > IsA ( FRigVMExprAST : : CachedValue ) )
{
IndexExpr = IndexExpr - > To < FRigVMCachedValueExprAST > ( ) - > GetVarExpr ( ) ;
}
FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( IndexExpr ) ;
FRigVMOperand & ResultOperand = WorkData . ExprToOperand . FindChecked ( ResultExpr ) ;
// setup the jumps for each case
TArray < uint64 > JumpToCaseBytes ;
TArray < int32 > JumpToCaseInstructions ;
JumpToCaseBytes . Add ( 0 ) ;
JumpToCaseInstructions . Add ( 0 ) ;
for ( int32 CaseIndex = 1 ; CaseIndex < NumCases ; CaseIndex + + )
{
// compare and jump eventually
2020-12-04 11:37:54 -04:00
WorkData . VM - > GetByteCode ( ) . AddEqualsOp ( IndexOperand , WorkData . IntegerLiterals . FindChecked ( CaseIndex ) , WorkData . ComparisonOperand ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
2020-09-24 00:43:27 -04:00
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2020-09-24 00:43:27 -04:00
}
2020-12-04 11:37:54 -04:00
uint64 JumpByte = WorkData . VM - > GetByteCode ( ) . AddJumpIfOp ( ERigVMOpCode : : JumpForwardIf , 1 , WorkData . ComparisonOperand , true ) ;
2020-09-24 00:43:27 -04:00
int32 JumpInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
JumpToCaseBytes . Add ( JumpByte ) ;
JumpToCaseInstructions . Add ( JumpInstruction ) ;
}
TArray < uint64 > JumpToEndBytes ;
TArray < int32 > JumpToEndInstructions ;
for ( int32 CaseIndex = 0 ; CaseIndex < NumCases ; CaseIndex + + )
{
if ( CaseIndex > 0 )
{
int32 NumInstructionsInCase = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToCaseInstructions [ CaseIndex ] ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpIfOp > ( JumpToCaseBytes [ CaseIndex ] ) . InstructionIndex = NumInstructionsInCase ;
}
TraverseExpression ( CaseExpressions [ CaseIndex ] , WorkData ) ;
// add copy op to copy the result
2021-08-18 06:18:21 -04:00
FRigVMOperand & CaseOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( CaseExpressions [ CaseIndex ] ) ) ;
2021-05-17 12:35:41 -04:00
WorkData . VM - > GetByteCode ( ) . AddCopyOp ( WorkData . VM - > GetCopyOpForOperands ( CaseOperand , ResultOperand ) ) ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
if ( CaseIndex < NumCases - 1 )
{
uint64 JumpByte = WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpForward , 1 ) ;
int32 JumpInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
2021-03-19 06:35:50 -04:00
if ( Settings . SetupNodeInstructionIndex )
{
2021-05-11 17:13:58 -04:00
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-03-19 06:35:50 -04:00
}
2020-09-24 00:43:27 -04:00
JumpToEndBytes . Add ( JumpByte ) ;
JumpToEndInstructions . Add ( JumpInstruction ) ;
}
}
for ( int32 CaseIndex = 0 ; CaseIndex < NumCases - 1 ; CaseIndex + + )
{
int32 NumInstructionsToEnd = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToEndInstructions [ CaseIndex ] ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpOp > ( JumpToEndBytes [ CaseIndex ] ) . InstructionIndex = NumInstructionsToEnd ;
2020-01-22 17:58:55 -05:00
}
}
2021-08-18 06:18:21 -04:00
void URigVMCompiler : : TraverseArray ( const FRigVMArrayExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
URigVMArrayNode * ArrayNode = Cast < URigVMArrayNode > ( InExpr - > GetNode ( ) ) ;
2021-09-08 07:57:30 -04:00
if ( ! ValidateNode ( ArrayNode ) )
{
return ;
}
2021-08-18 06:18:21 -04:00
if ( WorkData . bSetupMemory )
{
TraverseChildren ( InExpr , WorkData ) ;
}
else
{
const FRigVMCallstack Callstack = InExpr - > GetProxy ( ) . GetCallstack ( ) ;
static const FName ExecuteName = FRigVMStruct : : ExecuteName ;
static const FName ArrayName = * URigVMArrayNode : : ArrayName ;
static const FName NumName = * URigVMArrayNode : : NumName ;
static const FName IndexName = * URigVMArrayNode : : IndexName ;
static const FName ElementName = * URigVMArrayNode : : ElementName ;
static const FName SuccessName = * URigVMArrayNode : : SuccessName ;
static const FName OtherName = * URigVMArrayNode : : OtherName ;
static const FName CloneName = * URigVMArrayNode : : CloneName ;
static const FName CountName = * URigVMArrayNode : : CountName ;
static const FName RatioName = * URigVMArrayNode : : RatioName ;
static const FName ResultName = * URigVMArrayNode : : ResultName ;
static const FName ContinueName = * URigVMArrayNode : : ContinueName ;
static const FName CompletedName = * URigVMArrayNode : : CompletedName ;
const ERigVMOpCode OpCode = ArrayNode - > GetOpCode ( ) ;
switch ( OpCode )
{
case ERigVMOpCode : : ArrayReset :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayResetOp ( ArrayOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayGetNum :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & NumOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayGetNumOp ( ArrayOperand , NumOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArraySetNum :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & NumOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArraySetNumOp ( ArrayOperand , NumOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayGetAtIndex :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayGetAtIndexOp ( ArrayOperand , IndexOperand , ElementOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArraySetAtIndex :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 3 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArraySetAtIndexOp ( ArrayOperand , IndexOperand , ElementOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayAdd :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 3 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayAddOp ( ArrayOperand , ElementOperand , IndexOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayInsert :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 3 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayInsertOp ( ArrayOperand , IndexOperand , ElementOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayRemove :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayRemoveOp ( ArrayOperand , IndexOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayFind :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
const FRigVMOperand & SuccessOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 3 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayFindOp ( ArrayOperand , ElementOperand , IndexOperand , SuccessOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayAppend :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & OtherOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayAppendOp ( ArrayOperand , OtherOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayClone :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & CloneOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayCloneOp ( ArrayOperand , CloneOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayIterator :
{
const FRigVMExprAST * ExecuteExpr = InExpr - > ChildAt ( 0 ) ;
const FRigVMExprAST * ArrayExpr = InExpr - > ChildAt ( 1 ) ;
const FRigVMExprAST * ElementExpr = InExpr - > ChildAt ( 2 ) ;
const FRigVMExprAST * IndexExpr = InExpr - > ChildAt ( 3 ) ;
const FRigVMExprAST * CountExpr = InExpr - > ChildAt ( 4 ) ;
const FRigVMExprAST * RatioExpr = InExpr - > ChildAt ( 5 ) ;
const FRigVMExprAST * ContinueExpr = InExpr - > ChildAt ( 6 ) ;
const FRigVMExprAST * CompletedExpr = InExpr - > ChildAt ( 7 ) ;
const FRigVMOperand & ExecuteOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ExecuteExpr ) ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ArrayExpr ) ) ;
const FRigVMOperand & ElementOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ElementExpr ) ) ;
const FRigVMOperand & IndexOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( IndexExpr ) ) ;
const FRigVMOperand & CountOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( CountExpr ) ) ;
const FRigVMOperand & RatioOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( RatioExpr ) ) ;
const FRigVMOperand & ContinueOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( ContinueExpr ) ) ;
const FRigVMOperand & CompletedOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( CompletedExpr ) ) ;
WorkData . ExprToSkip . AddUnique ( ExecuteExpr ) ;
WorkData . ExprToSkip . AddUnique ( CompletedExpr ) ;
// traverse the input array
TraverseExpression ( ArrayExpr , WorkData ) ;
// zero the index
WorkData . VM - > GetByteCode ( ) . AddZeroOp ( IndexOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// add the iterator
WorkData . VM - > GetByteCode ( ) . AddArrayIteratorOp ( ArrayOperand , ElementOperand , IndexOperand , CountOperand , RatioOperand , ContinueOperand ) ;
const int32 IteratorInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// jump to the end of the loop
const uint64 JumpToEndByte = WorkData . VM - > GetByteCode ( ) . AddJumpIfOp ( ERigVMOpCode : : JumpForwardIf , 0 , ContinueOperand , false ) ;
const int32 JumpToEndInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// begin the block
WorkData . VM - > GetByteCode ( ) . AddBeginBlockOp ( CountOperand , IndexOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// traverse the per iteration instructions
WorkData . ExprToSkip . Remove ( ExecuteExpr ) ;
TraverseExpression ( ExecuteExpr , WorkData ) ;
// end the block
WorkData . VM - > GetByteCode ( ) . AddEndBlockOp ( ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// increment index per loop iteration
WorkData . VM - > GetByteCode ( ) . AddIncrementOp ( IndexOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// jump backwards instruction (to the beginning of the iterator)
const int32 JumpToStartInstruction = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) ;
WorkData . VM - > GetByteCode ( ) . AddJumpOp ( ERigVMOpCode : : JumpBackward , JumpToStartInstruction - IteratorInstruction ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
// fix up the first jump instruction
const int32 InstructionsToEnd = WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - JumpToEndInstruction ;
WorkData . VM - > GetByteCode ( ) . GetOpAt < FRigVMJumpIfOp > ( JumpToEndByte ) . InstructionIndex = InstructionsToEnd ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
WorkData . ExprToSkip . Remove ( CompletedExpr ) ;
TraverseExpression ( CompletedExpr , WorkData ) ;
break ;
}
case ERigVMOpCode : : ArrayUnion :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & OtherOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayUnionOp ( ArrayOperand , OtherOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayDifference :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & OtherOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & ResultOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayDifferenceOp ( ArrayOperand , OtherOperand , ResultOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayIntersection :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 0 ) ) ) ;
const FRigVMOperand & OtherOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
const FRigVMOperand & ResultOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 2 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayIntersectionOp ( ArrayOperand , OtherOperand , ResultOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
case ERigVMOpCode : : ArrayReverse :
{
TraverseChildren ( InExpr , WorkData ) ;
const FRigVMOperand & ArrayOperand = WorkData . ExprToOperand . FindChecked ( GetSourceVarExpr ( InExpr - > ChildAt ( 1 ) ) ) ;
WorkData . VM - > GetByteCode ( ) . AddArrayReverseOp ( ArrayOperand ) ;
if ( Settings . SetupNodeInstructionIndex )
{
WorkData . VM - > GetByteCode ( ) . SetSubject ( WorkData . VM - > GetByteCode ( ) . GetNumInstructions ( ) - 1 , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
}
break ;
}
default :
{
checkNoEntry ( ) ;
break ;
}
}
}
}
2021-05-11 17:13:58 -04:00
void URigVMCompiler : : InitializeLocalVariables ( const FRigVMExprAST * InExpr , FRigVMCompilerWorkData & WorkData )
{
// Initialize local variables if we are entering a new graph
if ( ! WorkData . bSetupMemory )
{
FRigVMByteCode & ByteCode = WorkData . VM - > GetByteCode ( ) ;
2021-08-20 12:55:39 -04:00
const FRigVMASTProxy * Proxy = nullptr ;
2021-05-11 17:13:58 -04:00
switch ( InExpr - > GetType ( ) )
{
case FRigVMExprAST : : EType : : CallExtern :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMCallExternExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : NoOp :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMNoOpExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : Var :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMVarExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : Literal :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMLiteralExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : ExternalVar :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMExternalVarExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : Branch :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMBranchExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : If :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMIfExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
case FRigVMExprAST : : EType : : Select :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMSelectExprAST > ( ) - > GetProxy ( ) ;
2021-05-11 17:13:58 -04:00
break ;
}
2021-08-18 06:18:21 -04:00
case FRigVMExprAST : : EType : : Array :
{
2021-08-20 12:55:39 -04:00
Proxy = & InExpr - > To < FRigVMArrayExprAST > ( ) - > GetProxy ( ) ;
2021-08-18 06:18:21 -04:00
break ;
}
2021-05-11 17:13:58 -04:00
}
2021-08-20 12:55:39 -04:00
if ( Proxy ! = nullptr )
2021-05-11 17:13:58 -04:00
{
2021-08-20 12:55:39 -04:00
const FRigVMCallstack & Callstack = Proxy - > GetCallstack ( ) ;
ensure ( Callstack . Num ( ) > 0 ) ;
2021-08-26 10:32:00 -04:00
// Find all function references in the callstack and initialize their local variables if necessary
for ( int32 SubjectIndex = 0 ; SubjectIndex < Callstack . Num ( ) ; + + SubjectIndex )
2021-05-11 17:13:58 -04:00
{
2021-08-26 10:32:00 -04:00
if ( const URigVMLibraryNode * Node = Cast < const URigVMLibraryNode > ( Callstack [ SubjectIndex ] ) )
2021-05-11 17:13:58 -04:00
{
2021-08-26 10:32:00 -04:00
// Check if this is the first time we are accessing this function reference
bool bFound = false ;
for ( int32 i = ByteCode . GetNumInstructions ( ) - 1 ; i > 0 ; - - i )
2021-05-11 17:13:58 -04:00
{
2021-08-26 10:32:00 -04:00
const TArray < UObject * > * PreviousCallstack = ByteCode . GetCallstackForInstruction ( i ) ;
if ( PreviousCallstack & & PreviousCallstack - > Contains ( Node ) )
{
bFound = true ;
break ;
}
2021-05-11 17:13:58 -04:00
}
2021-08-26 10:32:00 -04:00
// If it is the first time we access this function reference, initialize all local variables
if ( ! bFound )
2021-05-11 17:13:58 -04:00
{
for ( FRigVMGraphVariableDescription Variable : Node - > GetContainedGraph ( ) - > LocalVariables )
{
FString TargetPath = FString : : Printf ( TEXT ( " LocalVariable::%s|%s " ) , * Node - > GetNodePath ( ) , * Variable . Name . ToString ( ) ) ;
2021-06-07 06:49:07 -04:00
FString SourcePath = FString : : Printf ( TEXT ( " LocalVariableDefault::%s|%s::Const " ) , * Node - > GetContainedGraph ( ) - > GetGraphName ( ) , * Variable . Name . ToString ( ) ) ;
2021-05-17 12:35:41 -04:00
FRigVMOperand * TargetPtr = WorkData . PinPathToOperand - > Find ( TargetPath ) ;
FRigVMOperand * SourcePtr = WorkData . PinPathToOperand - > Find ( SourcePath ) ;
if ( SourcePtr & & TargetPtr )
2021-05-11 17:13:58 -04:00
{
2021-05-17 12:35:41 -04:00
const FRigVMOperand & Source = * SourcePtr ;
const FRigVMOperand & Target = * TargetPtr ;
2021-08-26 10:32:00 -04:00
2021-08-20 12:55:39 -04:00
ByteCode . AddCopyOp ( WorkData . VM - > GetCopyOpForOperands ( Source , Target ) ) ;
if ( Settings . SetupNodeInstructionIndex )
{
const int32 InstructionIndex = ByteCode . GetNumInstructions ( ) - 1 ;
WorkData . VM - > GetByteCode ( ) . SetSubject ( InstructionIndex , Callstack . GetCallPath ( ) , Callstack . GetStack ( ) ) ;
2021-08-26 10:32:00 -04:00
}
2021-08-20 12:55:39 -04:00
}
}
2021-05-11 17:13:58 -04:00
}
}
}
}
}
}
2021-03-19 12:43:05 -04:00
FString URigVMCompiler : : GetPinHash ( const URigVMPin * InPin , const FRigVMVarExprAST * InVarExpr , bool bIsDebugValue )
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 bIsParameter = false ;
bool bIsVariable = false ;
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 )
{
return GetPinHash ( SourceVarExpr - > GetPin ( ) , SourceVarExpr , bIsDebugValue ) ;
}
}
2020-09-24 00:43:27 -04:00
bIsExecutePin = InPin - > IsExecuteContext ( ) ;
bIsLiteral = InVarExpr - > GetType ( ) = = FRigVMExprAST : : EType : : Literal ;
bIsParameter = Cast < URigVMParameterNode > ( Node ) ! = nullptr ;
2020-10-26 06:51:31 -04:00
bIsVariable = Cast < URigVMVariableNode > ( Node ) ! = nullptr | | InVarExpr - > IsA ( FRigVMExprAST : : ExternalVar ) ;
2020-01-22 17:58:55 -05:00
// determine if this is an initialization for an IO pin
2020-09-24 00:43:27 -04:00
if ( ! bIsLiteral & & ! bIsParameter & & ! bIsVariable & &
! 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 ;
2020-01-22 17:58:55 -05:00
if ( URigVMParameterNode * ParameterNode = Cast < URigVMParameterNode > ( Node ) )
{
2021-07-29 14:29:52 -04:00
if ( InPin - > GetName ( ) = = TEXT ( " Value " ) & & ! bIsLiteral & & ! bIsDebugValue )
2020-01-22 17:58:55 -05:00
{
return FString : : Printf ( TEXT ( " %sParameter::%s%s " ) , * Prefix , * ParameterNode - > GetParameterName ( ) . ToString ( ) , * Suffix ) ;
}
}
else if ( URigVMVariableNode * VariableNode = Cast < URigVMVariableNode > ( Node ) )
{
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
{
2021-06-02 06:17:52 -04:00
// Literal values will be reused for all instance of local variables
2021-06-07 06:49:07 -04:00
if ( InVarExpr - > NumParents ( ) = = 0 & & InVarExpr - > NumChildren ( ) = = 0 )
{
return FString : : Printf ( TEXT ( " %sLocalVariableDefault::%s|%s%s " ) , * Prefix , * Node - > GetGraph ( ) - > GetGraphName ( ) , * VariableName . ToString ( ) , * Suffix ) ;
}
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
{
2021-06-02 06:17:52 -04:00
// Local variables for non-root graphs are in the format "LocalVariable::PathToGraph|VariableName"
return FString : : Printf ( TEXT ( " %sLocalVariable::%s|%s%s " ) , * Prefix , * LibraryNode - > GetNodePath ( true ) , * VariableName . ToString ( ) , * Suffix ) ;
2021-05-11 17:13:58 -04:00
}
2021-04-27 03:19:42 -04:00
}
2021-06-02 06:17:52 -04:00
// Local variables for root graphs are in the format "LocalVariable::VariableName"
return FString : : Printf ( TEXT ( " %sLocalVariable::%s%s " ) , * Prefix , * VariableName . ToString ( ) , * Suffix ) ;
2021-04-27 03:19:42 -04:00
}
}
}
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 UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2021-01-12 06:47:41 -04:00
if ( InVarExpr )
2021-07-29 14:29:52 -04:00
# else
if ( InVarExpr & & ! bIsDebugValue )
# endif
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 */ ) ;
2021-01-12 06:47:41 -04:00
if ( ! CallStackPath . IsEmpty ( ) )
{
Prefix + = CallStackPath + TEXT ( " | " ) ;
2021-05-14 02:36:03 -04:00
bUseFullNodePath = false ;
2021-01-12 06:47:41 -04:00
}
}
}
}
2021-05-14 02:36:03 -04:00
return FString : : Printf ( TEXT ( " %s%s%s " ) , * Prefix , * InPin - > GetPinPath ( bUseFullNodePath ) , * Suffix ) ;
2020-01-22 17:58:55 -05:00
}
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
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2021-04-29 05:02:50 -04:00
void URigVMCompiler : : CreateDebugRegister ( URigVMPin * InPin , URigVM * OutVM ,
TMap < FString , FRigVMOperand > * OutOperands , TSharedPtr < FRigVMParserAST > InRuntimeAST )
{
check ( InPin ) ;
check ( OutVM ) ;
check ( OutOperands ) ;
check ( InRuntimeAST . IsValid ( ) ) ;
FRigVMCompilerWorkData WorkData ;
WorkData . VM = OutVM ;
WorkData . PinPathToOperand = OutOperands ;
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 ) ;
for ( const FRigVMExprAST * Expression : Expressions )
{
check ( Expression - > IsA ( FRigVMExprAST : : EType : : Var ) ) ;
const FRigVMVarExprAST * VarExpression = Expression - > To < FRigVMVarExprAST > ( ) ;
const FString PinHash = GetPinHash ( SourcePin , VarExpression , false ) ;
if ( const FRigVMOperand * Operand = OutOperands - > Find ( PinHash ) )
{
const FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( Pin ) ;
FRigVMVarExprAST TempVarExpr ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
TempVarExpr . ParserPtr = InRuntimeAST . Get ( ) ;
const FRigVMOperand DebugOperand = FindOrAddRegister ( & TempVarExpr , WorkData , true ) ;
if ( DebugOperand . IsValid ( ) )
{
FRigVMOperand KeyOperand ( Operand - > GetMemoryType ( ) , Operand - > GetRegisterIndex ( ) ) ; // no register offset
OutVM - > OperandToDebugRegisters . FindOrAdd ( KeyOperand ) . AddUnique ( DebugOperand ) ;
}
}
}
}
void URigVMCompiler : : RemoveDebugRegister ( URigVMPin * InPin , URigVM * OutVM ,
TMap < FString , FRigVMOperand > * OutOperands , TSharedPtr < FRigVMParserAST > InRuntimeAST )
{
check ( OutVM ) ;
check ( OutOperands ) ;
URigVMPin * Pin = InPin - > GetRootPin ( ) ;
const FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( Pin ) ;
FRigVMVarExprAST TempVarExpr ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
TempVarExpr . ParserPtr = InRuntimeAST . Get ( ) ;
const FString PinHash = GetPinHash ( Pin , & TempVarExpr , true ) ;
if ( const FRigVMOperand * DebugOperand = OutOperands - > Find ( PinHash ) )
{
TArray < FRigVMOperand > KeysToRemove ;
for ( TPair < FRigVMOperand , TArray < FRigVMOperand > > & Pair : OutVM - > OperandToDebugRegisters )
{
if ( Pair . Value . Remove ( * DebugOperand ) > 0 )
{
if ( Pair . Value . IsEmpty ( ) )
{
KeysToRemove . AddUnique ( Pair . Key ) ;
}
}
}
for ( const FRigVMOperand & KeyToRemove : KeysToRemove )
{
OutVM - > OperandToDebugRegisters . Remove ( KeyToRemove ) ;
}
OutOperands - > Remove ( PinHash ) ;
}
}
2021-07-29 14:29:52 -04:00
# else
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 ;
for ( const FRigVMExprAST * Expression : Expressions )
{
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 ) )
{
continue ;
}
}
const FString PinHash = GetPinHash ( SourcePin , VarExpression , false ) ;
if ( const FRigVMOperand * Operand = OutOperands - > Find ( PinHash ) )
{
const FRigVMASTProxy PinProxy = FRigVMASTProxy : : MakeFromUObject ( Pin ) ;
FRigVMVarExprAST TempVarExpr ( FRigVMExprAST : : EType : : Var , PinProxy ) ;
TempVarExpr . ParserPtr = InRuntimeAST . Get ( ) ;
const FString DebugPinHash = GetPinHash ( Pin , & TempVarExpr , true ) ;
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 ) ;
}
}
}
}
}
}
}
}
# endif
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
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
if ( Pin - > IsExecuteContext ( ) & & bIsDebugValue )
{
return FRigVMOperand ( ) ;
}
# endif
2021-07-27 14:04:39 -04:00
FString CPPType = Pin - > GetCPPType ( ) ;
FString BaseCPPType = Pin - > IsArray ( ) ? Pin - > GetArrayElementCppType ( ) : CPPType ;
2020-01-22 17:58:55 -05:00
FString Hash = GetPinHash ( Pin , InVarExpr , bIsDebugValue ) ;
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 ;
2020-01-22 17:58:55 -05:00
bool bIsParameter = InVarExpr - > IsGraphParameter ( ) ;
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
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2021-04-29 05:02:50 -04:00
FRigVMMemoryContainer & Memory =
bIsLiteral ? WorkData . VM - > GetLiteralMemory ( ) :
( bIsDebugValue ? WorkData . VM - > GetDebugMemory ( ) : WorkData . VM - > GetWorkMemory ( ) ) ;
2021-07-27 14:04:39 -04:00
const ERigVMMemoryType MemoryType = Memory . GetMemoryType ( ) ;
# else
const ERigVMMemoryType MemoryType =
bIsLiteral ? ERigVMMemoryType : : Literal :
( bIsDebugValue ? ERigVMMemoryType : : Debug : ERigVMMemoryType : : Work ) ;
# endif
2020-01-22 17:58:55 -05:00
FRigVMOperand const * ExistingOperand = WorkData . PinPathToOperand - > Find ( Hash ) ;
if ( ExistingOperand )
{
2021-07-27 14:04:39 -04:00
if ( ExistingOperand - > GetMemoryType ( ) = = MemoryType )
2020-01-22 17:58:55 -05:00
{
2021-04-29 05:02:50 -04:00
if ( ! bIsDebugValue )
{
check ( ! WorkData . ExprToOperand . Contains ( InVarExpr ) ) ;
WorkData . ExprToOperand . Add ( InVarExpr , * ExistingOperand ) ;
}
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-29 14:29:52 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-01-22 17:58:55 -05:00
ensure ( WorkData . DefaultStructs . Num ( ) > 0 ) ;
2020-09-24 00:43:27 -04:00
TSharedPtr < FStructOnScope > DefaultStruct = WorkData . DefaultStructs . Last ( ) ;
FRigVMStruct * VMStruct = ( FRigVMStruct * ) DefaultStruct - > GetStructMemory ( ) ;
2020-01-22 17:58:55 -05:00
2020-09-24 00:43:27 -04:00
int32 DesiredArraySize = VMStruct - > GetArraySize ( Pin - > GetFName ( ) , WorkData . RigVMUserData ) ;
2020-01-22 17:58:55 -05:00
2021-07-29 14:29:52 -04:00
# endif
2021-07-27 14:04:39 -04:00
JoinedDefaultValue = Pin - > GetDefaultValue ( PinOverride ) ;
DefaultValues = URigVMPin : : SplitDefaultValue ( JoinedDefaultValue ) ;
2020-01-22 17:58:55 -05:00
2021-07-29 14:29:52 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-01-22 17:58:55 -05:00
if ( DefaultValues . Num ( ) ! = DesiredArraySize )
{
2021-07-27 14:04:39 -04:00
FString FirstDefaultValue ;
2020-01-22 17:58:55 -05:00
if ( Pin - > GetArraySize ( ) > 0 )
{
2021-07-27 14:04:39 -04:00
FirstDefaultValue = Pin - > GetSubPins ( ) [ 0 ] - > GetDefaultValue ( PinOverride ) ;
2020-01-22 17:58:55 -05:00
}
DefaultValues . Reset ( ) ;
for ( int32 Index = 0 ; Index < DesiredArraySize ; Index + + )
{
2021-07-27 14:04:39 -04:00
DefaultValues . Add ( FirstDefaultValue ) ;
2020-01-22 17:58:55 -05:00
}
}
2021-07-29 14:29:52 -04:00
# endif
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 UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2021-04-29 05:02:50 -04:00
if ( bIsDebugValue & & Memory . SupportsNames ( ) )
{
Register = Memory . GetIndex ( RegisterName ) ;
if ( Register ! = INDEX_NONE )
{
bool bFoundValidRegister = false ;
if ( ScriptStruct )
{
if ( Memory [ Register ] . BaseCPPTypeObject = = ScriptStruct )
{
bFoundValidRegister = true ;
}
}
else if ( UEnum * Enum = Pin - > GetEnum ( ) )
{
if ( Memory [ Register ] . BaseCPPTypeObject = = Enum )
{
bFoundValidRegister = true ;
}
}
else
{
if ( Memory [ Register ] . BaseCPPType = = * BaseCPPType )
{
bFoundValidRegister = true ;
}
}
if ( bFoundValidRegister )
{
Operand = Memory . GetOperand ( Register ) ;
if ( ExistingOperand = = nullptr )
{
WorkData . PinPathToOperand - > Add ( Hash , Operand ) ;
}
return Operand ;
}
}
}
2021-07-27 14:04:39 -04:00
# else
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 ( ) )
{
if ( ExistingOperand = = nullptr )
{
WorkData . PinPathToOperand - > Add ( Hash , Operand ) ;
}
return Operand ;
}
}
}
# endif
2021-04-29 05:02:50 -04:00
2021-07-27 14:04:39 -04:00
# if UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
2020-01-22 17:58:55 -05:00
if ( ScriptStruct )
{
TArray < uint8 , TAlignedHeapAllocator < 16 > > Data ;
Data . AddUninitialized ( ScriptStruct - > GetStructureSize ( ) * DefaultValues . Num ( ) ) ;
uint8 * Ptr = Data . GetData ( ) ;
for ( FString DefaultValue : DefaultValues )
{
ScriptStruct - > InitializeStruct ( Ptr , 1 ) ;
if ( ! DefaultValue . IsEmpty ( ) & & DefaultValue ! = TEXT ( " () " ) )
{
FRigVMCompilerImportErrorContext ErrorPipe ( this ) ;
ScriptStruct - > ImportText ( * DefaultValue , Ptr , nullptr , PPF_None , & ErrorPipe , ScriptStruct - > GetName ( ) ) ;
}
Ptr = Ptr + ScriptStruct - > GetStructureSize ( ) ;
}
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , ScriptStruct - > GetStructureSize ( ) , DefaultValues . Num ( ) , Pin - > IsArray ( ) , Data . GetData ( ) , NumSlices , ERigVMRegisterType : : Struct , ScriptStruct ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * ScriptStruct - > GetStructCPPName ( ) ;
Memory . Registers [ Register ] . BaseCPPTypeObject = ScriptStruct ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
ScriptStruct - > DestroyStruct ( Data . GetData ( ) , DefaultValues . Num ( ) ) ;
Operand = Memory . GetOperand ( Register ) ;
}
else if ( UEnum * Enum = Pin - > GetEnum ( ) )
{
2020-09-24 00:43:27 -04:00
FRigVMByteArray Values ;
2020-01-22 17:58:55 -05:00
for ( FString DefaultValue : DefaultValues )
{
if ( DefaultValue . IsEmpty ( ) )
{
Values . Add ( ( uint8 ) Enum - > GetValueByIndex ( 0 ) ) ;
}
else
{
Values . Add ( ( uint8 ) Enum - > GetValueByNameString ( DefaultValue ) ) ;
}
}
2020-09-24 00:43:27 -04:00
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < uint8 > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Plain , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * Enum - > CppType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = Enum ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " bool " ) )
{
TArray < bool > Values ;
for ( FString DefaultValue : DefaultValues )
{
Values . Add ( ( DefaultValue = = TEXT ( " True " ) ) | | ( DefaultValue = = TEXT ( " true " ) ) | | ( DefaultValue = = TEXT ( " 1 " ) ) ) ;
}
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < bool > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Plain , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " int32 " ) )
{
TArray < int32 > Values ;
for ( FString DefaultValue : DefaultValues )
{
if ( DefaultValue . IsEmpty ( ) )
{
Values . Add ( 0 ) ;
}
else
{
Values . Add ( FCString : : Atoi ( * DefaultValue ) ) ;
}
}
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < int32 > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Plain , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " float " ) )
{
TArray < float > Values ;
for ( FString DefaultValue : DefaultValues )
{
if ( DefaultValue . IsEmpty ( ) )
{
Values . Add ( 0.f ) ;
}
else
{
Values . Add ( FCString : : Atof ( * DefaultValue ) ) ;
}
}
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < float > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Plain , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2021-06-22 14:11:52 -04:00
# if WITH_EDITORONLY_DATA
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
# endif
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " double " ) )
{
TArray < double > Values ;
for ( FString DefaultValue : DefaultValues )
{
if ( DefaultValue . IsEmpty ( ) )
{
Values . Add ( 0.0 ) ;
}
else
{
Values . Add ( FCString : : Atod ( * DefaultValue ) ) ;
}
}
Register = Memory . AddRegisterArray < double > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Plain , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " FName " ) )
{
TArray < FName > Values ;
for ( FString DefaultValue : DefaultValues )
{
Values . Add ( * DefaultValue ) ;
}
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < FName > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , Values . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) Values . GetData ( ) , NumSlices , ERigVMRegisterType : : Name , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else if ( BaseCPPType = = TEXT ( " FString " ) )
{
2021-04-29 05:02:50 -04:00
Register = Memory . AddRegisterArray < FString > ( ! Pin - > IsDynamicArray ( ) & & ! bIsDebugValue , RegisterName , DefaultValues . Num ( ) , Pin - > IsArray ( ) , ( uint8 * ) DefaultValues . GetData ( ) , NumSlices , ERigVMRegisterType : : String , nullptr ) ;
check ( Register ! = INDEX_NONE ) ;
2020-11-02 13:35:21 -04:00
# if WITH_EDITORONLY_DATA
2020-12-04 11:37:54 -04:00
Memory . Registers [ Register ] . BaseCPPType = * BaseCPPType ;
Memory . Registers [ Register ] . BaseCPPTypeObject = nullptr ;
2020-11-02 13:35:21 -04:00
# endif
2020-01-22 17:58:55 -05:00
Operand = Memory . GetOperand ( Register ) ;
}
else
{
ensure ( false ) ;
}
Memory [ Operand . GetRegisterIndex ( ) ] . bIsArray = Pin - > IsArray ( ) ;
}
2021-07-27 14:04:39 -04:00
# else
}
2021-07-29 14:29:52 -04:00
if ( bIsDebugValue )
{
// debug values are always stored as arrays
2021-10-19 06:24:52 -04:00
CPPType = FString : : Printf ( URigVMController : : TArrayTemplate , * CPPType ) ;
2021-08-06 19:39:37 -04:00
JoinedDefaultValue = URigVMPin : : GetDefaultValueForArray ( { JoinedDefaultValue } ) ;
2021-07-29 14:29:52 -04:00
}
2021-07-30 15:49:56 -04:00
else if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Hidden & & Pin - > GetNode ( ) - > IsA < URigVMUnitNode > ( ) )
{
UScriptStruct * UnitStruct = Cast < URigVMUnitNode > ( Pin - > GetNode ( ) ) - > GetScriptStruct ( ) ;
const FProperty * Property = UnitStruct - > FindPropertyByName ( Pin - > GetFName ( ) ) ;
check ( Property ) ;
if ( ! Property - > HasMetaData ( FRigVMStruct : : SingletonMetaName ) )
{
2021-10-19 06:24:52 -04:00
CPPType = FString : : Printf ( URigVMController : : TArrayTemplate , * 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
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Hidden )
{
JoinedDefaultValue . Empty ( ) ;
}
2021-08-18 06:18:21 -04:00
2021-07-27 14:04:39 -04:00
Operand = WorkData . AddProperty ( MemoryType , RegisterName , CPPType , Pin - > GetCPPTypeObject ( ) , JoinedDefaultValue ) ;
# endif
2021-07-29 14:29:52 -04:00
if ( bIsParameter & & ! bIsLiteral & & ! bIsDebugValue )
2020-01-22 17:58:55 -05:00
{
URigVMParameterNode * ParameterNode = Cast < URigVMParameterNode > ( Pin - > GetNode ( ) ) ;
check ( ParameterNode ) ;
FName Name = ParameterNode - > GetParameterName ( ) ;
ERigVMParameterType ParameterType = ParameterNode - > IsInput ( ) ? ERigVMParameterType : : Input : ERigVMParameterType : : Output ;
FRigVMParameter Parameter ( ParameterType , Name , Operand . GetRegisterIndex ( ) , Pin - > GetCPPType ( ) , ScriptStruct ) ;
2020-04-07 04:27:49 -04:00
WorkData . VM - > ParametersNameMap . FindOrAdd ( Parameter . Name ) = WorkData . VM - > Parameters . Add ( Parameter ) ;
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
{
2021-11-18 12:28:07 -05:00
const FRigVMCompilerWorkData : : FRigVMASTProxyArray & PinProxies = FindProxiesWithSharedOperand ( InVarExpr , WorkData ) ;
ensure ( ! PinProxies . IsEmpty ( ) ) ;
for ( const FRigVMASTProxy & Proxy : PinProxies )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
if ( URigVMPin * VirtualPin = Cast < URigVMPin > ( Proxy . GetSubject ( ) ) )
{
FString VirtualPinHash = GetPinHash ( VirtualPin , InVarExpr , bIsDebugValue ) ;
WorkData . PinPathToOperand - > Add ( VirtualPinHash , Operand ) ;
}
}
2021-03-31 13:16:23 -04:00
}
}
else
2021-03-30 10:21:09 -04:00
{
2021-04-29 05:02:50 -04:00
if ( ExistingOperand = = nullptr )
{
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 ) ;
for ( int32 ProxyIndex = 0 ; ProxyIndex < PinProxiesToProcess . Num ( ) ; ProxyIndex + + )
{
const FRigVMASTProxy & CurrentProxy = PinProxiesToProcess [ ProxyIndex ] ;
if ( CurrentProxy . IsValid ( ) )
2021-09-27 11:48:28 -04:00
{
2021-11-18 12:28:07 -05:00
if ( URigVMPin * Pin = Cast < URigVMPin > ( CurrentProxy . GetSubject ( ) ) )
2021-09-27 11:48:28 -04:00
{
if ( Pin - > GetNode ( ) - > IsA < URigVMVariableNode > ( ) | | Pin - > GetNode ( ) - > IsA < URigVMParameterNode > ( ) )
{
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input )
{
continue ;
}
}
}
2021-11-18 12:28:07 -05:00
PinProxies . Add ( CurrentProxy ) ;
2021-09-27 11:48:28 -04:00
}
2021-11-18 12:28:07 -05:00
if ( const FRigVMASTProxy * SourceProxy = ProxySources . Find ( CurrentProxy ) )
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 ) ;
}
}
}
if ( const FRigVMCompilerWorkData : : FRigVMASTProxyArray * TargetProxies = WorkData . ProxyTargets . Find ( CurrentProxy ) )
{
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
}
2021-09-08 07:57:30 -04:00
bool URigVMCompiler : : ValidateNode ( URigVMNode * InNode )
{
check ( InNode ) ;
if ( InNode - > HasUnknownTypePin ( ) )
{
static const FString UnknownTypeMessage = TEXT ( " Node @@ has unresolved pins of unknown type. " ) ;
Settings . Report ( EMessageSeverity : : Error , InNode , UnknownTypeMessage ) ;
return false ;
}
return true ;
}
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
}