UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VVMBytecodeAnalysis.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#if WITH_VERSE_VM || defined(__INTELLISENSE__)
6
10
11namespace Verse
12{
13struct VProcedure;
14
15namespace BytecodeAnalysis
16{
17using FBlockIndex = uint32;
18
19// A basic block is a list of bytecode instructions with a set of predecessors and successors.
20struct FBasicBlock
21{
22 FBlockIndex Index{std::numeric_limits<uint32>::max()};
23
24 // These First/Last bytecodes are inclusive.
25 uint32 First() const { return Bytecodes[0]; }
26 uint32 Last() const { return Bytecodes.Last(); }
27
28 bool Contains(uint32 BytecodeOffset) const { return First() <= BytecodeOffset && BytecodeOffset <= Last(); }
29
30 // For now, we store these just as offsets from the procedures start bytecode to make it easy to walk backwards.
31 // In the future we could compact this by storing it as offsets between instructions.
33
36};
37
38struct FFailureContext
39{
41 : Id(Id)
43 , Parent(Parent)
44 {
45 }
47 FOp* FailurePC;
49};
50
51struct FTask
52{
53 FTask(FOp* YieldPC)
55 {
56 }
57 FOp* YieldPC;
58};
59
60// A CFG is composed of a list of basic blocks and some metadata to tell us about which instructions
61// belong in which tasks and/or failure contexts.
62struct FCFG
63{
66
67 // Maps bytecode offset to innermost failure context. This is exclusive of both
68 // BeginFailureContext and EndFailureContext because those instructions can't jump
69 // to the FailurePC.
71 // Maps bytecode offset to innermost task. This is exclusive of BeginTask but inclusive of EndTask.
72 // The reason for this is BeginTask won't branch to YieldPC, but any bytecode within the range, including
73 // EndTask, might.
75
78
79 FBasicBlock& GetJumpTarget(uint32 BytecodeOffset);
80 // Returns the innermost failure context we're in, if we're in one.
82 // Returns the innermost task we're in, if we're in one.
83 FTask* FindCurrentTask(uint32 BytecodeOffset);
84 // Returns the unwind edge, if one exists.
85 FOp* FindCurrentUnwindPC(uint32 BytecodeOffset);
86
87 uint32 NumBlocks() const
88 {
89 return Blocks.Num();
90 }
91};
92
94
95// Bitset used to represent the live set of registers at a point in the program.
96struct FLiveSet
97{
99 {
100 Live.Init(false, Num);
101 }
102 FLiveSet(const FLiveSet&) = default;
103
104 // Returns true if this changed.
105 bool Union(const FLiveSet& Other)
106 {
107 V_DIE_UNLESS(Other.Live.Num() == Live.Num());
109 NewLive.CombineWithBitwiseOR(Other.Live, EBitwiseOperatorFlags::MaintainSize);
110 if (NewLive != Live)
111 {
112 Live = NewLive;
113 return true;
114 }
115 return false;
116 }
117
118 bool operator==(const FLiveSet& Other) const
119 {
120 return Live == Other.Live;
121 }
122 bool operator!=(const FLiveSet& Other) const
123 {
124 return !(*this == Other);
125 }
126
127 template <typename FunctionType>
128 void ForEach(FunctionType&& Function) const
129 {
130 for (TConstSetBitIterator<> Iter(Live); Iter; ++Iter)
131 {
132 Function(FRegisterIndex{static_cast<uint32>(Iter.GetIndex())});
133 }
134 }
135
137 {
138 return Live[Register.Index];
139 }
140
141private:
143};
144
145// This data structure caches liveness at basic block boundaries.
146// To get the liveness in at an individual instruction, use FLocalCalc
147// and walk the basic block backwards.
148struct FLiveness
149{
150 struct FLocalCalc
151 {
153 void Step(FOp*);
157 };
158
159 FCFG* CFG;
162};
163
164struct FLiveRange
165{
166 bool IsDead() const
167 {
168 return Begin > End;
169 }
170
171 void Join(uint32 BytecodeOffset)
172 {
173 Begin = std::min(Begin, BytecodeOffset);
174 End = std::max(End, BytecodeOffset);
175 }
176
177 void Join(FLiveRange Right)
178 {
179 Begin = std::min(Begin, Right.Begin);
180 End = std::max(End, Right.End);
181 }
182
183 bool Contains(uint32 BytecodeOffset) const
184 {
185 return Begin <= BytecodeOffset && BytecodeOffset <= End;
186 }
187
188 friend bool operator<(const FLiveRange& Left, const FLiveRange& Right)
189 {
190 if (Left.Begin < Right.Begin)
191 {
192 return true;
193 }
194 if (Right.Begin < Left.Begin)
195 {
196 return false;
197 }
198 return Left.End < Right.End;
199 }
200
201 template <typename TVisitor>
202 friend void Visit(TVisitor& Visitor, FLiveRange& Value)
203 {
204 Visitor.Visit(Value.Begin, TEXT("Begin"));
205 Visitor.Visit(Value.End, TEXT("End"));
206 }
207
208 static FLiveRange Top()
209 {
210 return {0, std::numeric_limits<uint32>::max()};
211 }
212
213 // Range is inclusive, [Begin, End], as bytecode offsets. If you're a bytecode
214 // in this range, it means this register is live-in to that bytecode instruction.
215 uint32 Begin{std::numeric_limits<uint32>::max()};
216 uint32 End{0};
217};
218
224} // namespace BytecodeAnalysis
225
226} // namespace Verse
227
228#endif
EForEachResult ForEach(T &Array, const PREDICATE_CLASS &Predicate)
Definition AISense_Sight.cpp:60
#define TEXT(x)
Definition Platform.h:1272
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
bool operator<(const FTextFormatString &LHS, const FTextFormatString &RHS)
Definition ITextFormatArgumentModifier.h:147
UE_FORCEINLINE_HINT bool operator!=(const FIndexedPointer &Other) const
Definition LockFreeList.h:76
@ Top
Definition MaterialExpressionFunctionInput.h:42
@ Num
Definition MetalRHIPrivate.h:234
decltype(auto) Visit(Func &&Callable, Variants &&... Args)
Definition TVariant.h:271
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition BitArray.h:189
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_FORCEINLINE_HINT void Init(bool bValue, int32 InNumBits)
Definition BitArray.h:828
Definition BitArray.h:1944
Definition UnrealString.h.inl:34
Definition UniquePtr.h:107
@ Contains
Definition AutomationTest.h:160
@ Visitor
Definition XmppMultiUserChat.h:94
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
auto Join(RangeType &&Range, DelimiterType &&Delimiter) -> Private::TJoinBy< RangeType, FIdentityFunctor, DelimiterType >
Definition Join.h:208
Private::FTaskHandle FTask
Definition Task.h:333
Definition Archive.h:36
U16 Index
Definition radfft.cpp:71