libjit-sys 0.2.1

Just-In-Time Compilation in Rust using LibJIT bindings
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
/*
 * jit-type.c - Functions for manipulating type descriptors.
 *
 * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
 *
 * This file is part of the libjit library.
 *
 * The libjit library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * The libjit library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include "jit-internal.h"
#include "jit-apply-rules.h"
#include "jit-rules.h"

/*@

@cindex jit-type.h
@tindex jit_type_t

The functions that are defined in @code{<jit/jit-type.h>} allow
the library user to create and manipulate objects that represent
native system types.  For example, @code{jit_type_int} represents
the signed 32-bit integer type.

Each @code{jit_type_t} object represents a basic system type,
be it a primitive, a struct, a union, a pointer, or a function signature.
The library uses this information to lay out values in memory.

The following pre-defined types are available:

@table @code
@vindex jit_type_void
@item jit_type_void
Represents the @code{void} type.

@vindex jit_type_sbyte
@item jit_type_sbyte
Represents a signed 8-bit integer type.

@vindex jit_type_ubyte
@item jit_type_ubyte
Represents an unsigned 8-bit integer type.

@vindex jit_type_short
@item jit_type_short
Represents a signed 16-bit integer type.

@vindex jit_type_ushort
@item jit_type_ushort
Represents an unsigned 16-bit integer type.

@vindex jit_type_int
@item jit_type_int
Represents a signed 32-bit integer type.

@vindex jit_type_uint
@item jit_type_uint
Represents an unsigned 32-bit integer type.

@vindex jit_type_nint
@item jit_type_nint
Represents a signed integer type that has the same size and
alignment as a native pointer.

@vindex jit_type_nuint
@item jit_type_nuint
Represents an unsigned integer type that has the same size and
alignment as a native pointer.

@vindex jit_type_long
@item jit_type_long
Represents a signed 64-bit integer type.

@vindex jit_type_ulong
@item jit_type_ulong
Represents an unsigned 64-bit integer type.

@vindex jit_type_float32
@item jit_type_float32
Represents a 32-bit floating point type.

@vindex jit_type_float64
@item jit_type_float64
Represents a 64-bit floating point type.

@vindex jit_type_nfloat
@item jit_type_nfloat
Represents a floating point type that represents the greatest
precision supported on the native platform.

@vindex jit_type_void_ptr
@item jit_type_void_ptr
Represents the system's @code{void *} type.  This can be used wherever
a native pointer type is required.
@end table

Type descriptors are reference counted.  You can make a copy of a type
descriptor using the @code{jit_type_copy} function, and free the copy with
@code{jit_type_free}.

Some languages have special versions of the primitive numeric types
(e.g. boolean types, 16-bit Unicode character types, enumerations, etc).
If it is important to distinguish these special versions from the
numeric types, then you should use the @code{jit_type_create_tagged}
function below.

The following types correspond to the system types on the local
platform.  i.e. @code{jit_type_sys_int} will be the same size as
@code{long} on the local platform, whereas @code{jit_type_long} is
always 64 bits in size.  These types should not be used to compile
code that is intended to work identically on all platforms:

@table @code
@vindex jit_type_sys_bool
@item jit_type_sys_bool
Corresponds to the system @code{bool} type.

@vindex jit_type_sys_char
@item jit_type_sys_char
Corresponds to the system @code{char} type.  This may be either signed
or unsigned, depending upon the underlying system.

@vindex jit_type_sys_schar
@item jit_type_sys_schar
Corresponds to the system @code{signed char} type.

@vindex jit_type_sys_uchar
@item jit_type_sys_uchar
Corresponds to the system @code{unsigned char} type.

@vindex jit_type_sys_short
@item jit_type_sys_short
Corresponds to the system @code{short} type.

@vindex jit_type_sys_ushort
@item jit_type_sys_ushort
Corresponds to the system @code{unsigned short} type.

@vindex jit_type_sys_int
@item jit_type_sys_int
Corresponds to the system @code{int} type.

@vindex jit_type_sys_uint
@item jit_type_sys_uint
Corresponds to the system @code{unsigned int} type.

@vindex jit_type_sys_long
@item jit_type_sys_long
Corresponds to the system @code{long} type.

@vindex jit_type_sys_ulong
@item jit_type_sys_ulong
Corresponds to the system @code{unsigned long} type.

@vindex jit_type_sys_longlong
@item jit_type_sys_longlong
Corresponds to the system @code{long long} type (@code{__int64} under Win32).

@vindex jit_type_sys_ulonglong
@item jit_type_sys_ulonglong
Corresponds to the system @code{unsigned long long} type
(@code{unsigned __int64} under Win32).

@vindex jit_type_sys_float
@item jit_type_sys_float
Corresponds to the system @code{float} type.

@vindex jit_type_sys_double
@item jit_type_sys_double
Corresponds to the system @code{double} type.

@vindex jit_type_sys_long_double
@item jit_type_sys_long_double
Corresponds to the system @code{long double} type.
@end table

@*/

/*
 * Pre-defined type descriptors.
 */
struct _jit_type const _jit_type_void_def =
	{1, JIT_TYPE_VOID, 0, 1, 0, 1, 1};
jit_type_t const jit_type_void = (jit_type_t)&_jit_type_void_def;
struct _jit_type const _jit_type_sbyte_def =
	{1, JIT_TYPE_SBYTE, 0, 1, 0, sizeof(jit_sbyte), JIT_ALIGN_SBYTE};
jit_type_t const jit_type_sbyte = (jit_type_t)&_jit_type_sbyte_def;
struct _jit_type const _jit_type_ubyte_def =
	{1, JIT_TYPE_UBYTE, 0, 1, 0, sizeof(jit_ubyte), JIT_ALIGN_UBYTE};
jit_type_t const jit_type_ubyte = (jit_type_t)&_jit_type_ubyte_def;
struct _jit_type const _jit_type_short_def =
	{1, JIT_TYPE_SHORT, 0, 1, 0, sizeof(jit_short), JIT_ALIGN_SHORT};
jit_type_t const jit_type_short = (jit_type_t)&_jit_type_short_def;
struct _jit_type const _jit_type_ushort_def =
	{1, JIT_TYPE_USHORT, 0, 1, 0, sizeof(jit_ushort), JIT_ALIGN_USHORT};
jit_type_t const jit_type_ushort = (jit_type_t)&_jit_type_ushort_def;
struct _jit_type const _jit_type_int_def =
	{1, JIT_TYPE_INT, 0, 1, 0, sizeof(jit_int), JIT_ALIGN_INT};
jit_type_t const jit_type_int = (jit_type_t)&_jit_type_int_def;
struct _jit_type const _jit_type_uint_def =
	{1, JIT_TYPE_UINT, 0, 1, 0, sizeof(jit_uint), JIT_ALIGN_UINT};
