forked from Xeeynamo/sonic-hybrid-rsdk
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,807 additions
and
0 deletions.
There are no files selected for viewing
75 changes: 75 additions & 0 deletions
75
sonic3air-main/Oxygen/lemonscript/source/lemon/runtime/RuntimeFunction.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution. | ||
* Copyright (C) 2017-2024 by Eukaryot | ||
* | ||
* Published under the GNU GPLv3 open source software license, see license.txt | ||
* or https://www.gnu.org/licenses/gpl-3.0.en.html | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "lemon/runtime/RuntimeOpcode.h" | ||
|
||
// Experimental change of conditional jump to being executed as a runtime opcode function | ||
// -> It works, but has a negative impact on performance | ||
//#define USE_JUMP_CONDITIONAL_RUNTIME_EXEC | ||
|
||
|
||
namespace lemon | ||
{ | ||
class Program; | ||
class ScriptFunction; | ||
|
||
struct RuntimeOpcodeBuffer | ||
{ | ||
public: | ||
~RuntimeOpcodeBuffer(); | ||
|
||
inline bool empty() const { return mSize == 0; } | ||
inline size_t size() const { return mSize; } | ||
inline const uint8* getStart() const { return mBuffer; } | ||
inline const uint8* getEnd() const { return mBuffer + mSize; } | ||
|
||
inline const uint8& operator[](size_t offset) const { return mBuffer[offset]; } | ||
|
||
inline const std::vector<RuntimeOpcode*>& getOpcodePointers() const { return mOpcodePointers; } | ||
|
||
void clear(); | ||
void reserveForOpcodes(size_t numOpcodes); | ||
RuntimeOpcode& addOpcode(size_t parameterSize); | ||
|
||
void copyFrom(const RuntimeOpcodeBuffer& other, rmx::OneTimeAllocPool& memoryPool); | ||
|
||
public: | ||
std::vector<RuntimeOpcode*> mOpcodePointers; // Direct pointers to runtime opcodes | ||
|
||
private: | ||
uint8* mBuffer = nullptr; | ||
bool mSelfManagedBuffer = false; | ||
size_t mSize = 0; // In bytes | ||
size_t mReserved = 0; // In bytes | ||
}; | ||
|
||
|
||
class API_EXPORT RuntimeFunction | ||
{ | ||
public: | ||
void build(Runtime& runtime); | ||
|
||
const uint8* getFirstRuntimeOpcode() const { return mRuntimeOpcodeBuffer.getStart(); } | ||
|
||
size_t translateFromRuntimeProgramCounter(const uint8* runtimeProgramCounter) const; | ||
int translateFromRuntimeProgramCounterOptional(const uint8* runtimeProgramCounter) const; | ||
const uint8* translateToRuntimeProgramCounter(size_t originalProgramCounter) const; | ||
|
||
private: | ||
void createRuntimeOpcode(RuntimeOpcodeBuffer& buffer, const Opcode* opcodes, int numOpcodesAvailable, int firstOpcodeIndex, int& outNumOpcodesConsumed, const Runtime& runtime); | ||
const uint8* translateJumpTarget(uint32 targetOpcodeIndex) const; | ||
|
||
public: | ||
const ScriptFunction* mFunction = nullptr; | ||
RuntimeOpcodeBuffer mRuntimeOpcodeBuffer; | ||
std::vector<size_t> mProgramCounterByOpcodeIndex; // Program counter (= byte index inside "mRuntimeOpcodeData") where runtime opcode for given original opcode index starts | ||
}; | ||
|
||
} |
76 changes: 76 additions & 0 deletions
76
sonic3air-main/Oxygen/lemonscript/source/lemon/runtime/RuntimeOpcode.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution. | ||
* Copyright (C) 2017-2024 by Eukaryot | ||
* | ||
* Published under the GNU GPLv3 open source software license, see license.txt | ||
* or https://www.gnu.org/licenses/gpl-3.0.en.html | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "lemon/program/Opcode.h" | ||
#include "lemon/runtime/Runtime.h" | ||
|
||
|
||
namespace lemon | ||
{ | ||
class Runtime; | ||
struct RuntimeOpcode; | ||
struct RuntimeOpcodeBuffer; | ||
struct RuntimeOpcodeContext; | ||
|
||
|
||
typedef void(*ExecFunc)(const RuntimeOpcodeContext context); | ||
|
||
class API_EXPORT RuntimeOpcodeProvider | ||
{ | ||
public: | ||
virtual bool buildRuntimeOpcode(RuntimeOpcodeBuffer& buffer, const Opcode* opcodes, int numOpcodesAvailable, int firstOpcodeIndex, int& outNumOpcodesConsumed, const Runtime& runtime) = 0; | ||
}; | ||
|
||
|
||
struct API_EXPORT RuntimeOpcodeBase | ||
{ | ||
public: | ||
enum class Flag : uint8 | ||
{ | ||
CALL_IS_BASE_CALL = 0x20, // For CALL opcodes only: It is a base call | ||
CALL_TARGET_RESOLVED = 0x40, // For CALL opcodes only: Call target is already resolved and can be found in the parameter (as pointer) | ||
CALL_TARGET_RUNTIME_FUNC = 0x80 // For CALL opcodes only: Call target is resolved and is a RuntimeFunction, not a Function | ||
}; | ||
|
||
ExecFunc mExecFunc; | ||
RuntimeOpcode* mNext = nullptr; | ||
Opcode::Type mOpcodeType = Opcode::Type::NOP; | ||
uint8 mSize = 0; | ||
BitFlagSet<Flag> mFlags; | ||
uint8 mSuccessiveHandledOpcodes = 0; // Number of internally handled opcodes (i.e. not manipulating control flow) in a row from this one -- including this one, so if this is 0, the opcode is not handled | ||
}; | ||
|
||
struct API_EXPORT RuntimeOpcode : public RuntimeOpcodeBase | ||
{ | ||
public: | ||
static const constexpr size_t PARAMETER_OFFSET = sizeof(RuntimeOpcodeBase); | ||
|
||
template<typename T> FORCE_INLINE T getParameter() const | ||
{ | ||
return *reinterpret_cast<const T*>((uint8*)this + PARAMETER_OFFSET); | ||
} | ||
|
||
template<typename T> FORCE_INLINE T getParameter(size_t offset) const | ||
{ | ||
return *reinterpret_cast<const T*>((uint8*)this + PARAMETER_OFFSET + offset); | ||
} | ||
|
||
template<typename T> void setParameter(T value) | ||
{ | ||
*reinterpret_cast<T*>((uint8*)this + PARAMETER_OFFSET) = value; | ||
} | ||
|
||
template<typename T> void setParameter(T value, size_t offset) | ||
{ | ||
*reinterpret_cast<T*>((uint8*)this + PARAMETER_OFFSET + offset) = value; | ||
} | ||
}; | ||
|
||
} |
64 changes: 64 additions & 0 deletions
64
sonic3air-main/Oxygen/lemonscript/source/lemon/runtime/RuntimeOpcodeContext.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution. | ||
* Copyright (C) 2017-2024 by Eukaryot | ||
* | ||
* Published under the GNU GPLv3 open source software license, see license.txt | ||
* or https://www.gnu.org/licenses/gpl-3.0.en.html | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "lemon/runtime/Runtime.h" | ||
#include "lemon/runtime/RuntimeOpcode.h" | ||
#include "lemon/utility/AnyBaseValue.h" | ||
|
||
|
||
namespace lemon | ||
{ | ||
struct API_EXPORT RuntimeOpcodeContext | ||
{ | ||
ControlFlow* mControlFlow = nullptr; | ||
const RuntimeOpcode* mOpcode = nullptr; | ||
|
||
template<typename T> | ||
FORCE_INLINE T getParameter() const | ||
{ | ||
return mOpcode->getParameter<T>(); | ||
} | ||
|
||
template<typename T> | ||
FORCE_INLINE T getParameter(size_t offset) const | ||
{ | ||
return mOpcode->getParameter<T>(offset); | ||
} | ||
|
||
template<typename T> | ||
FORCE_INLINE T readValueStack(int offset) const | ||
{ | ||
return mControlFlow->readValueStack<T>(offset); | ||
} | ||
|
||
template<typename T> | ||
FORCE_INLINE void writeValueStack(int offset, T value) const | ||
{ | ||
mControlFlow->writeValueStack<T>(offset, value); | ||
} | ||
|
||
FORCE_INLINE void moveValueStack(int change) const | ||
{ | ||
mControlFlow->moveValueStack(change); | ||
} | ||
|
||
template<typename T> | ||
FORCE_INLINE T readLocalVariable(size_t index) const | ||
{ | ||
return BaseTypeConversion::convert<int64, T>(mControlFlow->mCurrentLocalVariables[index]); | ||
} | ||
|
||
template<typename T> | ||
FORCE_INLINE void writeLocalVariable(size_t index, T value) const | ||
{ | ||
mControlFlow->mCurrentLocalVariables[index] = BaseTypeConversion::convert<T, int64>(value); | ||
} | ||
}; | ||
} |
Oops, something went wrong.