// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.

#ifndef MRT_INTERPRETER_EH_FRAMEINFO_H
#define MRT_INTERPRETER_EH_FRAMEINFO_H

#ifdef INTERPRETER_ENABLED

#include "Exception/EhFrameInfo.h"
#include "Common/StackType.h"

namespace MapleRuntime {

class InterpreterEHFrameInfo : public IEHFrameInfo, public FrameInfo {
public:

    InterpreterEHFrameInfo(const FrameInfo& info, uintptr_t landingPad): FrameInfo(info), landingPad(landingPad)
    {
    }

    // forbid copying, objects are accessed through unique_ptr
    InterpreterEHFrameInfo(const InterpreterEHFrameInfo&) = delete;
    InterpreterEHFrameInfo& operator=(const InterpreterEHFrameInfo&) = delete;

    ~InterpreterEHFrameInfo() override = default;

    bool IsCatchException() const override
    {
        // Interpreted frames alawys catch exception, allowing interpreter to search for catch block for this method.
        // Transition stubs are not catch points.
        return !IsTransitionStubFrame();
    }

    uint64_t GetTTypeIndex() const override
    {
        return 0;
    }

    uintptr_t GetLandingPad() const override
    {
        return landingPad;
    }

    void RestoreToCallerContext(CalleeSavedRegisterContext& context, uint32_t adjustedSize = 0) const override
    {
        // this method should not be called because interpreted frame always catches exception
        LOG(RTLOG_FATAL, "IntepreterEHFrameInfo::RestoreToCallerContext should not be called\n");
    }

    const uint32_t* GetIP() const override
    {
        return mFrame.GetIP();
    }

    FrameAddress* GetFA() const override
    {
        return mFrame.GetFA();
    }

    MachineFrame GetMachineFrame() const override
    {
        return mFrame;
    }

    const CString GetFunctionName() const override
    {
        return FrameInfo::GetFuncName();
    }

private:
    bool IsTransitionStubFrame() const
    {
        return mFrame.IsC2IStubFrame() || mFrame.IsI2IFrame() || mFrame.IsI2NFrame();
    }

    uintptr_t landingPad;
};

} // namespace MapleRuntime

#endif // INTERPRETER_ENABLED
#endif // MRT_INTERPRETER_EH_FRAMEINFO_H