jit_type_t const jit_type_uint = (jit_type_t)&_jit_type_uint_def;
struct _jit_type const _jit_type_nint_def =
	{1, JIT_TYPE_NINT, 0, 1, 0, sizeof(jit_nint), JIT_ALIGN_NINT};
jit_type_t const jit_type_nint = (jit_type_t)&_jit_type_nint_def;
struct _jit_type const _jit_type_nuint_def =
	{1, JIT_TYPE_NUINT, 0, 1, 0, sizeof(jit_nuint), JIT_ALIGN_NUINT};
jit_type_t const jit_type_nuint = (jit_type_t)&_jit_type_nuint_def;
struct _jit_type const _jit_type_long_def =
	{1, JIT_TYPE_LONG, 0, 1, 0, sizeof(jit_long), JIT_ALIGN_LONG};
jit_type_t const jit_type_long = (jit_type_t)&_jit_type_long_def;
struct _jit_type const _jit_type_ulong_def =
	{1, JIT_TYPE_ULONG, 0, 1, 0, sizeof(jit_ulong), JIT_ALIGN_ULONG};
jit_type_t const jit_type_ulong = (jit_type_t)&_jit_type_ulong_def;
struct _jit_type const _jit_type_float32_def =
	{1, JIT_TYPE_FLOAT32, 0, 1, 0, sizeof(jit_float32), JIT_ALIGN_FLOAT32};
jit_type_t const jit_type_float32 = (jit_type_t)&_jit_type_float32_def;
struct _jit_type const _jit_type_float64_def =
	{1, JIT_TYPE_FLOAT64, 0, 1, 0, sizeof(jit_float64), JIT_ALIGN_FLOAT64};
jit_type_t const jit_type_float64 = (jit_type_t)&_jit_type_float64_def;
struct _jit_type const _jit_type_nfloat_def =
	{1, JIT_TYPE_NFLOAT, 0, 1, 0, sizeof(jit_nfloat), JIT_ALIGN_NFLOAT};
jit_type_t const jit_type_nfloat = (jit_type_t)&_jit_type_nfloat_def;
struct _jit_type const _jit_type_void_ptr_def =
	{1, JIT_TYPE_PTR, 0, 1, 0, sizeof(void *), JIT_ALIGN_PTR,
	 (jit_type_t)&_jit_type_void_def};
jit_type_t const jit_type_void_ptr = (jit_type_t)&_jit_type_void_ptr_def;

/*
 * Type descriptors for the system "char", "int", "long", etc types.
 * These are defined to one of the above values, tagged with a value
 * that indicates which system type it is referring to.
 */
