src/share/vm/c1/c1_ValueType.hpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6680
78bbf4d43a14
parent 0
f90c822e73f8
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #ifndef SHARE_VM_C1_C1_VALUETYPE_HPP
aoqi@0 26 #define SHARE_VM_C1_C1_VALUETYPE_HPP
aoqi@0 27
aoqi@0 28 #include "c1/c1_Compilation.hpp"
aoqi@0 29 #include "ci/ciConstant.hpp"
aoqi@0 30 #include "ci/ciMethodData.hpp"
aoqi@0 31
aoqi@0 32 // type hierarchy
aoqi@0 33 class ValueType;
aoqi@0 34 class VoidType;
aoqi@0 35 class IntType;
aoqi@0 36 class IntConstant;
aoqi@0 37 class IntInterval;
aoqi@0 38 class LongType;
aoqi@0 39 class LongConstant;
aoqi@0 40 class FloatType;
aoqi@0 41 class FloatConstant;
aoqi@0 42 class DoubleType;
aoqi@0 43 class DoubleConstant;
aoqi@0 44 class ObjectType;
aoqi@0 45 class ObjectConstant;
aoqi@0 46 class ArrayType;
aoqi@0 47 class ArrayConstant;
aoqi@0 48 class InstanceType;
aoqi@0 49 class InstanceConstant;
aoqi@0 50 class MetadataType;
aoqi@0 51 class ClassType;
aoqi@0 52 class ClassConstant;
aoqi@0 53 class MethodType;
aoqi@0 54 class MethodConstant;
aoqi@0 55 class MethodDataType;
aoqi@0 56 class MethodDataConstant;
aoqi@0 57 class AddressType;
aoqi@0 58 class AddressConstant;
aoqi@0 59 class IllegalType;
aoqi@0 60
aoqi@0 61
aoqi@0 62 // predefined types
aoqi@0 63 extern VoidType* voidType;
aoqi@0 64 extern IntType* intType;
aoqi@0 65 extern LongType* longType;
aoqi@0 66 extern FloatType* floatType;
aoqi@0 67 extern DoubleType* doubleType;
aoqi@0 68 extern ObjectType* objectType;
aoqi@0 69 extern ArrayType* arrayType;
aoqi@0 70 extern InstanceType* instanceType;
aoqi@0 71 extern ClassType* classType;
aoqi@0 72 extern AddressType* addressType;
aoqi@0 73 extern IllegalType* illegalType;
aoqi@0 74
aoqi@0 75
aoqi@0 76 // predefined constants
aoqi@0 77 extern IntConstant* intZero;
aoqi@0 78 extern IntConstant* intOne;
aoqi@0 79 extern ObjectConstant* objectNull;
aoqi@0 80
aoqi@0 81
aoqi@0 82 // tags
aoqi@0 83 enum ValueTag {
aoqi@0 84 // all legal tags must come first
aoqi@0 85 intTag,
aoqi@0 86 longTag,
aoqi@0 87 floatTag,
aoqi@0 88 doubleTag,
aoqi@0 89 objectTag,
aoqi@0 90 addressTag,
aoqi@0 91 metaDataTag,
aoqi@0 92 number_of_legal_tags,
aoqi@0 93 // all other tags must follow afterwards
aoqi@0 94 voidTag = number_of_legal_tags,
aoqi@0 95 illegalTag,
aoqi@0 96 number_of_tags
aoqi@0 97 };
aoqi@0 98
aoqi@0 99
aoqi@0 100 class ValueType: public CompilationResourceObj {
aoqi@0 101 private:
aoqi@0 102 const int _size;
aoqi@0 103 const ValueTag _tag;
aoqi@0 104 ValueType();
aoqi@0 105 protected:
aoqi@0 106 ValueType(ValueTag tag, int size): _tag(tag), _size(size) {}
aoqi@0 107
aoqi@0 108 public:
aoqi@0 109 // initialization
aoqi@0 110 static void initialize(Arena* arena);
aoqi@0 111
aoqi@0 112 // accessors
aoqi@0 113 virtual ValueType* base() const = 0; // the 'canonical' type (e.g., intType for an IntConstant)
aoqi@0 114 ValueTag tag() const { return _tag; } // the 'canonical' tag (useful for type matching)
aoqi@0 115 int size() const { // the size of an object of the type in words
aoqi@0 116 assert(_size > -1, "shouldn't be asking for size");
aoqi@0 117 return _size;
aoqi@0 118 }
aoqi@0 119 virtual const char tchar() const = 0; // the type 'character' for printing
aoqi@0 120 virtual const char* name() const = 0; // the type name for printing
aoqi@0 121 virtual bool is_constant() const { return false; }
aoqi@0 122
aoqi@0 123 // testers
aoqi@0 124 bool is_void() { return tag() == voidTag; }
aoqi@0 125 bool is_int() { return tag() == intTag; }
aoqi@0 126 bool is_long() { return tag() == longTag; }
aoqi@0 127 bool is_float() { return tag() == floatTag; }
aoqi@0 128 bool is_double() { return tag() == doubleTag; }
aoqi@0 129 bool is_object() { return as_ObjectType() != NULL; }
aoqi@0 130 bool is_array() { return as_ArrayType() != NULL; }
aoqi@0 131 bool is_instance() { return as_InstanceType() != NULL; }
aoqi@0 132 bool is_class() { return as_ClassType() != NULL; }
aoqi@0 133 bool is_method() { return as_MethodType() != NULL; }
aoqi@0 134 bool is_method_data() { return as_MethodDataType() != NULL; }
aoqi@0 135 bool is_address() { return as_AddressType() != NULL; }
aoqi@0 136 bool is_illegal() { return tag() == illegalTag; }
aoqi@0 137
aoqi@0 138 bool is_int_kind() const { return tag() == intTag || tag() == longTag; }
aoqi@0 139 bool is_float_kind() const { return tag() == floatTag || tag() == doubleTag; }
aoqi@0 140 bool is_object_kind() const { return tag() == objectTag; }
aoqi@0 141
aoqi@0 142 bool is_single_word() const { return _size == 1; }
aoqi@0 143 bool is_double_word() const { return _size == 2; }
aoqi@0 144
aoqi@0 145 // casting
aoqi@0 146 virtual VoidType* as_VoidType() { return NULL; }
aoqi@0 147 virtual IntType* as_IntType() { return NULL; }
aoqi@0 148 virtual LongType* as_LongType() { return NULL; }
aoqi@0 149 virtual FloatType* as_FloatType() { return NULL; }
aoqi@0 150 virtual DoubleType* as_DoubleType() { return NULL; }
aoqi@0 151 virtual ObjectType* as_ObjectType() { return NULL; }
aoqi@0 152 virtual ArrayType* as_ArrayType() { return NULL; }
aoqi@0 153 virtual InstanceType* as_InstanceType() { return NULL; }
aoqi@0 154 virtual ClassType* as_ClassType() { return NULL; }
aoqi@0 155 virtual MetadataType* as_MetadataType() { return NULL; }
aoqi@0 156 virtual MethodType* as_MethodType() { return NULL; }
aoqi@0 157 virtual MethodDataType* as_MethodDataType() { return NULL; }
aoqi@0 158 virtual AddressType* as_AddressType() { return NULL; }
aoqi@0 159 virtual IllegalType* as_IllegalType() { return NULL; }
aoqi@0 160
aoqi@0 161 virtual IntConstant* as_IntConstant() { return NULL; }
aoqi@0 162 virtual LongConstant* as_LongConstant() { return NULL; }
aoqi@0 163 virtual FloatConstant* as_FloatConstant() { return NULL; }
aoqi@0 164 virtual DoubleConstant* as_DoubleConstant() { return NULL; }
aoqi@0 165 virtual ObjectConstant* as_ObjectConstant() { return NULL; }
aoqi@0 166 virtual InstanceConstant* as_InstanceConstant(){ return NULL; }
aoqi@0 167 virtual ClassConstant* as_ClassConstant() { return NULL; }
aoqi@0 168 virtual MethodConstant* as_MethodConstant() { return NULL; }
aoqi@0 169 virtual MethodDataConstant* as_MethodDataConstant() { return NULL; }
aoqi@0 170 virtual ArrayConstant* as_ArrayConstant() { return NULL; }
aoqi@0 171 virtual AddressConstant* as_AddressConstant() { return NULL; }
aoqi@0 172
aoqi@0 173 // type operations
aoqi@0 174 ValueType* meet(ValueType* y) const;
aoqi@0 175 ValueType* join(ValueType* y) const;
aoqi@0 176
aoqi@0 177 // debugging
aoqi@0 178 void print(outputStream* s = tty) { s->print("%s", name()); }
aoqi@0 179 };
aoqi@0 180
aoqi@0 181
aoqi@0 182 class VoidType: public ValueType {
aoqi@0 183 public:
aoqi@0 184 VoidType(): ValueType(voidTag, 0) {}
aoqi@0 185 virtual ValueType* base() const { return voidType; }
aoqi@0 186 virtual const char tchar() const { return 'v'; }
aoqi@0 187 virtual const char* name() const { return "void"; }
aoqi@0 188 virtual VoidType* as_VoidType() { return this; }
aoqi@0 189 };
aoqi@0 190
aoqi@0 191
aoqi@0 192 class IntType: public ValueType {
aoqi@0 193 public:
aoqi@0 194 IntType(): ValueType(intTag, 1) {}
aoqi@0 195 virtual ValueType* base() const { return intType; }
aoqi@0 196 virtual const char tchar() const { return 'i'; }
aoqi@0 197 virtual const char* name() const { return "int"; }
aoqi@0 198 virtual IntType* as_IntType() { return this; }
aoqi@0 199 };
aoqi@0 200
aoqi@0 201
aoqi@0 202 class IntConstant: public IntType {
aoqi@0 203 private:
aoqi@0 204 jint _value;
aoqi@0 205
aoqi@0 206 public:
aoqi@0 207 IntConstant(jint value) { _value = value; }
aoqi@0 208
aoqi@0 209 jint value() const { return _value; }
aoqi@0 210
aoqi@0 211 virtual bool is_constant() const { return true; }
aoqi@0 212 virtual IntConstant* as_IntConstant() { return this; }
aoqi@0 213 };
aoqi@0 214
aoqi@0 215
aoqi@0 216 class IntInterval: public IntType {
aoqi@0 217 private:
aoqi@0 218 jint _beg;
aoqi@0 219 jint _end;
aoqi@0 220
aoqi@0 221 public:
aoqi@0 222 IntInterval(jint beg, jint end) {
aoqi@0 223 assert(beg <= end, "illegal interval");
aoqi@0 224 _beg = beg;
aoqi@0 225 _end = end;
aoqi@0 226 }
aoqi@0 227
aoqi@0 228 jint beg() const { return _beg; }
aoqi@0 229 jint end() const { return _end; }
aoqi@0 230
aoqi@0 231 virtual bool is_interval() const { return true; }
aoqi@0 232 };
aoqi@0 233
aoqi@0 234
aoqi@0 235 class LongType: public ValueType {
aoqi@0 236 public:
aoqi@0 237 LongType(): ValueType(longTag, 2) {}
aoqi@0 238 virtual ValueType* base() const { return longType; }
aoqi@0 239 virtual const char tchar() const { return 'l'; }
aoqi@0 240 virtual const char* name() const { return "long"; }
aoqi@0 241 virtual LongType* as_LongType() { return this; }
aoqi@0 242 };
aoqi@0 243
aoqi@0 244
aoqi@0 245 class LongConstant: public LongType {
aoqi@0 246 private:
aoqi@0 247 jlong _value;
aoqi@0 248
aoqi@0 249 public:
aoqi@0 250 LongConstant(jlong value) { _value = value; }
aoqi@0 251
aoqi@0 252 jlong value() const { return _value; }
aoqi@0 253
aoqi@0 254 virtual bool is_constant() const { return true; }
aoqi@0 255 virtual LongConstant* as_LongConstant() { return this; }
aoqi@0 256 };
aoqi@0 257
aoqi@0 258
aoqi@0 259 class FloatType: public ValueType {
aoqi@0 260 public:
aoqi@0 261 FloatType(): ValueType(floatTag, 1) {}
aoqi@0 262 virtual ValueType* base() const { return floatType; }
aoqi@0 263 virtual const char tchar() const { return 'f'; }
aoqi@0 264 virtual const char* name() const { return "float"; }
aoqi@0 265 virtual FloatType* as_FloatType() { return this; }
aoqi@0 266 };
aoqi@0 267
aoqi@0 268
aoqi@0 269 class FloatConstant: public FloatType {
aoqi@0 270 private:
aoqi@0 271 jfloat _value;
aoqi@0 272
aoqi@0 273 public:
aoqi@0 274 FloatConstant(jfloat value) { _value = value; }
aoqi@0 275
aoqi@0 276 jfloat value() const { return _value; }
aoqi@0 277
aoqi@0 278 virtual bool is_constant() const { return true; }
aoqi@0 279 virtual FloatConstant* as_FloatConstant() { return this; }
aoqi@0 280 };
aoqi@0 281
aoqi@0 282
aoqi@0 283 class DoubleType: public ValueType {
aoqi@0 284 public:
aoqi@0 285 DoubleType(): ValueType(doubleTag, 2) {}
aoqi@0 286 virtual ValueType* base() const { return doubleType; }
aoqi@0 287 virtual const char tchar() const { return 'd'; }
aoqi@0 288 virtual const char* name() const { return "double"; }
aoqi@0 289 virtual DoubleType* as_DoubleType() { return this; }
aoqi@0 290 };
aoqi@0 291
aoqi@0 292
aoqi@0 293 class DoubleConstant: public DoubleType {
aoqi@0 294 private:
aoqi@0 295 jdouble _value;
aoqi@0 296
aoqi@0 297 public:
aoqi@0 298 DoubleConstant(jdouble value) { _value = value; }
aoqi@0 299
aoqi@0 300 jdouble value() const { return _value; }
aoqi@0 301
aoqi@0 302 virtual bool is_constant() const { return true; }
aoqi@0 303 virtual DoubleConstant* as_DoubleConstant() { return this; }
aoqi@0 304 };
aoqi@0 305
aoqi@0 306
aoqi@0 307 class ObjectType: public ValueType {
aoqi@0 308 public:
aoqi@0 309 ObjectType(): ValueType(objectTag, 1) {}
aoqi@0 310 virtual ValueType* base() const { return objectType; }
aoqi@0 311 virtual const char tchar() const { return 'a'; }
aoqi@0 312 virtual const char* name() const { return "object"; }
aoqi@0 313 virtual ObjectType* as_ObjectType() { return this; }
aoqi@0 314 virtual ciObject* constant_value() const { ShouldNotReachHere(); return NULL; }
aoqi@0 315 virtual ciType* exact_type() const { return NULL; }
aoqi@0 316 bool is_loaded() const;
aoqi@0 317 jobject encoding() const;
aoqi@0 318 };
aoqi@0 319
aoqi@0 320
aoqi@0 321 class ObjectConstant: public ObjectType {
aoqi@0 322 private:
aoqi@0 323 ciObject* _value;
aoqi@0 324
aoqi@0 325 public:
aoqi@0 326 ObjectConstant(ciObject* value) { _value = value; }
aoqi@0 327
aoqi@0 328 ciObject* value() const { return _value; }
aoqi@0 329
aoqi@0 330 virtual bool is_constant() const { return true; }
aoqi@0 331 virtual ObjectConstant* as_ObjectConstant() { return this; }
aoqi@0 332 virtual ciObject* constant_value() const;
aoqi@0 333 virtual ciType* exact_type() const;
aoqi@0 334 };
aoqi@0 335
aoqi@0 336
aoqi@0 337 class ArrayType: public ObjectType {
aoqi@0 338 public:
aoqi@0 339 virtual ArrayType* as_ArrayType() { return this; }
aoqi@0 340 };
aoqi@0 341
aoqi@0 342
aoqi@0 343 class ArrayConstant: public ArrayType {
aoqi@0 344 private:
aoqi@0 345 ciArray* _value;
aoqi@0 346
aoqi@0 347 public:
aoqi@0 348 ArrayConstant(ciArray* value) { _value = value; }
aoqi@0 349
aoqi@0 350 ciArray* value() const { return _value; }
aoqi@0 351
aoqi@0 352 virtual bool is_constant() const { return true; }
aoqi@0 353 virtual ArrayConstant* as_ArrayConstant() { return this; }
aoqi@0 354 virtual ciObject* constant_value() const;
aoqi@0 355 virtual ciType* exact_type() const;
aoqi@0 356 };
aoqi@0 357
aoqi@0 358
aoqi@0 359 class InstanceType: public ObjectType {
aoqi@0 360 public:
aoqi@0 361 virtual InstanceType* as_InstanceType() { return this; }
aoqi@0 362 };
aoqi@0 363
aoqi@0 364
aoqi@0 365 class InstanceConstant: public InstanceType {
aoqi@0 366 private:
aoqi@0 367 ciInstance* _value;
aoqi@0 368
aoqi@0 369 public:
aoqi@0 370 InstanceConstant(ciInstance* value) { _value = value; }
aoqi@0 371
aoqi@0 372 ciInstance* value() const { return _value; }
aoqi@0 373
aoqi@0 374 virtual bool is_constant() const { return true; }
aoqi@0 375 virtual InstanceConstant* as_InstanceConstant(){ return this; }
aoqi@0 376 virtual ciObject* constant_value() const;
aoqi@0 377 virtual ciType* exact_type() const;
aoqi@0 378 };
aoqi@0 379
aoqi@0 380
aoqi@0 381 class MetadataType: public ValueType {
aoqi@0 382 public:
aoqi@0 383 MetadataType(): ValueType(metaDataTag, 1) {}
aoqi@0 384 virtual ValueType* base() const { return objectType; }
aoqi@0 385 virtual const char tchar() const { return 'a'; }
aoqi@0 386 virtual const char* name() const { return "object"; }
aoqi@0 387 virtual MetadataType* as_MetadataType() { return this; }
aoqi@0 388 bool is_loaded() const;
aoqi@0 389 jobject encoding() const;
aoqi@0 390 virtual ciMetadata* constant_value() const { ShouldNotReachHere(); return NULL; }
aoqi@0 391 };
aoqi@0 392
aoqi@0 393
aoqi@0 394 class ClassType: public MetadataType {
aoqi@0 395 public:
aoqi@0 396 virtual ClassType* as_ClassType() { return this; }
aoqi@0 397 };
aoqi@0 398
aoqi@0 399
aoqi@0 400 class ClassConstant: public ClassType {
aoqi@0 401 private:
aoqi@0 402 ciInstanceKlass* _value;
aoqi@0 403
aoqi@0 404 public:
aoqi@0 405 ClassConstant(ciInstanceKlass* value) { _value = value; }
aoqi@0 406
aoqi@0 407 ciInstanceKlass* value() const { return _value; }
aoqi@0 408
aoqi@0 409 virtual bool is_constant() const { return true; }
aoqi@0 410 virtual ClassConstant* as_ClassConstant() { return this; }
aoqi@0 411 virtual ciMetadata* constant_value() const { return _value; }
aoqi@0 412 virtual ciType* exact_type() const;
aoqi@0 413 };
aoqi@0 414
aoqi@0 415
aoqi@0 416 class MethodType: public MetadataType {
aoqi@0 417 public:
aoqi@0 418 virtual MethodType* as_MethodType() { return this; }
aoqi@0 419 };
aoqi@0 420
aoqi@0 421
aoqi@0 422 class MethodConstant: public MethodType {
aoqi@0 423 private:
aoqi@0 424 ciMethod* _value;
aoqi@0 425
aoqi@0 426 public:
aoqi@0 427 MethodConstant(ciMethod* value) { _value = value; }
aoqi@0 428
aoqi@0 429 ciMethod* value() const { return _value; }
aoqi@0 430
aoqi@0 431 virtual bool is_constant() const { return true; }
aoqi@0 432
aoqi@0 433 virtual MethodConstant* as_MethodConstant() { return this; }
aoqi@0 434 virtual ciMetadata* constant_value() const { return _value; }
aoqi@0 435 };
aoqi@0 436
aoqi@0 437
aoqi@0 438 class MethodDataType: public MetadataType {
aoqi@0 439 public:
aoqi@0 440 virtual MethodDataType* as_MethodDataType() { return this; }
aoqi@0 441 };
aoqi@0 442
aoqi@0 443
aoqi@0 444 class MethodDataConstant: public MethodDataType {
aoqi@0 445 private:
aoqi@0 446 ciMethodData* _value;
aoqi@0 447
aoqi@0 448 public:
aoqi@0 449 MethodDataConstant(ciMethodData* value) { _value = value; }
aoqi@0 450
aoqi@0 451 ciMethodData* value() const { return _value; }
aoqi@0 452
aoqi@0 453 virtual bool is_constant() const { return true; }
aoqi@0 454
aoqi@0 455 virtual MethodDataConstant* as_MethodDataConstant() { return this; }
aoqi@0 456 virtual ciMetadata* constant_value() const { return _value; }
aoqi@0 457 };
aoqi@0 458
aoqi@0 459
aoqi@0 460 class AddressType: public ValueType {
aoqi@0 461 public:
aoqi@0 462 AddressType(): ValueType(addressTag, 1) {}
aoqi@0 463 virtual ValueType* base() const { return addressType; }
aoqi@0 464 virtual const char tchar() const { return 'r'; }
aoqi@0 465 virtual const char* name() const { return "address"; }
aoqi@0 466 virtual AddressType* as_AddressType() { return this; }
aoqi@0 467 };
aoqi@0 468
aoqi@0 469
aoqi@0 470 class AddressConstant: public AddressType {
aoqi@0 471 private:
aoqi@0 472 jint _value;
aoqi@0 473
aoqi@0 474 public:
aoqi@0 475 AddressConstant(jint value) { _value = value; }
aoqi@0 476
aoqi@0 477 jint value() const { return _value; }
aoqi@0 478
aoqi@0 479 virtual bool is_constant() const { return true; }
aoqi@0 480
aoqi@0 481 virtual AddressConstant* as_AddressConstant() { return this; }
aoqi@0 482 };
aoqi@0 483
aoqi@0 484
aoqi@0 485 class IllegalType: public ValueType {
aoqi@0 486 public:
aoqi@0 487 IllegalType(): ValueType(illegalTag, -1) {}
aoqi@0 488 virtual ValueType* base() const { return illegalType; }
aoqi@0 489 virtual const char tchar() const { return ' '; }
aoqi@0 490 virtual const char* name() const { return "illegal"; }
aoqi@0 491 virtual IllegalType* as_IllegalType() { return this; }
aoqi@0 492 };
aoqi@0 493
aoqi@0 494
aoqi@0 495 // conversion between ValueTypes, BasicTypes, and ciConstants
aoqi@0 496 ValueType* as_ValueType(BasicType type);
aoqi@0 497 ValueType* as_ValueType(ciConstant value);
aoqi@0 498 BasicType as_BasicType(ValueType* type);
aoqi@0 499
aoqi@0 500 inline ValueType* as_ValueType(ciType* type) { return as_ValueType(type->basic_type()); }
aoqi@0 501
aoqi@0 502 #endif // SHARE_VM_C1_C1_VALUETYPE_HPP

mercurial