|
42 | 42 | import java.util.Deque;
|
43 | 43 | import java.util.List;
|
44 | 44 | import java.util.stream.Collectors;
|
| 45 | +import java.util.stream.IntStream; |
45 | 46 |
|
46 | 47 | /**
|
47 | 48 | * This class generates static utilities class for C structs, unions.
|
@@ -133,13 +134,21 @@ public void addFunctionalInterface(Declaration parentDecl, Type.Function funcTyp
|
133 | 134 | public void addVar(Declaration.Variable varTree) {
|
134 | 135 | String javaName = JavaName.getOrThrow(varTree);
|
135 | 136 | appendBlankLine();
|
136 |
| - String offsetField = emitOffsetFieldDecl(varTree); |
| 137 | + String layoutField = emitLayoutFieldDecl(varTree, javaName); |
| 138 | + appendBlankLine(); |
| 139 | + String offsetField = emitOffsetFieldDecl(varTree, javaName); |
137 | 140 | if (Utils.isArray(varTree.type()) || Utils.isStructOrUnion(varTree.type())) {
|
138 |
| - String sizeField = emitSizeFieldDecl(varTree); |
139 |
| - emitSegmentGetter(javaName, varTree, offsetField, sizeField); |
140 |
| - emitSegmentSetter(javaName, varTree, offsetField, sizeField); |
| 141 | + emitSegmentGetter(javaName, varTree, offsetField, layoutField); |
| 142 | + emitSegmentSetter(javaName, varTree, offsetField, layoutField); |
| 143 | + int dims = Utils.dimensions(varTree.type()).size(); |
| 144 | + if (dims > 0) { |
| 145 | + emitDimensionsFieldDecl(varTree, javaName); |
| 146 | + String arrayHandle = emitArrayElementHandle(javaName, varTree, layoutField, dims); |
| 147 | + IndexList indexList = IndexList.of(dims); |
| 148 | + emitFieldArrayGetter(javaName, varTree, arrayHandle, indexList); |
| 149 | + emitFieldArraySetter(javaName, varTree, arrayHandle, indexList); |
| 150 | + } |
141 | 151 | } else if (Utils.isPointer(varTree.type()) || Utils.isPrimitive(varTree.type())) {
|
142 |
| - String layoutField = emitLayoutFieldDecl(varTree); |
143 | 152 | emitFieldGetter(javaName, varTree, layoutField, offsetField);
|
144 | 153 | emitFieldSetter(javaName, varTree, layoutField, offsetField);
|
145 | 154 | } else {
|
@@ -199,29 +208,94 @@ private void emitFieldSetter(String javaName, Declaration.Variable varTree, Stri
|
199 | 208 | """);
|
200 | 209 | }
|
201 | 210 |
|
202 |
| - private void emitSegmentGetter(String javaName, Declaration.Variable varTree, String offsetField, String sizeField) { |
| 211 | + private void emitSegmentGetter(String javaName, Declaration.Variable varTree, String offsetField, String layoutField) { |
203 | 212 | appendBlankLine();
|
204 | 213 | emitFieldDocComment(varTree, "Getter for field:");
|
205 | 214 | String segmentParam = safeParameterName(kindName());
|
206 | 215 | appendIndentedLines(STR."""
|
207 | 216 | public static MemorySegment \{javaName}(MemorySegment \{segmentParam}) {
|
208 |
| - return \{segmentParam}.asSlice(\{offsetField}, \{sizeField}); |
| 217 | + return \{segmentParam}.asSlice(\{offsetField}, \{layoutField}.byteSize()); |
209 | 218 | }
|
210 | 219 | """);
|
211 | 220 | }
|
212 | 221 |
|
213 |
| - private void emitSegmentSetter(String javaName, Declaration.Variable varTree, String offsetField, String sizeField) { |
| 222 | + private void emitSegmentSetter(String javaName, Declaration.Variable varTree, String offsetField, String layoutField) { |
214 | 223 | appendBlankLine();
|
215 | 224 | emitFieldDocComment(varTree, "Setter for field:");
|
216 | 225 | String segmentParam = safeParameterName(kindName());
|
217 | 226 | String valueParam = safeParameterName("fieldValue");
|
218 | 227 | appendIndentedLines(STR."""
|
219 | 228 | public static void \{javaName}(MemorySegment \{segmentParam}, MemorySegment \{valueParam}) {
|
220 |
| - MemorySegment.copy(\{valueParam}, 0L, \{segmentParam}, \{offsetField}, \{sizeField}); |
| 229 | + MemorySegment.copy(\{valueParam}, 0L, \{segmentParam}, \{offsetField}, \{layoutField}.byteSize()); |
221 | 230 | }
|
222 | 231 | """);
|
223 | 232 | }
|
224 | 233 |
|
| 234 | + private String emitArrayElementHandle(String javaName, Declaration.Variable varTree, String fieldLayoutName, int dims) { |
| 235 | + String arrayHandleName = STR."\{javaName}$ELEM_HANDLE"; |
| 236 | + String path = IntStream.range(0, dims) |
| 237 | + .mapToObj(_ -> "sequenceElement()") |
| 238 | + .collect(Collectors.joining(", ")); |
| 239 | + Type elemType = Utils.typeOrElemType(varTree.type()); |
| 240 | + if (Utils.isStructOrUnion(elemType)) { |
| 241 | + appendIndentedLines(STR.""" |
| 242 | + private static final MethodHandle \{arrayHandleName} = \{fieldLayoutName}.sliceHandle(\{path}); |
| 243 | + """); |
| 244 | + } else { |
| 245 | + appendIndentedLines(STR.""" |
| 246 | + private static final VarHandle \{arrayHandleName} = \{fieldLayoutName}.varHandle(\{path}); |
| 247 | + """); |
| 248 | + } |
| 249 | + return arrayHandleName; |
| 250 | + } |
| 251 | + |
| 252 | + private void emitFieldArrayGetter(String javaName, Declaration.Variable varTree, String arrayElementHandle, IndexList indexList) { |
| 253 | + String segmentParam = safeParameterName(kindName()); |
| 254 | + Type elemType = Utils.typeOrElemType(varTree.type()); |
| 255 | + Class<?> elemTypeCls = Utils.carrierFor(elemType); |
| 256 | + appendBlankLine(); |
| 257 | + emitFieldDocComment(varTree, "Indexed getter for field:"); |
| 258 | + if (Utils.isStructOrUnion(elemType)) { |
| 259 | + appendIndentedLines(STR.""" |
| 260 | + public static MemorySegment \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}) { |
| 261 | + try { |
| 262 | + return (MemorySegment)\{arrayElementHandle}.invokeExact(\{segmentParam}, 0L, \{indexList.use()}); |
| 263 | + } catch (Throwable ex$) { |
| 264 | + throw new AssertionError("should not reach here", ex$); |
| 265 | + } |
| 266 | + } |
| 267 | + """); |
| 268 | + } else { |
| 269 | + appendIndentedLines(STR.""" |
| 270 | + public static \{elemTypeCls.getSimpleName()} \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}) { |
| 271 | + return (\{elemTypeCls.getSimpleName()})\{arrayElementHandle}.get(\{segmentParam}, 0L, \{indexList.use()}); |
| 272 | + } |
| 273 | + """); |
| 274 | + } |
| 275 | + } |
| 276 | + |
| 277 | + private void emitFieldArraySetter(String javaName, Declaration.Variable varTree, String arrayElementHandle, IndexList indexList) { |
| 278 | + String segmentParam = safeParameterName(kindName()); |
| 279 | + String valueParam = safeParameterName("fieldValue"); |
| 280 | + Type elemType = Utils.typeOrElemType(varTree.type()); |
| 281 | + Class<?> elemTypeCls = Utils.carrierFor(elemType); |
| 282 | + appendBlankLine(); |
| 283 | + emitFieldDocComment(varTree, "Indexed setter for field:"); |
| 284 | + if (Utils.isStructOrUnion(elemType)) { |
| 285 | + appendIndentedLines(STR.""" |
| 286 | + public static void \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}, MemorySegment \{valueParam}) { |
| 287 | + MemorySegment.copy(\{valueParam}, 0L, \{javaName}(\{segmentParam}, \{indexList.use()}), 0L, \{layoutString(elemType)}.byteSize()); |
| 288 | + } |
| 289 | + """); |
| 290 | + } else { |
| 291 | + appendIndentedLines(STR.""" |
| 292 | + public static void \{javaName}(MemorySegment \{segmentParam}, \{indexList.decl()}, \{elemTypeCls.getSimpleName()} \{valueParam}) { |
| 293 | + \{arrayElementHandle}.set(\{segmentParam}, 0L, \{indexList.use()}, \{valueParam}); |
| 294 | + } |
| 295 | + """); |
| 296 | + } |
| 297 | + } |
| 298 | + |
225 | 299 | private void emitAsSlice() {
|
226 | 300 | String arrayParam = safeParameterName("array");
|
227 | 301 | appendIndentedLines(STR."""
|
@@ -309,29 +383,53 @@ public static final GroupLayout layout() {
|
309 | 383 | """);
|
310 | 384 | }
|
311 | 385 |
|
312 |
| - private String emitOffsetFieldDecl(Declaration field) { |
313 |
| - String offsetFieldName = STR."\{field.name()}$OFFSET"; |
| 386 | + private String emitOffsetFieldDecl(Declaration.Variable field, String javaName) { |
| 387 | + String offsetFieldName = STR."\{javaName}$OFFSET"; |
314 | 388 | appendIndentedLines(STR."""
|
315 | 389 | private static final long \{offsetFieldName} = \{ClangOffsetOf.getOrThrow(field) / 8};
|
316 | 390 | """);
|
| 391 | + appendBlankLine(); |
| 392 | + emitFieldDocComment(field, "Offset for field:"); |
| 393 | + appendIndentedLines(STR.""" |
| 394 | + public static final long \{javaName}$offset() { |
| 395 | + return \{offsetFieldName}; |
| 396 | + } |
| 397 | + """); |
317 | 398 | return offsetFieldName;
|
318 | 399 | }
|
319 | 400 |
|
320 |
| - private String emitLayoutFieldDecl(Declaration.Variable field) { |
321 |
| - String layoutFieldName = STR."\{field.name()}$LAYOUT"; |
| 401 | + private String emitLayoutFieldDecl(Declaration.Variable field, String javaName) { |
| 402 | + String layoutFieldName = STR."\{javaName}$LAYOUT"; |
322 | 403 | String layoutType = Utils.layoutCarrierFor(field.type()).getSimpleName();
|
323 | 404 | appendIndentedLines(STR."""
|
324 | 405 | private static final \{layoutType} \{layoutFieldName} = (\{layoutType})$LAYOUT.select(\{fieldElementPaths(field.name())});
|
325 | 406 | """);
|
| 407 | + appendBlankLine(); |
| 408 | + emitFieldDocComment(field, "Layout for field:"); |
| 409 | + appendIndentedLines(STR.""" |
| 410 | + public static final \{layoutType} \{javaName}$layout() { |
| 411 | + return \{layoutFieldName}; |
| 412 | + } |
| 413 | + """); |
326 | 414 | return layoutFieldName;
|
327 | 415 | }
|
328 | 416 |
|
329 |
| - private String emitSizeFieldDecl(Declaration field) { |
330 |
| - String sizeFieldName = STR."\{field.name()}$SIZE"; |
| 417 | + private void emitDimensionsFieldDecl(Declaration.Variable field, String javaName) { |
| 418 | + String dimsFieldName = STR."\{javaName}$DIMS"; |
| 419 | + List<Long> dimensions = Utils.dimensions(field.type()); |
| 420 | + String dimsString = dimensions.stream().map(d -> d.toString()) |
| 421 | + .collect(Collectors.joining(", ")); |
331 | 422 | appendIndentedLines(STR."""
|
332 |
| - private static final long \{sizeFieldName} = \{ClangSizeOf.getOrThrow(field) / 8}; |
| 423 | +
|
| 424 | + private static long[] \{dimsFieldName} = { \{dimsString} }; |
| 425 | + """); |
| 426 | + appendBlankLine(); |
| 427 | + emitFieldDocComment(field, "Dimensions for array field:"); |
| 428 | + appendIndentedLines(STR.""" |
| 429 | + public static long[] \{javaName}$dimensions() { |
| 430 | + return \{dimsFieldName}; |
| 431 | + } |
333 | 432 | """);
|
334 |
| - return sizeFieldName; |
335 | 433 | }
|
336 | 434 |
|
337 | 435 | private String structOrUnionLayoutString(Type type) {
|
|
0 commit comments