#define DECLARE_TAGGED(name,real,tag)	\
static struct jit_tagged_type const name##_tagged = \
	{{1, JIT_TYPE_FIRST_TAGGED + (tag), 0, 1, 0, 0, 0, \
	 (jit_type_t)&_jit_type_##real}, 0, 0}; \
jit_type_t const jit_type_##name = (jit_type_t)&name##_tagged
DECLARE_TAGGED(sys_bool, ubyte_def, JIT_TYPETAG_SYS_BOOL);
#ifdef __CHAR_UNSIGNED__
DECLARE_TAGGED(sys_char, ubyte_def, JIT_TYPETAG_SYS_CHAR);
#else
DECLARE_TAGGED(sys_char, sbyte_def, JIT_TYPETAG_SYS_CHAR);
#endif
DECLARE_TAGGED(sys_schar, sbyte_def, JIT_TYPETAG_SYS_SCHAR);
DECLARE_TAGGED(sys_uchar, ubyte_def, JIT_TYPETAG_SYS_UCHAR);
#if SIZEOF_SHORT == 4
DECLARE_TAGGED(sys_short, int_def, JIT_TYPETAG_SYS_SHORT);
DECLARE_TAGGED(sys_ushort, uint_def, JIT_TYPETAG_SYS_USHORT);
#elif SIZEOF_SHORT == 8
DECLARE_TAGGED(sys_short, long_def, JIT_TYPETAG_SYS_SHORT);
DECLARE_TAGGED(sys_ushort, ulong_def, JIT_TYPETAG_SYS_USHORT);
#else
DECLARE_TAGGED(sys_short, short_def, JIT_TYPETAG_SYS_SHORT);
DECLARE_TAGGED(sys_ushort, ushort_def, JIT_TYPETAG_SYS_USHORT);
#endif
#if SIZEOF_INT == 8
DECLARE_TAGGED(sys_int, long_def, JIT_TYPETAG_SYS_INT);
DECLARE_TAGGED(sys_uint, ulong_def, JIT_TYPETAG_SYS_UINT);
#elif SIZEOF_INT == 2
DECLARE_TAGGED(sys_int, short_def, JIT_TYPETAG_SYS_INT);
DECLARE_TAGGED(sys_uint, ushort_def, JIT_TYPETAG_SYS_UINT);
#else
DECLARE_TAGGED(sys_int, int_def, JIT_TYPETAG_SYS_INT);
DECLARE_TAGGED(sys_uint, uint_def, JIT_TYPETAG_SYS_UINT);
#endif
#if SIZEOF_LONG == 8
DECLARE_TAGGED(sys_long, long_def, JIT_TYPETAG_SYS_LONG);
DECLARE_TAGGED(sys_ulong, ulong_def, JIT_TYPETAG_SYS_ULONG);
#elif SIZEOF_LONG == 2
DECLARE_TAGGED(sys_long, short_def, JIT_TYPETAG_SYS_LONG);
DECLARE_TAGGED(sys_ulong, ushort_def, JIT_TYPETAG_SYS_ULONG);
#else
DECLARE_TAGGED(sys_long, int_def, JIT_TYPETAG_SYS_LONG);
DECLARE_TAGGED(sys_ulong, uint_def, JIT_TYPETAG_SYS_ULONG);
#endif
#if SIZEOF_LONG_LONG == 8 || SIZEOF___INT64 == 8
DECLARE_TAGGED(sys_longlong, long_def, JIT_TYPETAG_SYS_LONGLONG);
DECLARE_TAGGED(sys_ulonglong, ulong_def, JIT_TYPETAG_SYS_ULONGLONG);
#elif SIZEOF_LONG_LONG == 4
DECLARE_TAGGED(sys_longlong, int_def, JIT_TYPETAG_SYS_LONGLONG);
DECLARE_TAGGED(sys_ulonglong, uint_def, JIT_TYPETAG_SYS_ULONGLONG);
#elif SIZEOF_LONG_LONG == 2
DECLARE_TAGGED(sys_longlong, short_def, JIT_TYPETAG_SYS_LONGLONG);
DECLARE_TAGGED(sys_ulonglong, ushort_def, JIT_TYPETAG_SYS_ULONGLONG);
#else
DECLARE_TAGGED(sys_longlong, long_def, JIT_TYPETAG_SYS_LONGLONG);
DECLARE_TAGGED(sys_ulonglong, ulong_def, JIT_TYPETAG_SYS_ULONGLONG);
#endif
DECLARE_TAGGED(sys_float, float32_def, JIT_TYPETAG_SYS_FLOAT);
DECLARE_TAGGED(sys_double, float64_def, JIT_TYPETAG_SYS_DOUBLE);
DECLARE_TAGGED(sys_long_double, nfloat_def, JIT_TYPETAG_SYS_LONGDOUBLE);

/*
 * Special offset flags.
 */
#define	JIT_OFFSET_IS_INTERNAL	(((jit_nuint)1) << (sizeof(jit_nint) * 8 - 1))
#define	JIT_OFFSET_NOT_SET		(~((jit_nuint)0))

/*
 * Layout flags.
 */
#define	JIT_LAYOUT_NEEDED			1
#define	JIT_LAYOUT_EXPLICIT_SIZE	2
#define	JIT_LAYOUT_EXPLICIT_ALIGN	4

/*
 * Perform layout on a structure or union type.
 */
static void perform_layout(jit_type_t type)
{
	jit_nuint size = 0;
	jit_nuint maxSize = 0;
	jit_nuint maxAlign = 1;
	jit_nuint alignLimit;
	jit_nuint fieldSize;
	jit_nuint fieldAlign;
	unsigned int index;

	/* Determine the alignment limit, if there is an override */
#ifdef JIT_ALIGN_OVERRIDES
	if((type->layout_flags & JIT_LAYOUT_EXPLICIT_ALIGN) != 0)
	{
		alignLimit = type->alignment;
	}
	else
#endif
	{
		alignLimit = 0;
	}

	/* Lay out all of the fields in this structure */
	for(index = 0; index < type->num_components; ++index)
	{
		/* Get the size and alignment of the field */
		fieldSize = jit_type_get_size(type->components[index].type);
		fieldAlign = jit_type_get_alignment(type->components[index].type);

		/* Clamp the alignment if we have a limit */
		if(alignLimit != 0 && fieldAlign > alignLimit)
		{
			fieldAlign = alignLimit;
		}

		/* Update the size and alignment values */
		if(type->kind == JIT_TYPE_STRUCT)
		{
			/* Perform layout for a struct type */
			if((type->components[index].offset & JIT_OFFSET_IS_INTERNAL) != 0)
			{
				/* Calculate the offset for the field automatically */
				if((size % fieldAlign) != 0)
				{
					size += fieldAlign - (size % fieldAlign);
				}
				type->components[index].offset = JIT_OFFSET_IS_INTERNAL | size;
				size += fieldSize;
			}
			else
			{
				/* Use the explicitly-supplied offset for the field */
				size = type->components[index].offset + fieldSize;
			}
			if(size > maxSize)
			{
				maxSize = size;
			}
		}
		else
		{
			/* Perform layout for a union type (offset is always zero) */
			type->components[index].offset = JIT_OFFSET_IS_INTERNAL | 0;
			if((fieldSize % fieldAlign) != 0)
			{
				fieldSize += fieldAlign - (fieldSize % fieldAlign);
			}
			if(fieldSize > maxSize)
			{
				maxSize = fieldSize;
			}
		}
		if(fieldAlign > maxAlign)
		{
			maxAlign = fieldAlign;
		}
	}

	/* Align the full structure */
	if((maxSize % maxAlign) != 0)
	{
		maxSize += maxAlign - (maxSize % maxAlign);
	}

	/* Record the final size and alignment values */
	if((type->layout_flags & JIT_LAYOUT_EXPLICIT_SIZE) != 0)
	{
		if(maxSize > type->size)
		{
			type->size = maxSize;
		}
	}
	else
	{
		type->size = maxSize;
	}
	if(maxAlign > type->alignment)
	{
		type->alignment = maxAlign;
	}
}

/*@
 * @deftypefun jit_type_t jit_type_copy (jit_type_t @var{type})
 * Make a copy of the type descriptor @var{type} by increasing
 * its reference count.
 * @end deftypefun
@*/
jit_type_t jit_type_copy(jit_type_t type)
{
	if(!type || type->is_fixed)
	{
		return type;
	}
	++(type->ref_count);
	return type;
}

/*@
 * @deftypefun void jit_type_free (jit_type_t @var{type})
 * Free a type descriptor by decreasing its reference count.
 * This function is safe to use on pre-defined types, which are
 * never actually freed.
 * @end deftypefun
@*/
void jit_type_free(jit_type_t type)
{
	unsigned int index;
	if(!type || type->is_fixed)
	{
		return;
	}
	if(--(type->ref_count) != 0)
	{
		return;
	}
	jit_type_free(type->sub_type);
	for(index = 0; index < type->num_components; ++index)
	{
		jit_type_free(type->components[index].type);
		if(type->components[index].name)
		{
			jit_free(type->components[index].name);
		}
	}
	if(type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		struct jit_tagged_type *tagged = (struct jit_tagged_type *)type;
		if(tagged->free_func)
		{
			(*(tagged->free_func))(tagged->data);
		}
	}
	jit_free(type);
}

static jit_type_t create_complex(int kind, jit_type_t *types,
								 unsigned int num, int incref)
{
	jit_type_t type;
	unsigned int index;
	if(num <= 1)
	{
		type = jit_cnew(struct _jit_type);
	}
	else
	{
		type = (jit_type_t)jit_calloc
				(1, sizeof(struct _jit_type) +
				    (num - 1) * sizeof(struct jit_component));
	}
	if(!type)
	{
		return 0;
	}
	type->ref_count = 1;
	type->kind = kind;
	type->layout_flags = JIT_LAYOUT_NEEDED;
	type->num_components = num;
	for(index = 0; index < num; ++index)
	{
		if(incref)
		{
			type->components[index].type = jit_type_copy(types[index]);
		}
		else
		{
			type->components[index].type = types[index];
		}
		type->components[index].offset = JIT_OFFSET_NOT_SET;
		type->components[index].name = 0;
	}
	return type;
}

/*@
 * @deftypefun jit_type_t jit_type_create_struct (jit_type_t *@var{fields}, unsigned int @var{num_fields}, int @var{incref})
 * Create a type descriptor for a structure.  Returns NULL if out of memory.
 * If there are no fields, then the size of the structure will be zero.
 * It is necessary to add a padding field if the language does not allow
 * zero-sized structures.  The reference counts on the field types are
 * incremented if @var{incref} is non-zero.
 *
 * The @code{libjit} library does not provide any special support for
 * implementing structure inheritance, where one structure extends the
 * definition of another.  The effect of inheritance can be achieved
 * by always allocating the first field of a structure to be an instance
 * of the inherited structure.  Multiple inheritance can be supported
 * by allocating several special fields at the front of an inheriting
 * structure.
 *
 * Similarly, no special support is provided for vtables.  The program
 * is responsible for allocating an appropriate slot in a structure to
 * contain the vtable pointer, and dereferencing it wherever necessary.
 * The vtable will itself be a structure, containing signature types
 * for each of the method slots.
 *
 * The choice not to provide special support for inheritance and vtables
 * in @code{libjit} was deliberate.  The layout of objects and vtables
 * is highly specific to the language and virtual machine being emulated,
 * and no single scheme can hope to capture all possibilities.
 * @end deftypefun
@*/
jit_type_t jit_type_create_struct(jit_type_t *fields, unsigned int num_fields,
								  int incref)
{
	return create_complex(JIT_TYPE_STRUCT, fields, num_fields, incref);
}

/*@
 * @deftypefun jit_type_t jit_type_create_union (jit_type_t *@var{fields}, unsigned int @var{num_fields}, int @var{incref})
 * Create a type descriptor for a union.  Returns NULL if out of memory.
 * If there are no fields, then the size of the union will be zero.
 * It is necessary to add a padding field if the language does not allow
 * zero-sized unions.  The reference counts on the field types are
 * incremented if @var{incref} is non-zero.
 * @end deftypefun
@*/
jit_type_t jit_type_create_union(jit_type_t *fields, unsigned int num_fields,
								 int incref)
{
	return create_complex(JIT_TYPE_UNION, fields, num_fields, incref);
}

/*@
 * @deftypefun jit_type_t jit_type_create_signature (jit_abi_t @var{abi}, jit_type_t @var{return_type}, jit_type_t *@var{params}, unsigned int @var{num_params}, int @var{incref})
 * Create a type descriptor for a function signature.  Returns NULL if out
 * of memory.  The reference counts on the component types are incremented
 * if @var{incref} is non-zero.
 *
 * When used as a structure or union field, function signatures are laid
 * out like pointers.  That is, they represent a pointer to a function
 * that has the specified parameters and return type.
 *
 * @tindex jit_abi_t
 * The @var{abi} parameter specifies the Application Binary Interface (ABI)
 * that the function uses.  It may be one of the following values:
 *
 * @table @code
 * @vindex jit_abi_cdecl
 * @item jit_abi_cdecl
 * Use the native C ABI definitions of the underlying platform.
 *
 * @vindex jit_abi_vararg
 * @item jit_abi_vararg
 * Use the native C ABI definitions of the underlying platform,
 * and allow for an optional list of variable argument parameters.
 *
 * @vindex jit_abi_stdcall
 * @item jit_abi_stdcall
 * Use the Win32 STDCALL ABI definitions, whereby the callee pops
 * its arguments rather than the caller.  If the platform does
 * not support this type of ABI, then @code{jit_abi_stdcall} will be
 * identical to @code{jit_abi_cdecl}.
 *
 * @vindex jit_abi_fastcall
 * @item jit_abi_fastcall
 * Use the Win32 FASTCALL ABI definitions, whereby the callee pops
 * its arguments rather than the caller, and the first two word
 * arguments are passed in ECX and EDX.  If the platform does
 * not support this type of ABI, then @code{jit_abi_fastcall} will be
 * identical to @code{jit_abi_cdecl}.
 * @end table
 * @end deftypefun
@*/
jit_type_t jit_type_create_signature(jit_abi_t abi, jit_type_t return_type,
                                     jit_type_t *params,
									 unsigned int num_params, int incref)
{
	jit_type_t type;
	type = create_complex(JIT_TYPE_SIGNATURE, params, num_params, incref);
	if(type)
	{
		type->abi = (int)abi;
		type->layout_flags = 0;
		type->size = 0;
		type->alignment = JIT_ALIGN_PTR;
		if(incref)
		{
			type->sub_type = jit_type_copy(return_type);
		}
		else
		{
			type->sub_type = return_type;
		}
	}
	return type;
}

/*@
 * @deftypefun jit_type_t jit_type_create_pointer (jit_type_t @var{type}, int @var{incref})
 * Create a type descriptor for a pointer to another type.  Returns NULL
 * if out of memory.  The reference count on @var{type} is incremented if
 * @var{incref} is non-zero.
 * @end deftypefun
@*/
jit_type_t jit_type_create_pointer(jit_type_t type, int incref)
{
	jit_type_t ntype;
	if(type == jit_type_void)
	{
		return jit_type_void_ptr;
	}
	if((ntype = jit_cnew(struct _jit_type)) == 0)
	{
		return 0;
	}
	ntype->ref_count = 1;
	ntype->kind = JIT_TYPE_PTR;
	ntype->size = sizeof(void *);
	ntype->alignment = JIT_ALIGN_PTR;
	if(incref)
	{
		ntype->sub_type = jit_type_copy(type);
	}
	else
	{
		ntype->sub_type = type;
	}
	return ntype;
}

/*@
 * @deftypefun jit_type_t jit_type_create_tagged (jit_type_t @var{type}, int @var{kind}, void *@var{data}, jit_meta_free_func @var{free_func}, int @var{incref})
 * Tag a type with some additional user data.  Tagging is typically used by
 * higher-level programs to embed extra information about a type that
 * @code{libjit} itself does not support.
 *
 * As an example, a language might have a 16-bit Unicode character type
 * and a 16-bit unsigned integer type that are distinct types, even though
 * they share the same fundamental representation (@code{jit_ushort}).
 * Tagging allows the program to distinguish these two types, when
 * it is necessary to do so, without affecting @code{libjit}'s ability
 * to compile the code efficiently.
 *
 * The @var{kind} is a small positive integer value that the program
 * can use to distinguish multiple tag types.  The @var{data} pointer is
 * the actual data that you wish to store.  And @var{free_func} is a
 * function that is used to free @var{data} when the type is freed
 * with @code{jit_type_free}.
 *
 * If you need to store more than one piece of information, you can
 * tag a type multiple times.  The order in which multiple tags are
 * applied is irrelevant to @code{libjit}, although it may be relevant
 * to the higher-level program.
 *
 * Tag kinds of 10000 or greater are reserved for @code{libjit} itself.
 * The following special tag kinds are currently provided in the
 * base implementation:
 *
 * @table @code
 * @vindex JIT_TYPETAG_NAME
 * @item JIT_TYPETAG_NAME
 * The @var{data} pointer is a @code{char *} string indicating a friendly
 * name to display for the type.
 *
 * @vindex JIT_TYPETAG_STRUCT_NAME
 * @vindex JIT_TYPETAG_UNION_NAME
 * @vindex JIT_TYPETAG_ENUM_NAME
 * @item JIT_TYPETAG_STRUCT_NAME
 * @itemx JIT_TYPETAG_UNION_NAME
 * @itemx JIT_TYPETAG_ENUM_NAME
 * The @var{data} pointer is a @code{char *} string indicating a friendly
 * name to display for a @code{struct}, @code{union}, or @code{enum} type.
 * This is for languages like C that have separate naming scopes for
 * typedef's and structures.
 *
 * @vindex JIT_TYPETAG_CONST
 * @item JIT_TYPETAG_CONST
 * The underlying value is assumed to have @code{const} semantics.
 * The @code{libjit} library doesn't enforce such semantics: it is
 * up to the front-end to only use constant values in appopriate contexts.
 *
 * @vindex JIT_TYPETAG_VOLATILE
 * @item JIT_TYPETAG_VOLATILE
 * The underlying value is assumed to be volatile.  The @code{libjit}
 * library will automatically call @code{jit_value_set_volatile} when a
 * value is constructed using this type.
 *
 * @vindex JIT_TYPETAG_REFERENCE
 * @item JIT_TYPETAG_REFERENCE
 * The underlying value is a pointer, but it is assumed to refer to a
 * pass-by-reference parameter.
 *
 * @vindex JIT_TYPETAG_OUTPUT
 * @item JIT_TYPETAG_OUTPUT
 * This is similar to @code{JIT_TYPETAG_REFERENCE}, except that the
 * underlying parameter is assumed to be output-only.
 *
 * @vindex JIT_TYPETAG_RESTRICT
 * @item JIT_TYPETAG_RESTRICT
 * The underlying type is marked as @code{restrict}.  Normally ignored.
 *
 * @vindex JIT_TYPETAG_SYS_BOOL
 * @vindex JIT_TYPETAG_SYS_CHAR
 * @vindex JIT_TYPETAG_SYS_SCHAR
 * @vindex JIT_TYPETAG_SYS_UCHAR
 * @vindex JIT_TYPETAG_SYS_SHORT
 * @vindex JIT_TYPETAG_SYS_USHORT
 * @vindex JIT_TYPETAG_SYS_INT
 * @vindex JIT_TYPETAG_SYS_UINT
 * @vindex JIT_TYPETAG_SYS_LONG
 * @vindex JIT_TYPETAG_SYS_ULONG
 * @vindex JIT_TYPETAG_SYS_LONGLONG
 * @vindex JIT_TYPETAG_SYS_ULONGLONG
 * @vindex JIT_TYPETAG_SYS_FLOAT
 * @vindex JIT_TYPETAG_SYS_DOUBLE
 * @vindex JIT_TYPETAG_SYS_LONGDOUBLE
 * @item JIT_TYPETAG_SYS_BOOL
 * @itemx JIT_TYPETAG_SYS_CHAR
 * @itemx JIT_TYPETAG_SYS_SCHAR
 * @itemx JIT_TYPETAG_SYS_UCHAR
 * @itemx JIT_TYPETAG_SYS_SHORT
 * @itemx JIT_TYPETAG_SYS_USHORT
 * @itemx JIT_TYPETAG_SYS_INT
 * @itemx JIT_TYPETAG_SYS_UINT
 * @itemx JIT_TYPETAG_SYS_LONG
 * @itemx JIT_TYPETAG_SYS_ULONG
 * @itemx JIT_TYPETAG_SYS_LONGLONG
 * @itemx JIT_TYPETAG_SYS_ULONGLONG
 * @itemx JIT_TYPETAG_SYS_FLOAT
 * @itemx JIT_TYPETAG_SYS_DOUBLE
 * @itemx JIT_TYPETAG_SYS_LONGDOUBLE
 * Used to mark types that we know for a fact correspond to the system
 * C types of the corresponding names.  This is primarily used to distinguish
 * system types like @code{int} and @code{long} types on 32-bit platforms
 * when it is necessary to do so.  The @code{jit_type_sys_xxx} values are
 * all tagged in this manner.
 * @end table
 * @end deftypefun
@*/
jit_type_t jit_type_create_tagged(jit_type_t type, int kind, void *data,
								  jit_meta_free_func free_func, int incref)
{
	struct jit_tagged_type *ntype;
	if((ntype = jit_cnew(struct jit_tagged_type)) == 0)
	{
		return 0;
	}
	ntype->type.ref_count = 1;
	ntype->type.kind = JIT_TYPE_FIRST_TAGGED + kind;
	ntype->type.size = 0;
	ntype->type.alignment = 1;
	if(incref)
	{
		ntype->type.sub_type = jit_type_copy(type);
	}
	else
	{
		ntype->type.sub_type = type;
	}
	ntype->data = data;
	ntype->free_func = free_func;
	return &(ntype->type);
}

/*@
 * @deftypefun int jit_type_set_names (jit_type_t @var{type}, char **@var{names}, unsigned int @var{num_names})
 * Set the field or parameter names for @var{type}.  Returns zero
 * if there is insufficient memory to set the names.
 *
 * Normally fields are accessed via their index.  Field names are a
 * convenience for front ends that prefer to use names to indices.
 * @end deftypefun
@*/
int jit_type_set_names(jit_type_t type, char **names, unsigned int num_names)
{
	char *temp;
	if(!type || type->is_fixed || !names)
	{
		return 1;
	}
	if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION ||
	   type->kind == JIT_TYPE_SIGNATURE)
	{
		if(num_names > type->num_components)
		{
			num_names = type->num_components;
		}
		while(num_names > 0)
		{
			--num_names;
			if(type->components[num_names].name)
			{
				jit_free(type->components[num_names].name);
				type->components[num_names].name = 0;
			}
			if(names[num_names])
			{
				temp = jit_strdup(names[num_names]);
				if(!temp)
				{
					return 0;
				}
				type->components[num_names].name = temp;
			}
		}
	}
	return 1;
}

/*@
 * @deftypefun void jit_type_set_size_and_alignment (jit_type_t @var{type}, jit_nint @var{size}, jit_nint @var{alignment})
 * Set the size and alignment information for a structure or union
 * type.  Use this for performing explicit type layout.  Normally
 * the size is computed automatically.  Ignored if not a
 * structure or union type.  Setting either value to -1 will cause
 * that value to be computed automatically.
 * @end deftypefun
@*/
void jit_type_set_size_and_alignment(jit_type_t type, jit_nint size,
									 jit_nint alignment)
{
	if(!type)
	{
		return;
	}
	if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
	{
		type->size = (jit_nuint)size;
		type->alignment = (jit_nuint)alignment;
		if(size != -1)
		{
			type->layout_flags |= JIT_LAYOUT_EXPLICIT_SIZE;
		}
		if(alignment != -1)
		{
			type->layout_flags |= JIT_LAYOUT_EXPLICIT_ALIGN;
		}
		type->layout_flags |= JIT_LAYOUT_NEEDED;
	}
}

/*@
 * @deftypefun void jit_type_set_offset (jit_type_t @var{type}, unsigned int @var{field_index}, jit_nuint @var{offset})
 * Set the offset of a specific structure field.  Use this for
 * performing explicit type layout.  Normally the offset is
 * computed automatically.  Ignored if not a structure type,
 * or the field index is out of range.
 * @end deftypefun
@*/
void jit_type_set_offset(jit_type_t type, unsigned int field_index,
						 jit_nuint offset)
{
	if(!type || field_index >= type->num_components)
	{
		return;
	}
	if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
	{
		type->components[field_index].offset = offset;
		type->layout_flags |= JIT_LAYOUT_NEEDED;
	}
}

/*@
 * @deftypefun int jit_type_get_kind (jit_type_t @var{type})
 * Get a value that indicates the kind of @var{type}.  This allows
 * callers to quickly classify a type to determine how it should be
 * handled further.
 *
 * @table @code
 * @vindex JIT_TYPE_INVALID
 * @item JIT_TYPE_INVALID
 * The value of the @var{type} parameter is NULL.
 *
 * @vindex JIT_TYPE_VOID
 * @item JIT_TYPE_VOID
 * The type is @code{jit_type_void}.
 *
 * @vindex JIT_TYPE_SBYTE
 * @item JIT_TYPE_SBYTE
 * The type is @code{jit_type_sbyte}.
 *
 * @vindex JIT_TYPE_UBYTE
 * @item JIT_TYPE_UBYTE
 * The type is @code{jit_type_ubyte}.
 *
 * @vindex JIT_TYPE_SHORT
 * @item JIT_TYPE_SHORT
 * The type is @code{jit_type_short}.
 *
 * @vindex JIT_TYPE_USHORT
 * @item JIT_TYPE_USHORT
 * The type is @code{jit_type_ushort}.
 *
 * @vindex JIT_TYPE_INT
 * @item JIT_TYPE_INT
 * The type is @code{jit_type_int}.
 *
 * @vindex JIT_TYPE_UINT
 * @item JIT_TYPE_UINT
 * The type is @code{jit_type_uint}.
 *
 * @vindex JIT_TYPE_NINT
 * @item JIT_TYPE_NINT
 * The type is @code{jit_type_nint}.
 *
 * @vindex JIT_TYPE_NUINT
 * @item JIT_TYPE_NUINT
 * The type is @code{jit_type_nuint}.
 *
 * @vindex JIT_TYPE_LONG
 * @item JIT_TYPE_LONG
 * The type is @code{jit_type_long}.
 *
 * @vindex JIT_TYPE_ULONG
 * @item JIT_TYPE_ULONG
 * The type is @code{jit_type_ulong}.
 *
 * @vindex JIT_TYPE_FLOAT32
 * @item JIT_TYPE_FLOAT32
 * The type is @code{jit_type_float32}.
 *
 * @vindex JIT_TYPE_FLOAT64
 * @item JIT_TYPE_FLOAT64
 * The type is @code{jit_type_float64}.
 *
 * @vindex JIT_TYPE_NFLOAT
 * @item JIT_TYPE_NFLOAT
 * The type is @code{jit_type_nfloat}.
 *
 * @vindex JIT_TYPE_STRUCT
 * @item JIT_TYPE_STRUCT
 * The type is the result of calling @code{jit_type_create_struct}.
 *
 * @vindex JIT_TYPE_UNION
 * @item JIT_TYPE_UNION
 * The type is the result of calling @code{jit_type_create_union}.
 *
 * @vindex JIT_TYPE_SIGNATURE
 * @item JIT_TYPE_SIGNATURE
 * The type is the result of calling @code{jit_type_create_signature}.
 *
 * @vindex JIT_TYPE_PTR
 * @item JIT_TYPE_PTR
 * The type is the result of calling @code{jit_type_create_pointer}.
 * @end table
 *
 * @vindex JIT_TYPE_FIRST_TAGGED
 * If this function returns @code{JIT_TYPE_FIRST_TAGGED} or higher,
 * then the type is tagged and its tag kind is the return value minus
 * @code{JIT_TYPE_FIRST_TAGGED}.  That is, the following two expressions
 * will be identical if @var{type} is tagged:
 *
 * @example
 * jit_type_get_tagged_kind(type)
 * jit_type_get_kind(type) - JIT_TYPE_FIRST_TAGGED
 * @end example
 * @end deftypefun
@*/
int jit_type_get_kind(jit_type_t type)
{
	if(!type)
	{
		return JIT_TYPE_INVALID;
	}
	else
	{
		return type->kind;
	}
}

/*@
 * @deftypefun jit_nuint jit_type_get_size (jit_type_t @var{type})
 * Get the size of a type in bytes.
 * @end deftypefun
@*/
jit_nuint jit_type_get_size(jit_type_t type)
{
	if(!type)
	{
		return 0;
	}
	if(type->kind == JIT_TYPE_SIGNATURE)
	{
		/* The "size" field is used for argument size, not type size,
		   so we ignore it and return the real size here */
		return sizeof(void *);
	}
	else if(type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		return jit_type_get_size(type->sub_type);
	}
	if((type->layout_flags & JIT_LAYOUT_NEEDED) != 0)
	{
		perform_layout(type);
	}
	return type->size;
}

/*@
 * @deftypefun jit_nuint jit_type_get_alignment (jit_type_t @var{type})
 * Get the alignment of a type.  An alignment value of 2 indicates
 * that the type should be aligned on a two-byte boundary, for example.
 * @end deftypefun
@*/
jit_nuint jit_type_get_alignment(jit_type_t type)
{
	if(!type)
	{
		return 0;
	}
	if(type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		return jit_type_get_alignment(type->sub_type);
	}
	if((type->layout_flags & JIT_LAYOUT_NEEDED) != 0)
	{
		perform_layout(type);
	}
	return type->alignment;
}

/*@
 * @deftypefun {unsigned int} jit_type_num_fields (jit_type_t @var{type})
 * Get the number of fields in a structure or union type.
 * @end deftypefun
@*/
unsigned int jit_type_num_fields(jit_type_t type)
{
	if(!type ||
	   (type->kind != JIT_TYPE_STRUCT && type->kind != JIT_TYPE_UNION))
	{
		return 0;
	}
	else
	{
		return type->num_components;
	}
}

/*@
 * @deftypefun jit_type_t jit_type_get_field (jit_type_t @var{type}, unsigned int @var{field_index})
 * Get the type of a specific field within a structure or union.
 * Returns NULL if not a structure or union, or the index is out of range.
 * @end deftypefun
@*/
jit_type_t jit_type_get_field(jit_type_t type, unsigned int field_index)
{
	if(!type || field_index >= type->num_components)
	{
		return 0;
	}
	if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
	{
		return type->components[field_index].type;
	}
	return 0;
}

/*@
 * @deftypefun jit_nuint jit_type_get_offset (jit_type_t @var{type}, unsigned int @var{field_index})
 * Get the offset of a specific field within a structure.
 * Returns zero if not a structure, or the index is out of range,
 * so this is safe to use on non-structure types.
 * @end deftypefun
@*/
jit_nuint jit_type_get_offset(jit_type_t type, unsigned int field_index)
{
	if(!type || field_index >= type->num_components)
	{
		return 0;
	}
	if(type->kind != JIT_TYPE_STRUCT && type->kind != JIT_TYPE_UNION)
	{
		return 0;
	}
	if((type->layout_flags & JIT_LAYOUT_NEEDED) != 0)
	{
		perform_layout(type);
	}
	return type->components[field_index].offset & ~JIT_OFFSET_IS_INTERNAL;
}

/*@
 * @deftypefun {const char *} jit_type_get_name (jit_type_t @var{type}, unsigned int @var{index})
 * Get the name of a structure, union, or signature field/parameter.
 * Returns NULL if not a structure, union, or signature, the index
 * is out of range, or there is no name associated with the component.
 * @end deftypefun
@*/
const char *jit_type_get_name(jit_type_t type, unsigned int index)
{
	if(!type || index >= type->num_components)
	{
		return 0;
	}
	else
	{
		return type->components[index].name;
	}
}

/*@
 * @deftypefun {unsigned int} jit_type_find_name (jit_type_t @var{type}, const char *@var{name})
 * Find the field/parameter index for a particular name.  Returns
 * @code{JIT_INVALID_NAME} if the name was not present.
 * @end deftypefun
@*/
unsigned int jit_type_find_name(jit_type_t type, const char *name)
{
	unsigned int index;
	if(!type || !name)
	{
		return JIT_INVALID_NAME;
	}
	if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION ||
	   type->kind == JIT_TYPE_SIGNATURE)
	{
		for(index = 0; index < type->num_components; ++index)
		{
			if(type->components[index].name &&
			   !jit_strcmp(type->components[index].name, name))
			{
				return index;
			}
		}
	}
	return JIT_INVALID_NAME;
}

