blob: 7f85e398f2bc6e9f38a50a9b63e0e890e4264aeb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#ifndef SLANG_VM_H
#define SLANG_VM_H
#include "core/slang-string-util.h"
#include "slang-vm-bytecode.h"
using namespace slang;
namespace Slang
{
struct ByteCodeExecutionContext
{
void* currentWorkingSet;
uint32_t currentWorkingSetSizeInBytes;
};
class ByteCodeInterpreter;
// Represents a relocated function code ready for execution.
// Relocated functions are VMInsts allocated in a 8-byte aligned buffer, and instruction headers
// Replaced with actual function pointers that can execute the instruction.
class ExecutableFunction
{
public:
typedef VMInstIterator<VMExecOperand, VMExecInstHeader> InstIterator;
List<uint64_t> m_codeBuffer;
VMFuncHeader* m_header;
List<uint32_t> m_parameterOffsets;
InstIterator begin();
InstIterator end();
};
struct StackFrame
{
VMExecInstHeader* m_currentInst = nullptr;
void* m_currentFuncCode = nullptr;
size_t m_workingSetOffset = 0;
};
class ByteCodeInterpreter : public RefObject, public IByteCodeRunner
{
public:
SLANG_REF_OBJECT_IUNKNOWN_ALL
ISlangUnknown* getInterface(const Guid& guid);
public:
VMModuleView m_moduleView;
List<uint8_t> m_code;
StringBuilder m_errorBuilder;
List<ExecutableFunction> m_functions;
Dictionary<String, VMExtFunction> m_extInstHandlers;
SlangResult prepareModuleForExecution();
void* m_extInstHandlerUserData = nullptr;
List<uint8_t> m_returnRegister;
List<uint64_t> m_workingSetBuffer;
List<StackFrame> m_stack;
List<const char*> m_stringLits;
const char** m_stringLitsPtr = nullptr;
size_t m_returnValSize = 0;
void pushFrame(uint32_t size)
{
StackFrame frame;
frame.m_workingSetOffset =
(uint32_t)((uint64_t*)m_currentWorkingSet - m_workingSetBuffer.getBuffer());
m_stack.add(frame);
auto stackBufferCount = m_workingSetBuffer.getCount();
m_workingSetBuffer.setCount(m_workingSetBuffer.getCount() + size / sizeof(uint64_t));
m_currentWorkingSet = m_workingSetBuffer.getBuffer() + stackBufferCount;
}
void popFrame()
{
auto& stackFrame = m_stack.getLast();
auto lastWorkingSetBufferCount =
(uint32_t)((uint64_t*)m_currentWorkingSet - m_workingSetBuffer.getBuffer());
m_workingSetBuffer.setCount(lastWorkingSetBufferCount);
m_currentInst = stackFrame.m_currentInst->getNextInst();
m_currentFuncCode = stackFrame.m_currentFuncCode;
m_currentWorkingSet = m_workingSetBuffer.getBuffer() + stackFrame.m_workingSetOffset;
m_stack.removeLast();
}
VMExecInstHeader* m_currentInst = nullptr;
void* m_currentFuncCode = nullptr;
void* m_currentWorkingSet = nullptr;
VMPrintFunc m_printCallback = nullptr;
void* m_printCallbackUserData = nullptr;
template<typename... Args>
void reportError(const char* format, Args... args)
{
m_errorBuilder.append(StringUtil::makeStringWithFormat(format, args...));
m_errorBuilder.append("\n");
}
static void defaultPrintCallback(const char* message, void* userData);
ByteCodeInterpreter();
public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadModule(IBlob* moduleBlob) override;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
selectFunctionByIndex(uint32_t functionIndex) override;
virtual SLANG_NO_THROW int SLANG_MCALL findFunctionByName(const char* name) override;
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
getFunctionInfo(uint32_t index, ByteCodeFuncInfo* outInfo) override;
virtual SLANG_NO_THROW void* SLANG_MCALL getCurrentWorkingSet() override
{
return m_currentWorkingSet;
}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
execute(void* argumentData, size_t argumentSize) override;
virtual SLANG_NO_THROW void SLANG_MCALL getErrorString(slang::IBlob** outBlob) override;
virtual SLANG_NO_THROW void* SLANG_MCALL getReturnValue(size_t* outValueSize) override
{
*outValueSize = m_returnValSize;
return m_returnRegister.getBuffer();
}
virtual SLANG_NO_THROW void SLANG_MCALL setExtInstHandlerUserData(void* userData) override
{
m_extInstHandlerUserData = userData;
}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
registerExtCall(const char* name, VMExtFunction functionPtr) override
{
m_extInstHandlers[name] = functionPtr;
return SLANG_OK;
}
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
setPrintCallback(VMPrintFunc callback, void* userData) override;
};
} // namespace Slang
#endif
|