1/*
2 * Copyright (C) 2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "Opcode.h"
29#include "OpcodeSize.h"
30
31namespace JSC {
32
33struct Instruction {
34
35 struct Metadata { };
36
37protected:
38 Instruction()
39 { }
40
41private:
42 template<OpcodeSize Width>
43 class Impl {
44 public:
45 OpcodeID opcodeID() const { return static_cast<OpcodeID>(m_opcode); }
46
47 private:
48 typename TypeBySize<Width>::type m_opcode;
49 };
50
51public:
52 OpcodeID opcodeID() const
53 {
54 if (isWide())
55 return wide()->opcodeID();
56 return narrow()->opcodeID();
57 }
58
59 const char* name() const
60 {
61 return opcodeNames[opcodeID()];
62 }
63
64 bool isWide() const
65 {
66 return narrow()->opcodeID() == op_wide;
67 }
68
69 size_t size() const
70 {
71 auto wide = isWide();
72 auto padding = wide ? 1 : 0;
73 auto size = wide ? 4 : 1;
74 return opcodeLengths[opcodeID()] * size + padding;
75 }
76
77 template<class T>
78 bool is() const
79 {
80 return opcodeID() == T::opcodeID;
81 }
82
83 template<class T>
84 T as() const
85 {
86 ASSERT(is<T>());
87 return T::decode(reinterpret_cast<const uint8_t*>(this));
88 }
89
90 template<class T>
91 T* cast()
92 {
93 ASSERT(is<T>());
94 return bitwise_cast<T*>(this);
95 }
96
97 template<class T>
98 const T* cast() const
99 {
100 ASSERT(is<T>());
101 return reinterpret_cast<const T*>(this);
102 }
103
104 const Impl<OpcodeSize::Narrow>* narrow() const
105 {
106 return reinterpret_cast<const Impl<OpcodeSize::Narrow>*>(this);
107 }
108
109 const Impl<OpcodeSize::Wide>* wide() const
110 {
111
112 ASSERT(isWide());
113 return reinterpret_cast<const Impl<OpcodeSize::Wide>*>(bitwise_cast<uintptr_t>(this) + 1);
114 }
115};
116
117} // namespace JSC
118