/*@
 * @deftypefun {unsigned int} jit_type_num_params (jit_type_t @var{type})
 * Get the number of parameters in a signature type.
 * @end deftypefun
@*/
unsigned int jit_type_num_params(jit_type_t type)
{
	if(!type || type->kind != JIT_TYPE_SIGNATURE)
	{
		return 0;
	}
	else
	{
		return type->num_components;
	}
}

/*@
 * @deftypefun jit_type_t jit_type_get_return (jit_type_t @var{type})
 * Get the return type from a signature type.  Returns NULL if
 * not a signature type.
 * @end deftypefun
@*/
jit_type_t jit_type_get_return(jit_type_t type)
{
	if(type)
	{
		if(type->kind == JIT_TYPE_SIGNATURE)
		{
			return type->sub_type;
		}
	}
	return 0;
}

/*@
 * @deftypefun jit_type_t jit_type_get_param (jit_type_t @var{type}, unsigned int @var{param_index})
 * Get a specific parameter from a signature type.  Returns NULL
 * if not a signature type or the index is out of range.
 * @end deftypefun
@*/
jit_type_t jit_type_get_param(jit_type_t type, unsigned int param_index)
{
	if(!type || param_index >= type->num_components)
	{
		return 0;
	}
	if(type->kind == JIT_TYPE_SIGNATURE)
	{
		return type->components[param_index].type;
	}
	return 0;
}

