remotemono
RMonoVariant_Impl.h
1 /*
2  Copyright 2020 David "Alemarius Nexus" Lerch
3 
4  This file is part of RemoteMono.
5 
6  RemoteMono is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  RemoteMono is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with RemoteMono. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include "../config.h"
23 
24 #include "RMonoVariant_Def.h"
25 #include "abi/RMonoABITypeTraits.h"
26 
27 #include <exception>
28 
29 
30 
31 
32 namespace remotemono
33 {
34 
35 
36 
38 {
39  if ((flags & FlagIsAlias) != 0) {
40  return alias->isNullPointer();
41  }
42 
43  switch (getType()) {
44  case TypeInvalid:
45  return true;
46  case TypeValue:
47  return ((flags & FlagOwnMemory) == 0) && v.ddata == nullptr;
48  case TypeMonoObjectPtr:
49  return ((flags & FlagOwnMemory) == 0) && op == nullptr;
50  case TypeRawPtr:
51  return ((flags & FlagOwnMemory) == 0) && pp == nullptr;
52  default:
53  assert(false);
54  }
55 
56  return true;
57 }
58 
59 
60 template <typename ABI>
61 size_t RMonoVariant::getRemoteMemorySize(ABI& abi, size_t& alignment) const
62 {
63  typedef RMonoABITypeTraits<ABI> ABITypeTraits;
64 
65  if ((flags & FlagIsAlias) != 0) {
66  return alias->getRemoteMemorySize(abi, alignment);
67  }
68 
69  size_t size;
70 
71  if (isNullPointer()) {
72  alignment = 1;
73  size = 0;
74  } else {
75  // TODO: Actually, I have no clue what the minimum alignments for those types are. It's just a wild guess that errs
76  // somewhat on the safe side...
77 
78  switch (getType()) {
79  case TypeValue:
80  if (v.size <= 1) {
81  alignment = 1;
82  } else if (v.size <= 2) {
83  alignment = 2;
84  } else if (v.size <= 4) {
85  alignment = 4;
86  } else if (v.size <= 8) {
87  alignment = 8;
88  } else {
89  alignment = 16; // Might be necessary for SIMD instructions
90  }
91  size = v.size;
92  break;
93  case TypeMonoObjectPtr:
94  alignment = sizeof(typename ABITypeTraits::irmono_gchandle);
95  size = sizeof(typename ABITypeTraits::irmono_gchandle);
96  break;
97  case TypeRawPtr:
98  alignment = sizeof(typename ABITypeTraits::irmono_voidp);
99  size = sizeof(typename ABITypeTraits::irmono_voidp);
100  break;
101  default:
102  assert(false);
103  alignment = 1;
104  size = 0;
105  }
106  }
107 
108  assert(alignment <= getMaxRequiredAlignment());
109 
110  return size;
111 }
112 
113 
114 template <typename ABI>
115 void RMonoVariant::copyForRemoteMemory(ABI& abi, void* buf) const
116 {
117  typedef RMonoABITypeTraits<ABI> ABITypeTraits;
118 
119  if ((flags & FlagIsAlias) != 0) {
120  alias->copyForRemoteMemory(abi, buf);
121  return;
122  }
123 
124  if (isNullPointer()) {
125  return;
126  }
127 
128  switch (getType()) {
129  case TypeValue:
130  memcpy(buf, getValueData(), v.size);
131  break;
132  case TypeMonoObjectPtr:
133  *((typename ABITypeTraits::irmono_gchandle*) buf) = abi.hp2i_RMonoObjectPtr(getMonoObjectPtr());
134  break;
135  case TypeRawPtr:
136  *((typename ABITypeTraits::irmono_voidp*) buf) = abi.p2i_rmono_voidp(getRawPtr());
137  break;
138  }
139 }
140 
141 
142 template <typename ABI>
143 void RMonoVariant::updateFromRemoteMemory(ABI& abi, RMonoAPIBase& mono, void* buf)
144 {
145  typedef RMonoABITypeTraits<ABI> ABITypeTraits;
146 
147  if ((flags & FlagIsAlias) != 0) {
148  alias->updateFromRemoteMemory(abi, mono, buf);
149  return;
150  }
151 
152  if (isNullPointer()) {
153  return;
154  }
155 
156  switch (getType()) {
157  case TypeValue:
158  memcpy(getValueData(), buf, v.size);
159  break;
160  case TypeMonoObjectPtr:
161  if ((flags & FlagOwnMemory) != 0) {
162  o = abi.hi2p_RMonoObjectPtr(*((typename ABITypeTraits::irmono_gchandle*) buf), &mono);
163  } else {
164  *op = abi.hi2p_RMonoObjectPtr(*((typename ABITypeTraits::irmono_gchandle*) buf), &mono);
165  }
166  break;
167  case TypeRawPtr:
168  if ((flags & FlagOwnMemory) != 0) {
169  p = abi.i2p_rmono_voidp(*((typename ABITypeTraits::irmono_voidp*) buf));
170  } else {
171  *pp = abi.i2p_rmono_voidp(*((typename ABITypeTraits::irmono_voidp*) buf));
172  }
173  break;
174  default:
175  assert(false);
176  }
177 }
178 
179 
180 
181 };
remotemono::RMonoVariant::isNullPointer
bool isNullPointer() const
Definition: RMonoVariant_Impl.h:37
remotemono::RMonoVariant::getMaxRequiredAlignment
static constexpr size_t getMaxRequiredAlignment()
Definition: RMonoVariant_Def.h:187
remotemono::RMonoVariant::TypeMonoObjectPtr
@ TypeMonoObjectPtr
Definition: RMonoVariant_Def.h:89
remotemono::RMonoAPIBase
Definition: RMonoAPIBase_Def.h:43
remotemono::RMonoVariant::copyForRemoteMemory
void copyForRemoteMemory(ABI &abi, void *buf) const
Definition: RMonoVariant_Impl.h:115
remotemono::RMonoVariant::getRemoteMemorySize
size_t getRemoteMemorySize(ABI &abi, size_t &alignment) const
Definition: RMonoVariant_Impl.h:61
remotemono::RMonoVariant::updateFromRemoteMemory
void updateFromRemoteMemory(ABI &abi, RMonoAPIBase &mono, void *buf)
Definition: RMonoVariant_Impl.h:143
remotemono::RMonoVariant::TypeRawPtr
@ TypeRawPtr
Definition: RMonoVariant_Def.h:94
remotemono::RMonoVariant::getValueData
void * getValueData()
Definition: RMonoVariant_Def.h:467
remotemono::RMonoVariant::getType
Type getType() const
Definition: RMonoVariant_Def.h:411
remotemono::RMonoVariant::getMonoObjectPtr
RMonoObjectPtr getMonoObjectPtr() const
Definition: RMonoVariant_Def.h:507
remotemono::RMonoVariant::TypeValue
@ TypeValue
Definition: RMonoVariant_Def.h:84
remotemono::RMonoVariant::getRawPtr
rmono_voidp getRawPtr() const
Definition: RMonoVariant_Def.h:525