123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- #pragma once
- #include <unordered_set>
- #include <set>
- #include "TemporaryMemoryArena.h"
- #include "../metadata/Image.h"
- #include "../interpreter/Instruction.h"
- #include "../interpreter/Engine.h"
- #include "../metadata/MetadataUtil.h"
- #include "../metadata/Opcodes.h"
- #include "../metadata/MetadataModule.h"
- #include "../interpreter/Instruction.h"
- #include "../interpreter/Interpreter.h"
- #include "../interpreter/InterpreterModule.h"
- #include "Transform.h"
- namespace hybridclr
- {
- namespace transform
- {
- using namespace hybridclr::metadata;
- using namespace hybridclr::interpreter;
- struct IRBasicBlock
- {
- bool visited;
- bool inPending;
- uint32_t ilOffset;
- uint32_t codeOffset;
- std::vector<interpreter::IRCommon*> insts;
- };
- struct ArgVarInfo
- {
- const Il2CppType* type;
- Il2CppClass* klass;
- int32_t argOffset; // StackObject index
- int32_t argLocOffset;
- };
- struct LocVarInfo
- {
- const Il2CppType* type;
- Il2CppClass* klass;
- int32_t locOffset;
- };
- enum class EvalStackReduceDataType
- {
- I4,
- I8,
- R4,
- R8,
- Other,
- };
- struct EvalStackVarInfo
- {
- EvalStackReduceDataType reduceType;
- int32_t byteSize;
- int32_t locOffset;
- };
- #if HYBRIDCLR_ARCH_64
- #define NATIVE_INT_OP opI8
- constexpr EvalStackReduceDataType NATIVE_INT_REDUCE_TYPE = EvalStackReduceDataType::I8;
- #else
- #define NATIVE_INT_OP opI4
- constexpr EvalStackReduceDataType NATIVE_INT_REDUCE_TYPE = EvalStackReduceDataType::I4;
- #endif
- #define CreateIR(varName, typeName) IR##typeName* varName = pool.AllocIR<IR##typeName>(); varName->type = HiOpcodeEnum::typeName;
- #define CreateAddIR(varName, typeName) IR##typeName* varName = pool.AllocIR<IR##typeName>(); varName->type = HiOpcodeEnum::typeName; curbb->insts.push_back(varName); if (ir2offsetMap) { ir2offsetMap->add(varName, ipOffset); }
- enum class LocationDescType
- {
- I1,
- U1,
- I2,
- U2,
- I4,
- I8,
- Ref,
- S,
- StructContainsRef,
- };
- #if HYBRIDCLR_ARCH_64
- #define NATIVE_INT_DESC_TYPE LocationDescType::I8
- #define ARCH_ARGUMENT(x32, x64) x64
- #else
- #define NATIVE_INT_DESC_TYPE LocationDescType::I4
- #define ARCH_ARGUMENT(x32, x64) x32
- #endif
- struct LocationDescInfo
- {
- LocationDescType type;
- int32_t size;
- };
- struct FlowInfo
- {
- uint32_t curStackSize;
- uint32_t offset;
- il2cpp::utils::dynamic_array<EvalStackVarInfo> evalStack;
- };
- typedef Il2CppHashMap<IRCommon*, uint32_t, il2cpp::utils::PointerHash<IRCommon>> IR2OffsetMap;
- LocationDescInfo ComputLocationDescInfo(const Il2CppType* type);
- class TransformContext
- {
- private:
- metadata::Image* image;
- const MethodInfo* methodInfo;
- metadata::MethodBody& body;
- TemporaryMemoryArena& pool;
- const Il2CppGenericContext* genericContext;
- const Il2CppGenericContainer* klassContainer;
- const Il2CppGenericContainer* methodContainer;
- int32_t actualParamCount;
- std::set<uint32_t> splitOffsets;
- IRBasicBlock** ip2bb;
- IRBasicBlock* curbb;
- ArgVarInfo* args;
- LocVarInfo* locals;
- EvalStackVarInfo* evalStack;
- int32_t evalStackTop;
- int32_t evalStackBaseOffset;
- il2cpp::utils::dynamic_array<uint64_t>& resolveDatas;
- Il2CppHashMap<uint32_t, uint32_t, il2cpp::utils::PassThroughHash<uint32_t>> token2DataIdxs;
- Il2CppHashMap<const void*, uint32_t, il2cpp::utils::PassThroughHash<const void*>> ptr2DataIdxs;
- std::vector<int32_t*> relocationOffsets;
- std::vector<std::pair<int32_t, int32_t>> switchOffsetsInResolveData;
- std::vector<FlowInfo*> pendingFlows;
- int32_t nextFlowIdx;
- int32_t maxStackSize;
- int32_t curStackSize;
- const byte* ipBase;
- const byte* ip;
- uint32_t ipOffset;
- IR2OffsetMap* ir2offsetMap;
- int32_t prefixFlags;
- const MethodInfo* shareMethod;
- std::vector<IRBasicBlock*> irbbs;
- il2cpp::utils::dynamic_array<InterpExceptionClause> exClauses;
- uint32_t totalIRSize;
- int32_t totalArgSize;
- int32_t totalArgLocalSize;
- bool initLocals;
- public:
- TransformContext(hybridclr::metadata::Image* image, const MethodInfo* methodInfo, metadata::MethodBody& body, TemporaryMemoryArena& pool, il2cpp::utils::dynamic_array<uint64_t>& resolveDatas);
- static void InitializeInstinctHandlers();
- uint32_t GetOrAddResolveDataIndex(const void* ptr);
- TemporaryMemoryArena& GetPool() const
- {
- return pool;
- }
- int32_t GetEvalStackTop() const
- {
- return evalStackTop;
- }
- IRBasicBlock* GetCurbb() const
- {
- return curbb;
- }
- uint32_t GetIpOffset() const
- {
- return ipOffset;
- }
- IR2OffsetMap* GetIr2offsetMap() const
- {
- return ir2offsetMap;
- }
- int32_t GetArgOffset(int32_t idx) const
- {
- return args[idx].argOffset;
- }
- int32_t GetArgLocOffset(int32_t idx) const
- {
- return args[idx].argLocOffset;
- }
- int32_t GetLocOffset(int32_t idx) const
- {
- return locals[idx].locOffset;
- }
- int32_t GetEvalStackOffset(int32_t idx) const
- {
- return idx < evalStackTop ? evalStack[idx].locOffset : curStackSize;
- }
- int32_t GetEvalStackTopOffset() const
- {
- return evalStackTop > 0 ? evalStack[evalStackTop - 1].locOffset : curStackSize;
- }
- int32_t GetEvalStackNewTopOffset() const
- {
- return curStackSize;
- }
- int32_t GetEvalStackOffset_5() const
- {
- return evalStack[evalStackTop - 5].locOffset;
- }
- int32_t GetEvalStackOffset_4() const
- {
- return evalStack[evalStackTop - 4].locOffset;
- }
- int32_t GetEvalStackOffset_3() const
- {
- return evalStack[evalStackTop - 3].locOffset;
- }
- int32_t GetEvalStackOffset_2() const
- {
- return evalStack[evalStackTop - 2].locOffset;
- }
- int32_t GetEvalStackOffset_1() const
- {
- return evalStack[evalStackTop - 1].locOffset;
- }
- void PushStackByType(const Il2CppType* type);
- void PushStackByReduceType(EvalStackReduceDataType t);
- void DuplicateStack();
- void PopStack();
- void PopStackN(int32_t n);
- void PopAllStack();
- void InsertMemoryBarrier();
- void ResetPrefixFlags();
- void Add_ldind(HiOpcodeEnum opCode, EvalStackReduceDataType dataType);
- void Add_stind(HiOpcodeEnum opCode);
- void PushOffset(int32_t* offsetPtr);
- void PushBranch(int32_t targetOffset);
- bool FindNextFlow();
- void AddInst(IRCommon* ir);
- void AddInst_ldarg(int32_t argIdx);
- bool IsCreateNotNullObjectInstrument(IRCommon* ir);
- IRCommon* GetLastInstrument()
- {
- return curbb->insts.empty() ? nullptr : curbb->insts.back();
- }
- void RemoveLastInstrument();
- void AddInst_ldarga(int32_t argIdx);
- void AddInst_starg(int32_t argIdx);
- void CreateAddInst_ldloc(int32_t locIdx);
- void CreateAddInst_stloc(int32_t locIdx);
- void CreateAddInst_ldloca(int32_t locIdx);
- void CreateAddInst_ldc4(int32_t c, EvalStackReduceDataType rtype);
- void CreateAddInst_ldc8(int64_t c, EvalStackReduceDataType rtype);
- void Add_brtruefalse(bool c, int32_t targetOffset);
- void Add_bc(int32_t ipOffset, int32_t brOffset, int32_t opSize, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8);
- void Add_conv(int32_t dstTypeSize, EvalStackReduceDataType dstReduceType, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8);
- void Add_conv_ovf(int32_t dstTypeSize, EvalStackReduceDataType dstReduceType, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8);
- void Add_binop(HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8);
- void Add_shiftop(HiOpcodeEnum opI4I4, HiOpcodeEnum opI4I8, HiOpcodeEnum opI8I4, HiOpcodeEnum opI8I8);
- void Add_compare(HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8);
- void Add_ldelem(EvalStackReduceDataType resultType, HiOpcodeEnum opI4);
- void Add_stelem(HiOpcodeEnum opI4);
- bool FindFirstLeaveHandlerIndex(const std::vector<ExceptionClause>& exceptionClauses, uint32_t leaveOffset, uint32_t targetOffset, uint16_t& index);
- bool IsLeaveInTryBlock(const std::vector<ExceptionClause>& exceptionClauses, uint32_t leaveOffset);
- void Add_leave(uint32_t targetOffset);
- uint16_t FindFirstThrowHandlerIndex(const std::vector<ExceptionClause>& exceptionClauses, uint32_t throwOffset);
- bool TryAddInstinctInstruments(const MethodInfo* method)
- {
- return TryAddInstinctInstrumentsByName(method) || TryAddArrayInstinctInstruments(method);
- }
- bool TryAddInstinctInstrumentsByName(const MethodInfo* method);
- bool TryAddArrayInstinctInstruments(const MethodInfo* method);
- bool TryAddInstinctCtorInstruments(const MethodInfo* method);
- bool TryAddCallCommonInstruments(const MethodInfo* method, uint32_t methodDataIndex)
- {
- bool resolvedIsInstanceMethod = IsInstanceMethod(method);
- bool add = resolvedIsInstanceMethod ? TryAddCallCommonInstanceInstruments(method, methodDataIndex)
- : TryAddCallCommonStaticInstruments(method, methodDataIndex);
- if (add)
- {
- int32_t resolvedTotalArgNum = method->parameters_count + resolvedIsInstanceMethod;
- PopStackN(resolvedTotalArgNum);
- if (method->return_type->type != IL2CPP_TYPE_VOID)
- {
- PushStackByType(method->return_type);
- }
- return true;
- }
- return false;
- }
- bool TryAddCallCommonInstanceInstruments(const MethodInfo* method, uint32_t methodDataIndex);
- bool TryAddCallCommonStaticInstruments(const MethodInfo* method, uint32_t methodDataIndex);
- HiOpcodeEnum CalcGetMdArrElementVarVarOpcode(const Il2CppType* type);
- void TransformBody(int32_t depth, int32_t localVarOffset, interpreter::InterpMethodInfo& result);
- private:
- void TransformBodyImpl(int32_t depth, int32_t localVarOffset);
- void BuildInterpMethodInfo(interpreter::InterpMethodInfo& result);
- static bool TransformSubMethodBody(TransformContext& callingCtx, const MethodInfo* subMethod, int32_t depth, int32_t localVarOffset);
- };
- }
- }
|