/*@
 * @deftypefun jit_abi_t jit_type_get_abi (jit_type_t @var{type})
 * Get the ABI code from a signature type.  Returns @code{jit_abi_cdecl}
 * if not a signature type.
 * @end deftypefun
@*/
jit_abi_t jit_type_get_abi(jit_type_t type)
{
	if(type)
	{
		return (jit_abi_t)(type->abi);
	}
	else
	{
		return jit_abi_cdecl;
	}
}

/*@
 * @deftypefun jit_type_t jit_type_get_ref (jit_type_t @var{type})
 * Get the type that is referred to by a pointer type.  Returns NULL
 * if not a pointer type.
 * @end deftypefun
@*/
jit_type_t jit_type_get_ref(jit_type_t type)
{
	if(type)
	{
		if(type->kind == JIT_TYPE_PTR)
		{
			return type->sub_type;
		}
	}
	return 0;
}

/*@
 * @deftypefun jit_type_t jit_type_get_tagged_type (jit_type_t @var{type})
 * Get the type that underlies a tagged type.  Returns NULL
 * if not a tagged type.
 * @end deftypefun
@*/
jit_type_t jit_type_get_tagged_type(jit_type_t type)
{
	if(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		return type->sub_type;
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun void jit_type_set_tagged_type (jit_type_t @var{type}, jit_type_t @var{underlying}, int @var{incref})
 * Set the type that underlies a tagged type.  Ignored if @var{type}
 * is not a tagged type.  If @var{type} already has an underlying
 * type, then the original is freed.  The reference count on @var{underlying}
 * is incremented if @var{incref} is non-zero.
 *
 * This function is typically used to flesh out the body of a
 * forward-declared type.  The tag is used as a placeholder
 * until the definition can be located.
 * @end deftypefun
@*/
void jit_type_set_tagged_type(jit_type_t type, jit_type_t underlying,
                              int incref)
{
	if(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		if(type->sub_type != underlying)
		{
			jit_type_free(type->sub_type);
			if(incref)
			{
				type->sub_type = jit_type_copy(underlying);
			}
			else
			{
				type->sub_type = underlying;
			}
		}
	}
}

/*@
 * @deftypefun int jit_type_get_tagged_kind (jit_type_t @var{type})
 * Get the kind of tag that is applied to a tagged type.  Returns -1
 * if not a tagged type.
 * @end deftypefun
@*/
int jit_type_get_tagged_kind(jit_type_t type)
{
	if(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		return type->kind - JIT_TYPE_FIRST_TAGGED;
	}
	else
	{
		return -1;
	}
}

/*@
 * @deftypefun {void *} jit_type_get_tagged_data (jit_type_t @var{type})
 * Get the user data is associated with a tagged type.  Returns NULL
 * if not a tagged type.
 * @end deftypefun
@*/
void *jit_type_get_tagged_data(jit_type_t type)
{
	if(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		return ((struct jit_tagged_type *)type)->data;
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun void jit_type_set_tagged_data (jit_type_t @var{type}, void *@var{data}, jit_meta_free_func @var{free_func})
 * Set the user data is associated with a tagged type.  The original data,
 * if any, is freed.
 * @end deftypefun
@*/
void jit_type_set_tagged_data(jit_type_t type, void *data,
                              jit_meta_free_func free_func)
{
	if(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		struct jit_tagged_type *tagged = (struct jit_tagged_type *)type;
		if(tagged->data != data)
		{
			if(tagged->free_func)
			{
				(*(tagged->free_func))(tagged->data);
			}
			tagged->data = data;
			tagged->free_func = free_func;
		}
	}
}

/*@
 * @deftypefun int jit_type_is_primitive (jit_type_t @var{type})
 * Determine if a type is primitive.
 * @end deftypefun
@*/
int jit_type_is_primitive(jit_type_t type)
{
	if(type)
	{
		return (type->kind <= JIT_TYPE_MAX_PRIMITIVE);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun int jit_type_is_struct (jit_type_t @var{type})
 * Determine if a type is a structure.
 * @end deftypefun
@*/
int jit_type_is_struct(jit_type_t type)
{
	if(type)
	{
		return (type->kind == JIT_TYPE_STRUCT);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun int jit_type_is_union (jit_type_t @var{type})
 * Determine if a type is a union.
 * @end deftypefun
@*/
int jit_type_is_union(jit_type_t type)
{
	if(type)
	{
		return (type->kind == JIT_TYPE_UNION);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun int jit_type_is_signature (jit_type_t @var{type})
 * Determine if a type is a function signature.
 * @end deftypefun
@*/
int jit_type_is_signature(jit_type_t type)
{
	if(type)
	{
		return (type->kind == JIT_TYPE_SIGNATURE);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun int jit_type_is_pointer (jit_type_t @var{type})
 * Determine if a type is a pointer.
 * @end deftypefun
@*/
int jit_type_is_pointer(jit_type_t type)
{
	if(type)
	{
		return (type->kind == JIT_TYPE_PTR);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun int jit_type_is_tagged (jit_type_t @var{type})
 * Determine if a type is a tagged type.
 * @end deftypefun
@*/
int jit_type_is_tagged(jit_type_t type)
{
	if(type)
	{
		return (type->kind >= JIT_TYPE_FIRST_TAGGED);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun jit_nuint jit_type_best_alignment (void)
 * Get the best alignment value for this platform.
 * @end deftypefun
@*/
jit_nuint jit_type_best_alignment(void)
{
	return JIT_BEST_ALIGNMENT;
}

/*@
 * @deftypefun jit_type_t jit_type_normalize (jit_type_t @var{type})
 * Normalize a type to its basic numeric form.  e.g. "jit_type_nint" is
 * turned into "jit_type_int" or "jit_type_long", depending upon
 * the underlying platform.  Pointers are normalized like "jit_type_nint".
 * If the type does not have a normalized form, it is left unchanged.
 *
 * Normalization is typically used prior to applying a binary numeric
 * instruction, to make it easier to determine the common type.
 * It will also remove tags from the specified type.
 * @end deftypefun
@*/
jit_type_t jit_type_normalize(jit_type_t type)
{
	while(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		/* Remove any tags that are attached to the type */
		type = type->sub_type;
	}
	if(!type)
	{
		return type;
	}
	if(type == jit_type_nint || type->kind == JIT_TYPE_PTR ||
	   type->kind == JIT_TYPE_SIGNATURE)
	{
	#ifdef JIT_NATIVE_INT32
		return jit_type_int;
	#else
		return jit_type_long;
	#endif
	}
	else if(type == jit_type_nuint)
	{
	#ifdef JIT_NATIVE_INT32
		return jit_type_uint;
	#else
		return jit_type_ulong;
	#endif
	}
	else if(type == jit_type_nfloat)
	{
		if(sizeof(jit_nfloat) == sizeof(jit_float64))
		{
			return jit_type_float64;
		}
		else if(sizeof(jit_nfloat) == sizeof(jit_float32))
		{
			return jit_type_float32;
		}
	}
	return type;
}

/*@
 * @deftypefun jit_type_t jit_type_remove_tags (jit_type_t @var{type})
 * Remove tags from a type, and return the underlying type.
 * This is different from normalization, which will also collapses
 * native types to their basic numeric counterparts.
 * @end deftypefun
@*/
jit_type_t jit_type_remove_tags(jit_type_t type)
{
	while(type && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		type = type->sub_type;
	}
	return type;
}

/*@
 * @deftypefun jit_type_t jit_type_promote_int (jit_type_t @var{type})
 * If @var{type} is @code{jit_type_sbyte} or @code{jit_type_short},
 * then return @code{jit_type_int}.  If @var{type} is
 * @code{jit_type_ubyte} or @code{jit_type_ushort}, then return
 * @code{jit_type_uint}.  Otherwise return @var{type} as-is.
 * @end deftypefun
@*/
jit_type_t jit_type_promote_int(jit_type_t type)
{
	if(type == jit_type_sbyte || type == jit_type_short)
	{
		return jit_type_int;
	}
	else if(type == jit_type_ubyte || type == jit_type_ushort)
	{
		return jit_type_uint;
	}
	else
	{
		return type;
	}
}

/*@
 * @deftypefun int jit_type_return_via_pointer (jit_type_t @var{type})
 * Determine if a type should be returned via a pointer if it appears
 * as the return type in a signature.
 * @end deftypefun
@*/
int jit_type_return_via_pointer(jit_type_t type)
{
	extern unsigned char const _jit_apply_return_in_reg[];
	unsigned int size;

	/* Normalize the type first, just in case the structure is tagged */
	type = jit_type_normalize(type);

	/* Only structure and union types require special handling */
	if(!jit_type_is_struct(type) && !jit_type_is_union(type))
	{
		return 0;
	}

	/* Determine if the structure can be returned in a register */
	size = jit_type_get_size(type);
	if(size >= 1 && size <= 64)
	{
		if((_jit_apply_return_in_reg[(size - 1) / 8] &
		    	(1 << ((size - 1) % 8))) != 0)
		{
			return 0;
		}
	}
	return 1;
}

/*@
 * @deftypefun int jit_type_has_tag (jit_type_t @var{type}, int @var{kind})
 * Determine if @var{type} has a specific kind of tag.  This will
 * resolve multiple levels of tagging.
 * @end deftypefun
@*/
int jit_type_has_tag(jit_type_t type, int kind)
{
	while(type != 0 && type->kind >= JIT_TYPE_FIRST_TAGGED)
	{
		if(type->kind == (JIT_TYPE_FIRST_TAGGED + kind))
		{
			return 1;
		}
		type = type->sub_type;
	}
	return 0;
}